world The places. Terrain, palettes, biomes, areas, points of interest, gates, rooms, encounters, dungeons, maps, and the clock.
Biome, then area, then point of interest. A biome is a theme: room templates, encounter tables, ambience, palette. An area belongs to one biome and joins others by declared connections. A point of interest is a place inside an area. A generated dungeon hangs off a point of interest and does not replace it.
How a map gets built Three sources, highest first. map.static names a hand drawn grid. map.layout plus map.legend draws one inline with glyphs. Otherwise the size, palette, and starting number generate one. Maps are built on arrival and kept.
roomCount is a request Spacing between rooms comes from the average of corridorLength, not from roomCount. Fifteen rooms with long corridors on a small floor can come out as two. The studio measures what a dungeon really generates and offers a size that matches.
Two guarantees Every room is reachable. Every key lies before its lock. Both hold for any settings.
Three algorithms carve a floor:
"algorithm": "rooms" places rectangles and joins them with corridors
"algorithm": "bsp" splits the bounds recursively; the splits are the tree
"algorithm": "caverns" noise and smoothing; keeps the largest connected floor
Field Type Req Default What it does terrainsobject [] []What a tile can be. Passability and cost are read from here, not baked in. palettesobject [] []Which terrains a generator builds with. One generator, many looks. biomesobject [] []A theme. Room templates, encounter tables, ambience, and a palette. areasobject [] []A named place on the map, belonging to a biome and joined to others. pointsOfInterestobject [] []Somewhere you go inside an area. A shrine, a camp, a dungeon mouth. gatesobject [] []Something in the way, and what gets you past it. roomTemplatesobject [] []The kinds of room a generated dungeon draws from. encounterTablesobject [] []Weighted groups of monsters, drawn on arrival and in rooms. dungeonsobject [] []A generated interior. Hangs off a point of interest rather than replacing it. mapsobject [] []Hand authored grids, identical on every seed. No randomness is consulted. timeobject {}The clock. Day length, phases, and what each action costs in minutes. generationDefaultsobject {}Fallback chances for rooms that name none.
Field Type Req Default What it does idid yes Id of the terrain, named by palettes, legends, and map cells. namestring yes Display name. Used when something blocks you and has to say why. descriptionstring ""What it looks like underfoot. tagsid [] []Free labels for grouping and gating. glyphstring "."One or two characters drawn for it on the map. colorredgreenyellowbluemagentacyanwhitegrayColour it is drawn in. passableboolean trueWhether anything can walk onto it. opaqueboolean falseWhether it blocks sight and any sense stopped by opaque things. moveCostnumber 1Movement spent entering it. requiresModerules.movementModes [] []Movement modes that can cross it. Empty means any. providesCoverrules.coverTypes Cover a creature standing here gets. onEntereffect [] []Effects run on whoever steps onto it. onOccupyeffect [] []Effects run on whoever ends their turn on it. lightRadiusnumber 0Indexed but unread. There is no light model; a sense carries its own reach. marks{ rules.senses : number } How well this ground keeps a trace, per sense. Zero keeps none. isDoorboolean falseIndexed but unread. Doors live on the map's gate record, not on the terrain. extra{ string : any } {}Open bag of your own data on this terrain.
Field Type Req Default What it does idid yes Id of the palette. namestring Display name. floorworld.terrains yes Terrain used for open ground. wallworld.terrains yes Terrain used for solid rock. doorworld.terrains Terrain used where a corridor meets a room. scatterobject [] []Terrains sprinkled over the floor, and how they are spread. exteriorworld.terrains Terrain filling everything outside the built area. extra{ string : any } {}Open bag of your own data on this palette.
Field Type Req Default What it does terrainworld.terrains yes Which terrain is scattered. frequencynumber 0.05Share of floor it covers, 0 to 1. distributionspecklepatch"speckle"Speckle rolls each tile alone. Patch uses noise, so it comes out connected. scalenumber 8Size of the noise features, for patch. octavesnumber 2Layers of noise, for patch. More gives rougher edges. edgeTerrainworld.terrains Terrain ringing each patch. edgeWidthnumber 1How many tiles wide that ring is. prioritynumber 0Which scatter wins where two overlap. Higher wins.
Field Type Req Default What it does idid yes Id of the biome. namestring yes Display name. descriptionstring ""What this kind of place is like. tagsid [] []Free labels for grouping and gating. layeroverworldunderworldboth"underworld"Whether places here sit above ground, below it, or either. roomTemplatesworld.roomTemplates [] []Rooms a dungeon in this biome may draw. encounterTablesworld.encounterTables [] []What may be met here. lootTablescontent.lootTables [] []What may be found here. trapscontent.traps [] []Traps that may be placed here. ambienceKeynarrative.textGrammar Text pool for the background of the place. triggersobject [] []Things that happen anywhere in this biome. paletteworld.palettes Terrains generators use here. Overrides a palette named on the map. extra{ string : any } {}Open bag of your own data on this biome.
Field Type Req Default What it does idid yes Id of the trigger. Also the key under which firing is remembered. descriptionstring ""What happens and why. modeonceeveryEntryuntilCompletelooprestart"once"How often it may fire. Choosing this correctly is most of the work. onenterexitrestsearchcombatStartcombatEndtimePasscustom"enter"The occasion it listens for. eventstring Event name to watch, when on is custom. requiresobject Gate on firing, in the requirement vocabulary. whenpredicate Predicate checked on top of requires. cooldownMinutesnumber 0World minutes between firings, for loop mode. completeWhenpredicate Predicate that ends untilComplete mode once it holds. rememberboolean trueWhether the world records that it happened. Off makes the event ambient. chancenumber 1Chance it fires once the gates pass. Rolled last, so a failed gate costs no randomness. effectseffect [] []What it does. textKeynarrative.textGrammar Text pool narrating it.
areas world.areasField Type Req Default What it does idid yes Id of the area. Its map is keyed area:<id>. namestring yes Display name. descriptionstring ""What the place is. tagsid [] []Free labels for grouping and gating. biomeworld.biomes yes Theme it belongs to. Supplies rooms, encounters, ambience, and palette. layeroverworldunderworld"overworld"Whether it sits above ground or below. Decides whether the sky is visible. descriptionKeynarrative.textGrammar Text pool read on arrival. connectionsobject [] []Roads out. Travel is only possible along a declared connection. triggersobject [] []Things that happen here. encounterTablesworld.encounterTables [] []What may be met here, on top of the biome's. controllingFactioncontent.factions Who holds it. dangerLevelnumber 1How dangerous it is. Feeds the default encounter chance. encounterChanceexpression {"min":[0.75,{"mul":[{"ref":"dangerLevel"…Formula for the chance of an encounter, overriding the danger based default. recommendedLevelnumber Party level the area is written for. Advisory. requiresobject Gate on entering at all. mapobject {}How the ground here is built. Size, palette, or a hand authored grid. entryPointobject Tile the party arrives on. Without one the engine picks a free tile. extra{ string : any } {}Open bag of your own data on this area.
Field Type Req Default What it does toworld.areas yes Area at the other end. travelMinutesnumber 60World minutes the journey costs. gateworld.gates Something in the way on this road. oneWayboolean falseSet on the destination's back link. A road listed both ways is two way. encounterTablesworld.encounterTables [] []What may be met on the road itself.
Field Type Req Default What it does widthdice "7"Tiles across, as dice notation so it can vary by seed. heightdice "7"Tiles down, as dice notation. paletteworld.palettes Terrains to build with. Dead whenever the biome names one, since the biome wins. staticworld.maps A hand authored map to use instead. Beats layout and generation. layoutstring [] []Rows of glyphs drawn by hand. Beats generation. All rows must be equal length. legend{ string : world.terrains } {}Which terrain each layout glyph means. extra{ string : any } {}Open bag of your own data on this map spec.
Field Type Req Default What it does xnumber yes Column, counting from zero. ynumber yes Row, counting from zero.
Field Type Req Default What it does idid yes Id of the place. Its map is keyed poi:<id>. namestring yes Display name. descriptionstring ""What is here. tagsid [] []Free labels for grouping and gating. areaworld.areas yes Area it sits in. A place whose area does not exist never appears. kindsettlementshrineruincampdungeonEntrancelandmarkcrossinglairmarketwilds"landmark"What sort of place it is. Decides the icon and some phrasing. descriptionKeynarrative.textGrammar Text pool read on arrival. gateworld.gates Something in the way of going in. hiddenboolean falseWhether it must be found before it can be travelled to. discoverobject The check that finds it. Without one a hidden place stays hidden. triggersobject [] []Things that happen here. encounterTablesworld.encounterTables [] []What may be met here. encounterChancenumber Chance of an encounter here, overriding the area. residentscontent.npcs [] []Who lives here. The other way to place people, alongside an NPC's home. lootcontent.lootTables [] []Tables drawn when the place is searched. dungeonworld.dungeons Interior reached from here. The dungeon hangs off the place, it does not replace it. servicesinnmarkettemplesmithguildstablehealer[] []What can be done here. Trade, rest, healing, training. rumourReachnumber 1How many hops news of this place travels among its people. controllingFactioncontent.factions Who holds it. travelMinutesnumber 0World minutes to reach it from the area entrance. positionobject Where it sits on the area map. mapobject How the ground here is built, when the place has an interior of its own. extra{ string : any } {}Open bag of your own data on this place.
Field Type Req Default What it does skillcontent.skills yes Skill rolled to find it. difficultyexpression yes Difficulty of that roll. Often a formula over what the party has heard.
gates world.gatesField Type Req Default What it does idid yes Id of the gate. Its state is flagged gate:<id>:open. namestring yes Display name. descriptionstring ""What is in the way. tagsid [] []Free labels for grouping and gating. kindlockwardpuzzletollstoryhazard"lock"What sort of obstacle it is. requiresobject What opens it outright. Items marked consume are spent doing so. bypassobject A check that gets past it instead. opensWithcontent.abilities [] []Abilities that open it. onOpeneffect [] []Effects run when it opens. onBlockedeffect [] []Effects run when someone fails to open it. blockedTextKeynarrative.textGrammar Text pool for being turned away. staysOpenboolean trueWhether opening it is permanent.
Field Type Req Default What it does skillcontent.skills yes Skill rolled to get past. difficultyexpression yes Difficulty of that roll. onSuccesseffect [] []Effects run on getting past. onFailureeffect [] []Effects run on failing. retryableboolean trueWhether a failure may be tried again. False records the attempt and refuses more.
Field Type Req Default What it does idid yes Id of the template. namestring yes Display name. tagsid [] []Free labels for grouping and gating. descriptionKeynarrative.textGrammar yes Text pool read on first entering a room built from it. weightnumber 1Relative likelihood of being drawn against other templates. roleentrancecorridorchambervaultbossshrinelair"chamber"What the room is for. Generation guarantees some roles exist. minExitsnumber 1Fewest doors the room may have. maxExitsnumber 4Most doors it may have. Connectivity wins over this cap. encounterChancenumber 0.3Chance the room is occupied, 0 to 1. trapChancenumber 0.1Chance the room is trapped, 0 to 1. lootChancenumber 0.25Chance the room holds something, 0 to 1. alwaysEncounterboolean falseForce an occupant regardless of the chance. neverEncounterboolean falseForbid an occupant regardless of the chance. neverTrapboolean falseForbid a trap regardless of the chance. requiresobject Gate on the template being drawn at all. triggersobject [] []Things that happen in a room built from it. mapobject {}How the room itself is built. extra{ string : any } {}Open bag of your own data on this template.
Field Type Req Default What it does idid yes Id of the table. namestring Display name. descriptionstring ""What this table is for. minDepthnumber 0Shallowest dungeon depth it may be drawn at. maxDepthnumber 999Deepest dungeon depth it may be drawn at. chancenumber 1Chance a draw yields anything at all, 0 to 1. emptyWeightnumber 0Weight of the nothing row against the groups. scalePerLevelsnumber 2Party levels per step of scaling on entries that scale. groupsobject [] yes The weighted rows. Each is a whole encounter.
Field Type Req Default What it does idid yes Id of the group. namestring Display name. weightnumber 1Relative likelihood against the other groups. requiresobject Gate on the group. Failing removes it before the draw, not after. entriesobject [] yes The creatures in it. At least one is required. onEncountereffect [] []Effects run when this group is drawn. textKeynarrative.textGrammar Text pool narrating the meeting. hostileboolean trueWhether they attack. False makes it a meeting rather than a fight.
Field Type Req Default What it does monstercontent.monsters yes Which statblock appears. countdice "1"How many, as dice notation. scaleWithLevelboolean falseWhether the count grows with party level.
Field Type Req Default What it does idid yes Id of the dungeon. Its maps are keyed by it and the depth. namestring yes Display name. descriptionstring ""What is down there. biomeworld.biomes yes Theme it is built from. Supplies room templates and encounters. roomCountdice "8"Rooms requested per floor. A request, not a promise; packing may fit fewer. depthdice "1"How many floors deep it goes. branchinessnumber 0.35Extra loops added past the spanning tree, 0 to 1. 0 gives a pure tree. lockedDoorChancenumber 0.15Chance a tree edge gets a lock. Keys are always placed before their lock. doorGatesworld.gates [] []Gates that may be used as locks. guaranteedRolesstring [] ["entrance","boss"]Room roles that must exist. Bare strings, not checked references. safeEntranceboolean trueWhether the entrance room is guaranteed empty. bossTableworld.encounterTables Drawn in the boss room. Without one the deepest room generates like any other. completionTriggersobject [] []Things that happen when the dungeon is finished. paletteworld.palettes Terrains to build with, overriding the biome. corridorLengthdice "3d3"Corridor length, which is what actually sets the spacing between rooms. windingobject {}How much corridors wander, when the corridor style is winding. roomSizedice "2d3+3"How large a room is on a side. algorithmroomsbspcaverns"rooms"How the floor is carved. Placed rooms, split rectangles, or grown caves. bspobject {}Settings for the bsp algorithm. cavernsobject {}Settings for the caverns algorithm. staticMapworld.maps A hand authored map to use instead. Skips generation entirely. rollEncountersboolean falseWhether rooms roll their own encounters as well as the placed ones. corridorobject {}Shape and width of the corridors. widthdice Floor width in tiles. Without one the engine sizes it from the room count. heightdice Floor height in tiles. extra{ string : any } {}Open bag of your own data on this dungeon.
Field Type Req Default What it does continueChancenumber 0.6Chance a corridor keeps going the way it was, 0 to 1. turnPenaltynumber 0.4How much a turn is discouraged, 0 to 1.
Field Type Req Default What it does minLeafnumber 5Smallest rectangle the splitting stops at.
Field Type Req Default What it does fillnumber 0.45Share of the floor filled with rock before smoothing, 0 to 1. smoothingPassesnumber 4How many rounds of smoothing are run. birthThresholdnumber 5Neighbours needed for a cell to become rock.
Field Type Req Default What it does stylelstraightwinding"l"Whether corridors turn once, run straight, or wander. widthnumber 1Tiles across. Crossings are never widened, so a locked door stays one tile.
maps world.mapsField Type Req Default What it does idid yes Id of the map, named by an area, place, dungeon, or room template. namestring Display name. descriptionstring ""What this map is. tagsid [] []Free labels for grouping and gating. entryid "entry"Marker the party arrives at. layersobject, 7 variants [] yes Grids stacked in draw order. The layer kind decides what its cells mean. extra{ string : any } {}Open bag of your own data on this map.
Field Type Req Default What it does kindterrainyes What the cells name. Terrain, items, monsters, npcs, gates, traps, or free markers. nameid Names the layer in the editor and its file on disk. cells | world.terrains [] [] yes Rows of ids, one per tile. An empty cell means nothing here. extra{ string : any } {}Open bag of your own data on this layer.
time world.timeField Type Req Default What it does minutesPerDaynumber 1440How long a day is. minutesPerHournumber 60How long an hour is. daysPerMonthnumber 30How long a month is. monthNamesstring [] []Names of the months, in order. dayPhasesobject [] []Named parts of the day and when each begins. startMinutenumber 480Minute of the first day play begins at. actionMinutes{ string : number } {"search":10,"disarm":10,"sense":1,"wait"…World minutes each action costs outside combat. minutesPerTilenumber 0World minutes a step costs. Only charged outside combat.
Field Type Req Default What it does idid yes Id of the phase, read as world.phase. namestring yes Display name. startMinutenumber yes Minute of the day it begins at.
Field Type Req Default What it does encounterChancenumber 0.3Encounter chance for a room whose template names none. lootChancenumber 0.25Loot chance for a room whose template names none. trapChancenumber 0.1Trap chance for a room whose template names none.