How WallCrawlers Work

The main work of the DungeonMaker is done in a loop like this:
   Crawler -> MakeStep;

Most of what makes the dungeons what they are goes on inside of MakeStep. This is simplified pseudocode for it:
frontFree = LookAhead();
//determine how many rows are free of wall tiles in front of the Crawler
//to a width of (2 * corridorWidth + 1) so we can build a wall through the middle
if(frontFree > corridorWidth + 1)
{//there is room to build wall tiles straight ahead
   BuildSomeWallTiles();   //as many as possible, but no more than stepLength
   if( RollOfDice )
//very complicated conditions here to determine new direction
      CreateNewCrawler();   //or several, or none, or ColumnJumper
else if( RoomToGoSideways() )

WallCrawler and ColumnJumper are subclasses of Builder, but to make things simpler I will just describe the WallCrawler class including the Builder members. There are integer members locX and locY that give the location in the grid - a member Forward, which gives the direction the Crawler is currently facing (this can be North, South, East, and West) - and a member Direction which gives the direction the WallCrawler intends to go. Direction can have 9 values - the directions used by Forward, the intermediate directions (NE, SE, SW, NW), and a value of zero to indicate that no direction is preferred. When direction is non-zero, only the two directions adjacent to Direction are legal values for Forward, plus possibly Direction itself. This implies that e.g. if Direction points North, then West, North, and East are legal values for Forward, but if Direction points e.g. Northeast, then only North and East are legal.

The lifespan of WallCrawlers is governed by members age and maxAge, which work like this: While age is smaller than 0, the Crawler is dormant - when its MakeStep method is called, it does nothing but increment age. When age >= 0, the Crawler does its work building walls, and when age > maxAge, it is deleted. While age is used internally to assign Crawlers to generations, maxAge is an important design parameter.

The type of dungeon that is built is strongly influenced by member stepLength, which gives the maximum number of wall tiles this Crawler can lay down in one step. This also determines the distance between points where the Crawler is given the option to change direction, and, even when going straight, the distance between points where it can spawn a baby. Member corridorWidth determines the minimum width of the corridors this Crawler leaves open between the wall tiles it builds and other pre-existing walls.

Finally there is the member opening with 3 possible values:
(opening == 0) <==> the Crawler will try and leave no opening in the wall;
(opening == 1) <==> the Crawler will leave an opening in the wall at the end of its run;
(opening == 2) <==> the Crawler leave an opening at the start of its run, then switch itself to (opening = 0).

The fact that Crawlers with (opening == 0) can build a wall right up to and adjoining another wall means they must be used with care. If such a Crawler is placed on the outside wall of the dungeon, it has the potential to cut off all paths between the entrance of the dungeon and the exit. They are intended for situations where a room with doors is placed, and walls are desired that force the player to go through this room, or they can be started in the open, often back to back with a Crawler with (opening == 1). Another problem is this: If many Crawlers are started with (opening == 2), they will switch to (opening == 0), and two such Crawlers can join up with each other, creating a room without an opening. I have found that this is not a problem as long as such Crawlers are rare in the first few generations (where they might create huge enclosed spaces) and no generation has more than 50% of them. However, if you randomly place items or monsters in the dungeon and rely on them being accessible, you must either avoid using such Crawlers, or test for enclosed rooms and deal with them properly before placing your items.

previous page            contents            next page