in reply to Re: RFC: RPG ;-)
in thread RFC: RPG ;-)

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";

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

    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

      I'll check out wxPerl, but I'm pretty set on Tk.

      The SQLite problems were pretty simple performance over large datasets problems. Basically, tried to use an SQLite backend on Amarok with over 4000 songs, and it would freeze and fail. Switched to a MySQL backend, and voila, Amarok runs great. Probably there will be much less data to deal with here, but I'd rather find something that I know will scale reasonably from the start.

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

        Your choice of datastore should be orthogonal to the rest of your application. Design so that it can be changed. If YAML or XML does the job now, use it. But plan to be flexible.

        I just completed a project where I wound up switching between five different serialization methods to get the combination of reliability and speed we needed with the sort of data structure we were using. Fortunately, I designed with this in mind and it took only a few minutes to make each change as we tested the different back-ends. If you are wondering, I didn't use or even evaluate SQLite for this project, because it wasn't a good fit.

        On other projects I have had very good luck with SQLite. I ran into speed issues a couple of times, but I was able to resolve each one. I'll breifly describe each one, because it might be useful to you or someone else.

        When I had huge 100+ MB files in SQLite, I did have some slowness, but I added appropriate indexes, and the problem vanished.

        Another speed issue I had was when I was making many inserts. I solved the issue by wrapping the inserts in a transaction, so that the on-disk database only had to be updated once.

        I also had to refactor some code that was trying to do the RDBMS' work. Behind the scenes, the code was making boatloads (thousands) of single row select statements, and then using that data from these to do another series of selects (hundreds per initial select) - fear the power of the dreaded cross-product! I replaced all that crud with some slightly more complex queries that got the data all in one go, and saw a vast speedup. The application went from LOCKED UP ALL THE TIME to snappy.

        SQLite is a widely used RDBMS, I have no problem using it in production systems when it is appropriate.

        The main thing is to remember that there are a variety of SQL databases (MySQL, Firebird, SQLite, PostgreSQL, blah blah blah) out there that can do searches, sorts, and joins for you. Used appropriately, they can save lots of hackery on your part.


        TGI says moo