----------------------------------------------- How to make levels for Dungeon Crawl Stone Soup ----------------------------------------------- Part II: SYNTAX ====== Contents: G. Glyphs H. Header information This document contains the syntax needed for making maps and vaults. It does not say anything about principles of vault making; for this, see introduction.txt. For more technical aspects, including tests, lua and portal vaults, refer to advanced.txt. For Triggerables, please see triggerables.txt. G. Glyphs =========== 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) t - trees - a single square doesn't block LOS (DNGN_TREES) . - 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 (e.g. of Zin etc) in dungeon.cc, in order. C - Random Altar. 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. NOTE: F used to put down a granite Statue most of the time but occasionally Orange or Silver or Ice statues (1 in 100). You can reproduce this by using F on the map together with SUBST: F = G:100 F:1 KMONS: F = orange crystal statue / silver statue / ice statue T - Water fountain U - Magic fountain V - Permanently dry fountain Y - Blood fountain (use sparingly!) 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. d-k - item array item. See section below on ITEM: arrays for more info. NOTE: The P (place a rune here with 1/3 chance) and R (place a honeycomb with 2/3 chance or else a royal jelly) symbols have been removed. You can produce the desired behaviour using SUBST: P = O.. KITEM: R = w:2 honeycomb / w:1 royal jelly 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 [*] (using '0', '9', and '8' in portal vaults will use monsters from the level that the portal was entered from, unless a random monster list has been set) H. Header information ======================= (All declarations apart from NAME: are translated to Lua function calls behind the scenes. See the Lua reference for more information.) Try to respect line lengths of 80 characters. Should some line exceed that (which is quite possible, especially for ITEM and MONS lines), you can use the \ symbol to break a line. You can break a line anywhere, with the exception of comma-separated lists, where you cannot start a new line with a comma. See the end of this section for examples. 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. * "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 ORIENT: float vaults 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:3-6 (Anywhere between levels 3-6 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: : or CHANCE allows you to control the probability that your map is used on any given level with an absolute roll. There are two ways to specify the CHANCE roll: CHANCE: 500 or CHANCE: 5% If specified as a raw number, the chance of selecting the vault is in 10000. If specified as a percentage, the chance of selecting the vault is * 100 in 10000. Note that CHANCE accepts only integers, no fractions or decimals. For any map with alternatives, a CHANCE influences how likely the map is to be picked instead of the alternatives. If a map has a CHANCE, Crawl will roll a random number in the range 1-10000, and select the map if the CHANCE is >= the rolled random number. If there are multiple alternative maps with CHANCE, they will be tested in an unspecified order; the first map that makes the CHANCE roll will be used. If you'd like to specify an order of testing CHANCEs, specify a CHANCE with a priority: CHANCE: 10 : 20% This specifies a CHANCE of 20%, with a priority of 10, which means this vault will be checked before any other vault with a lower priority (the default priority is 0). If no map with a CHANCE is picked, Crawl will select a map based on WEIGHT, ignoring vaults with a CHANCE set. Note that the Lua equivalent for CHANCE is a two-argument function: : chance(, ) These lines are all equivalent: CHANCE: 5% CHANCE: 500 CHANCE: 0 : 5% CHANCE: 0 : 500 : chance(0, 500) A common case when using CHANCE is to assign a CHANCE to a set of maps. For instance, if you have a set of portal vault entries, and you want one of the set to be used on 5% of all levels, you can do this: NAME: portal_a CHANCE: 50 : 5% TAGS: chance_portal_group ... NAME: portal_b CHANCE: 50 : 5% TAGS: chance_portal_group ... That is, if you have a set of maps that use CHANCE and are tagged chance_xxx, then one map of that set will be used when the chance is met. WEIGHT: (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 WEIGHT: is 10. The likelihood of a vault getting picked is: [vault's WEIGHT: / sum of all WEIGHT:s of vaults of that type] PLACE: Used to specify certain special levels. Existing special levels include most branch ends. The branches need to use the official abbreviations also used e.g. in the overmap (Ctrl-O): D, Temple, Orc, Elf, Lair, Swamp, Shoal, Slime, Snake, Hive, Vault, Blade, Crypt, Tomb, Hell, Dis, Geh, Coc, Tar, Zot. 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 on a TAGS: line and are space-separated. You can have several TAGS: lines, or use \ for very long ones. 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. * "chance_FOO": Maps can be tagged chance_ with any unique suffix to indicate that if the map's CHANCE roll is made, one of the maps tagged chance_FOO should be picked. * "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. * "extra": requests that the dungeon builder treat this as an extra vault and try to immediately place another vault of the same type it was trying to place when it placed this vault. "extra" is good to use for things like labyrinth entries that should not affect the chance of other minivaults on the level. If you use "extra", you probably want to use one of the "luniq" tags as well if your map is tagged "allow_dup". * "generate_awake": Monsters placed (using MONS, KMONS) in this vault will be generated awake. * "patrolling": Monsters placed (using MONS, KMONS) in this vault will be generated with their starting position as patrol point. If not otherwise occupied (fighting, seeking) they will patrol the area. * "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. * "no_wall_fixup": In Dis, the Vaults and the Crypt a vault's rock walls will be changed to be the same as the wall type of the rest of the level. If you don't want that to happen then use this tag. * "uniq_BAR": (uniq_ with any suffix) specifies that only one of the vaults with this tag can be used in a game. * "luniq": specifies that this vault can be used only once on a given level. "luniq" is only relevant when used with "allow_dup". * "luniq_BAR": (luniq_ with any suffix) specifies that only one of the vaults with this tag can be used on any given level. "luniq_BAR" is only relevant when used with "allow_dup". * "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. Note: if any TAG argument contains an "entry", the vault will be no longer eligible for random placement. (Currently, this just affects your choice of BAR when using uniq_BAR.) * "mnoleg" or the name of some other pandemonium lord. This makes the map eligible for said pan lord's lair. See pan.des. * "minotaur" turns this into a labyrinth exit vault. "lab" turns this into an additional labyrinth flavour vault. See lab.des for examples and details. * "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. * "layout": Lua code that dungeon.cc uses for generating level layouts. Do *NOT* use or mess with unless you know what you're doing. * "layout_foo": Indicates what sort of level layouts this vault is compatible with, for vaults that don't fit in with all layouts; the absence of this type of tags means it can go with any layout. Multiple layout_foo tags can be used if it can be used with multiple layouts. Current values for "foo" are: rooms, city, open, caves, cross, shoals, swamp, labyrinth (though currently random vaults aren't placed in the last three). * "trowel_portal": This vault can be created by the Trowel card. This tag should be used exclusively for the generic (one tile) entries to portal vaults, like bazaars and labyrinths. Other portal vaults may be eligible for Trowel, too. * "no_dump": Don't dump out this vault's name in the list of vaults generated during the game. Use this if the vault is predictable (like the Vault:8 and Slime:6 vaults) or are for weird internal uses (like the shoalhut vaults). LFLAGS: Persistent, changeable per-level flags which affect game behaviour (FLAGS just controls how the vault is placed); should only be used for vaults with ORIENT encompass or with PLACE. Causes a level's flags to be set when the level is first created. These flags can later be altered using Lua markers; for examples, look at the slime pit vault in lair.des, and the vaults in hell.des and elf.des. Valid flags are: * no_tele_control - prevents the player from using teleport control * not_mappable - prevents the player from remembering where they've been (like in the Abyss) * no_magic_map - which prevents magic mapping from working. BFLAGS: Persistent, changeable per-*branch* flags which affect game behaviour; should only be used for vaults which go on the first 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 - prevents the player from using teleport control * not_mappable - prevents the player from remembering where they've been (like in the Abyss) * no_magic_map - which prevents magic mapping from working. LFLOORCOL: blue LFLOORCOL: allows you to set the floor colour for the level the vault appears in. Should only be used for bazaars and other portal vaults. LROCKCOL: yellow LROCKCOL: 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. LFLOORTILE: (tile name string, e.g. "floor_tomb") Like LFLOORCOL, this overrides the default floor tiles used for this level. If the tile specified has variations, those will be used automatically. LROCKTILE: (tile name string, e.g. "wall_hive") Same as LFLOORTILE, but for rock walls. 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). * "acquire" requests the use of the acquirement code itself, ensuring that the player gets wearable armour, etc. You can also use acquire: to request that the acquired item be treated as a god gift. Examples: "acquire any", "acquire armour", "acquire:sif_muna book", "acquire:trog weapon". * "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). * "damaged" sets the item plusses to -1..-4. * "cursed" gets a curse plus plusses as in "damaged". * "any" by itself gives a random choice; you can combine "any" with "good_item." * "star_item" by itself makes an item equivalent to the "*" glyph. * "superb_item" by itself makes an item equivallent to the "|" glyph. * "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" or "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. * "unrand:item_name" will make a given unrandom by a given name, like "long sword unrand:singing_sword". Omit any apostrophes in the name (e.g, unrand:vampires_tooth). If the name has something between double quotes then use that string (e.g, unrand:bloodbane). If the unique already exists, the base item will be given instead. * "randart" will force a randart. Most of the above modifiers will be ignored, except for "ego" (for weapons only). 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 armours, 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 specific pluses or number of charges. You also can't lay down corpses, skeletons, or chunks. Randart spell books ------------------- You can specify random artefact spell books using: * "any fixed theme book" will generate a book with a fixed theme (set of spell schools). * "any fixed level book" will generate a book with a fixed set of spells around the same level. You can further specify artefact spell books using "randbook" and any combination of the following tags: * "disc:spell_school", the first spell school that should be included in the book. For example, "disc:earth" or "disc:ice". * "disc2:spell_school" an optional second spell school that can be included in the book. Note: specifying two spell schools doesn't mean that they will both definitely be included, just that they might be. * "numspells:number" a number of spells to include in the book. Will not always be followed. * "slevels:max_levels" the total, combined level of spells to include in the book. "slevels:6" will use three level two spells, two level three spells, a level two and a level four spell, and so on. * "spell:spell" a spell to include in the book. All of "_" will be replaced with " " and will be parsed as such. * "owner:name" will be used to generate the title of the book if provided. For example, "owner:Roxanne" may create "Roxanne's Treatise on Mountains". NOTE: You can place multiple items on the same square by using the KITEM directive. See that section for more information. 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. Also note that for entry vaults (D:1), all monsters in sight of the hero are removed. This does not hold for plants. You can use weights as for ITEM: lines. A hydra can be given a specific number of heads by calling it an "n-headed hydra" (with a maximum of 20 heads): MONS: four-headed hydra A slime creature's size can be set to other than normal using the prefixes "large", "very large", "enormous" or "titanic": MONS: very large slime creature Individual monsters may be prefixed with the "generate_awake" (without the quotes). Use this sparingly: MONS: generate_awake giant beetle Individual monsters may be prefixed with the "patrolling" (without the quotes). Use this sparingly: MONS: patrolling naga guardian Monsters can also be given colours that override their default colour. Use this *very* sparingly: MONS: col:darkgrey fungus The colour "any" can be given, in which case a random colour will be chosen when the monster is placed. You can override the displayed monster tile using the "tile:" specifier as follows: MONS: rat tile:mons_giant_bat In tiles version, this would create a monster that uses the 'mons_giant_bat' tile, but is otherwise identical to a rat. Obviously, this substition of one monster onto another should never be used, but it can be useful for customised vault monsters if an alternate tile exists. In ASCII mode, this will do nothing. You can set the monster's faction by specifying "att:" one of: * att:hostile -- the default * att:friendly -- tame, will follow you * att:neutral -- hostile to both you and att:hostile monsters * att:good_neutral -- hostile to att:hostile * att:fellow_slime -- tame, won't follow you Note that 8, 9, 0 also place monsters (see the table). If you want to place a random monster suitable for the level the map is generated on, you can use MONS: random If you want to place a random monster suitable for some other place, you can use a place: tag in the monster spec: MONS: place:Abyss or MONS: place:Slime:6 Using place: with MONS implies that you want a random monster. You can also request zombies from random monsters suitable for some other depth as: MONS: place:Elf:7 zombie or MONS: place:Zot:5 simulacrum or MONS: place:Vault:8 spectre The available modifiers are "zombie", "skeleton", "simulacrum" and "spectre". If a monster is a member of a band, you can request that it be eligible for band members by adding the keyword "band" to the name. For instance: MONS: orc warlord band Specifying "band" doesn't force bands to be placed - it requests that the game use the normal chances of creating a band. If you use "band", leave some empty space around the monster for its band members to be placed. 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 to 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. Overriding Monster Names: ------------------------- Individual monsters can be given names as follows: MONS: kobold name:Durwent This will cause the monster to appear as "Durwent the kobold". Spaces can be placed in the name by substituting them with the _ symbol. It is worth noting that "the " will be appended to all names, which should be considered when coming up with them. The name tag is also useable in KMONS. It should be used carefully to avoid having multiple monsters named the same (ie, as above, and then using the glyph '1' multiple times will result in multiple "Durwent the Kobold"s). There are three different modifiers that by used on a name: name_adjective, name_suffix and name_replace. name_adjective makes the name act as an adjective. For example: MONS: kobold name:ugly name_adjective Will cause "An ugly kobold", "The ugly kobold hits you", and so on. name_suffix does the same, but after the monster's base name: MONS: kobold name:wearing_mittens name_suffix Will give "A kobold wearing mittens", "The kobold wearing mittens hits you", and so on. name_replace causes the base name to be replaced by given name, as if the monster was a unique: MONS: kobold name:Durwent name_replace Will result in "Durwent" rather than "Durwent the Kobold". In combination with name_replace, there are two further tags that can be used when renaming monsters, but not giving them an actual "name": name_descriptor, and name_definite. For example: MONS: kobold name:goblin name_replace Will result in "goblin hits you". However, adding name_descriptor from the above flags will result in "The goblin hits you" and in the description of the monster, "A goblin". MONS: kobold name:goblin name_replace name_descriptor The name_definite flag ensures that it is never referred to as "a" or "an", but that the definite object is always used. Therefore, you will see "The goblin hits you", as per above, but also "The goblin" in its description. Setting name_definite will automatically set the flag name_descriptor, therefore meaning that: MONS: kobold name:goblin name_replace name_definite Is exactly the same as: MONS: kobold name:goblin name_replace name_descriptor name_definite This allows for shorter definitions. For instances where space in definitions is limited, you can use abbreviated forms of these tags: name_suffix -> n_suf name_adjective -> n_adj name_replace -> n_rpl name_descriptor -> n_des name_definite -> n_the Monster names should be used very sparingly. Overriding Monster Stats: ------------------------- Further monster customisation can be made by using "hd" and "hp". These two tags allow you to completely overwrite the original hit dice and hit points of a monster: MONS: kobold hd:20 Creates a kobold with a hit dice of 20. As its hp is randomised, based on its hit dice, this will also be re-rolled. Monsters with a specific hit point value will not have this value change. You can also have a specific value for hit points: MONS: kobold hp:20 Creates a kobold with 20 hit points. This is also useful for monsters (such as statues) which come with non-randomised HP values. Monsters can be marked as summoned by using "dur" and "sum" tags. The "dur" tag accepts an integer between 1 and 6 inclusive. The "sum" tag accepts the name of a spell (parsed as per the spells tag, described below) or any of "clone" (Rakshasa), "animate" (from animate dead), "chaos" (made from pure chaos), "miscast" (summoned from by spell miscast effect), "zot" (summoned by a Zot trap), "wrath" (summoned by a god in an act of retribution), "aid" (summoned by a god in order to give aid). Of the spells, "shadow_creatures" has the most significant effect, in that monsters will dissipate into the shadows rather than disappear in a puff of smoke. Using non-summoning spells will also have no effect. Tagging a monster with "seen" will override the system and force that player to be marked as already viewed; this means that it won't generate messages such as "XYZ comes into view". Overriding Monster Spells: -------------------------- Monster spell sets can be overridden with a spells: tag, used as follows: MONS: goblin spells:throw_flame MONS: ancient lich spells:symbol_of_torment;ice_storm;ice_storm (a list of spell names, spaces replaced with underscores, and names separated by ';' with no spaces around the ';' or after the spell: prefix) Monster spells currently use a limited spell-slot system, with these slots: 1. Bolt spell 2. Enchantment 3. Self-enchantment 4. Misc(1) 5. Misc(2) 6. Emergency/escape These slots are not hard and fast rules, but it is sometimes useful to drop a spell in a specific slot, for instance the emergency/escape slot: MONS: hobgoblin spells:.;.;.;.;.;teleport_self Spell names must exactly match the names in spl-data.h, with spaces replaced by underscores. You may use "." or an empty string to specify that a slot should be left empty. You can force a spell-less monster with: MONS: orc wizard spells:. (although why you'd want to do this is open to question.) If you define spells for a monster that cannot cast spells normally, you may want to mark the monster as a real spellcaster with 'actual_spells': MONS: goblin spells:throw_flame actual_spells Or as a priestly (divine) caster with 'priest_spells': MONS: goblin spells:smiting priest_spells Real spellcasters and priests can be silenced and will trigger appropriate conducts (Trog will appreciate killing spellcasters, Beogh will appreciate killing priests). If you define spells without specifying 'actual_spells' or 'priest_spells', and the monster cannot cast spells normally, the spells will be treated as innate abilities, so the monster can use these spells even when silenced. Treating spells as innate abilities may produce odd casting message (such as: "the rat throws fire at you"). If you find the messages you get unsatisfactory, add suitable entries to source/dat/database/monspell.txt. 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 or traps unless you really know what you do!) If you apply COLOUR to a glyph and then apply a SUBST, the COLOUR will transfer to the resulting transformed glyph. There are two types of colour available: base and "elemental". Available base colours are as follows: blue, green, cyan, red, magenta, brown, lightgrey, darkgrey, lightblue, lightgreen, lightcyan, lightred, lightmagenta, yellow and white. Elemental colours are: fire, ice, earth, electricity, air, poison, water, magic, mutagenic, warp, enchant, heal, holy, dark, death, necro, unholy, vehumet, beogh, crystal, blood, smoke, slime, jewel, elven, dwarven, orcish, gila, mist, shimmer_blue, decay, silver, gold, iron, bone, random. See view.h for comments on each. Even more so than base colours, elemental colours should be used very, very, very sparingly. Colours apply automatically to floor and rock wall tiles, although not all branches have coloured variations for their tile set. FTILE: . = floor_grass:20 / floor_dirt / none Similar to COLOUR, FTILE allows you to attach explicit floor tiles to any glyph. In non-tiles builds, this does nothing. If the tile specified has variations, those will be used automatically. Only tiles from the dungeon image can be used. This will not (necessarily) replace the feature tile itself, only the floor. If you set the FTILE on a fountain glyph, then the fountain will still appear normally, but the floor underneath it will be the tile that was specified. If a feature that normally covers the floor (e.g. rock walls) is destroyed, this floor tile will be used in place of the normal floor. Thus, it can be useful even for non-floor features. Like COLOUR, this should be used sparingly. If COLOUR is also specified and there is a coloured variation of this tile, then it will be used. RTILE: x = wall_hive:15 / wall_lair / none Identical to FTILE, but for rock walls. Not useful for anything but the rock wall feature. TILE: x = wall_flesh Identical to FTILE and RTILE in syntax, but closer to COLOUR in functionality. Instead of replacing the floor or relevant rock tiles, this can be used to replace the tile used for any specific feature. This can be used in combination with FTILE and RTILE to change the appearance of features. It can only be used with previously specified tiles, however. Like COLOUR and FTILE, this should be used sparingly and to good effect. If COLOUR is also specified and there is a coloured variation of this tile, then it will be used. To override doors, use the specific tile set in combination with the "no_random" specifier. Example: + = no_random dngn_fleshy_orifice 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 can 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: G = 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 G with C (random altar), a needle trap, an antique armour shop, or an altar of Zin. Different instances of G may receive different replacements. To force a single replacement for all G, use: KFEAT: G : C / needle trap / antique armour shop You'll notice that 'G' is the symbol of a granite statue. 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'. If you want a trap to start out known to the player, add "known" to the trap name: KFEAT: A = known needle trap 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_wall_fixup": prevents (rock) walls from being converted to the level's default wall type, such as in Vaults. * "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. KPROP: x = bloody KPROP: allows you to assign a specific property to a feature. Like KFEAT: and KMONS:, it can be combined with these for the same place- holder. Available properties are: * "bloody": Causes features to appear as though splattered with blood. This should be used very, very sparingly! * "no_cloud_gen": Prevents clouds from being generated over this feature (usually lava). Does not stop fog generators or clouds entering from nearby squares. * "no_rtele_into": Prevents random teleport from chosing to use this square. Should be used sparingly. * "no_ctele_into": Prevents controlled teleportation into this square. Will instead generate the message "A strong magical force throws you back!". Should be used sparingly. * "no_tele_into": Combines the above no_rtele_into and no_ctele_into in one flag, and disallows both random and controlled teleports. 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: or lua: 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. This behaviour applies only to the Vestibule of Hell. Lua markers are used for more complex triggers, such as for bazaar and labyrinth gates, rune pickup triggers for the branches of Hell, fog generators, etc. Here's a Lua marker that creates a cloud generator (for a full explanation of the various parameters, read the header of dat/clua/lm_fog.lua): MARKER: A = lua:fog_machine { \ pow_max = 15, delay_min = 100, delay_max = 150, \ size = 1, size_buildup_amnt = 29, \ size_buildup_time = 1000 } 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. An important note about markers is that they are also considered map transforms along with SUBST, NSUBST and SHUFFLE. You usually want to place a MARKER line after all SUBST, NSUBST and SHUFFLE lines so that the final position of the marker key is used. For instance, if you want to attach a marker to the rune in a map which randomises the position of the rune, this is a mistake: MARKER: O = lua: SHUFFLE: Oa/|c because the marker will be placed at O (the rune), then O may be shuffled to a different position. The correct order in this case is: SHUFFLE: Oa/|c MARKER: O = lua: SUBVAULT: X : some_vault_tag / some_other_vault_tag:20 Pick a vault that matches the tag and replace matching glyphs in the current map with the cells from that vault. Multiple glyphs can be specified on the left hand side and weighted sets of tags can be used on the right hand side. The use of an equal sign to pick a different subvault per-glyph, e.g. "X = some_vault_tag" is not supported at this time. Use a ':' instead to fix the choice of vault tag among all glyphs. When a subvault is applied, the first step is finding the smallest bounding box around the glyphs. For example, in the following vault definition, the smallest bounding box around the X glyph is a 4x3 rectangle: ...... ..XXX. ..XXX. .XXX.. ...... After the bounding box is calculated, a valid subvault that matches the given tags and is no larger than the bounding box will be found. If no subvault can be found, the vault will throw an error. If a subvault is found that is smaller than the provided bounding box, then it will be randomly placed and possibly rotated within the bounding box. There is not much optimization to best fit a subvault into the glyphs provided by the parent vault. So, take some care when using non-rectangular subvaults. The only special case is if you provide a subvault that is the exact same shape as what the parent vault requests. Everything from the subvault cell (feature, items, monsters, properties, markers) overwrite the glyph in the parent map. Once replaced, this cell is immutable and cannot be changed with something like SUBST, MARKER, or KFEAT. Additional glyphs that are not replaced by the subvault will be left untouched so that the parent vault can replace them with whatever feature it desires. These untouched glyphs can occur either because the subvault was smaller than the bounding box or because the subvault left the glyph blank (' '). Because of this, a SUBVAULT command should usually be followed by a SUBST command to clean up these remaining glyphs. Subvaults are allowed to include subvaults themselves, recursively. However, there is no checking for infinite loops or cycles of subvaults, so use this feature with some care. During map verification, the SUBVAULT command does not do anything. Therefore, the compilation step for Lua vaults will not catch errors where no maps exist for a given tag or where all maps that do exist are too big to fit into the provided space in the parent map. (The reasoning for not verifying the subvault command is so that you can specify maps by tag that may be defined later in the file or even in another file that hasn't been loaded yet.) So, test your subvaults! As the size of the subvault may vary depending on the parent vault, there are some helpful Lua functions (in the dgn library) that can be used to get more information about what the parent vault is requesting. Here's a quick reference: is_subvault() This function returns true if the current map is being used as a subvault and false if the current map is a normal vault. local width, height = subvault_size() This function returns the width and height of the subvault. If not a subvault, it returns 0. iter.subvault_iterator(_G) Can be used to iterate through all the 0-indexed coordinates in the subvault that will get copied back to the parent vault. It will return no points if this is not a subvault. default_subvault_glyphs() This is a convenience function that replaces the current subvault map with one that is the exact size of the bounding box. For any valid square that the parent map will replace with the subvault, it will place a '.' in the map. For any invalid square that will not be replaced by the subvault, it will place a ' ' in the map. If not a subvault, it does nothing. The advantage of this is that a vault author can then use nsubst on the '.' feature to ensure that a fixed number of objects will be created in the parent vault. NOTE: This function will also entirely clear the current map, so call it first in the subvault definition. Handling long lines ------------------- For most map headers, you can split long lines by ending the line that will be continued on the next line with \ as: KMONS: * = orc ; katana | quick blade . chain mail | scale mail / \ goblin ; dagger If you're using continuation lines for comma-separated lists of monsters or items, split your line after the comma, not before. For example: Wrong: ITEM: potion of healing \ , potion of speed Right: ITEM: potion of healing, \ potion of speed But in general, it is preferable to use multiple ITEM or MONS lines if you're splitting comma-separated values: Preferred: ITEM: potion of healing ITEM: potion of speed Spaces before the \ of the continued line are significant, leading spaces of the next (continuing) line are not. In other words, given: ITEM: potion of\ healing Crawl will see "potion ofhealing", not "potion of healing". Assigning multiple glyphs at once --------------------------------- Declarations that modify glyphs allow multiple glyphs to be assigned simultaneously as a convenience. For example, the following declaration will assign floor_orc as the tile to be used for all up stair cases and floor: FTILE: .[{( = floor_orc This case is identical to the longer syntax: FTILE: . = floor_orc FTILE: [ = floor_orc FTILE: { = floor_orc FTILE: ( = floor_orc Using : instead of = while assigning glyphs will assign the same value to all glyphs. In the following example, the glyphs A, B, and C will either all contain gold or all contain nothing: KITEM: ABC : gold / nothing Note: The number of items assigned in an NSUBST expression applies to the entire group of glyphs being assigned. For example: # Among all A, B, and C glyphs, make one a floor and the rest walls. NSUBST: ABC = 1:. / *:x # Make one A glyph floor, one B glyph floor, and one C glyph floor. # Make the rest of the A, B, and C glyphs walls. NSUBST: A = 1:. / *:x NSUBST: B = 1:. / *:x NSUBST: C = 1:. / *:x