Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

RFC: RPG ;-)

by pobocks (Chaplain)
on Nov 06, 2008 at 01:05 UTC ( [id://721873]=perlmeditation: print w/replies, xml ) Need Help??

I'm considering starting work on a project. This project will be a portable, easy to use program for handling RPG characters, setting, and administrative details. It should work something like the now defunct grapevine, but should handle other RPG systems than White Wolf's LARP. Ideally it should handle any system, based on a descriptive settings file (possibly XML, JSON, etc) describing how that system's characters are notated.

I am attempting to design this project data-structure first, as I feel that is the part of the program that will be the biggest pain to change down the road. I submit for discussion, criticism, and suggestions the outline for the data structures, starting with a high level overview, and descending to what ideas I have for the implementation.

At any time, there will be one global "System" object, representing the roleplaying system in effect. This isn't very friendly to crossovers, I know, but I feel that this model will handle any games that use the same basic system for dealing with characters, provided the character-type descriptions are sophisticated enough. In addition to information on the system being used, Categories, Traits and attributes available to all types of characters live here, as well as the types of characters allowed.

Character types are what they sound like. For instance, in a White Wolf system, Vampire, Werewolf, and Mortal would all be character types. In D&D, this might be PC, Monster. Basically, this should deal with differences to the structure of the character's sheet (Different categories of powers, different costs for traits, etc.) Information here should override information in the base system settings (For instance, if everyone pays 10 XP for a merit, but ghosts pay 5, then this is how you would resolve that.)

Categories are types of traits available (example: Levels, Disciplines, Skills, Powers.) Ideally, information shared by all traits in a category (cost, for instance) would be kept here. Categories are only attachable to either the System or to a Character type. They do override: if a character doesn't have a particular category that everyone else in the system has, it should be possible to override with a sentinel or null value to signify this.

Traits are... well, just about everything. These are going to be the bread and butter of the data structure. They will be capable of having both traits and attributes; they will represent anything that is potentially present or not-present. They may contain other traits (subtraits such as merits attached to a power in some system, or alternate powers in others. One way to handle White Wolf disciplines might be to have each discipline learned be a trait, and each level in the discipline also be a trait. They may also have attributes attached to them.

Attributes will be key-value pairs that represent single-value, unique data attached to an object. Each data object will have a separate group of attributes.

Implementation-wise, attributes will probably be represented by a plain old hash, one per object. Traits and categories will be more complex objects, although they probably will have relatively few methods. Systems will probably be a collection of local/package variables that the other layers depend on, with container hashes or arrays for the other objects, and a large number of attributes that program logic will be built around.

As you can see, I'm still at a very early stage in planning this. Any design advice or examples to learn from would be most welcome, as well as any suggestions for implementation.

Some of the things I'd most like to hear about are:

  • Should categories and traits be separate object types, or should I eliminate categories and just use traits? Or do I need more different types of things than System, category, trait, attribute? How would you divide this up?
  • What should I use for the system/character description formats? Are there any formats that work particularly well with Perl? Particularly badly?
  • What CPAN modules (other than TK, which is a given) would you recommend to look at?

In addition, I definitely intend to open source this once there's any source to open; if anyone is willing to collaborate with a novice programmer on something like this, understanding that it's kind of a learning project (as well as a serious attempt to scratch a real-world itch), let me know.

for(split(" ","tsuJ rehtonA lreP rekcaH")){print reverse . " "}print "\b.\n";

Replies are listed 'Best First'.
Re: RFC: RPG ;-)
by TGI (Parson) on Nov 06, 2008 at 04:21 UTC

    Is Tk a given? It is ok, but doesn't (last time I checked) run natively on a Mac. Wx works well on Macs, windows and Linux. I'm not sure about other options, but there has been lots of talk around here about choosing a GUI library. Whatever GUI you decide on, make sure you are not tightly coupled to it. You may learn to hate your choice. If your design relies on it, you will be stuck with it.

    When designing your data structures, I would pick at least two very different games (GURPs vs 1st Edition AD&D) as test cases. If the abstractions can handle very different systems easily, then you know you are on the right track.

    For data persistence, look at DBD::SQLite and DBM::Deep. YAML::XS is very nice for quick storage and retrieval of data structures.

    If you decide to go OOP with your software, you will either want to drink to Kool-Aid and use Moose, or use classical perl hash-based objects. Pick one. In any case, if you choose OOP, remember that 9 out of 10 times composition is a better strategy than inheritance.

    This sounds like a big project. Break it into tiny pieces with usable deliverables. That way you can start benefiting from it quickly, and you will stay interested. Plus you will be more likely to get others interested as well.

    From the start, plan on using something like PAR::Packer to make bundled executables for the Perl challenged. You will increase your chances of getting users.

    Most important: have fun.


    TGI says moo

      Thank you! Very helpful.

      TK isn't a given in terms of being installed on Macs, but it does work on them. Plus, it's the GUI toolkit that I know anything about ;-) I have a tendency to flit between technologies... a little bit of lisp, some javascript, some PHP, etc. Part of this is about forcing myself to gain some depth.

      When designing your data structures, I would pick at least two very different games (GURPs vs 1st Edition AD&D) as test cases. If the abstractions can handle very different systems easily, then you know you are on the right track.

      Exactly my plan. I'm going to test it with D&D 3.5, oldskool White Wolf, and Paranoia.

      As far as data persistance goes... What little I have of a workflow planned out is based on the idea that you load up (or create) a game, and it reads it off disk and keeps it in memory until it gets saved. Seems like a better fit for a JSON, YAML, XML, etc type solution than for SQLite. (Also, my experience with Amarok and SQLite makes me a bit unreasonably squeamish about it.). I'll definitely check out YAML::XS.

      I'll check out Moose, but I should be able to manage this with little more than Perl's built in data types... I definitely agree on the "Composition over inheritance;" as far as I can tell, inheritance is something that is useful in either in radical redesign or in adapting someone else's code in a hurry.

      I definitely want to... Do you have any suggestions for a logical first deliverable? I mean, I guess maybe a character-sheet creator would be the first step... but maybe that's too big. I'ma scared! ;-)

      Thanks SO much for the PAR::Packer suggestion. I've done some things with Perl2exe, but until I have more cash flow than I do at the moment, that's not an option for anything to be distributed more widely.

      for(split(" ","tsuJ rehtonA lreP rekcaH")){print reverse . " "}print "\b.\n";

        I tend to use oop if I am working with deep data structures. It makes my life much easier.

        Instead of having to remember that I've got a hash of arrays of hashes with arrays under key Foo and hashes under Bar. Its easier for me to think of I have an array of Characters, each character has a set of Attributes.

        Inheritance is a way reuse code. If I need to model Apple, Banana, and Orange in my code, I can create a Fruit base class that defines common attributes and interfaces for all of the fruit types. Fruit would provide "weight", "color", "stem", "remove_peel" and "eat" methods. Each fruit would inherit the "weight" method, since it would be the same for all of them. "Apple" may be able to inherit "eat", but "Banana" and "Orange" would override "eat" to check that the peel has been removed first. "Banana" would need to add a "remove_nast_black_thing_from_the_end" method, and make sure that it gets called as part of the "eat" method as well. This example works well because an Apple is really a Fruit. As is an Orange and a Banana.

        The comments about inheritance are important. People do stupid things like, my "Apple" object has a bunch of stuff that is much like what I want my "Orange" object to do. So, If I make "Orange" a subclass of "Apple" I can reuse my code and that is good. Another misuse of inheritance would be to say that an "Office" object is a "Person" so that you can call the Person methods and get the name of the person assigned to the office. The right way to do this is to say that an Office 'has a' Person, in other words, use composition, not inheritance. Office could then define an "assigned_to" method, to fetch the name of its Person.

        Read some tutorials on OOP, and Damian Conway's Object Oriented Perl book also provides some excellect information. OO design is a bit tricky at first, but it is a worthwhile skill to build.

        If you want to print from your program, WxPerl has an easy to use cross platform printing interface (but it depends on using WxPerl for your UI). You may also wish to look at Win32::Printer, I haven't used it, so I can't really comment on it. Another option would be to punt and generate PDF files.

        One thing that annoyed me when I was gaming a lot, was copying and recopying character sheets, as spills or eraser wear destroyed old copies. A nice character sheet printer would be very handy. Printing nice blank sheets would be a nice bonus.

        I think that you will eventually want to have search capabilities. That's where an SQL type db comes in really handy. I've never had any problems with SQLite, even with very large files (hundreds of MB). I don't know what the problems were with Amarok, so I can't comment about that. If you go with an embedded SQL datastore, you may want to look at some of the ORM opptions, like Class::DBI or Rose::DB. My best advice is to keep you serialization and deserialization code isolated from everything else, so that you can change or add different data stores easily.


        TGI says moo

