The Biblyon Broadsheet

Gods & Monsters Fantasy Role-Playing

Beyond here lie dragons
Biblyon, Illustrious Valley, Highland
Saturday, April 21, 1984
Jerry Stratton, Editor
Lulu price drop—Monday, April 21st, 2014

Lulu.com has recently dropped their printing costs. In response to this, I have dropped the price of the Gods & Monsters rulebook from $12 to $8.50, and the price of the introductory adventure Lost Castle of the Astronomers from $10 to $7.50. If you haven’t bought the print copy yet (and, let’s face it, you haven’t) head over to the Gods & Monsters storefront!

This is an amazing price drop. I’m very impressed. And I need to pick up the newly-repriced Fight On! too!

I’m currently working on converting Illustrious Castle to the new format—9 by 7, with Inkscape maps. When I have that done (don’t hold your breath), that will go on Lulu as well.

Automatically roll subtables—Saturday, April 5th, 2014

Now that the “random” script handles percentage tables for wandering encounters, it’s very close to being able to handle the hierarchical encounter charts I use in Gods & Monsters. All that remains is for it to detect that an entry on the table is itself another table.

In order to do this, we need to be able to detect whether an entry matches a table file. We already have a function, tableFactory, that returns a table based on the filename; currently, however, it fails if the filename does not exist as a file. What we can do is make it return “no file” if the file doesn’t exist. In Python terms, we want it to return None instead of returning a Table object.

Before the “open” line in “def tableFactory(name):”, check to see that the filepath exists:

[toggle code]

  • #load the table into the appropriate class
  • def tableFactory(name):
    • filename = name + '.txt'
    • filepath = filename
    • if options.locale:
      • localepath = os.path.join(options.locale, filename)
      • if os.path.exists(localepath):
        • filepath = localepath
    • if not os.path.exists(filepath):
      • return None
    • items = open(filepath).read()
    • if "\t" in items:
      • table = PercentTable(items)
    • else:
      • table = SimpleTable(items)
    • return table

If the path represented by the filepath variable does not exist, the function returns None. This means we can use it for checking to see if a table file exists. Currently, if there is no “number appearing”, the system assumes “1”. Let’s change it to assume nothing. Change “appearing = '1'” to:

  • #generate the number appearing
  • appearing = ''

Now, we can detect this on making our random choice:

T is for Tower… of the Elementalist—Wednesday, April 2nd, 2014

T is for Tower. Of the Elementalist. Of plaster, green and swirled, round, and four stories high.

That’s from James Pacek’s The Wilderness Alphabet. From Archway to Ziggurat, it’s a collection of tables of things to find in the wilderness when randomness is useful.

Next, add a stout round altar with a trapezoidal base, and written on it… and epitaph.

The altar comes from Richard J. LeBlanc Jr.’s A-to-Z d30 tables, and the epitaph from Risus Monkey’s DungeonWords.

LeBlanc is into the d30, and while he just started his A-to-Z series he has several other d30 tables already done, including a dinosaur table! Need a random dinosaur? How about number 17, the ornithomimus! “Very intelligent: surprises on 1-2 (on 1d6)”.

The d30 tables and DungeonWords are free; The Wilderness Alphabet is available on Lulu.com in a nice 6x9 paperback with illustrations. For his cover, he uses the very appropriate Knight at the Crossroads by Russian folklorist painter Victor Vasnetsov.

All of these tables will, of course, work very handily with the random item Python script described in Programming for Gamers: Choosing a random item and included with the The World of Highland Guidebook resources archive. The wilderness letter choice is a percentile-based breakout table, and almost everything else is a simple list.

These tables are the kinds of things I might use on or just before game day when I need a new adventure and don’t even have the nut ready. A random roll, and sure enough, a tower is a good place to start, and an elementalist a good way to theme it. And then at the center of the tower, an altar? I can run with that pretty quickly. And the altar contains an epitaph? Oh, my, who died, and why is their epitaph on the altar at the center of this green tower? Oh yes, that’s making me want to stop writing this blog post and start writing that adventure!

Random table rolls—Saturday, March 29th, 2014

Our random table script is doing a lot for us now. We can roll any arbitrary number of times on any text file. But often, we aren’t rolling a known number of times: our number of rolls on the random table is itself random. So it would be nice to, in addition to ./random 3 gems we could also do ./random d4 gems.

Now that we have the dice library installed, we can do this. The main issue is that the script currently knows whether to roll more than once by looking to see if the first item on the command line is all digits:

