Friday, March 30, 2012

Room Grammar

I've been working this week on extending the grammar to support creating rulesets for the geometry of the rooms within the dungeon. I've broken the room grammar into two distinct parts:  geometry and decorations. Geometry helps the dungeon generator understand the layouts rooms can have and decoration rules, clearly, assist it with placing plausible geometry.

Geometry Rules

I decided to approach the rooms from a Quake-era mentality of level design. Rooms are cut-out from a solid. So, as we add shapes to a room's definition, we "cut" those shape out of the solid map. When we subtract shapes from the room, we fill those areas back in with solid walls.

Decoration Rules

Decorations can be much more complex. I've decided to start with a state stack. You can push as many "decor rules" as necessary and, when you run the placeDecor command, the rules will be evaluated and then the current state will be reset back to "identity". Decor rules include adding what decor(s) can be placed, how many and where they can be placed, and what method the room can use to select the decor to place - currently a round robin and random are implemented.

Procedurally created rooms.

Grammar Script Sample

Here's the script used to generate the above rooms: 

$generateRoom {
   // add two rectangles (one tall and thin, one shorter and wider)
   ?addGeometry [rect;3;6;5;8]
   ?addGeometry [rect;6;9;3;5]

   // prepare to add beds (up to 2)
   ?addDecorRule [border;3;2;2;2]
   ?addDecorType [bed]
   ?placeDecor [2]

   // prepare to add a chest south of each bed placed (up to 2)
   ?addDecorType [chest]
   ?addDecorRule [border;bed;0;0;0]
   ?placeDecor [2]

For every room created in the above image (except for the two rectangle samples), we add two rectangles. Then, we setup the rules for placing beds. The "border" rule describes the requirements around a valid place for the bed. In this case, the tile to the north of the bed must be a wall (3) and the tiles to the east, west, and south must be empty floor (3). This forces at least one tile to appear between two beds in a room. Last, we create the rules for the chests by setting up the "border" rule requiring a "bed" to the north of the chest and setting the other directions to "don't care" (0). 

A note on grammar

I'm currently using semi-colon to separate parameters in the grammar, but I'll probably change this before I release a version. I can see semi-colon being used frequently when the grammar is also used to create procedural room descriptions and/or narrative. To allow for this, I'm planning to switch to a pipe character as the parameter separator.

Longer term, I'd like to add a mechanism to use descriptors in place of numbers for parameters. So, you could say "?addDecorRule [border;wall;open;open;open]" instead of requiring knowledge of the enumerations in the code.

In closing

This ended up much longer than I intended, but my hope is that it's informative and/or inspiring. If you have any questions or comments, please feel free to contact me or leave a comment. 

No comments:

Post a Comment