Dungeon file format
A *.dungeon.json file is the lossless export of a generated dungeon: the cell map, optional layers (rooms, entities, generation steps) and enough metadata to reproduce it. It is written by toDungeonJson from dungeonmaker-js/export, by the generate command of the CLI and by the download menu of the playground. The format has a version (formatVersion: 1); a reader should check it before it trusts the layout.
The format is described by the JSON Schema dungeonmaker-js/dungeon.schema.json. This specification and dungeon.schema.json are released under CC0-1.0: write an importer in any language under any license.
Example
A shortened file for the preset design3A with seed 42 (the cells data is cut; <version> stands for the package version that wrote the file):
{
"format": "dungeonmaker-js/dungeon",
"formatVersion": 1,
"generator": "dungeonmaker-js@<version>",
"width": 160,
"height": 81,
"seed": 42,
"source": { "preset": "design3A" },
"legend": { "0": "open", "1": "closed", "…": "…", "19": "column" },
"cells": { "encoding": "base64", "data": "…" }
// "rooms", "entities" and "steps" appear only when the layer was requested
}Cells and layers
cells is row-major with north up: the cell at column x and row y is cells[y * width + x]. See Orientation for the axes and the meaning of the 20 cell values. The legend maps each value to a name, so a reader does not need the table.
cells comes in three encodings, chosen by the writer (cells: 'base64' | 'rows' | 'array'):
base64(default): one byte per cell, base64 encoded. Compact; use it when you parse the file.rows: one string per row, one character per cell, taken from the storedalphabet. It is lossless (unlike the ASCII export, which merges cells) and readable in a diff.array: a plain JSON array ofwidth * heightintegers.
Binary layers are base64 as well, and every multi-byte value is little-endian: rooms.roomIds is one uint16 per cell (0 = no room, otherwise the room id), steps.offsets and steps.index are uint32 arrays. steps.cell is one byte per recorded change. Entity and room positions use the same axes as cells: x is the column, y the row.
The source field
source says which design the dungeon came from, without copying designs that are not yours to copy:
- A preset appears as
{ "preset": "<name>" }, never with its text. The CLI andgenerateToFileswrite this form for any design whose text equals a preset, even with--embed-design. - Any other design appears as
{ "designHash": "sha256:…" }, the SHA-256 of the design text. The design itself is embedded (design) only on request. - A file without
sourcemakes no claim about its origin.
With the seed, the generator version and the design, a file can be reproduced byte for byte: the same version writes the same bytes.
Fields
| Field | Type | Constraints | Default | Description | Upstream |
|---|---|---|---|---|---|
$schema | string | optional (omitted: not written by the exporters) | JSON Schema URL for editor support; exporters do not emit it. | ||
format | string | = "dungeonmaker-js/dungeon" | required | ||
formatVersion | number | = 1 | required | ||
generator | string | required | dungeonmaker-js@<version> | ||
width | integer | ≥ 0 | required | Map width in cells. | |
height | integer | ≥ 0 | required | Map height in cells. | |
seed | integer | ≥ 0 | required | Seed the dungeon was generated with. | |
source | object | one of 2 variants | optional (omitted: origin not recorded) | Where the design came from: a preset name, or its hash. | |
source{preset}.preset | string | required | Name of an upstream preset. | ||
source{designHash}.designHash | string | pattern ^sha256:[0-9a-f]{64}$ | required | SHA-256 of the UTF-8 design text. | |
source{designHash}.design | object | optional (omitted: design not embedded) | The embedded design (see design.schema.json); only on request. | ||
legend | object | keys 0 … 19 | required | Cell value to cell name. | |
cells | object | one of 3 variants | required | The map, row-major, north up: index = y * width + x. | |
cells{base64}.encoding | string | = "base64" | required | ||
cells{base64}.data | string | required | Base64 of width * height bytes, one per cell. | ||
cells{rows}.encoding | string | = "rows" | required | ||
cells{rows}.alphabet | string | required | One character per cell value (index = cell); lossless. | ||
cells{rows}.data | string[] | required | One string of width characters per row. | ||
cells{array}.encoding | string | = "array" | required | ||
cells{array}.data | integer[] | items: 0 … 19 | required | width * height cell values, row-major. | |
rooms | object | optional (omitted: layer not requested) | Room id per cell (uint16 LE, base64) and the room table. | ||
rooms.roomIds | object | required | |||
rooms.roomIds.encoding | string | = "base64" | required | ||
rooms.roomIds.data | string | required | Base64 of the little-endian bytes. | ||
rooms.rooms | object[] | required | |||
rooms.rooms[].id | integer | ≥ 0 | required | Index + 1 in creation order; matches the values in roomIds. | |
rooms.rooms[].area | string | = "labyrinth"; = "dungeon" | required | ||
rooms.rooms[].size | integer | ≥ 0 | required | Number of squares. | |
rooms.rooms[].bounds | object | required | |||
rooms.rooms[].bounds.x | integer | ≥ 0 | required | Column. | |
rooms.rooms[].bounds.y | integer | ≥ 0 | required | Row. | |
rooms.rooms[].bounds.width | integer | ≥ 0 | required | Width. | |
rooms.rooms[].bounds.height | integer | ≥ 0 | required | Height. | |
entities | object[] | optional (omitted: layer not requested) | MOBs, then treasure. | ||
entities[].kind | string | = "mob"; = "treasure" | required | ||
entities[].x | integer | ≥ 0 | required | Column. | |
entities[].y | integer | ≥ 0 | required | Row. | |
entities[].level | integer | ≥ 0 | required | Index in the design's population list. | |
steps | object | optional (omitted: layer not requested) | Recorded generation steps. | ||
steps.offsets | string | required | Base64 uint32 LE; frame k = index[offsets[k]..offsets[k+1]). | ||
steps.index | string | required | Base64 uint32 LE; y * width + x. | ||
steps.cell | string | required | Base64 bytes; the cell value set at index. |
