Rollem is a table rolling program (actually a set of programs) intended to be an aid to playing role-playing games (RPGs). Frequently in RPGs there is a need to decide randomly between various possibilities, such as today's weather, the name of a non-player character (NPC), whether the players have encountered anyone on the road while travelling (and if so, who), and so on. While all of this could (and often is) made up by the game-master(GM) on the fly, many GMs find it a strain to keep having to come up with detailed information, and even GMs who are comfortable with it can find themselves falling into a rut ("Wasn't the innkeeper at the last inn also named Carfax?") and can use the occassional kick-start to the imagination.
Rollem answers this need by letting the GM define any number of tables, including sub-tables, containing entries for the various possible results, and assigning probabilities to each of those entries. The GM can then invoke the table to get a random result, either on-the-fly if the GM is using a computer at the gaming table, or in advance when writing up a scenario, or to produce a list to print out and pick from during play. Future releases of Rollem will include ways for the GM to "fudge" the roll, either before or after the fact, in order to take into account local conditions not built into the table or to eliminate nonsensical answers. (For instance, a generalized encounter table might include a small chance of meeting a camel caravan--but that wouldn't make sense if the players are on a small island at the time of the roll.)
Basically, a table consists of a number of text entries with attached probabilities. Each entry can contain further subentries, including calculations (e.g. "the merchant has (1d10) gold pieces") or references to a subtable ("the (roll on subtable type-of-goods) merchant has (1d10) gold pieces.") that will be evaluated as part of the process of generating a result, so that the prior example might produce text along the lines of "the silk merchant has 7 gold pieces".
Originally, Rollem (then called Generate) was an attempt to replace the shareware TableMaster program from Wintertree Software. Basically, I liked the idea of TableMaster, but after trying to buy the program unsuccessfully three different times (including directly from the publisher), I decided it was better to reimplement it from scratch than deal with the non-existent sales and support of the commercial program (it didn't help that the author of the program is exceptionally paranoid about spam, and refuses to include a working email address anywhere on the Wintertree website). I did, however, talk to the author of the program, and she liked the idea of the TableMaster language becoming a standard, with support from other programs.
Generate was written in Perl, and it turned out that in attempting to handle the TableMaster language in all its gory detail, I had bitten off more than I could chew. The problem was that, as far as I could tell from trying to reverse engineer the example tables, the TableMaster language was not a context-free language--which means that parsing it was a bear. In addition, the language had a lot of apparently redundant features and kruft that had grown there as the author had implemented this or that neat idea on top of what was originally a pretty simple structure. What's more, despite how fast a quickie version came together in Perl, keeping it going got harder and harder as the program grew. I may not have been reaching the limits of Perl's capabilities, but I certainly was reaching the limits of my ability to grok my own Perl code. I released Generate on my website, but I never was able to kill some of the subtler recursion bugs in complicated tables (such as the character history table), and it never completely implemented the TableMaster language.
Meanwhile, I had been learning Python, and the more I played with Python, the better I liked it. At first I was merely going to reimplement Generate in Python, hoping that Python's cleaner style would help me find and fix some of the things that never did work in Generate, but then I decided that jumping through hoops to accommodate what I saw more and more as severe shortcomings in the TableMaster language wasn't the way to go. I began to design my own language to accomplish the same tasks (and this one was going to be context-free, by gum!), when I was struck by a minor epiphany. Why go to all the trouble of designing and getting people to adopt yet another proprietary language, and write and debug a parser for it, when the newly emerging XML standard promised to solve all those problems in one fell swoop, and with free software (in both the Beer and Speech sense) to boot?
Thus was born the new incarnation of the project, rechristened Rollem, with the language being replaced by an XML Document Type Definition (DTD). The table markup was going to be slightly more complex (no more open-ended entries), but the complexities were going to be ones that anyone used to dealing with XML--or even HTML--were already used to.
As of version 0.4, Rollem requires version 2.0 of Python, available for free from PythonLabs for all the major platforms, as well as the Python MegaWidgets if you want to use the GUI tools. Previous versions also required the PyXML extension available from SourceForge, but those have been folded into the regular Python distribution as of Version 2.0
Currently there are three Rollem command line programs: rolltext.py, roll.py, and compile.py, and two Rollem GUI programs: rollem.py and rolledit.py .
(Note that on a system that understands the #! notation, you shouldn't need to explicitly use the python command)
python rolltext.py [-nNumber][-oOutfile][-eErrfile][-d] table.xml Where: Number indicates number of times to roll on the table Outfile is the name of a file in which to save the output (default is stdout) Errfile is the name of a file in which to save any errors (default is stderr) d is for debug mode. Currently not implemented table.xml is an XML file in the format defined by the rollem.dtd
rolltext.py reads in a Rollem Table XML file and outputs one or more results from rolling on that table.
python roll.py [-nNumber][-oOutfile][-eErrfile][-d] table.pickle Where: Number indicates number of times to roll on the table Outfile is the name of a file in which to save the output (default is stdout) Errfile is the name of a file in which to save any errors (default is stderr) d is for debug mode. Currently not implemented table.pickle is the parsed and pickled MasterTable object created from an XML file in the format defined by the rollem.dtd In order to create a suitable pickled object, run compile.py against the table.xml file (substituting the actual name of the table, of course.)
roll.py reads in the pickled Rollem MasterTable object created from the table.xml file and rolls against it. In the case of a large table, this is much faster. Future versions of Rollem will automatically detect whether the file is XML or a pickled object, and react appropriately--creating a new pickled object file if the old one is out-of-date with respect to its source file. (This is much the same behavior as Python itself.)
python compile.py [-oOutfile][-eErrfile] table.xml Where: Outfile is the name of a file in which to save the output (default is stdout) Errfile is the name of a file in which to save any errors (default is stderr) table.xml is the Rollem XML file to be parsed and pickled into a Rollem MasterTable object.
compile.py reads in a Rollem XML file and parses it, creating a Rollem MasterTable object, which it then "pickles" (serializes to disk), usually to the file named in the -o option. I've been giving these files the same name as the table, but with a .pickle extension instead of the .xml, but that's not required as long as you can keep track of which files contain XML and which files contain pickled Python objects. Future enhancements may include an attempt to guess whether the file is XML or pickle based on contents.
python rollem.py
rollem is a GUI program for rolling on Rollem XML tables. It is implemented using Tkinter, so it should run on any platform on which Python runs, but it does require the Python MegaWidgets package, from the Python MegaWidgets site Upon start-up rollem looks for a sub-directory of its installation directory called "tables" and loads a list of everything in that directory that looks like a Rollem XML table (anything that ends in .xml). This default can be overridden in the .rollem configuration file in the base directory of the program, or by setting the Preferences from within the GUI. The list of available tables shows up in the left-hand pane of the display. The right-hand pane is for the results. Clicking on a table in the tables pane makes it the current table. Pressing the Roll button on the toolbar (or the Tables | Roll command in the menu) causes Rollem to roll on the current table and write the results to the display pane. You can set the number of times it should roll on a single press of the button with the (Tables | Times menu entry). The output in the display pane can be saved to a log file, using the Save button or the File | Save menu entry. Log files can be created, selected, and viewed from the File menu, and are created by default in the log subdirectory of the base directory. As with tables, the default directory can be overridden.
.python rolledit.py
rolledit is a GUI program for creating and editing Rollem XML tables. It is implemented using Tkinter, so it should run on any platform on which Python runs, but it does require the Python MegaWidgets package, from the Python MegaWidgets site Like rollem, rolledit has two primary panes. The top pane is to edit the current table, and bottom pane is to display results of rolling on that table (for testing purposes). There are also a number of toolbar buttons to allow you to quickly insert most of the tags needed by a Rollem table (See the Reference Documents for details of the Rollem XML language); clicking on the buttons will pop up dialog boxes that prompt you for the necessary entries for the attributes of the entity tag being inserted.
.