# des-file format
The des-file format is the language which is used to describe the special levels for NetHack. It is compiled into a binary file by lev_comp.
It is not a real programming language: there is no flow control, and the order in which different NetHack features are created is fixed.
There are two types of levels you can create: mazes and rooms. For MAZE-type levels you "draw" one or more maps with ASCII characters and then describe the monsters, objects and so on that are in the map (example: Bigroom.des). For ROOM-type levels, you describe rooms and their contents (example: Oracle.des). The maze-levels are easier to make and understand, and room-type levels do not offer as much control over the level.
lev_comp will create a .lev-file for each MAZE and LEVEL definition in the file. These .lev-files will be loaded into NetHack to make the special levels. The .lev-files NetHack loads are actually defined in dungeon.def.
This page is in the process of being updated to Nethack 3.6, and it should not be assumed that syntax in earlier versions is the same as in 3.6. For a complete guide on des files in 3.4.3, see Des-file format (NetHack 3.4.3).
UnNetHack uses a somewhat different format.

Contents

1 Language syntax

1.1 Comments
1.2 Types
1.3 Variables
1.4 Shorthand for conditionals
1.5 Terrain selections

2 MAZE-type levels

2.1 MAZE
2.2 FLAGS
2.3 INIT_MAP
2.4 MESSAGE
2.5 NOMAP
2.6 GEOMETRY
2.7 MAP
2.8 NON_DIGGABLE
2.9 NON_PASSWALL
2.10 RANDOM_PLACES
2.11 RANDOM_MONSTERS
2.12 RANDOM_OBJECTS
2.13 DOOR
2.14 DRAWBRIDGE
2.15 REGION
2.16 STAIR-region
2.17 PORTAL
2.18 TELEPORT_REGION
2.19 BRANCH
2.20 MAZEWALK
2.21 WALLIFY
2.22 LADDER
2.23 GOLD

3 ROOM-type levels

3.1 LEVEL
3.2 RANDOM_CORRIDORS
3.3 ROOM
3.4 SUBROOM
3.5 NAME
3.6 CHANCE
3.7 Room DOOR
3.8 Common syntax
3.9 ALTAR
3.10 CONTAINER
3.11 ENGRAVING
3.12 FOUNTAIN
3.13 GRAVE
3.14 MONSTER
3.15 OBJECT
3.16 SINK
3.17 STAIR
3.18 TRAP
3.19 Map characters
3.20 Trap names
3.21 Room types

4 See also

Language syntax
Comments
All lines beginning with # are comments and are ignored by the level compiler, except between MAP and ENDMAP.
Example:

# This is a comment.

Types
There are many data types used in des files. Some are relatively simple, such as characters, strings, and numbers. More complex ones include:

Type

Description

Example

coord

A coordinate pair, that is, a pair of numbers (x,y) representing a location on the last defined MAP or on the whole level if no MAP is defined, where (0,0) represents the point in the upper left corner. By convention, coordinates less than 10 have a leading 0, so that all coordinates are two digits, but this is not required.
Also, using rndcoord on any terrain selection (see below) will select one pair of coordinates at random from that selection and thus resolves to a single coord.

(70,06)

math expression

Fairly intuitive. Supported math operators are addition, subtraction, multiplication, division, and modulo division. Must resolve to an integer. Parentheses are also supported.

(3 + 5) / (2 * 4)

dice notation

Represents a roll of an arbitrary amount of arbitrary-sided dice, in the format XdY (roll X dice with Y sides and total them). Resolves to an integer and can be used in math expressions.

4d6

comparison statement

A percentage or math-based comparison that can be used to evaluate whether an IF block will be processed. Brackets are required.

[33%]
[$variable &lt; 10]

region

A rectangular region of the level, expressed with the x and y coordinates of its upper left and lower right corners, respective to the most recently defined MAP. A variation is a levregion, which is the same thing except that the coordinates are absolute on the level irrespective of any MAPs.

(03,10,64,10)
levregion(10,18,21,25)

mapchar

One of the map characters, or a pair of that with a light state.

'T'
('.',lit)

monster

Either a single character representing a monster class (producing a random monster from that class), a string giving the name of a specific type of monster, or both  as a parenthetical pair.

'F'
"lichen"
('F',"lichen")

object

Either a single character representing an object class (producing a random object from that class), a string giving the name of a specific type of object, or both as a parenthetical pair.

