Level generation I: Layout

After a break working on other things (and playing games for research purposes 🙂 ), at about July I started working on level generation, as an exciting way back in to development. Exciting does not mean short, however, as I have certain expectations from the level generator to be quite capable and flexible, instead of just generating a “caves” level, a “dungeon” or a “forest”. As a result, 6 weeks later, I’m nowhere near done, but some parts now do work, and this is what this and following posts will be about.

Parts of level generation

Levels are not generated in a single pass; the process is split into the following (tentative) order:

  • Layout: Passable/impassable areas, rocks, trees, doors, water, open sea, etc. Where creatures can move.
  • Gateways: Staircases, etc. How to connect one level to another
  • Foreground objects: altars, fountains, bookshelves, tables, etc.
  • Traps, puzzles, secret doors
  • Creatures
  • Decoration: Grass, cobwebs, carpets, etc

The order, while not final, should reflect some form of logical dependent order, for example layout comes first, gateways need a layout, foreground objects need a layout and also need to avoid staircases, traps are based on layout and foreground objects, creatures need to be generated based on the dungeon layout and also need to be aware of traps and maybe foreground objects, and finally decoration is applied to layout but needs to know about other elements, such as gateways and foreground objects, that exist on the level.

Requirements and use-cases

Example levels should contain:

  • Building interiors ( manor, guild hall, temple complex)
  • Buildings outdoors (village, ruins, cabin in the woods)
  • Outdoors environments (forest, desert, sea coast, and generally biome-themed areas)
  • Typical dungeon
  • Cave complex

Zones: The ${dungeon_type} in the ${biome_type}

One of the goals of the level generation system is to be able to utilise multiple generators for single level, so that level separation is not always artificial.

An example is the first level of a wizard tower in some location. The tower can be located in the swamp (don’t ask me how they built it, it’s probably not too structurally sound), in the snow, near the sea, in the desert etc. In order to add some sense of exploration, we want the player to wander a bit in the biome to find the tower. So, we need a biome-specific generator, depending on our location. When we find the building, instead of having some sort stairs to change to a different level, we can generate the first level of the tower embedded within the biome map. So you find the tower, open the door, get in and explore the ground floor of the tower, all in the same level. To achieve this, we need 2 different generators, the biome generator and a “wizard tower ground floor” generator, and embed the latter into the former and make sure the entrance is accessible and makes sense. The areas belonging to different generators will be called from now on zones.

Masks: Controlling the shape of zones

Instead of using simplistic rectangles to differentiate between areas, we can use some more freeform masks using noise and cleaning up the shape by removing islands, or even custom ones. As a result, we get zones like this:

Coastal map (red) with lighthouse (green)
Outdoors (red), mountain (green), dungeon (blue)
Outdoors (red), mountain (green), temple (blue)

Each zone uses its own generator, and we just need to make sure that the zones can be connected. Zones can be “open” or “closed”. Open zones are ones where the default location is passable, for example outdoors. Closed locations are ones where the default is impassable, such as caverns, dungeons, etc, as these are spaces carved into rock. We have to worry about connecting zones if at least one of them is closed.

Prefabs: Handcrafted areas in procedural levels

Procedural generation nice, but sometimes we want to place particular, handcrafted rooms and areas and mix them with procedural elements. Examples:

  • Boss lair: specially designed room, but we shouldn’t know where to find it
  • Fortress entry hall. If we enter the fortress we’re in that room, but we don’t know the rest of the layout
  • Fortress prison. It has a fixed layout, but we don’t know where it is.
  • Glade in the forest. We want a small area in the forest to have a very particular look (special placement of lake, trees, ruins), but we won’t know where to find it.

In the example images in this page, I use a small number of prefab rooms:

Entry hall: When I use this, it’s always the first room to be connected to a connecting zone, via the door on the top. The doors appear exactly at that location, and we won’t have any more doors.

Entry hall

Lair: When I use this, I ensure that it’s never connected to a different zone, so all doors lead somewhere in the same zone. The doors appear exactly at that location, and we won’t have any more doors.

Lair, in case it wasn’t clear

OpenArea: This is an example of an area that is open and has a few things in.

Open area

Not fancy, but serving as proof of concept.

Configurability

A very important part of the process is being able to configure the generator using simple data structs, loadable from configuration files (or dynamically created configurations). This “heterogeneous” generator was designed with that in mind, so that creating permutations is easy, although there are still quite a few parameters to set up. In this page I’m using 3 presets:

  • The dungeon under the mountain V1: An outdoors map, with a cavern system on the left side, that leads to a dungeon map
  • The dungeon under the mountain V2: An outdoors map, with a cavern system on the left side, that leads to a temple. The temple generator is different than the dungeon generator in V1, and uses a dragon-shaped mask, so that any rooms are forced to be confined in that shape
  • The lighthouse by the sea: An outdoors map, bordering with the sea, that contains the lower level of a lighthouse: a circular tiny “dungeon” which is effectively a few rooms (maybe even one) and a staircase. Players might or might not traverse water to get to the lighthouse.

Examples

Below are some examples, 10 per preset. Using basic tiles and minimal decoration, more on that in another post.