Tilde~A: Alexios' Homepage

Python Bindings for DungeonSpawn

This project aims to bring the power of DungeonSpawn to Python. It originally started as a set of bindings for DungeonMaker, but my own needs steered it away from that and prompted various extensions to the original code. It comes in the form of a binary Python extension that wraps the DungeonSpawn library. A batteries-included, Pythonic approach to dungeon making was the main motivation behind the design of the library. I like to use Python to design maps (another project of mine already does this, and uses a plugin system to provide numerous means of doing this — these bindings will eventually be used to make another such plugin).


It's incredibly easy to make a dungeon with these bindings. It takes five lines of code to make a complex, random dungeon with tunnels, rooms and anterooms. Here's an example that makes such a dungeon map and gets information about it.

import dungeonspawn
from dungeonspawn import config, const

# Start a new dungeon configuration. All tiles CLOSED (rock).
c = dungeonspawn.Config (100, 100, map_type=const.CLOSED)

# Add an entrances to the north.
c.entrance (loc=const.N)

# Add a tunneler.
c.add (config.Tunneler (50, 2, const.S))

# Generate a dungeon according to our specifications.
ds = dungeonspawn.DungeonSpawn(c)

# That's it! Now print out information about the map.
print "Time taken to generate: %.3f msec" % (ds.dt * 1000.0,)
print "Rooms: %d" % ds.num_rooms
print "Anterooms: %d" % ds.num_anterooms
print "Reachability: %d" % ds.reachability

# Process the generated map. We can do this in one of two ways. Look
# at for a more standard one, based on
# a pair of y/x nested loops.
for x, y, map_tile in ds.iter_map():
    print "map(%d,%d) = %d (%s)" % (x, y, map_tile, const.tiles[map_tile])

# A more standard way of doing this:
#for y in xrange (ds.h):
#    for x in xrange (ds.w):
#        map_tile = ds.get_map(x, y)
#        print "map(%d,%d) = %d (%s)" % (x, y, map_tile, const.tiles[map_tile])

# End of file.


The original code could use both the unexpanded DungeonMaker (version 2.05), and my own expanded version. When this expanded version became DungeonSpawn, I chose to stop supporting the unexpanded version. The expanded version is a drop-in replacement for DungeonMaker, after all, and it allows for a considerably more Pythonic way of making dungeons.


Examples and Screenshots

DungeonMaker, DungeonSpawn and the DungeonSpawn Python bindings don't really generate any visual output, but the intent is there. So here are various examples rendered as colour-coded images.


These are sample outputs of the various labyrinth-generating examples bundled with the source code. All of these examples are bundled with the distribution.

The simplest possible form of a labyrinth: all values at their defaults.
A labyrinth with wide corridors.
A labyrinth with medium corridors.
An insane labyrinth. It may be a bad idea to use this in a game. Note how some areas are gated and become strangely-shaped rooms.
A complex labyrinth. This one includes a dungeon in its centre.

Simple Dungeons

This is the standard dungeon-building behaviour, without changing any defaults.
A maze of twisty little passages, all alike: a dungeon built by very dizzy tunnelers — they take short steps, changing directions very frequently.
A mine. Long wide tunnels branch off into narrow ones, making a grid. The dots denote rock impenetrable to the tunneling critters. They avoid them like the plague, and this simulates similar areas in real mines.

Complex Dungeons

This dungeon has a bottleneck in its middle. The player has to pass through this point to get from the entrance to the exit.
Randomising the bottleneck using a randomly-generated configuration.
An example of a disjoint dungeon. This map includes three distinct areas, each inaccessible from the others.
A very complex dungeon. Two distinct tunneling styles, one shabby, the other wide and stately. The latter leads to big rooms and a pre-positioned, huge treasure/encounter room at its far east edge.