[toggle code]

  • if firstArgument.isdigit():
    • count = int(firstArgument)

If we are going to accept die rolls, then we need to accept another character as well as digits: the letter ‘d’. There does, however, have to be at least one number. Basically, we need our script to recognize a die roll.

When we need to recognize text patterns, the most common tool is a regular expression. In Python, we use regular expressions by importing the re library. Add this to the top of the script with the rest of the imports:

  • import re

Replace the if/count lines above with:

[toggle code]

  • if re.match(r'[0-9]*d?[1-9][0-9]*$', firstArgument):
    • count = firstArgument

That looks complicated—and regular expressions can certainly become complicated—but in this case it isn’t.

  1. re.match matches text patterns from the beginning of the text.
  2. The last character is a dollar sign, which requires that the pattern match the entire piece of text instead of just the beginning.
  3. The first set of characters are in square brackets: [0-9]. Items in square brackets mean, match any character in that range. For example, [a-m] would mean any character from lower-case ‘a’ through lower-case ‘m’. In this case, it’s any number.
  4. The next character immediately following the first set is an asterisk. The asterisk means any number of the preceding character. The preceding character is any digit. So, “[0-9]*” means any number of digits. Any number includes zero, so this means zero or more digits at the start of the text.
  5. The next portion is the letter ‘d’ followed by a question mark. The letter ‘d’ is needed to show that this is a die roll, and the question mark means that we need zero or one of the previous characters. If this is not a die roll, there will be no ‘d’. If this is a die roll, there will be only one ‘d’. The question mark handles this for us.
  6. The next portion is “[1-9]”. There must be at least one digit from 1 to 9 in either a die roll or an arbitrary number.
  7. And the final portion is “[0-9]*”. We have already seen this; it means from zero to any amount of digits.
David A. Trampier dies—Friday, March 28th, 2014

The wyvern howls, and the dragon sits forlornly at the window of a deserted house. David A. Trampier died Monday in Carbondale. He’d recently had a stroke, and possibly some form of cancer.

Trampier was by far the most evocative of the AD&D era of artists. Look at the full-page spider on page 91 of the Monster Manual, for example, and everyone always brings up his Emirikol the Chaotic from the Dungeon Masters Guide.

For me, however, the two images that influenced my adventures most were the Pseudo-Dragon and the Wyvern. They weren’t full page (though I’d love to see the originals). But the image of that tiny dragon, sitting at a window, autumn leaves inside and out, turning back from gazing outside (to talk to someone in the house?) meant that there was always some sense of longing when I went to fill out an adventure.

And that wyvern, howling against the oversized moon, a broken forest against the pulsing sky! You end up feeling more sorry for the wyvern than for its prey. It always came to mind when there were night creatures on mountains (for some reason, I always saw that as atop a mountain, even though the wyvern is flying), such as in the “how to create an adventure” section of The Adventure Guide’s Handbook.

For me, “how to create an adventure” has always had an element of Trampier’s influence from those early images. It’s also the image I always think of when running the wyvern in the hidden cavern of The Vale of the Azure Sun. Even without any mountain tops, I still had to get that feeling in the adventure.

Trampier’s artwork appears in all of the original AD&D books as well as much of Dragon Magazine and other games. It stands out wherever it appears. Every player had the Players Handbook, and the very first two images they saw were his incredibly iconic cover with its adventurers looting a glowing orange demon idol while recovering from a battle with lizard-men and planning their next move—any film that really wants to be a D&D movie ought to include that scene, probably even use it as the nut of the script—and the happy magic-user smoking in a lush forest and sitting on a die (which had rolled a six before letting the foliage grow around it!).

Percentage-based random tables—Wednesday, March 19th, 2014

Our current random item generator assumes that each item shows up as often as any other item. That’s very OD&D-ish; as often as not, there will be six items per table. But AD&D game masters often use percentage dice to generate some monsters and items more than others. Their tables look like:

01-15Orcs (d6)
16-25Goblins (2d20)
26-00Astertarte the Red Dragon

In this table, most likely for the red dragon’s lair, the red dragon shows up far more often than orcs and goblins. You can see more about this kind of table using the Wandering monster chart assistant.

We can make our random item generator recognize these tables and choose appropriately from them. The main difference is that, instead of creating a list of items and choosing from the list, we will need to generate a number from 1 to 100, and determine where that number falls in the list.