Re: RFC: RPG ;-)
by dragonchild (Archbishop) on Nov 06, 2008 at 14:55 UTC
    Where to start? The following should be done in order.
    1. Is this a rules description or a rules engine? What I mean by this is are you intending on using this to just build and maintain characters or run games with? I would say to start with just a character sheet maintainer. You can always expand later.
    2. Figure out which systems you intend on supporting at first. White Wolf? AD&D (if so, which edition? 2? 3? 3.5? 4?)? You can always add systems later, but trying to solve ALL systems is going to doom you to failure. I would suggest just supporting what you play right now. You will need to refactor later anyways, so embrace it.
    3. How amenable do you intend on being to supporting house rules? Initially, I would say no.

    Those questions are going to define the initial scope of the project. For the first 0.01 release, you should make the scope as narrow and tight as possible. Remember, you're going to "release early, release often". It's hard to release early (like in 2 weeks) if you have more than 20-40 hours of work to do.

    Now, let's take a look at tools. You're right to look at the data structure first. Programs are nothing more than data manipulation and visualization tools. So, 0.01 should be that and just enough of a UI to manipulate what you release. Then, as you refine the data structure, you will refine UI and vice versa. But, start very very small. A possible release schedule might be:

    1. Fire up the UI and create a character with a name. Additional features (each one tested):
      • Be able to save the character.
      • Be able to retrieve it later from a list of known characters.
      • Be able to delete it.
      • Be able to change the name.
    2. Define a trait. This includes (all tested):
      • Name a trait. Guarantee the name is unique.
      • Provide descriptions (long and short).
      • Be able to modify, delete.
      • Be able to find traits. (Search is very very difficult. Providing a good UI is even harder.)
    3. Connect a trait to a character. This includes (all tested):
      • Altering traits connected to a character (adding, deleting).
      • Providing a number of 'points' a character has in a trait.
      • Preventing the deletion of a trait if any character has it.
      • Adding to the UI (find all characters with a trait, etc)

    Just getting to that point will take a good 2-4 weeks. I think we would start there. And, yes, I'm offering to help out, but on one condition - the initial datastore be DBM::Deep (which I support). I want to get some real-world usage of it in a database-like setting because I want to add search capabilities to it, possibly using Data::Structure::Utils, possibly even using Presto as an overlay. The datastore can change should this project exceed the capabilities of DBM::Deep - I don't care. I just want it to be the first if you want my help. :-)


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      1. Is this a rules description or a rules engine? What I mean by this is are you intending on using this to just build and maintain characters or run games with? I would say to start with just a character sheet maintainer. You can always expand later.

      The scope of this is rules description with (eventually) some level of logical build support (i.e. It will do some of your math for you). If you have Windows or Wine, check out Grapevine, a Whitewolf LARP administration utility. It's not going to be a clone, but my intent is to eventually provide that sort of support system for GMs, possibly with a restricted-subset mode for players (one of the problems with grapevine is that, if you want everyone to have access to their own character sheet and such, you basically end up passing around the whole gamefile, and run into synchronization issues between users. Definitely a "version number" sort of thing, at least.

      2. Figure out which systems you intend on supporting at first. White Wolf? AD&D (if so, which edition? 2? 3? 3.5? 4?)? You can always add systems later, but trying to solve ALL systems is going to doom you to failure. I would suggest just supporting what you play right now. You will need to refactor later anyways, so embrace it.

      My plan right now is to try and generalize the data structure so that it can cover White Wolf, D&D3.5, and Paranoia (which will be simple enough if you can cover White Wolf). As far as which ones I'm actually going to try and handle making a valid configuration file to handle in the first release... definitely one, either White Wolf or Paranoia. Paranoia is simpler, White Wolf is an itch I'm more likely to scratch, and would be closer to a complete test of this.

      3. How amenable do you intend on being to supporting house rules? Initially, I would say no.

      I definitely intend on there being support for player-created traits and such. One advantage of loading the description of the system from a description document is that it seems like it would make it fairly easy to support multiple cascading documents. So that, for instance, loading White_Wolf.xyajsonml would get you the standard traits, and then you would load "White_Wolf_User.xyajsonml" and superimpose trait redefinitions and new traits.

      I think this provides for a fairly graceful path for building the system. At first, you can only edit the main file to add house-rules and user-created traits. Then you can load a second file to do so. Then, finally, you can do so in-GUI.

      That seems like a very sensible release schedule, with the caveat that I might want to be able to load and display a system's rules for characters before having a character to display. Maybe not, though... I still have a lot of planning and thinking to do before I start coding ;-)

      I've found this really helpful, and I may very well take you up on your offer of help. I do have to say that I'm a little worried about being overwhelmed... this is my first non-school/trivial programming project, and I do definitely want to collaborate with people on this... but I also feel like I need to have SOMETHING that I made that's remotely functional before I bring people in. Maybe it's just insecurity, but I feel like, if I don't have some of the skeleton first, I risk being a useless appendix on my own project.

      That being said, I'll definitely take a look at DBM::Deep, and I'll let you know when/if I'm ready to open it up. Thanks VERY much for the detailed analysis... the suggested roadmap especially is really useful.

      for(split(" ","tsuJ rehtonA lreP rekcaH")){print reverse . " "}print "\b.\n";
        Take your time and don't feel the pressure. It's a lot easier to edit than create.

        I do definitely want to collaborate with people on this... but I also feel like I need to have SOMETHING that I made that's remotely functional before I bring people in.

        That's like cleaning the house before the maid comes to clean the house. Think about it.

        Now, if you're worried about losing control or creative direction, then the best solution is to get a Git repository (from github) or SVN (from svn.ali.as, for example) and just allow people to check into their branches. You are the only person to merge into the trunk. That way, at least at first, everything has to be reviewed by you. This also has the neat benefit of you reading everyone else's code and having the ability to ask them questions. You'll learn a lot. :-)

        Don't worry about system rules - remember, those are going to be mutable. And, what you write first isn't what the user is going to see first. In fact, it's very likely that what you write for 0.01 won't make it into 1.00. Well, those specific lines of code won't, but what's built from them will.

        Lastly, and I cannot stress this enough, you have to work in small chunks. Otherwise, how on earth are you going to be able to test them? In just those tiny pieces of functionality I mentioned, there's at least a 3-1 test LOC to code LOC (Lines Of Code). It's only going to get bigger from there. Think about it.


        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: RFC: RPG ;-)