'('
"tin opener"
('(',"tin opener")

selection

One, or a combination of multiple, terrain selections (see below), representing an area of the level that is not necessarily rectangular. Frequently, rndcoord is used on a selection to pick a pair of coordinates in it at random.

rect (10,10,20,20) &amp; line (50,50),(60,50) &amp; (61,61)

array

An ordered list which can contain many of a single data type (any of the above, as well as the primitives).

{ (43,11), (34,11), (23,12), (45,06) }

Variables
You can define variables, which must begin with a $ sign. The name of the variable can contain only uppercase and lowercase letters and underscores. Variables must be assigned to something on the first line that they appear; they can then be used multiple times later.
Examples:

# select and place exactly one of these four specific monsters at (10,18)
# SHUFFLE can't be used because it would error if you tried to create for instance ('A',"minotaur")
$mon_letters = { 'A', 'L', 'V', 'H' }
$mon_names = { "Archon", "arch-lich", "vampire lord", "minotaur" }
$mon_index = 1d4 - 1
MONSTER:($mon_letters[$mon_index],$mon_names[$mon_index]),(10,18)

Various types of variables require their type to be declared when set, with a colon:

$path = selection: randline (34,05),(43,05),10
$enemy = monster: ('X',"xorn")
$treasure = object: '/'
$tree = terrain: 'T'

Shorthand for conditionals
If there happens to be only one statement that will either execute or not based on a condition, a shorthand is to put the conditional at the beginning of the line followed by a :, and then the rest of the statement. 
Example:

[45%]: MONSTER:"xorn",random

However, if two or more statements need to be processed from the same condition, it's better to put them in an IF block.

Terrain selections
Many complicated shapes can be generated with terrain selections, and these shapes can even be combined with each other. The easiest way to think of them is as a set of points. These are the available definitions for terrain selections:

Definition

Explanation

Example

coord

Just a single point, one pair of coordinates.

(44,12)

rect region

An unfilled rectangle, containing just the edges and none of the interior points.

rect (20,13,40,15)

fillrect region

A filled rectangle containing the edges and all of the interior points.

fillrect (20,13,40,15)

line coord,coord

A straight line drawn from one pair of coordinates to the other using Bresenham's line algorithm.

line (76,03),(55,19)

randline coord,coord,math expression

A line that is guaranteed to start at one pair of coordinates and finish at the other, but uses a random walk to get there. Specifically, the algorithm uses a form of fractal noise: it takes the midpoint of the line, moves it to a random point nearby no farther than the user-provided roughness (the last argument), then recurses over each resulting half of the line with the roughness reduced to 2/3 of its previous value.

randline (00,10),(75,10),15

grow(selection)
grow(direction(s),selection)

Grows the provided selection by 1 in the specified directions, or in all directions if the first format is used.

grow(north,randline(20,12),(30,15),8)

filter(percentage,selection)

Independently for every space in the selection, keep it in the selection with a chance equal to the provided percentage; otherwise remove it.

filter(50%, fillrect(23,12,66,16))

filter(selection1,selection2)

Perform a set intersection operation on the two selections. Points that appear in both selections will be kept in the resulting selection; points that appear in only one or the other are removed.

filter(floodfill(23,23), fillrect(20,20,25,25))

filter(mapchar,selection)

This is a complicated one. If the mapchar is a simple character, then anything in the selection whose terrain type doesn't match that mapchar will be removed. If the mapchar is bundled with a lit or unlit light state, then anything in the selection whose light state doesn't match the provided state will additionally be removed, even if the mapchar matches. If the mapchar is bundled with a random light state, then matching mapchar locations in the selection have a 50% chance of being removed.

filter('.',fillrect(20,10,50,20))
filter(('.',unlit),line(20,00),(30,05))

floodfill coord

Performs a flood fill from the pair of coordinates provided, adding to the selection all the connected spaces with the same terrain type as the starting location. It does not fill across diagonals.

floodfill (34,15)

circle (coord, radius [, unfilled])

Adds points in a ring around the given center point with the given radius, using McIlroy's Ellipse Algorithm. If "unfilled" is provided as an optional third argument the selection will be only that ring; otherwise the interior of the circle will also be added to the selection.

circle ((55,17),3)

ellipse (coord, xradius, yradius [, unfilled])

