summaryrefslogtreecommitdiffstats
path: root/crawl-ref/docs/level_design.txt
diff options
context:
space:
mode:
authordploog <dploog@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-20 21:14:03 +0000
committerdploog <dploog@c06c8d41-db1a-0410-9941-cceddc491573>2008-03-20 21:14:03 +0000
commit0c537338e73735c2e869e3d7c20e4aa9631780df (patch)
treeaa0a81e5128dfdf0cc38c0bdf9f775be1392a049 /crawl-ref/docs/level_design.txt
parent5efa2c8d72281546295d159f8916c6598ad7291e (diff)
downloadcrawl-ref-0c537338e73735c2e869e3d7c20e4aa9631780df.tar.gz
crawl-ref-0c537338e73735c2e869e3d7c20e4aa9631780df.zip
Fixed readme.txt.
Renamed level-design.txt to level_design.txt. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3764 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/docs/level_design.txt')
-rw-r--r--crawl-ref/docs/level_design.txt1381
1 files changed, 1381 insertions, 0 deletions
diff --git a/crawl-ref/docs/level_design.txt b/crawl-ref/docs/level_design.txt
new file mode 100644
index 0000000000..e4acab6d6a
--- /dev/null
+++ b/crawl-ref/docs/level_design.txt
@@ -0,0 +1,1381 @@
+How to make levels for Dungeon Crawl Stone Soup
+===============================================
+
+Contents: A. Introduction
+ B. Sample map
+ C. Map symbols
+ D. Header information
+ E. Conditionalising levels
+ F. Validating levels
+ G. Hints for level makers
+ H. Lua reference
+ I. Feature names
+ J. Map statistics
+ K. Portal vaults
+
+A. Introduction
+-----------------
+
+All fixed level information resides in various .des files to be found in
+the dat directory. If you are interested in adding some vaults, say, start
+with the existing ones and modify them. Currently, the following .des files
+are in use:
+
+ bazaar.des - entrances to bazaar portal vaults, and bazaars proper
+ crypt.des - Crypt:5, Tomb:1, Tomb:2, Tomb:3
+ elf.des - Elf:7
+ entry.des - entry vaults (each game - but not tutorial games - uses one of
+ these premade maps for the vicinity of the entrance)
+ float.des - floating vaults
+ hells.des - hell entrances, Geryon's vestibule, Coc:7, Tar:7, Dis:7, Geh:7
+ hive.des - hive entrances, Hive:4
+ lab.des - labyrinths exits and flavour vaults
+ lair.des - lair entrances, Shoals:5, Swamp:5, Snake:5, Slime:6
+ large.des - all regular vaults which have ORIENT:encompass/northwest etc.
+ mini.des - minivaults (no ORIENT line at all)
+ orc.des - orcish mine entrances, orc only vaults
+ pan.des - vaults of the Pan demon lords, Pan minivaults
+ portal.des - portal vaults entrances
+ temple.des - Ecumenical Temples, and Temple entrances
+ vaults.des - entrances for the Vaults, and Vaults:8
+ zot.des - Zot:5
+
+
+Kinds of Vaults
+---------------
+The different kinds of vaults used by Crawl are described briefly below. In
+most cases, when the dungeon builder places a vault on a level, the rest of the
+level (assuming the vault is not a full-map vault) is generated as
+rooms+corridors. The only exceptions to this are branch entry vaults and
+minivaults, both of which are placed after the rest of the level is generated,
+and therefore do not influence level generation.
+
+* Entry vault:
+
+A map designed for D:1, which (usually) contains the primary upstair { and is
+always tagged "entry". A player starting a new game will usually land in an
+entry vault.
+
+
+* Branch entry vault, or branch portal vault:
+
+A map containing the entry to a branch - either a branch stair (such as the
+stair to the Orcish Mines), or a branch portal (a portal to Hell, say). Always
+tagged "<branchname>_entry".
+
+
+* Special level:
+
+A map for a location of significance in the game, such as the Ecumenical
+Temple, or the end of branches such as level 5 of the Snake Pit (Snake:5).
+Special level maps usually have a PLACE: attribute.
+
+
+* Random vaults:
+
+Random vaults may be randomly generated at any level in the dungeon. Random
+vault maps are selected by the dungeon builder based on their DEPTH:
+attributes.
+
+
+* Random minivaults:
+
+Random minivaults are small maps that are placed onto a level that the
+dungeon builder has already constructed fully otherwise (the level may
+include other vaults).
+
+Minivaults are distinguished from normal vaults solely by the absence
+of an ORIENT: declaration. Any map without a specified ORIENT: is a
+minivault.
+
+
+B. Sample Map
+---------------
+
+Before going into the technical details of the level-file syntax,
+let's look at an example - a branch entry for the Ecumenical Temple -
+to see what a map definition looks like.
+
+# name below:
+NAME: a_useless_temple_entry_02
+# header section below:
+ORIENT: float
+CHANCE: 5
+TAGS: temple_entry
+FLAGS: no_rotate
+SHUFFLE: de
+SUBST: 1=12.
+MONS: butterfly, plant
+ITEM: stone, w:10 any book / w:90 nothing
+# actual map below:
+MAP
+xx1@2xx
+x1wWw2x
+ewwOwwd
+x2www1x
+xx1.1xx
+ENDMAP
+
+Every map consists of a name, a header and the actual map (the order
+is not important as long as the name comes first, but stick to this
+order for consistency).
+
+Lines starting with # are comments. The keywords available are
+explained briefly after the example map and in detail in the following
+sections.
+
+"ORIENT: float" tells the level builder that this entry can be anywhere on the
+ level; other ORIENT: values can force a map to one edge of the
+ level.
+"CHANCE: 5" makes the map appear less often (default is 10).
+"TAGS: temple_entry" turns the 'O' on the map into stairs to the Temple.
+"FLAGS: no_rotate" forbids rotation (but mirroring is still allowed).
+"SHUFFLE: de" may replace all 'd' with 'e' in the map.
+"SUBST: 1=12." may replace each '1' with either '1' or '2' or '.'.
+"MONS: butterfly, plant" turns all '1' into butterflies, and '2' into plants.
+"ITEM: stone" turns all 'd' into stones.
+"ITEM: w:10 any book / w:90 nothing" turns all 'e' into a book
+ (with 10% chance) or creates no object (with 90% chance).
+
+The symbols on the map:
+ x - rock wall
+ w - water (could be deep or shallow)
+ W - shallow water
+ . - plain floor
+ @ - entry point (this square will be connected to the rest of the map)
+ O - stairs to the Temple
+ 1 - first monster from the list (here butterfly) - note the SUBST: 1=12.
+ 2 - second monster from the list (plant)
+ d - first item from the list (here stones)
+ e - second item from the list (here occassionally a book)
+
+
+D. Map symbols
+----------------
+
+Terrain
+-------
+ x - rock wall (DNGN_ROCK_WALL)
+ X - permanent rock wall - always undiggable (DNGN_PERMAROCK_WALL)
+ c - stone wall - only affected by Shatter (DNGN_STONE_WALL)
+ m - clear rock wall (DNGN_CLEAR_ROCK_WALL)
+ n - clear stone wall - only affected by Shatter (DNGN_CLEAR_STONE_WALL)
+ o - clear permanent rock wall - always undiggable (DNGN_CLEAR_PERMAROCK_WALL)
+ v - metal wall - grounds electricity (DNGN_METAL_WALL)
+ b - crystal wall - reflects cold and fire (DNGN_GREEN_CRYSTAL_WALL)
+ a - wax wall - can melt (DNGN_WAX_WALL)
+
+ . - floor (DNGN_FLOOR)
+ + - closed door (DNGN_CLOSED_DOOR)
+ = - secret door (DNGN_SECRET_DOOR)
+
+ W - shallow water
+ w - deep water - can be randomly turned into shallow water by the
+ level-builder; you can prevent this conversion with the no_pool_fixup TAG.
+ Also, water may automatically receive water creatures! For entry
+ vaults, avoid this with the no_monster_gen TAG or KMASK.
+ l - lava - again, use the no_monster_gen TAG or KMASK for entry vaults!
+
+Features
+--------
+ @ - entry point - must be on outside edge. If you use ORIENT: float, and do
+ not use any @, the dungeon builder will connect at least one floorspace on
+ the edge of your map to the rest of the level; if there is no floorspace
+ on the edge of your map, it will be isolated.
+ }{ - Stone stairs - You must be able to reach these from each other. The
+ { upstair is also the stair on which the player will enter the
+ dungeon for entry vaults.
+ )( - Stone stairs, set 2.
+ ][ - Stone stairs, set 3.
+
+ >< - escape hatches - you can leave the level by these but will usually
+ not land on stairs/hatches
+
+ I - orcish idol (does nothing)
+
+ ^ - random trap.
+ ~ - random trap suitable for the branch and depth the map is being used.
+
+ A - Vestibule gateway (opened by Horn).
+ B - Altar. These are assigned specific types (eg of Zin etc) in dungeon.cc,
+ in order.
+ C - Random Altar.
+
+ F - Usually a Granite Statue, but may be Orange or Silver or Ice (1 in 100)
+ G - Granite statue (does nothing) - you can see through but not walk through.
+ Also, sight-based effects like smiting work past granite statues, as does
+ apportation.
+
+ T - Water fountain
+ U - Magic fountain
+ V - Permanently dry fountain
+
+Note: Due to the level maker having seen incremental improvements over
+the years, there are some inconsistencies. For examples, dangerous
+statues (orange, silver, ice) are now genuine monsters. In particular,
+the 'H' and 'S' glyphs should be dispensed with (but many older vaults
+use them, of course) - especially as there's no glyph for ice statues.
+
+Also, the most of the other feature glyphs can be replaced with KFEAT:
+lines. The same goes for some item glyphs ('R', 'Z') which
+could be replaced by KITEM: lines.
+
+Items
+-----
+ $ - gold
+ % - normal item
+ * - higher level item (good)
+ | - acquirement-level item (almost guaranteed excellent)
+ O - place an appropriate rune here. For portal vaults, place the portal here.
+ P - maybe place a rune here (50%)
+ R - honeycomb (2/3) or royal jelly (1/3)
+ Z - the Orb of Zot
+ d-k - item array item. See section below on ITEM: arrays for more info.
+
+Monsters
+--------
+ 0 - normal monster
+ 9 - +5 depth monster
+ 8 - (+2) * 2 depth monster (aargh!). Can get golden dragons and titans
+ this way.
+ 1-7 - monster array monster. See section below on MONS: arrays for more
+ information
+
+
+D. Header information
+-----------------------
+
+(All declarations apart from NAME: are translated to Lua function
+calls behind the scenes. See the Lua reference for more information.)
+
+NAME: a_string
+ Each map must have a unique name. Underscores and digits are ok.
+
+ORIENT: (float |encompass | north | northwest | ... | southeast)
+
+ Some kind of ORIENT: line is mandatory for vaults; skipping
+ ORIENT: makes your map a minivault. As a rule of thumb, if
+ you're writing a small random map, skip the ORIENT: line and
+ make it a minivault. For special levels and (branch) entry
+ vaults, you do need an ORIENT: line.
+
+ * "float": The dungeon builder puts your vault wherever it wants to.
+ * "some_direction": The vault lies along that side of the map:
+ xxxxxxxxxx xxxxxxxxxxxxx
+ xORIENT:Nx xORIENT:NW|..
+ x.VAULT..x x.VAULT...|..
+ x--------x x---------|..
+ xrest....x xrest........
+ x...of...x x.....of.....
+ x...levelx x.......level
+ ...which brings us to padding. With any some_direction orientation,
+ you need 6 layers of x-padding along any level-edge that the vault
+ borders. For instance, if your map is ORIENT: north, you must have a
+ 6 deep border of rock wall (or any other kind of wall) along the
+ northern, eastern, and western edges of the map.
+ * "encompass": the vault completely occupies the entire level.
+ Padding is needed on all 4 sides.
+
+ ORIENT: float vaults need no padding and give a lot of
+ flexibility to the dungeon generator; float should generally
+ be preferred to other ORIENT: settings for new vaults.
+
+
+DEPTH: For random vaults, branch entry vaults, and minivaults, this
+ specifies the range of levels where the vault may be placed
+ in the dungeon. E.g.
+
+ DEPTH: 7-20
+
+ DEPTH: does not force a map to be placed in a particular place; it
+ applies only when the dungeon builder is looking for a random vault
+ or minivault, so you can control at what depths your vault gets
+ placed.
+
+ A simple DEPTH: declaration that does not specify a branch
+ applies to all branches. A map declared with depth 7-20 could
+ be used in the Lair, for instance. (Lair:1 will be treated as
+ a depth of 12 if the Lair entrance is on D:11.)
+
+ You can constrain a map by branch:
+
+ DEPTH: Lair:7-9
+
+ (Anywhere between levels 7-9 of the Lair, inclusive.)
+
+ You can apply multiple constraints in one DEPTH line,
+ comma-separated:
+
+ DEPTH: 7-20, !12-14
+
+ (Anywhere in the dungeon between depths 7-20, but not on levels
+ 12-14.)
+
+ DEPTH: 7-20, !Orc
+
+ (Anywhere in the dungeon between depths 7-20, but never in the Orcish
+ Mines.)
+
+ DEPTH: Lair:*
+
+ (Anywhere in the Lair. Can also be expressed as "DEPTH: Lair".)
+
+ Maps that do not specify a DEPTH: attribute will inherit their depth
+ constraints from the closest preceding default-depth: line. If there
+ is no preceding default-depth directive in the .des file, the map will
+ have no DEPTH: constraint. Note that maps without a DEPTH: constraint
+ cannot be selected as random vaults or minivaults.
+
+CHANCE: (number with 10 being default)
+ For entry vaults and any other vaults randomly picked from among
+ a set, this type of line affects the likelihood of the given vault
+ being picked in a given game. The default CHANCE: is 10. The
+ likelihood of a vault getting picked is:
+ [vault's CHANCE: / sum of all CHANCE:s of vaults of that type]
+
+PLACE: Used to specify certain special levels. Existing special levels are:
+ Temple, Hell, Dis:7, Geh:7, Coc:7, Tar:7, Hive:4, Vault:8, Snake:5,
+ Elf:7, Slime:6, Blade, Zot:5, Tomb:1, Tomb:2, Tomb:3, Swamp:5.
+
+ PLACE can also be used to specify arbitrary places, like D:3, which
+ will force the map (or one of the maps with PLACE: D:3) to be picked
+ when D:3 is generated.
+
+ PLACE cannot be used to specify places in the Abyss, Pandemonium,
+ or Labyrinths.
+
+ PLACE can be used with random vaults and minivaults for testing them.
+
+TAGS: Tags go an a TAGS: line and are space-separated. Valid tags are:
+ * "allow_dup": Vaults are normally used only once per game. If you
+ have a vault that can be used more than once, use allow_dup to tell
+ the dungeon builder that the vault can be reused.
+ * "dummy": this tag indicates that the vault is a stub; if the dungeon
+ builder picks a dummy vault, it pretends no vault was selected.
+ Dummies are used to reduce the probability of other vaults at the
+ same depth / place.
+ * "entry": this tag MUST be there for a vault to be pickable as an
+ entry vault.
+ * "generate_awake": Monsters placed (using MONS, KMONS) in this vault
+ will be generated awake.
+ * "no_item_gen": Prevents random item generation in the vault.
+ Items explicitly placed by the vault are not affected.
+ * "mini_float": applicable only to minivaults, requests that
+ the dungeon builder pick random exits from the minivault and
+ connect it to the rest of the level, similar to the exit behaviour
+ for floating vaults.
+ * "no_monster_gen": Prevents random monster generation at the time of
+ the vault's creation. Highly advised for entry vaults with a
+ player-hostile geography, MUST-HAVE for those with water/lava.
+ Can be applied only to particular symbols with KMASK.
+ * "no_pool_fixup": prevents water squares next to land from being
+ randomly converted from deep water (the default) to shallow.
+ * "branch_entry" eg. "orc_entry", "lair_entry" etc.
+ If chosen, these maps will contain the stairs for that
+ branch. Use "O" to place the stairs. If a branch has very
+ few entries, a dummy entry is advisable to make sure the
+ player doesn't get bored of the same few entries recycled
+ ad nauseam.
+ * "mnoleg" or the name of some other pandemonium lord. This makes
+ the map eligible for said pan lord's lair.
+ * "uniq_BAR": (uniq_ with any suffix) specifies that only one of
+ the vaults with this tag can be used in a game.
+ * "no_rotate": Normally, the dungeon builder can, at its whim,
+ rotate your vault. This flag tells it, "hey, don't do that to my
+ vault!"
+ * "no_hmirror": Like no_rotate, but for horizontal mirroring.
+ * "no_vmirror": Like no_rotate, but for vertical mirroring.
+
+ Pre-0.3 Crawl distinguished between TAGS and FLAGS. 0.3 and
+ newer Crawls treat TAGS and FLAGS as synonyms.
+
+LFLAGS: Persistent, changeable per-level flags which affect game
+ behavior (FLAGS just controls how the vault is placed); should
+ only be used for vaults with ORIENT encompass or with PLACE.
+ This causes a level's flags to be set when the level is first
+ created. These flags can later be altered using Lua markers;
+ see the slime pit vault in lair.des, and the vaults in hell.des
+ and elf.des for examples.
+
+ Valid flags are: no_tele_control, which prevents the player
+ from using teleport control; not_mappable, which prevents
+ the player from remembering where they've been (like in
+ the Abyss), and no_magic_map, which prevents magic mapping
+ from working.
+
+BFLAGS: Persistent, changeable per-*branch* flags which affect game
+ behavior; should only be used for vaults which go on the fist
+ level of a particular branch. These flags can later be altered
+ using Lua markers; see the Tomb vaults in vaults.lua for an
+ example.
+
+ Valid flags are: no_tele_control, which prevents the player
+ from using teleport control; not_mappable, which prevents
+ the player from remembering where they've been (like in
+ the Abyss), and no_magic_map, which prevents magic mapping
+ from working.
+
+FLOORCOL: blue
+ FLOORCOL: allows you to set the floor colour for the level
+ the vault appears in. Should only be used for bazaars and
+ other portal vaults.
+
+ROCKCOL: yellow
+ ROCKCOL: allows you to set the colour of rock walls for the
+ level the vault appears in. Should only be used for bazaars and
+ other portal vaults.
+
+ITEM: (list of items, separated by comma)
+ These are used to help place specified items at specific places
+ within a vault. They create an array with up to 8 positions. What's
+ in the first position in the array will be used when the dungeon
+ builder sees a "d" in the vault definition, the second will be used
+ for "e"s, etc. Positions are comma-separated; several ITEM: lines
+ are possible as well. The following defines letters 'd' - 'g':
+ ITEM: stone, ring mail, meat ration, ring of hunger
+
+ Positions can contain multiple possibilities, one of which the
+ builder will choose randomly. Separate such multiple possibilities
+ using a slash. Note that "nothing" (without the quotes) is a valid
+ possibility. The random choice is done for each individual occurence
+ of the letter. You can also give possibilities a "weight," which
+ affects their chance of being picked. The default weight is 10. You
+ can abbreviate "weight:30" by "w:30". The chance to pick a
+ possibility is
+ [possibility's weight: / sum of all weight:s in that array position]
+
+ For example, the following line makes letter 'd' into a bread ration
+ with 50% chance, or apple or orange with 25% chance each:
+
+ ITEM: bread ration / w:5 apple / w:5 orange
+
+ Modifiers:
+ * "q:N" sets the item quantity to N (if N > 0). Does nothing
+ if the item is not stackable.
+ * "no_uniq" prevents the item from being turned into an artefact.
+ * "good_item" makes the builder try to make the item a good one
+ (acquirement quality).
+ * "level:N" sets the object's item level (can't be used with
+ "good_item"). If set to -2 then the object's item level will
+ be the same as a "*" symbol item (five plus twice the
+ vault's level number).
+ * "any" by itself gives a random choice; you can combine "any" with
+ "good_item."
+ * "any book", "any misc" etc. gives a random item of that class.
+ Valid item class names are: gold, weapon, missile, armour,
+ wand, food, scroll, jewelry, potion, book, staff, orb,
+ misc, carrion. All of these are usable in map definitions,
+ apart from "orb" and "carrion".
+ * "race:race_name", where "race_name" is "elven", "dwarven"
+ or "orcish"; it can also be "none" or "no_race" to prevent
+ the item from being randomly being made racial. Has no effect
+ if the item can't take that kind of racial setting.
+ NOTE: Can result in a non-racial item if used with "any" and
+ the chosen item isn't compatible with the desired race.
+ * "ego:ego_name", where "ego_name" is something like
+ "running", "fire_resistance", and so on; "none" can be used
+ to prevent the item from getting an ego. The item must
+ be fully specified, so trying "any weapon ego:vorpal" or
+ "any armour ego:positive_energy" will result in an error.
+ Trying to give an ego to something which can't accept an
+ ego will also result in an error.
+
+ WARNING: While checks are done to make sure that an armour
+ ego isn't given to a weapon, a weapon ego to a missile,
+ and so on, and also to make sure that egos are only given
+ to amrours, weapons and missiles, no other checking is
+ done. Thus it is possible to create a demonic weapon of
+ holy wrath or a helmet of running.
+
+ Limitations: You can't specify curse status, specificy
+ pluses or number of charges, force a randart or give fixedarts.
+ You also can't lay down corpses, skeletons, or chunks.
+
+MONS: (list of monsters)
+ These are used to help place specific monsters at specific places
+ in a vault. They create an array with up to 7 positions. What's in
+ the first position in the array will be used when the dungeon
+ builder sees a "1" in the vault definition, the second for "2,"
+ etc. Note that if, for example, you place a 3 on the map, but your
+ MONS: line has no third position, the 3 will be filled with
+ RANDOM_MONSTER.
+ You can use weights as for ITEM: lines.
+
+ Individual monsters may be prefixed with the "generate_awake"
+ (without the quotes). Use this sparingly:
+ MONS: generate_awake giant beetle
+
+ Monsters can also be given colours that override their default
+ colour. Use this *very* sparingly:
+ MONS: col:darkgrey fungus
+
+ Note that 8, 9, 0 also place monsters (see the table).
+
+ A monster can be given specific items by following the monster
+ name with a semi-colon and then with an item list as described
+ in ITEM:, but with slashes replaced with pipes and commas replaced
+ with periods. For example:
+ MONS: orc ; katana | quick blade . chain mail | scale mail
+
+ will generate an orc wielding either a katana or a quick blade
+ and wearing either a chain mail or a scale mail. Randarts are
+ never generated, and ego items are only generated if the ego
+ is explicitly stated. Note that any items that the monster was
+ originally generated with will be removed and destroyed. This
+ can be used force a monster to have no items whatsoever:
+ MONS: orc; nothing
+
+ Items given to an orc or an elf will be made orcish or elven
+ unless the item's race type is explicitly set otherwise.
+
+ Limitations: If an item in the item list has alternatives,
+ there's no way to force all monsters dervied from that monster
+ spec to choose the same alternative. If a monster is given
+ a random launcher, there is no way to force the ammo type to
+ match the launcher type.
+
+COLOUR: . = green / blue:5 / red / none
+ COLOUR: allows you to attach explicit colours to any feature.
+ Explicit colours will override the default colour for that
+ feature. The example shown above colours all . (floor) in the
+ map green, blue, red, or unchanged (use the default colour).
+
+ You can use : to specify that all glyphs get the same colour:
+ COLOUR: x : red / blue
+ will colour all rock walls in the map red, or all rock
+ walls blue.
+
+ COLOUR: should be used very sparingly, and only for features
+ where it won't cause confusion (i.e.: never re-colour features
+ like lava!)
+
+SHUFFLE: def, 12/3?
+ This allows you to randomly permute glyphs on the map. There are
+ two ways:
+
+ SHUFFLE: 123w (i.e. list of glyphs, NOT slash-separated)
+ could, for example, swap all occurences of "1" with "2", as well as
+ swapping all "3" with "w" (or any other of the 24 possibilities).
+
+ SHUFFLE: 12/3w (i.e. list of slash-separated blocks of same size)
+ will either do nothing or swap all "1" with "3" and then also swap
+ "2" with "w" everywhere.
+
+ Several SHUFFLE: lines can be used, and mixed with SUBST:, and the
+ shuffles and substitutions will be applied in order. You can also
+ put multiple SHUFFLEs on one line, comma-separated. Shuffles cannot
+ use , or /. All spaces are stripped before shuffling.
+
+SUBST: ?=xc, !:bv, 1=2 1:100
+ The SUBST: directive allows you to specify a placeholder symbol
+ that is replaced with a random glyph from a set. For instance:
+
+ SUBST: ? = TUV
+ replaces occurrences of ? with one of TUV. Since whitespaces are
+ irrelevant, this is the same as
+ SUBST: ? = T U V
+
+ SUBST: ? = T:20 U V
+ makes T twice as likely to be used as U or V (the default weight
+ is 10). Note that there has to be at least one space before and
+ after T:20 and that whitespace in T:20 is not permitted.
+
+ SUBST: ? : TUV
+ replaces occurrences of ? with one of TUV, and guarantees that all
+ occurrences of ? will get the same replacement symbol.
+
+ The placeholder and replacement symbols can be any non-space,
+ printable character, including : and =, apart from commas. For
+ example, the following is valid:
+ SUBST: = = +=:123def"
+
+ SUBST: lines can safely replace symbols with themselves, as in:
+ SUBST: w = wW
+
+ Multiple SUBST: lines can be used, and mixed with SHUFFLE:, and
+ will be applied in order. Multiple substitutions can be performed
+ on one line, using commas.
+
+NSUBST: ? = 3:w / *:l
+
+ NSUBST is similar to SUBST, replacing placeholders with
+ replacement values. Unlike SUBST, however, it allows you to
+ replace different instances of the same placeholder with
+ completely different substitutions. For instance:
+
+ ? = 3:w / *:l
+
+ replaces three occurrences (randomly selected) of ? with w
+ and all others with l.
+
+ You can use complex SUBST specifications:
+
+ ? = 3= w .:15 A / *: =+CF
+
+ This is equivalent to SUBST: ? = w .:15 A for three ? and
+ SUBST: ? : =+CF for all the others.
+
+ You use any number of NSUBST specifiers:
+
+ ? = wW / l / A / 1234
+
+ Each specifier is preceded by the number of symbols to apply
+ it to, followed by : or = (: to use one substitution for all
+ occurrences, = to randomly pick for each occurrence). If you
+ omit the initial N: or N=, then 1= is assumed, except for the
+ last spec where *= is assumed.
+
+KFEAT: Z = C / needle trap / antique armour shop / altar_zin
+ The KFEAT: directive allows you to specify a placeholder symbol
+ that is replaced with another symbol, named feature, trap, or
+ shop. For example, the line above will replace occurrences of Z
+ with C (random altar), a needle trap, an antique armour shop, or
+ an altar of Zin. Different instances of Z may receive different
+ replacements. To force a single replacement for all Z, use:
+
+ KFEAT: Z : C / needle trap / antique armour shop
+
+ You'll notice that 'Z' is the symbol of the Orb of Zot. Kxxx
+ directives allow you to assign arbitrary definitions to any symbol.
+
+ KFEAT features are specified as a feature name (see section I
+ for a full list of feature names). As another example, you can
+ place a portal to the Abyss as:
+
+ KFEAT: A = enter_abyss
+
+ If you want no feature as an option in a KFEAT line, use '.' or
+ 'floor'. If you do not want to specify the type of shop, use
+ 'any shop' or 'random shop'.
+
+ The placeholder used by KFEAT can be shared by KITEM and KMONS;
+ see below. If the placeholder is shared, all defined Kxxxx
+ operations for the placeholder are performed. Also, all Kxxx
+ lines accept weights as for MONS or ITEM.
+
+KMONS: ? = orc priest / w:3 deep elf priest
+
+ KMONS: allows you to specify a placeholder symbol that indicates
+ the position of a monster (or monsters).
+ Using KMONS: allows you to exceed the 7 slot limit for monsters.
+ It is also useful if you want to place a monster on a non-floor
+ square (used in association with a KFEAT:). For example,
+ KFEAT: Z = W
+ KMONS: Z = rat
+ places a rat on a shallow water square for all occurrences of Z.
+
+ KMONS: also allows you to specify alternative monsters if the
+ primary monster you want to place is unavailable (because it
+ is a unique that was already generated). For instance, if you want
+ to generate one of Terence, Michael or Erica or a generic human
+ (whoever is available, in that order, you can use):
+ KMONS: n = Terence, Michael, Erica, human
+ Or if you want to pick randomly:
+ KMONS: n = Terence / Michael / Erica, human
+
+KMASK: Z = no_monster_gen
+
+ KMASK allows you set or unset various masks for particular
+ symbols, rather than for the entire vault like if you did it
+ with TAGS. Valid masks are
+
+ * "no_item_gen": Prevents random item on that symbol. Items
+ explicitly placed on that symbol aren't affected.
+ * "no_monster_gen": Prevents random monster generation on that
+ symbol. MUST-HAVE for those with water/lava symbols in
+ entry vaults.
+ * "no_pool_fixup": prevents a water square next to land from being
+ randomly converted from deep water (the default) to shallow.
+ * "no_secret_doors": prevents a door from randomly being turned
+ into a secret door.
+
+ For example
+
+ KMASK: W = no_monster_gen
+
+ will prevent monsters from randomly being generated on shallow
+ water squares. Note that if shuffling and substitutions cause
+ W to end up as water 10% of the time and floor 90% of the time,
+ then those floor squares will still have no_monster_gen set, but
+ that's still a higher degree of control than you get with TAGS.
+
+ If TAGS has been used to set a mask for the entire vault, you
+ can use KMASK to remove that mask from particular symbols.
+ For instance:
+
+ TAGS: no_monster_gen
+ KMASK: W = !no_monster_gen
+
+ would make it so that monsters are only randomly generated
+ on shallow water squares.
+
+KITEM: ? = potion of healing / potion of restore abilities
+ KITEM: places the specified item at all occurrences of the
+ placeholder. It can be combined with KFEAT: and KMONS: lines for
+ the same placeholder.
+
+ You can use "gold" or "$" to place gold:
+ KITEM: ? = nothing / gold
+ KITEM: ? = nothing / $
+
+ You can use q: to specify quantities:
+ KITEM: ? = q:100 gold
+
+ KITEM: allows you to place multiple items on the same square:
+ KITEM: ? = bread ration, potion of water, potion of porridge
+
+MARKER: A = feat:<feature_name> or timer:
+
+ A marker ties a square on the map to a game-trigger of some
+ sort (which depends on the marker and what feature it is on).
+
+ The portals to the Hells in the Vestibule of Hell are each
+ annotated with feature markers like this:
+
+ MARKER: D=feat:enter_dis, G=feat:enter_gehenna
+
+ When the horn is sounded, the stone arch at D becomes the
+ portal to Dis, the arch at G becomes the portal to Gehenna,
+ etc. This behaviour applies only to the Vestibule of Hell.
+
+ Timer feature markers set a timer on a particular square;
+ when time runs out, the feature at that square is changed
+ (usually to floor). For instance:
+
+ MARKER: A = timer: 500-1000
+
+ Sets a timer that's between 500-1000 turns, inclusive, at the
+ end of which whatever feature is on A gets converted to floor.
+
+ You can specify the final feature with a feat: qualifier:
+
+ MARKER: A = timer: 500 feat:deep_water
+
+ This sets a timer for exactly 500 turns, and changes the
+ feature to deep water at the end of it.
+
+ Feature names used in markers must be names matching the
+ names in the source code. There's a full list of feature
+ names in section I (Feature names) at the end of this
+ document.
+
+
+E. Conditionalising levels
+-----------------------------
+
+Crawl translates level (.des) files into Lua code chunks and runs
+these chunks to produce the final level that is generated. While you
+don't need to use Lua for most levels, using Lua allows you to
+conditionalise or randomise levels with greater control.
+
+Let's take a simple example of randomisation:
+
+NAME: random_test
+# Put it on D:1 so it's easy to test.
+PLACE: D:1
+ORIENT: float
+MAP
+xxxxxxxxxxxxxxxxxxx
+x........{........x
+xxxAxxxxxBxxxxxCxxx
+xxx.xxxxx.xxxxx.xxx
+xxx@xxxxx@xxxxx@xxx
+ENDMAP
+
+Now let's say you want A, B, and C to be randomly rock or floor, but B
+should be floor if both A and C are rock. Here's one way to do it (add
+these lines to the map definition):
+
+: local asolid, csolid
+: if crawl.random2(2) == 0 then
+: asolid = true
+: subst("A = x")
+: else
+: subst("A = .")
+: end
+: if crawl.random2(2) == 0 then
+: csolid = true
+: subst("C = x")
+: else
+: subst("C = .")
+: end
+: if asolid and csolid then
+: subst("B = .")
+: else
+: subst("B = .x")
+: end
+
+This code uses crawl.random2(N) which returns a number from 0 to N-1
+(in this case, returns 0 or 1). So we give A a 50% chance of being
+rock, and the same for C. If we made both A and C rock, we force B to
+be floor, otherwise we use a subst that gives B the same 50% chance of
+being rock.
+
+You can conditionalise on various factors, such as player experience
+level:
+
+NAME: condition_002
+DEPTH: 1-27
+ORIENT: float
+: if you.xl() > 18 then
+MONS: greater mummy
+: else
+MONS: deep elf priest / deep elf sorcerer / deep elf demonologist
+: end
+MAP
+xxxxxx
+x1...x
+x1...+
+x1...x
+xxxxxx
+ENDMAP
+
+Or based on where the map is being generated:
+
+NAME: condition_003
+DEPTH: Elf:*, Orc:*
+ORIENT: float
+: if you.branch() == "Orc" then
+MONS: orc priest, orc high priest
+: else
+MONS: deep elf priest, deep elf high priest
+: end
+MAP
+xxxxxx
+x1...x
+x2...+
+x1...x
+xxxxxx
+ENDMAP
+
+When conditionalising maps, remember that your Lua code executes in
+two contexts:
+
+1) An initial compilation phase before the game starts.
+2) The actual mapgen phase when the dungeon builder is at work.
+
+In context (1), you will not get useful answers from the Crawl Lua API
+in general, because the game hasn't started. This is generally
+ignorable (as in the case above) because the compilation phase just
+checks the syntax of your Lua code. If you conditionalise your map,
+however, you may run into compile failures. Take this variant, which
+(incorrectly) attempts to conditionalise the map:
+
+NAME: condition_004
+DEPTH: Elf:*, Orc:*
+ORIENT: float
+: if you.branch() == "Orc" then
+MONS: orc priest, orc high priest
+MAP
+xxxxxx
+x1...x
+x2.I.+
+x1...x
+xxxxxx
+ENDMAP
+: elseif you.branch() == "Elf" then
+MONS: deep elf priest, deep elf high priest
+MAP
+xxxxxx
+x1...x
+x2.U.+
+x1...x
+xxxxxx
+ENDMAP
+: end
+
+This map will break the compile with the cryptic message "Must define
+map." (to compound the confusion, the line number for this error will
+be the first line number of the map following the buggy map).
+
+This error is because although the map is Elf or Orc only, at compile
+time, the branch is *neither* Elf nor Orc, so the level-compiler
+thinks you've neglected to define a map.
+
+Lua code can detect the compile phase using crawl.game_started() which
+returns true only when the player has started a game (and will return
+false when the map is being initially compiled).
+
+For more details on the available Lua API and syntax, see the Lua
+reference section.
+
+
+F. Validating levels
+-----------------------
+
+If you have a map with lots of transforms (SUBST and SHUFFLE), and
+want to guarantee that the map is sane after the transforms, you can
+use a validation hook.
+
+To take a very contrived example:
+
+NAME: contrived_001
+PLACE: D:2
+ORIENT: float
+TAGS: no_pool_fixup
+SUBST: .=.w
+SUBST: c=x.
+MAP
+xxxxxx
+x{.+.c
+x..+>x
+xxxxxx
+ENDMAP
+
+This map has a chance of leaving the player stuck on the upstair
+without access to the rest of the level if the two floor squares near
+the doors are substituted with deep water (from the SUBST line), or
+the 'c' glyph is substituted with rock. Since a cut-off vault is
+uncool, you can force connectedness with the rest of the level:
+
+validate {{ return has_exit_from_glyph('{') }}
+
+The has_exit_from_glyph() function returns true if it is possible to
+leave the vault (without digging, etc.) from the position of the {
+glyph. (This takes things like the merfolk ability to swim into
+account, so a merfolk character may see deep water between the stair
+and door.)
+
+The validate Lua returns false (or nil) to indicate that the map is
+invalid, which will force the dungeon builder to reapply transforms
+(SUBST and SHUFFLE) and validate the map again. If the map fails
+validation enough times, the dungeon builder will discard the entire
+level and retry (this may cause a different map to be selected,
+bypassing the buggy map).
+
+Going back to the example, if you just want to ensure that the player
+can reach the > downstair, you can use:
+
+validate {{ return glyphs_connected('{', '>') }}
+
+NOTE: You cannot use the colon-prefixed syntax for validation Lua. If
+you have a big block of code, use the multiline syntax:
+
+validate {{
+ -- This level is always cool.
+ crawl.mpr("This level is guaranteed perfect!")
+ return true
+}}
+
+
+G. Hints for level makers
+----------------------------
+
+* Technical stuff:
+
+ If your map is not a minivault or a floating vault, make sure the
+ side(s) forming the border have a rock wall padding at least 6 deep. For
+ instance, if your map is ORIENT: north, you must have a 6 deep border of
+ rock wall (or any other kind of wall) along the northern, eastern, and
+ western edges of the map. If you're doing a fullscreen map (encompass),
+ you must pad all around the map with 6 layers of wall.
+
+ You do not have to place all of the stairs unless the level is full
+ screen, in which case you must place all except the extra stairs (> and
+ <). The <> stairs can be put anywhere and in any quantities but do not
+ have to be there. Any of the other stairs which are not present in the
+ vault will be randomly placed outside it. Also generally try to avoid
+ rooms with no exit (use at least > or < to make it possible for players
+ to get away).
+
+ Minivaults can use explicit @ exits, or be completely surrounded by
+ one space of floor for accessibility. Alternatively, you can request
+ that the dungeon builder pick appropriate exits as it does for
+ floating vaults by using the "mini_float" tag.
+
+ The entry point '@' must be present for all vaults (except
+ full-screen vaults where it must not, and floating vaults and
+ minivaults where it is optional). All @ will be connected to floor
+ space in the rest of the map (multiple @ close together may merge
+ into the same exit corridor). Make sure that no part of your entry
+ level can be cut off! If no @ is present in a floating vault (and
+ there are no doors on the edge of the map, see below), the level
+ builder will use one or more random floor spaces '.' or doors at the
+ circumference as exits. Note that it is not possible to predict
+ which spaces the level builder will choose to connect; if you need
+ predictability, use explicit @ exits on the edge.
+
+ The level-builder will also implicitly treat doors and secret doors
+ on the edge of a map as explicit exits (the same as using @) and
+ connect them to the rest of the level.
+
+ Not using @ and allowing the level-builder to pick exits is
+ acceptable in floating vaults, but when you use no @'s with this
+ feature in mind, please add comments stating this - else somebody
+ may just add @'s later on. :)
+
+ Non-rectangular maps will be padded (to the right) with rock walls
+ (or with floor spaces for minivaults) for the smallest rectangle
+ containing them. Unfortunately.
+
+ Entry levels should be rather small. Their intention is to provide some
+ atmosphere for the starting room, not to get a grip on the whole of D:1.
+ Minivaults should be rather small, as well, in order to increase the
+ chances they may actually be chosen during level generation.
+
+* Randomise!
+ The level making syntax is now very supportive for making a single map
+ appear in many versions. Use the SHUFFLE: and SUBST: directives and look
+ at the existing entry vaults. Besides reducing tedium, this avoids giving
+ veterans a spoiled edge. For example, if a secret chamber with loot is
+ always at the same place, it's a no-brainer for those who know. The same
+ goes for traps. This is much less so if there are several places for the
+ chamber (or trap) and there's even a chance it doesn't exist.
+
+ You can also use CHANCE to create modified versions of the same map. In
+ order to do this, make several maps and endow each with a chance such
+ that the sum of chances add up to 10.
+
+ Randomisation does not just apply to layout: you could also have
+ different monster population sets (for example make a branch end skewed
+ for either melee or ranged opponents), or perhaps couple difficulty to
+ loot.
+
+* Not too much loot.
+ For example, entry vaults should in general have very little loot - in
+ particular no good_xxx or '*' items lest they might give incentive for
+ start-scumming. For random vaults, there needn't be loot at all and, in
+ any case, there shouldn't be too much of it. Compare with the branch ends
+ rich in treasure (Tomb:3, Cocytus etc.) to get a feeling for this.
+
+* Have a theme.
+ It is often worthwhile (to me at least) to have a theme in mind before
+ making the actual level. For entry vaults, something simple like
+ 'fortress' or 'forest' may be enough. For later (or larger) maps, try
+ to think of distinguishing features your map may have. Being cool can
+ be good enough, but possessing some gameplay value (for example by being
+ easier for particular skills/capabilities like ranged attacks or
+ necromancy or Traps & Doors) is even better.
+
+* Testing your maps.
+ This is easy for entry vaults. Temporarily introducing a CHANCE: 5000
+ will make your entry appear almost always. For other vaults, you can
+ for the moment declare them as entry vaults with a huge CHANCE: as
+ above (and preferably in wizard mode). For more intricate things like
+ new branch ends, you have to resort to wizard mode and use the &~ command
+ to go directly to the place where the map is used, say Snake:5. You may want
+ to use a high CHANCE: again, if the map has alternatives (like Snake:5, or
+ Coc:7). Minivaults can also be tested by adding a PLACE: to the definition,
+ which makes it very likely that the minivault will appear in the chosen
+ level.
+
+ Larger vaults can be conjured up in wizard mode using the &L command.
+ You don't need to specify the full name of the vault, a substring which
+ uniquely determines the vault is enough. You can playtest portal vaults
+ using the &P wizard command. Branch ends can be conveniently tested with
+ the &~ command.
+
+ If the .des file syntax is incorrect, Crawl will tell you on which line of
+ which des file it found the syntax error, making for easier debugging.
+
+* Be fair!
+ Crawl is hard but try to balance your monsters. While it is true that Orc:1
+ can show an orcish knight, this is very rare. Hence it's probably a bad idea
+ to use orcish knights for an entry to the Orcish Mines.
+
+ Phrased more generally, do not use OOD (out-of-depth) monsters unless you
+ really know what you want.
+
+ Be especially fair when creating entry vaults. If your entry is too hard,
+ it might get just trashed. Keep in mind that your vault will be played
+ very very often, so even small chances of something stupid happening
+ (like creation of a really nasty monster) will kick in often enough.
+
+* Minivaults vs random vaults.
+ Minivaults are handled very differently from regular vaults and special
+ levels. They're placed *after* normal map generation, whereas normal
+ vaults are placed before generating the rest of the level. There's no
+ way to guarantee generation of a minivault on a particular level, although
+ using a PLACE: attribute makes the dungeon builder try very hard to place
+ the minivault on the specified level. Regular vaults can always be forced to
+ appear using a PLACE: attribute.
+
+ Technically, you make a minivault like a normal floating vault but
+ without an ORIENT: line. Note that minivaults used to be exclusively of
+ size 12x12 but this restriction is gone. Still, the smaller the better.
+
+ Where possible, use minivaults instead of regular vaults, because the dungeon
+ builder has greater freedom with the rest of the level layout when using
+ minivaults.
+
+* levdes.vim.
+ If you use vim, the levdes.vim syntax highlighting script (provided
+ in the dat directory) can make level-editing far more pleasant by colouring
+ different features in maps and syntax-highlighting .des-file syntax. vim is
+ available for nearly all operating systems, including Windows.
+
+
+H. Lua reference
+-------------------
+
+How maps are processed
+----------------------
+
+Crawl uses Lua heavily when dealing with .des files:
+
+* Level files are compiled into a series of Lua chunks. Each map can
+ have one or more Lua chunks associated with it: the prelude, the
+ body, and a validation chunk. The body is mandatory, but prelude and
+ validation chunks are necessary only if your map needs validation or
+ fancy selection criteria.
+
+* When first compiling a .des file, Crawl compiles each map's Lua
+ chunks, then compiles and runs the prelude, body and validation
+ immediately to verify that the Lua code is not broken. Lua errors at
+ this stage will cause Crawl to exit with an error message (hopefully
+ relevant). Note that the validation Lua chunk's return code is
+ completely ignored at this stage - it is only run to check for
+ syntax errors in the code.
+
+* When a new game is started, Crawl will run the Lua preludes for all
+ maps (most maps should have no prelude - map preludes slow the game
+ down). At this point, preludes can change the map's placement or
+ availability.
+
+* When the dungeon builder selects a map (based on TAGS, DEPTH,
+ PLACE), it re-runs the map prelude and the map body, applies
+ transforms (SUBST, SHUFFLE) if any, then calls the map's validation
+ Lua. If the map passes validation, the dungeon builder continues
+ with level-generation; otherwise, it restarts from the map prelude.
+
+The global prelude
+------------------
+
+Every .des file can have (at the start of the file) Lua code that is
+not associated with any specific map, but with all maps in the file.
+This is called the global prelude. The global prelude is run before
+running any other Lua code in the file, once during compilation, and
+once at start of game.
+
+You can use the global prelude to define functions and set up globals
+that the rest of the maps in the .des file use. If you have a lot of
+common code, you should probably add it to dungeon.lua instead.
+
+Syntax for using Lua in .des files
+----------------------------------
+
+* Colon-prefixed lines are individual Lua lines, extending to the end
+ of the line. E.g.
+
+ : crawl.mpr("Hello")
+
+ Colon-prefixed lines are always in the main Lua chunk, unless they occur
+ before any map definitions, in which case they go to the global prelude.
+
+* Lua blocks for the main (body) Lua
+ lua {{ <code> }}
+ or
+ lua {{
+ <code>
+ }}
+
+NOTE: Colon-prefixed lines, or lua {{ }} blocks defined before any
+map's NAME: directive will add the Lua code to the global prelude.
+
+* Lua blocks for the prelude:
+ prelude {{ <code> }}
+ or
+ prelude {{
+ <code>
+ }}
+
+* Lua blocks for the validate chunk:
+ validate {{ <code> }}
+ or
+ validate {{
+ <code>
+ }}
+
+
+Debugging Lua
+-------------
+
+Since Lua action happens in the guts of Crawl, it can be hard to tell
+what's going on. Lua debugging involves the time-honoured method of
+peppering your code with print statements:
+
+* Use error() or print() for compile-time work (i.e. when Crawl reads
+ the .des file). Note that print() just writes to the terminal and
+ keeps going, while error() forces Crawl to exit immediately (at
+ compile time; errors during level-generation are handled
+ differently).
+
+* Use crawl.mpr() for output when the game has started (at
+ level-generation time).
+
+It's very important that your finished level never croaks during
+level-generation. A Lua error at this stage is considered a validation
+failure.
+
+
+Lua API reference
+-----------------
+a. The Map.
+b. Global game state.
+c. Character information.
+
+
+Lua API - the Map
+-----------------
+
+Lua functions dealing with the map are mostly grouped under the "dgn"
+module. For convenience, .des file Lua chunks are run in an environment
+such that function calls written as:
+
+ fn(x, y, ...)
+
+are translated to
+
+ dgn.fn(map, x, y, ...)
+
+where "map" is the reference to the map that the currently executing
+Lua chunk belongs to. This is only for Lua chunks that belong to a
+map, Lua code in the global prelude does not get this treatment
+(because the global prelude is not associated with any map).
+
+Functions in the dgn module:
+
+default_depth, name, depth, place, tags, tags_remove, chance, weight,
+orient, shuffle, shuffle_remove, subst, subst_remove, map, mons, item,
+kfeat, kitem, kmons, grid, points_connected, gly_point, gly_points,
+original_map, glyphs_connected, orig_glyphs_connected, orig_gly_point,
+orig_gly_points, load_des_file, feature_number, feature_name,
+dgn_event_type, register_listener, remove_listener, remove_marker,
+num_matching_markers, feature_desc, feature_desc_at, item_from_index,
+mons_from_index, change_level_flags, change_branch_flags
+
+
+
+Lua API - global game state
+---------------------------
+
+The "crawl" module provides functions that describe the game state or
+provide utility methods.
+
+mpr, mesclr, random2, coinflip, one_chance_in, redraw_screen,
+input_line, c_input_line, getch, kbhit, flush_input, sendkeys,
+playsound, runmacro, bindkey, setopt, msgch_num, msgch_name, regex,
+message_filter, trim, split, game_started, err_trace, args
+
+
+Lua API - character information
+-------------------------------
+
+The "you" module provides functions that describe the player character.
+
+turn_is_over, spells, abilities, name, race, class, god, hp, mp,
+hunger, strength, intelligence, dexterity, xl, exp, res_poison,
+res_fire, res_cold, res_draining, res_shock, res_statdrain,
+res_mutation, res_slowing, gourmand, levitating, flying, transform,
+stop_activity, floor_items, where, branch, subdepth, absdepth
+
+
+I. Feature Names
+------------------
+
+These are the feature names usable in MARKER declarations:
+
+unseen, rock_wall, stone_wall, closed_door, metal_wall, secret_door,
+green_crystal_wall, orcish_idol, wax_wall, permarock_wall,
+silver_statue, granite_statue, orange_crystal_statue,
+statue_reserved_1, statue_reserved_2, lava, deep_water, shallow_water,
+water_stuck, floor, exit_hell, enter_hell, open_door, trap_mechanical,
+trap_magical, trap_iii, undiscovered_trap, enter_shop,
+enter_labyrinth, stone_stairs_down_i, stone_stairs_down_ii,
+stone_stairs_down_iii, rock_stairs_down, stone_stairs_up_i,
+stone_stairs_up_ii, stone_stairs_up_iii, rock_stairs_up, enter_dis,
+enter_gehenna, enter_cocytus, enter_tartarus, enter_abyss, exit_abyss,
+stone_arch, enter_pandemonium, exit_pandemonium, transit_pandemonium,
+builder_special_wall, builder_special_floor, enter_orcish_mines,
+enter_hive, enter_lair, enter_slime_pits, enter_vaults, enter_crypt,
+enter_hall_of_blades, enter_zot, enter_temple, enter_snake_pit,
+enter_elven_halls, enter_tomb, enter_swamp, enter_shoals,
+enter_reserved_2, enter_reserved_3, enter_reserved_4,
+return_from_orcish_mines, return_from_hive, return_from_lair,
+return_from_slime_pits, return_from_vaults, return_from_crypt,
+return_from_hall_of_blades, return_from_zot, return_from_temple,
+return_from_snake_pit, return_from_elven_halls, return_from_tomb,
+return_from_swamp, return_from_shoals, return_reserved_2,
+return_reserved_3, return_reserved_4, enter_portal_vault,
+exit_portal_vault, altar_zin, altar_shining_one, altar_kikubaaqudgha,
+altar_yredelemnul, altar_xom, altar_vehumet, altar_okawaru,
+altar_makhleb, altar_sif_muna, altar_trog, altar_nemelex_xobeh,
+altar_elyvilon, altar_lugonu, altar_beogh, blue_fountain,
+dry_fountain_i, sparkling_fountain, dry_fountain_ii, dry_fountain_iii,
+dry_fountain_iv, dry_fountain_v, dry_fountain_vi, dry_fountain_vii,
+dry_fountain_viii, permadry_fountain
+
+
+J. Map Statistics
+-------------------
+
+Full-debug Crawl builds (this does not include normal Crawl builds
+that have wizard-mode) can produce map generation statistics. To
+generate statistics, run crawl from the command-line as:
+
+crawl -mapstat
+
+This will generate 100 Crawl dungeons and report on the maps used in a
+file named "mapgen.log" in the working directory.
+
+You can change the number of dungeons to generate:
+
+crawl -mapstat 10
+
+Will generate 10 dungeons. If you merely want statistics on the
+probabilities of the levels, use:
+
+crawl -mapstat 1
+
+
+K. Portal Vaults
+------------------
+
+Portal vaults are vaults accessed by portals in the dungeon (bazaars
+are a special case of portal vaults). You can create custom portal
+vaults as follows:
+
+Define a vault to hold the portal itself:
+
+# Bare-bones portal vault entry
+NAME: portal_generic_entry
+TAGS: allow_dup
+ORIENT: float
+MARKER: O = lua:one_way_stair { desc = "A portal to places unknown", \
+ dst = "generic_portal" }
+KFEAT: O = enter_portal_vault
+MAP
+O
+ENDMAP
+
+Portal entries must contain a portal vault entry (enter_portal_vault).
+This feature must always have a marker that provides the portal with a
+description ("A portal to places unknown") and a destination
+("generic_portal").
+
+This will produce a portal, but attempting to use it will trigger an
+ASSERT since there's no map for the destination. So we create a
+destination map like so:
+
+NAME: portal_generic_generic
+# Tag must match dst value of portal in entry.
+TAGS: generic_portal allow_dup
+ORIENT: encompass
+MONS: ancient lich
+KFEAT: > = exit_portal_vault
+MAP
+xxxxxxxxxxx
+x111111111x
+x1A111111>x
+x111111111x
+xxxxxxxxxxx
+ENDMAP
+
+Note that the entry point into the map will be a stone arch. You must
+provide an exit to the dungeon explicitly (KFEAT: > =
+exit_portal_vault) or the player will not be able to leave.
+
+Stairs will not work right in portal vaults, do not use them.
+
+You can use multiple maps with the destination tag (generic_portal),
+and the dungeon builder will pick one at random.