by Taulmarill (Deacon) on Nov 06, 2008 at 11:09 UTC
    Sounds cool, i'd be interested what you'll come up with. Just don't underestimate how complex your data structure has to be. In many systems single points in traits can represent a whole lot of information. In Shadowrun the is a trait called connections, where every point represents a NPC which should at least be given a name an a few sentences of background. In the WoD-Games you have traits like language, where you have to decide what actual languages you buy when buying new points for that skill. These kinds of additional information are especially helpful for the storyteller/gamemaster when planing a story.

    Also it seems to me like a good idea to make information like character classes hierarchic. A good example would be prestige classes you get on top of you character class in D&D 3 but also things like Breed=>Auspice=>Tribe in Werewolf could be represented that way.

    If it would be helpful to you, i could try to describe my Demon: The Fallen character in a perl data structure.

      The way I'd currently represent that would be each that connections would be a trait, with a set of sub traits representing each point of connections, each of which would have an attribute explaining who the connection represents. Sound feasible?

      Hierarchic representations might make sense, but I want to avoid trying to push too much system-specific logic into the data structure, and that really doesn't seem like a terribly good fit for White Wolf and other trait-based (using a different definition of traits ;-) systems. Also, Prestige classes are often semantically based on existing classes, but in game terms, they've only got dependencies, not any actual subclassing-type behavior.

      That would be helpful... I've been coming at it from the description language end, but I'd be interested to see what someone else made of it from the Perl end.

      for(split(" ","tsuJ rehtonA lreP rekcaH")){print reverse . " "}print "\b.\n";