Same as the circle selection, but instead of a constant radius it is a more general ellipse whose x and y axes can be specified. Note that the des file is intended to specify the semi-x-axis and the semi-y-axis (the distances from the center to the right and top extremes of the ellipse), not the full axis lengths.

ellipse((55,17),10,4)

gradient (type, (mindist - maxdist [, limited]), coord [, coord])

Makes a radial gradient of probability that a space will independently be added to the selection.
The center of the gradient is either the single coord if only one is provided, or the line between the two coords if two are provided.
Within mindist of this center, no points will be added.
Between mindist and maxdist away from the center, each space has a probability of being added that linearly increases from 0% at mindist to 100% at maxdist.
Beyond maxdist, the probability for each square is either 0% if the limited flag is present, or 100% if it is missing or specified as "unlimited".
If the provided gradient type is "square" instead of "radial", the gradient will instead be square-shaped instead of circular/elliptical, but still emanating from the center point or line.

 gradient (radial, (4-10, unlimited), (35,08),(39,08))

complement selection

Inverts the selection across the whole level. Every point that was not in the selection will be added to it, and every point that was in the selection will be removed from it.

complement (fillrect(56,07,71,09))

MAZE-type levels
Maze-type levels begin with MAZE, followed with optional FLAGS, optional INIT_MAP, 0 or more MESSAGEs and up to 9 maze-parts, each of which consists either of NOMAP or GEOMETRY and MAP, followed by zero or more the random register initializers, one of each (RANDOM_MONSTERS, RANDOM_OBJECTS, RANDOM_PLACES), followed by zero or more of the map details (everything else, eg. MONSTER, OBJECT, TRAP, etc.)
That is:

MAZE
FLAGS, optional
INIT_MAP, optional
MESSAGE, 0 or more
up to 9 map-parts, which consist of:
NOMAP or GEOMETRY and MAP
RANDOM_MONSTERS, optional
RANDOM_OBJECTS, optional
RANDOM_PLACES, optional
The rest of the definitions of this map-part
Example:

MAZE:"test",' '
FLAGS:noteleport
MESSAGE:"Welcome!"
GEOMETRY:center,center
MAP
.....
.L.L.
.....
.L.L.
.....
ENDMAP
MONSTER:random,random,random
OBJECT:'%',random,random

Maze-type levels, or any level for which flags.is_maze_level is true in the code, have some different behaviors:

The level designer is expected to place any room furniture into rooms. Defining a throne room will only place a throne on non-maze-type levels, for instance.
Digging, where possible, will only dig one space, and will result in floor tiles being created instead of corridor tiles.
Mimics will mimic statues (instead of doors or boulders or objects).
MAZE
MAZE:"foo",'X'

foo is the unique file name which will be used for this special level, up to 8 characters. For example: soko3-2. This file name which NetHack loads is defined by the way this level is defined in dungeon.def.
'X' is the fill map character. The map will be filled with this dungeon feature before anything else is done. This can also be random, which fills the whole level with a checkerboard grid of walls and stone, so you can use MAZEWALK on it.
Example:

MAZE:"soko3-2",' '

FLAGS
FLAGS:flaglist

This sets level.flags.

<flag> as true for the whole level. Note that the flags are not fixed and can be changed over the course of the game: for example, raising the dead with the Book of the Dead sets level.flags.graveyard to true regardless of whether the level was previously a graveyard level.
flaglist is one or more of the following flags, separated by commas:

