Procedural Map Generation
Procedural map generation creates map geometry from region settings and tile metadata. The first generator is connected_rooms, a seed-based 2D dungeon generator for room-and-corridor layouts.
Use this workflow when you want a generated dungeon that can be rebuilt after changing tiles, item templates, character templates, or the seed.
Workflow
- Tag the tiles the generator may use with Edit Tile Meta.
- Add a
[procedural]section to the region settings. - Switch to the 2D editor view and run Build Procedural from the action list.
- Adjust tiles, spawn rules, or the seed and run Build Procedural again.
Running Build Procedural rebuilds the procedural region as an authored generator output: existing geometry, items, and non-player characters in that region are cleared before the new layout is created. Keep persistent handcrafted content in another region, and rebuild only the generated region.
Tile Metadata
Select a tile in the tile picker and use Edit Tile Meta to assign procedural metadata:
[procedural]
style = "stone"
kind = "floor"
weight = 1
style: groups tiles into a visual set, such asstone,cave, orcrypt.kind: describes what the tile is used for.weight: controls how often this tile is chosen relative to other tiles of the same style and kind.
Supported kind values for connected_rooms are:
floor: room and corridor floor tiles.wall: wall tiles around generated floor areas.entrance: marker tile for the start endpoint.exit: marker tile for the end endpoint.
Use none for tiles that should not be selected by procedural generation.
Doors, traps, potions, treasure, and monsters should not be tile kinds. Generate them as item or character instances from region settings instead.
Region Settings
The generator is configured in the current region's settings:
[procedural]
enabled = true
generator = "connected_rooms"
mode = "2d"
seed = 12345
style = "stone"
width = 32
height = 32
room_count = 6
room_min_size = 6
room_max_size = 10
door_placement = "both"
door_randomness = 1.0
[procedural.items.door]
names = ["Door"]
weights = [1]
[procedural.characters.skeleton]
names = ["Skeleton"]
weights = [1]
percentage = 35
enabled: iffalse, Build Procedural does nothing.generator: currently supportsconnected_rooms.mode:2dbuilds tile-map geometry.3dis reserved for a future direct geometry generator.seed: makes the generated layout deterministic.style: selects tiles whose procedural style matches this value.width/height: generated grid size.room_count: target number of connected rooms.room_min_size/room_max_size: room size range in tiles.door_placement:entrances,exits, orboth.door_randomness: probability from0.0to1.0afterdoor_placementfiltering.
If a matching tile style is not available, the generator can fall back to any procedural tile of the required kind. If no dedicated entrance or exit tile is available, floor tiles are used for those markers.
The same settings can be read or changed at runtime with region.procedural.* context paths before calling build_procedural():
region.procedural.seedregion.procedural.widthregion.procedural.heightregion.procedural.room_countregion.procedural.room_min_sizeregion.procedural.room_max_sizeregion.procedural.door_placementregion.procedural.door_randomnessregion.procedural.characters.<kind>.chanceregion.procedural.characters.<kind>.percentage
region.procedural.run is maintained by build_procedural(0). Each 0 rebuild increments it and derives a new deterministic seed from the region's configured seed. Use a positive seed argument if you want to rebuild from an exact seed instead.
For compatibility, region.procedural.rooms is accepted as an alias for region.procedural.room_count, and percent is accepted as an alias for character percentage.
Connected Rooms
connected_rooms creates a single connected path from the entrance room to the exit room. Rooms are standalone areas connected by corridors, rather than one large merged maze.
The endpoint marker tiles are named entrance and exit. These named sectors can be used by scripts, teleport targets, or entered/left events.
Door placement is controlled by door_placement:
entrances: only place doors on incoming room sides.exits: only place doors on outgoing room sides.both: place doors on both sides of room connections.
door_randomness decides whether an eligible door is actually placed. If no door is placed at a connection, that connection remains passable floor.
Items
Items are generated from [procedural.items.<kind>] tables. Door generation currently uses the door kind:
[procedural.items.door]
names = ["Wooden Door", "Iron Door"]
weights = [4, 1]
The generator creates item instances from the named item templates. The item template controls its tile, blocking behavior, script, and interactions.
You can also write weighted choices explicitly:
[procedural.items.door]
choices = [
{ name = "Wooden Door", weight = 4 },
{ name = "Iron Door", weight = 1 },
]
Characters
Characters are generated from [procedural.characters.<kind>] tables:
[procedural.characters.monster]
chance = 0.4
choices = [
{ name = "Skeleton", weight = 3 },
{ name = "Orc", weight = 1 },
]
Character spawn probability accepts either:
percentage = 40chance = 0.4
Generated characters are placed in room centers and skip the entrance and exit rooms.