Skip to main content

Dungeons as Code

·381 words·2 mins
chronicler - This article is part of a series.
Part 4: This Article

Claude is good at narration, but pretty awful at spatial reasoning.

While it’s fine to play encounters using the theatre of the mind without explicit tracking of character and monster locations, it can be fun to manage tactical positioning and get an overview of the party’s surroundings.

In order to solve this problem I defined a domain-specific language — DungML — that lets Claude generate tactical maps on the fly. Rooms, corridors, doors, windows, secret passages, and lighting are all declarative; the model only has to describe intent, not coordinates:

map "Quickstart" {
  grid { bounds 30 x 18 }
  renderer "hatched"
  background "#CCCCCC"
}

room "antechamber" {
  rect 2,4 12 x 10
  label "Antechamber"
  description "Cracked flagstones. Pillars hold up a sagging ceiling."

  feature pillar  at 4,6
  feature pillar  at 4,12
  feature pillar  at 12,6
  feature pillar  at 12,12
  feature brazier at 8,6
}

room "sanctum" {
  rect 18,4 10 x 10
  label "Inner Sanctum"
  description "A statue of a forgotten god still keeps watch."

  feature statue at 23,7
  feature altar  at 23,11 scale 1.2
}

# Short corridor bridging the 4-unit gap between the rooms.
corridor "passage" {
  width 2
  segment line from 14,9 to 18,9
}

# Default door — wooden, closed, width 1. Three more lines of property
# would let you change those.
door at 14,9 {
  connects room.antechamber, corridor.passage
}

door at 18,9 {
  connects room.sanctum, corridor.passage
  type iron
  state locked
  description "Old keyed lock. The wards still hum faintly."
}

# Windows on the antechamber's west wall — exterior light.
window at 2,7  { in room.antechamber  width 1.5 }
window at 2,11 { in room.antechamber  width 1.5 }

# A secret door in the antechamber's south wall — discoverable only
# on a successful Perception check.
door at 8,14 {
  connects room.antechamber
  type secret
  description "A pivot stone. Catch the seam and the wall turns."
}

Renders to:

Rendered tactical map showing the antechamber, sanctum, corridor, doors and windows defined in the DSL above

Using a structured language allows definition of more complex tactical maps:

Multi-room library rendered from DungML

The system is flexible enough to render houses, caves, outdoor maps and the like:

Outdoor map rendered from the same DSL

Rendering is performed by a small JavaScript component embedded in the Chronicler application, allowing the system to update the map as locations are discovered and players move around:

In-game map view updating as the party moves through a location

The DungML editor allows saving of locations as PDF in old-school module format:

Location exported as PDF in old-school module format
chronicler - This article is part of a series.
Part 4: This Article