Wikihack
Register
Advertisement

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. For ROOM-type levels, you describe rooms and their contents. 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.

Language syntax[]

All lines beginning with # are comments and are ignored by the level compiler, except between MAP and ENDMAP.

Example:

# This is a comment.

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:

Example:

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

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

flaglist is one or more of the following flags, separated by commas

  • noteleport: Player cannot teleport within the level.
  • 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.

Example:

FLAGS:noteleport,hardfloor

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:

MESSAGE: "Well done, mortal!"

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 registers, which you can access by using place[N] instead of a coordinate 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 coordinate, a RANDOM_PLACES place, or random

Example:

DOOR:locked,(10,5)

DRAWBRIDGE[]

DRAWBRIDGE:place,dir,state
  • place is either a coordinate, 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 coordinate 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 coordinate (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 coordinate, 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 note that 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.

Note that 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 note that 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 coordinate. See also STAIRS.

  • place is either a coordinate, 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 coordinate, 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:

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", 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.
  • 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 coordinate on the screen.
  • 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 on the previously defined map or ROOM or SUBROOM.

  • place is either a coordinate, 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",contained

ENGRAVING[]

ENGRAVING:place, type, "text"

Creates an engraving on the floor.

  • place is either a coordinate, a RANDOM_PLACES place, or random
  • type is one of dust, engrave, burn, mark or random.
  • "text" is the text to engrave 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.

Example:

FOUNTAIN:(10,08)

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 coordinate, 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:'&',"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 coordinate, 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

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.

After these you can also add a quoted string, which would become the object's name.

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, "The Orb of Fate"

STAIR[]

STAIR:place, updown

Places a stair up or down at coordinate. See also STAIR-region and LADDER.

  • place is either a coordinate, 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

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"

Advertisement