For test purposes, I’m going to use a modification of the default table from the wandering monster assistant:

  • 01-30 Orcs (d12)
  • 31-50 Mushroom People (2d20)
  • 51-70 Pixies (d100)
  • 71-83 Goblins (d20)
  • 84-95 Giant cucumbers (d4)
  • 96-00 Astertarte the Red Dragon

And I’m going to modify the “random” script to separate the parts where the script checks for the file and the part that loads the items in the file:

[toggle code]

  • #!/usr/bin/python
  • import random
  • import optparse
  • import os
  • parser = optparse.OptionParser()
  • parser.add_option('-l', '--locale')
  • (options, args) = parser.parse_args()
  • #load the table into the appropriate class
  • def tableFactory(name):
    • filename = name + '.txt'
    • filepath = filename
    • if options.locale:
      • localepath = os.path.join(options.locale, filename)
      • if os.path.exists(localepath):
        • filepath = localepath
    • items = open(filepath).read()
    • table = SimpleTable(items)
    • return table
  • #a table is a list of items that we choose randomly from
  • class Table(object):
    • #print some random items from the table
    • def choose(self, count):
      • for counter in range(count):
        • print counter+1, self.choice()
  • #a simple table is a list of items with equal probability

The part that looks for the appropriate file based on the given file name (“monsters” or “dragons” or “gems”) is now in the function called “tableFactory”. This function generates a table for us depending on the contents of the file—although at this point it only knows about one type of file. At the location where it says “table = SimpleTable(items)” we will eventually have it look in the file and create either a SimpleTable or a PercentTable object, depending on the contents.

The part that shows the random item has been broken from one class into two classes. The basic class is “Table”. All it knows to do is print out however many choices that we ask for. It doesn’t even know how to make the choice: it calls a method called “choice” that needs to be on the subclass.

SimpleTable is the subclass: because it has “Table” in parentheses, it inherits everything the Table class knows and also adds its own. SimpleTable has two methods: one to load the list of items into an array, and one to make a choice from that array.

Make these changes and run the script, and it should work exactly as it did before.

So, now that we can have a class for each type of table, let’s make one for percent tables:

38 modern-day dungeons—Monday, December 30th, 2013

“These real life ruins offer an eerie glimpse into a world without humans. Their dark walls inspire a sense of wonder like I’ve never felt before.”

Jake Heppner’s 38 most haunting abandoned places on Earth could just as well be labeled “38 places most likely to turn into real-live adventures”. From Willard Asylum to Six Flags Jazzland, which must rival the Saltair Park for creepy funhouse vibes, you can find photos of these places on the net, change the names slightly (or not, if you’re running a campaign that intersects with the modern world as in Helter Skelter), and you have an eerie adventure location ready for your own stylings.

There are several hospitals—while Willard is eerie, I think the Beelitz Military Hospital shows the most promise. There are even underwater adventures. Shicheng in China, a thirteen-hundred-year-old city flooded by a hydroelectric dam, and the very haunting Christ of the Abyss. Combine those with the Red Sands Sea Forts and I don’t know what you’ve got but it is almost guaranteed to be interesting.

(Hat tip to Gabriel Malor at Ace of Spades HQ.)
New, improved Divine Lore—Saturday, September 28th, 2013

The new Divine Lore is in a lot better shape. Because I’m syncing it with a database of spirit manifestations now, the list of manifestations per spirit type and per level should be more reliable; I no longer need to remember to change names in three different places.

Another advantage is that I can put the reverse versions in alphabetically with a note to see the normal version. I didn’t do that before because the risk of leaving in outdated information was much too high. At the moment, I’m only showing what’s different with the reverse version, but there’s no reason the reverse version couldn’t have a full entry.

While working on this and the online database, I’ve realized that reverse versions of spirit manifestations don’t make a lot of game sense. With spells, having a version and a reverse version means that, in-game, knowing one spell gives both versions, and memorizing one spell opens the possibility of using both versions. But prophets don’t memorize spirit manifestations; a spirit can manifest anything of its type. The only reason for keeping reverse versions of manifestations is the general idea that there are things the prophet can do with a spirit, and for some of those things, the reverse is also possible.

But from a rule sense, there’s no mechanical difference between marking animal bane as the reverse of animal call or just having two separate entries for animal bane and animal call. So I’ll be thinking about that.

As a side note, the on-line HTML version includes full stats for deities now that my conversion script handles floating content.

Also, don’t forget that you can also use the spirit manifestation database to create prayerbooks and spirit manifestation cheat sheets for your prophets!

Older posts.