noteleport: Teleportation within the level is blocked.
hardfloor: The floor is too hard to dig.
nommap: Magic mapping does not work.
arboreal: Supposedly an outdoor map. Solid walls and secret corridors will be shown as trees, digging makes floor instead of corridor and randomly created corridors are made out of floor instead of corridor.
shortsighted: Monsters cannot see you from far away.
mazelevel: Used when a ROOM-type level wants to set the maze level flag to be treated as a maze level, with the corresponding effects.
premapped: When the player enters the level, it is automatically mapped, including all traps and boulders. This is because it's only used for Sokoban at the moment.
shroud: Unseen locations on the level will not be remembered by the hero, instead of rendering as out-of-sight map, trap, and object glyphs like they normally do. No levels currently use this flag.
graveyard: Treats the level as a graveyard level (causes graveyard sounds and undead have a reduced chance of leaving corpses).
icedpools: Ice generated with the level will be treated as frozen pools instead of frozen moats.
solidify: Areas outside the specified level map are made undiggable and unphaseable. (Examples: Vlad's Tower, Sokoban, the Astral Plane)
corrmaze: If the level is a maze (not a maze-type level, an actual maze), the maze uses corridor tiles instead of floor tiles and solid rock instead of walls. Randomly generated mazes have a 1/3 chance of having corrmaze set.
inaccessibles: If inaccessible areas are generated, generate ways for them to connect to the "accessible" area. This tries first to create a secret door connecting it to the accessible area; if that fails it tries to create a hole or trapdoor; if that fails it tries to create an escape item (teleport items or digging tools). This code is not used for inaccessible closets, which always get a scroll of teleportation.
Example:

FLAGS:noteleport,hardfloor,graveyard

INIT_MAP
INIT_MAP:'X', 'Y', smoothed, joined, lighted, walled

This causes the level map to be initialized with a random map generator, similar to how the random Gnomish Mines look like.
Each MAZE-level can contain only 0 or 1 of these definitions.

'X' is the "foreground" fill map character. This should be something the player can walk on, as the walkable part will be made out of this.
'Y' is the "background" fill map character. This will surround the foreground area, so can be solid or harmful to player.
smoothed is either true or false, and denotes whether the level will be "smoothed". This means that any foreground character surrounded by fewer than 3 foreground characters is changed to background character.
joined is either true or false, and denotes whether the level will be "joined", so that all parts are accessible by walking.
lighted is either lit, unlit, or random
walled is either true or false. This is equivalent of using a WALLIFY -command.
Examples:

INIT_MAP: 'L', '.', false, false, unlit, false
INIT_MAP: '.', ' ', true, true, random, true

MESSAGE
MESSAGE:"string"

You can have 0 or more of these per special level. Each message line gets separated with a --more-- -prompt in the game.
"string" is any message you want player to see when entering the level.
Example (actual source from the Plane of Earth):

MAZE:"earth",' '
FLAGS: noteleport,hardfloor,shortsighted
MESSAGE: "Well done, mortal!"
MESSAGE: "But now thou must face the final Test..."
MESSAGE: "Prove thyself worthy or perish!"

NOMAP
NOMAP

Instead of GEOMETRY and MAP, you use this if you think that INIT_MAP creates a good enough random map and you don't want to use any fixed map-parts.
See also MAP

GEOMETRY
GEOMETRY:xadj,yadj

This must be followed by a MAP definition, and tells the approximate position of the following MAP-part on the level.

xadj is one of left, half-left, center, half-right, right or random
yadj is one of top, center, bottom or random
Example:

GEOMETRY:left,top

MAP
MAP
...
...
...
ENDMAP

This must be preceded by GEOMETRY definition.
You define a map-part by "drawing" with map characters between the MAP and ENDMAP. The map can be up to 21 lines high and each line can be up to 76 chars long. Each line must also be the same length. You can also use numbers inside the map, but those will be ignored; they're considered as line numbers.
See also NOMAP.

NON_DIGGABLE
NON_DIGGABLE:region

Sets the walls inside the region as non-diggable.
Example:

NON_DIGGABLE:(00,00,13,12)

NON_PASSWALL
NON_PASSWALL:region

Players and monsters cannot phase through the walls inside the region
Example:

NON_PASSWALL:(00,00,13,12)

RANDOM_PLACES
RANDOM_PLACES:place,...

With this command you can set up to 10 coordinate-pair registers, which you can access by using place[N] instead of a pair of coordinates in any other command. The registers are shuffled at level creation time.
Example:

RANDOM_PLACES:(23,9),(37,14),(51,9)
OBJECT:'?',"genocide",place[0]

RANDOM_MONSTERS
RANDOM_MONSTERS:'X',...

With this command you can set up 10 monster symbol registers, which you can access by using monster[N] instead of a monster symbol in any other command. The registers are shuffled at level creation time.
Example:

RANDOM_MONSTERS: 'E', 'X'
MONSTER:monster[0],random,(27,05)

RANDOM_OBJECTS
RANDOM_OBJECTS:'X',...

With this command you can set up 10 object class symbol registers, which you can access by using object[N] instead of a object class symbol in any other command. The registers are shuffled at level creation time.
Example:

RANDOM_OBJECTS:'[',')','*','%'
OBJECT:object[0],random,(39,05)

DOOR
DOOR:state,place

Puts a door on the map.

state is one of the following: nodoor, locked, closed, open or random
place is either a pair of coordinates, a RANDOM_PLACES place, or random
Example:

DOOR:locked,(10,5)

DRAWBRIDGE
DRAWBRIDGE:place,dir,state

place is either a pair of coordinates, a RANDOM_PLACES place, or random
dir is one of the following: north, east, south or west
state is one of the following: nodoor, locked, closed, open or random
Note that the drawbridge placement is different from door placement; the coordinates must be a place where the drawbridge would be when it's open, and from that place towards the direction there should be a wall, where the portcullis will be.
Example:

DRAWBRIDGE:(25,18), north, closed

REGION
REGION:(x1,y1,x2,y2), lighted, "type"

Define a region on the map with certain light-state and type.

lighted is one of lit, unlit or random.
"type" is one of the room types.
You can add filled or unfilled, it will denote whether the room will get stocked with the normal monsters or objects it would get. After that you can add true or false to denote whether the room is irregularly shaped. If the room is irregular, only the first pair of coordinates (x1,y1) must be inside the room, and the room must be closed off from other areas with non-floor map characters. Use the boundary symbol 'B' in the MAP to enclose an irregular room; it will be converted to floor symbol '.' after the level has been created.
Examples:

REGION:(43,12,49,16),unlit,"ordinary"
REGION:(12,01,20,09),unlit,"morgue",unfilled
REGION:(11,03,29,10),lit,"temple",filled,true

STAIR-region
STAIR:(x1,y1,x2,y2), (x3,y3,x4,y4), updown

Places a stair within an area covered by (x1,y1,x2,y2) and not covered by (x3,y3,x4,y4).

updown is either up or down, denoting the direction of the stairs.
If the area is prefixed with levregion then the coordinates are relative to the whole level, otherwise the coordinates are relative to the last-defined MAP.
Example:

STAIR:(0,0,79,20), (20,5,50,15), up
STAIR:levregion(01,0,79,20), (0,0,28,12), up
STAIR:(0,0,50,10), levregion(10,0,20,15), down

PORTAL
PORTAL:(x1,y1,x2,y2), (x3,y3,x4,y4),"levelname"

Places a magical portal within an area covered by (x1,y1,x2,y2) and not covered by (x3,y3,x4,y4). The portal will level teleport player to the level with the name "levelname".
If the area is prefixed with levregion then the coordinates are relative to the whole level, otherwise the coordinates are relative to the last-defined MAP.
Example:

PORTAL:levregion(57,01,78,19),(0,0,0,0),"fire"
PORTAL:(0,0,75,19),(65,13,75,19),"air"

TELEPORT_REGION
TELEPORT_REGION:(x1,y1,x2,y2),(x3,y3,x4,y4)

Restricts the area where player can end up on the level when he level teleports or falls in there. Player will end up within an area covered by (x1,y1,x2,y2) and not covered by (x3,y3,x4,y4).
If the area is prefixed with levregion then the coordinates are relative to the whole level, otherwise the coordinates are relative to the last-defined MAP.
You can also add an optional direction parameter, either up or down, which will tell when this rule is applied; when player is coming from below or above.
Example:

TELEPORT_REGION:(69,16,69,16),(0,0,0,0)
TELEPORT_REGION:levregion(56,00,79,20),levregion(01,00,55,20),down

BRANCH
BRANCH:(x1,y1,x2,y2),(x3,y3,x4,y4)

Places stairs or a magical portal to a dungeon branch within an area covered by (x1,y1,x2,y2) and not covered by (x3,y3,x4,y4).
If the area is prefixed with levregion then the coordinates are relative to the whole level, otherwise the coordinates are relative to the last-defined MAP.
Example:

BRANCH:levregion(51,2,77,18),(0,0,40,20)

MAZEWALK
MAZEWALK:place,dir

Creates a random maze, starting from place.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
dir is one of the following: north, east, south or west
Mazewalk turns map grids with solid stone (' ') into floor ('.'). From the starting position, it checks the mapgrid in the direction given, and if it's solid stone, it will move there, and turn that place into floor. Then it will choose a random direction, jump over the nearest mapgrid in that direction, and check the next mapgrid for solid stone. If there is solid stone, mazewalk will move that direction, changing that place and the intervening mapgrid to floor. Normally the generated maze will not have any loops.
For example

MAP
TTTTTTT
T T T T
TTTTTTT
T T T T
TTTTTTT
ENDMAP

Pointing mazewalk at that will create a small maze of trees, but unless the map (at the place where it's put into the level) is surrounded by something else than solid stone, mazewalk will get out of that MAP.  Substituting floor characters for some of the trees "in the maze" will make loops in the maze, which are not otherwise possible. Substituting floor characters for some of the trees at the edges of the map will make maze entrances and exits at those places.
If the total area NOT covered by all maze-parts in the level is greater than 1/10 of the total area of the level, then the mazes in the level will get stocked with maze-specific stuff, such as minotaurs, traps and items, proportionally to the amount of space not covered by MAPs.
Mazewalk will only work if the solid stone mapgrids in the level (where the MAP was put down) are on odd-numbered squares, both horizontally and vertically. You don't have to worry about this unless your MAP is 21 rows high or 76 columns wide, in which case you'll have to either make the MAP smaller, or move the places where the solid stone squares are.
Also, MAZEWALK will fail in certain types of MAP-parts if you also use WALLIFY, as that command is applied before MAZEWALKs.
Example:

MAZEWALK:(00,06),west

WALLIFY
WALLIFY

Turns walls completely surrounded by other walls into solid stone ' '.

LADDER
LADDER:place, updown

Places a ladder up or down at the given place. See also STAIRS.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
updown is either up or down, denoting the direction of the stairs.
Example:

LADDER:(11,05),down

GOLD
GOLD:place, amount

Places amount of gold in place.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
amount is any positive integer number.
Example:

GOLD:(5,5),12345

ROOM-type levels
Room-type levels begin with LEVEL, followed by optional FLAGS, optional INIT_MAP, 0 or more MESSAGEs, followed by optional random register initializers (RANDOM_MONSTERS and RANDOM_OBJECT), followed by 0 or more ROOM and SUBROOM definitions (and the contents for those rooms), followed by RANDOM_CORRIDORS.
That is:

LEVEL
FLAGS, optional
INIT_MAP, optional
MESSAGE, 0 or more
RANDOM_MONSTERS, optional
RANDOM_OBJECTS, optional
ROOM, 0 or more
contents for the room (monsters, objects, traps, etc.)
SUBROOM, 0 or more
contents for the subroom (monsters, objects, traps, etc.)
RANDOM_CORRIDORS
It's not possible to define arbitrarily shaped rooms with this type of level.

LEVEL
LEVEL: "name"

"name" is the unique file name for this level. Can be up to 8 chars long. This file name is defined by the way this level is defined in dungeon.def.
Example:

LEVEL: "oracle"

RANDOM_CORRIDORS
RANDOM_CORRIDORS

Creates random corridors between the rooms in the level, so that all rooms are accessible.

ROOM
ROOM: "type" [chance], lighted, pos, align, size

Creates a room. The room will be placed on a position defined both by pos and align. pos defines the rough position (in a 5-by-5 grid on the screen), and align defines the room position within that. NOTE: Creation of a randomly located room may fail, especially if there's little free space to fit it on the level. Contents of such a room won't be created either.

"type" is one of the room types, in double quotes.
chance is optional; if type is something other than "ordinary", this represents the chance (in percent) that the room will actually be generated as this special room type. Otherwise it will be an ordinary room.
lighted is one of lit, unlit or random.
pos is either random or (xpos, ypos), where both xpos and ypos are between 0 and 5. This is an approximate position.
align is either random or (xalign, yalign) and is the room alignment within the pos.
xalign is one of left, half-left, center, half-right, right or random
yalign is one of top, center, bottom or random.
size is either random or (width, height).
You can also give one additional parameter, which can either be true or false. This tells whether the room will get stocked by objects and monsters it would normally get (such as shopkeepers and items for sale for shops).
Example:

ROOM: "ordinary", random, random, random, random
ROOM: "ordinary", lit, (3,3), (center,center), (11,9)

SUBROOM
SUBROOM: "type", lighted, pos, size, "parent"

Creates a room inside previously defined ROOM.

"type" is one of the room types.
lighted is one of lit, unlit or random.
pos is either random or (xpos, ypos), where xpos and ypos define the absolute position of this subroom inside the parent room. (0,0) is the upper left corner of the parent.
size is either random or (width, height).
"parent" is the name of the parent room, as defined with NAME.
You can also give one additional parameter, which can either be true or false. This tells whether the room will get stocked by objects and monsters it would normally get (such as shopkeepers and items for sale for shops).
Example:

SUBROOM:"shop",lit,(10,10),(3,3),"town"
SUBROOM:"ordinary",random,(19,2),(2,2),"town"

NAME
NAME: "string"

Names the previously defined ROOM or SUBROOM. Subrooms need to know the name of their parent room, this has no other meaning.
Example:

NAME: "town"

CHANCE
CHANCE: int

Assigns a creation chance to the previously defined ROOM or SUBROOM. The room walls and doors will get created no matter what, this just tells whether the room contents will be created. int should be in the 0-100 range. Only non-ordinary rooms can have this.
Example:

CHANCE: 90

Room DOOR
DOOR: secret, state, wall, pos

Creates a door with certain state on the previously defined ROOM or SUBROOM. Note that Room DOOR format is different from MAZE-level DOOR.

secret can be true, false or random
state is one of the following: nodoor, locked, closed, open or random
wall is one of the following: north, east, south or west and tells on what wall of the room the door will be created.
pos is either random or a positive integer, and tells how far from top or left the door will be.
Example:

DOOR: false, closed, south, random

Common syntax
The following commands are common to both MAZE and ROOM-type levels. For the MAZE levels, the coordinates used are the previously defined MAP, for ROOM-levels, it's either the previously defined ROOM or SUBROOM.

ALTAR
ALTAR:place,align,type

Places an altar in the previously defined map or ROOM or SUBROOM.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
align is either noalign, law, neutral, chaos, coaligned, noncoaligned, random or an alignment register align[N], where N can be either 0,1 or 2.
type is one of sanctum, shrine, altar or random
Example:

ALTAR:(50,14),chaos,altar
ALTAR:place[0],noalign,altar
ALTAR:(07,09),align[0],sanctum

CONTAINER
This defines a container that you can put items in. It accepts exactly the same parameters as OBJECT. Normal content generation for this object is suppressed.
Example:

CONTAINER:('(',"chest"),(5,5){
OBJECT:('/',"wishing") }

ENGRAVING
ENGRAVING:place, type, "text"

Creates an engraving on the floor.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
type is one of dust, engrave, burn, mark or random. mark is the type used for graffiti.
"text" is the text engraved on the floor.
Example:

ENGRAVING:(12,03), engrave, "You are now entering the Gnome King's wine cellar."

FOUNTAIN
FOUNTAIN:place

Places a fountain on the map.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
Example:

FOUNTAIN:(10,08)

GRAVE
GRAVE:place,message

Places a headstone on the map.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
message is either a string which will be the epitaph on the grave, random (to place a random epitaph), or it can be left off entirely, in which case the grave will be blank.
Examples:

GRAVE:(10,18),"Epitaph goes here"
GRAVE:(10,18),random
GRAVE:(10,18)

MONSTER
MONSTER:'X',"monst",place

'X' is the monster class symbol, or random, or a RANDOM_MONSTERS index
"monst" is the specific monster, or random
place is either a pair of coordinates, a RANDOM_PLACES place, or random
Other things you can add to the monster definition:

hostile or peaceful
asleep or awake
For mimics and other shapechangers you can also add the following:
m_feature "dungeon_feature" to force the mimic to be a dungeon feature.
m_object "object_name" to force the mimic to be an object. object_name is the name of an object as they are in objects.c
m_monster "monster_name" to force the shapechanger to be a certain monster.
"Name" to name the monster.
Optionally, you can put [NN%] right after MONSTER to make the monster generation optional. NN is a percentage chance of the monster being generated when the level is created.
Examples:

MONSTER:'v',"dust vortex",(42,05)
MONSTER:'E',"earth elemental",(39,06),peaceful
MONSTER:'&amp;',"Pestilence",place[0],hostile
MONSTER:random,random,random
MONSTER:random,random,(01,01), asleep
MONSTER:monster[0],random,(27,05)
MONSTER:'m',"giant mimic",place[1],m_feature "fountain"
MONSTER:'m',random,place[0], m_object "luckstone"
MONSTER:'@',"rogue",(35,06),peaceful,"Pug"
MONSTER[50%]:'P', "green slime", random

OBJECT
OBJECT:('X',"name"),place

Each map-part can contain any number of object definitions.

'X': a character denoting one of the object classes.
"name": either an object name as listed in objects.c, or random
place: either a pair of coordinates, a RANDOM_PLACES place, or random, or contained. If contained, then this object will be placed in the previously defined CONTAINER.
Optional stuff you can add to the object definition:

cursestate, "monster_id", spe
cursestate, spe
"monster_id", spe
name:"name_given_object"
quantity:int
Where

cursestate is one of blessed, uncursed, cursed or random.
"monster_id" is a monster type, as defined in monst.c
spe is an integer, and defines different things depending on what kind of object is generated:
enchantment for armor and weapons
charges for wands, rings, magic markers and everything else that has charges.
historic and gender bit for statues. 1 is historic, 2 is male, 4 is female. Adding the values together is possible, so you can create eg. historic, male statue with value 3 and historic, female with 5. Leaving the gender specification out will either result in a random gender, or if the monster is always of certain gender, then the statue will be that gender too. (eg. nymphs)
tins: 1 means spinach, -1 is home-made.
containers: 1 means the box contains Shroedinger's cat.
oil lamps and candles: 0 means the lamp is out of oil.
Candelabrum: how many candles are attached to it.
scroll of mail: 1 means it was not delivered to current player.
eggs: 1 means hero laid it.
chests: 2 means it's a royal coffer in a throne room.
name:"name_of_object" gives the object a name as though the #name command had been used.
quantity:int specifies the quantity of objects just defined to be created.
Optionally, you can put [NN%] right after OBJECT to make the object generation optional. NN is a percentage chance of the object being generated when the level is created.
Examples:

OBJECT:('%', "food ration"), random
OBJECT:('*', random), (10,10)
OBJECT:'?', "genocide", place[0]
OBJECT[10%]:('"', "amulet of life saving"), random
OBJECT:('%', "corpse"), random, "archeologist", 0
OBJECT[50%]:(')', "scimitar"), contained, blessed, +2
OBJECT:'`', "statue", (0,0), "forest centaur", 1
OBJECT:('(', "crystal ball"), (17,08), blessed, 5,name:"The Orb of Fate"
OBJECT:('%',"egg"), (05,04), montype:"yellow dragon"

SINK
SINK:place

Places a sink on the map.

place is either a pair of coordinates, a terrain selection, or random.
STAIR
STAIR:place, updown

Places a stair up or down at the given coordinates. See also STAIR-region and LADDER.

place is either a pair of coordinates, a RANDOM_PLACES place, or random
updown is either up or down, denoting the direction of the stairs.
Example:

STAIR:(70,08), up
STAIR:random, down
STAIR:place[3], up

TRAP
TRAP:"name",place

"name" is the trap's name, or random
place is either a pair of coordinates, a RANDOM_PLACES place, or random
Optionally, you can put [NN%] right after TRAP to make the trap generation optional. NN is a percentage chance of the trap being generated when the level is created.
Examples:

TRAP:"hole",(12,10)
TRAP:"anti magic",random
TRAP:random,random
TRAP[25%]:"polymorph",random

Map characters

character

dungeon feature

' '

solid wall

'#'

corridor

'.'

room floor (Unlit, unless lit with REGION-command)

'-'

horizontal wall

'|'

vertical wall

'+'

door (State is defined with DOOR -command)

'A'

air

'B'

crosswall / boundary symbol hack (See REGION)

'C'

cloud

'S'

secret door

'H'

secret corridor

'{'

fountain

'\'

throne

'K'

sink

'}'

moat

'P'

pool of water

'L'

lava pool

'I'

ice

'W'

water

'T'

tree

'F'

iron bars

Trap names
"anti magic", "arrow", "bear", "board", "dart", "falling rock", "fire", "hole", "land mine", "level teleport", "magic portal", "magic", "pit", "polymorph", "rolling boulder", "rust", "sleep gas", "spiked pit", "statue", "teleport", "trap door", "web"

Room types
"ordinary", "throne", "swamp", "vault", "beehive", "morgue", "barracks", "zoo", "delphi", "temple", "anthole", "cocknest", "leprehall", "shop", "armor shop", "scroll shop", "potion shop", "weapon shop", "food shop", "ring shop", "wand shop", "tool shop", "book shop", "candle shop"

See also
Des-file format (NetHack 3.4.3)
Des-file format (UnNetHack)

This page may need to be updated for the current version of NetHack.
It may contain text specific to NetHack 3.6.0. Information on this page may be out of date.
Editors: After reviewing this page and making necessary edits, please change the {{nethack-360}} tag to the current version's tag or {{noversion}} as appropriate.

</flag>