Re: RFC: RPG ;-)
by zentara (Archbishop) on Nov 06, 2008 at 18:11 UTC
    What CPAN modules (other than TK, which is a given) would you recommend to look at?

    Look at Gtk2 and it's Treeview widget. DoubleClick an entry at any level to edit it. Gtk2 is not as cross-platform as Tk, but Tk is falling out of favor too on Win32. The latest ActiveState dosn't have Tk included by default anymore, so you need to install stuff anyways. Here is a deeply nested tree with nice tree animation.


    I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: RFC: RPG ;-)
by jhourcle (Prior) on Nov 06, 2008 at 18:36 UTC

    My first thought was 'you're trying to make an Army Builder for RPGs.' ... and then I realized, Lone Wolf already makes such a thing ... but they're a commercial software company, and from the looks of things, they only support three games right now.

    I've played way too many RPGs over the years, but never any of the White Wolf stuff -- you're probably going to need to talk to lots of people who are familiar with different systems, to discuss the relative difficulty of describing a system in a given data structure. I personally haven't done tabletop RPGs in almost a decade (or LARPs for more than 6), but you can probably track down people who are passionate about a given game system who are willing to give you a little time.

    I don't know how busy he is these days, but Drew Curtis from Fark was a huge Shadowrun fan back when I worked with him in the late '90s ... although I wouldn't suggest dropping my name, as I burned some bridges when leaving.

      I'm more setting my sights on Hero Lab, but the concept is similar. Shockingly similar, and I am kicking myself a little for not checking it out more thoroughly. But more focused on out-of-game management, and with slightly less hand-holding.

      I'm more and more thinking that the real problem with this is going to be figuring out how to programmatically decide how to layout the character-creation pages from the system descriptions. I think that alone will justify categories being separate objects.

      for(split(" ","tsuJ rehtonA lreP rekcaH")){print reverse . " "}print "\b.\n";

        Display is a separate issue than the modeling to actually store the data -- after all, you might want multiple displays for each sheet -- some for editing, some for printing, some for on-screen display. Depending on what you're envisioning for everything, you might have another screen for the DM-equivalent to see multiple player sheets at once, or a display for a player to update their character as the game is running (HPs, inventory, XP, etc) as opposed to the types of editing that'd take place at character creation.

        Even for character creation, you might have a 'randomly generate and tweak 20 NPCs' vs. 'nitpick every choice'

        ...

        I'd focus on what needs to be stored and how to store it before getting worried about how to display things and how to store the information about how to display it.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://721873]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (2)
As of 2024-04-24 17:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found