summaryrefslogtreecommitdiffstats
path: root/crawl-ref/docs/develop
diff options
context:
space:
mode:
authorDavid Ploog <dploog@users.sourceforge.net>2009-10-06 06:45:22 +0200
committerDavid Ploog <dploog@users.sourceforge.net>2009-10-06 06:45:22 +0200
commitfcb71db1fcffedef3196865d271fc897e562448d (patch)
tree4cf1e5457397d9f3b6dadcfbce840e4c2dca14e0 /crawl-ref/docs/develop
parent5eb01527a7ee911e6a7f2022e9bdfdc236095b99 (diff)
downloadcrawl-ref-fcb71db1fcffedef3196865d271fc897e562448d.tar.gz
crawl-ref-fcb71db1fcffedef3196865d271fc897e562448d.zip
Add develop/ and license/ folders in docs/.
Diffstat (limited to 'crawl-ref/docs/develop')
-rw-r--r--crawl-ref/docs/develop/coding_conventions.txt368
-rw-r--r--crawl-ref/docs/develop/level_design.txt1916
-rw-r--r--crawl-ref/docs/develop/monster_speech.txt900
-rw-r--r--crawl-ref/docs/develop/patch_guide.txt134
-rw-r--r--crawl-ref/docs/develop/release.txt122
-rw-r--r--crawl-ref/docs/develop/tiles_creation.txt106
6 files changed, 3546 insertions, 0 deletions
diff --git a/crawl-ref/docs/develop/coding_conventions.txt b/crawl-ref/docs/develop/coding_conventions.txt
new file mode 100644
index 0000000000..132ab62320
--- /dev/null
+++ b/crawl-ref/docs/develop/coding_conventions.txt
@@ -0,0 +1,368 @@
+Crawl coding conventions
+========================
+
+Introduction
+============
+
+This file documents the style conventions currently in use in the Crawl
+codebase, as well as the conventions that new and/or modified code should
+conform to. It is explicitly not meant to be a didactic "how to program
+effectively" treatise. That is something best left to books and websites,
+as well as experience.
+
+Conventions
+===========
+
+A) Indenting
+------------
+
+Generally, use 4 spaces to indent, and indent with spaces only (no tabs).
+Empty lines don't need any spacing at all.
+
+Methods
+-------
+
+If the parameter list of a method runs longer than a line length (80 columns),
+the remaining parameters are usually indented in the lines below.
+
+ static void replace_area(int sx, int sy, int ex, int ey,
+ dungeon_feature_type replace,
+ dungeon_feature_type feature, unsigned mapmask)
+ {
+ [...]
+ }
+
+The same is true when a method is called:
+
+ // place guardian {dlb}:
+ mons_place( MONS_GUARDIAN_NAGA, BEH_SLEEP, MHITNOT, true,
+ sr.x1 + random2( sr.x2 - sr.x1 ),
+ sr.y1 + random2( sr.y2 - sr.y1 ) );
+
+
+There are cases where this is not possible because the parameters themselves
+are too long for that, or because the method is already heavily indented,
+but otherwise, this convention should be followed.
+
+
+B) Logical operators
+--------------------
+
+Conditionals longer than a line should be indented under the starting bracket.
+This probably seems obvious for simple ifs ...
+
+ if (!player_in_branch(BRANCH_COCYTUS)
+ && !player_in_branch(BRANCH_SWAMP)
+ && !player_in_branch(BRANCH_SHOALS))
+ {
+ _prepare_water( level_number );
+ }
+
+... but it should also be followed for else if conditionals.
+
+ else if (keyin == ESCAPE || keyin == ' '
+ || keyin == '\r' || keyin == '\n')
+ {
+ canned_msg( MSG_OK );
+ return (false);
+ }
+
+Space allowing, logical connectives of different precedence should use nested
+indenting.
+
+ case ABIL_MAPPING: // Sense surroundings mutation
+ if (abil.ability == ABIL_MAPPING
+ && player_mutation_level(MUT_MAPPING) < 3
+ && (you.level_type == LEVEL_PANDEMONIUM
+ || !player_in_mappable_area()))
+ {
+ mpr("You feel momentarily disoriented.");
+ return (false);
+ }
+
+If a logical connective needs to be distributed over several lines,
+the conjunction/disjunction operators (&&, ||) should be placed at the
+beginning of the new line rather than at the end of the old one.
+
+ else if (you.mutation[mutat] >= 3
+ && mutat != MUT_STRONG && mutat != MUT_CLEVER
+ && mutat != MUT_AGILE && mutat != MUT_WEAK
+ && mutat != MUT_DOPEY && mutat != MUT_CLUMSY)
+ {
+ return (false);
+ }
+
+Since conjunctions (&&) take precedence over disjunctions (||), pure
+conjunctive logical connectives don't need to be bracketed, unless this is
+absolutely vital for understanding. (Nested indenting helps here.)
+
+ if (you.skills[SK_ICE_MAGIC] > you.skills[SK_FIRE_MAGIC]
+ || you.skills[SK_FIRE_MAGIC] == you.skills[SK_ICE_MAGIC]
+ && you.skills[SK_AIR_MAGIC] > you.skills[SK_EARTH_MAGIC])
+ {
+ book = BOOK_CONJURATIONS_II;
+ }
+
+In a switch conditional, the case listings don't have to be indented, though
+the conditional statements should be.
+
+ switch (mons_intel(monster_index(mon)))
+ {
+ case I_HIGH:
+ memory = 100 + random2(200);
+ break;
+ case I_NORMAL:
+ memory = 50 + random2(100);
+ break;
+ case I_ANIMAL:
+ case I_INSECT:
+ memory = 25 + random2(75);
+ break;
+ case I_PLANT:
+ memory = 10 + random2(50);
+ break;
+ }
+
+Comparisons using the ? shortcut may be indented ...
+
+ mpr( forget_spell() ? "You have forgotten a spell!"
+ : "You get a splitting headache." );
+
+... but really short ones don't have to be.
+
+ beam.thrower = (cause) ? KILL_MISC : KILL_YOU;
+
+
+C) Variable naming
+------------------
+
+When naming variables, use underscores_as_spaces instead of mixedCase. Other
+conventions are pointed out by example, below.
+
+Global variables are capitalized and underscored.
+Warning: there are currently many globals which don't do this.
+
+ int Some_Global_Variable;
+
+Internal functions are prefixed with underscores.
+Warning: This is a new convention, so much code doesn't follow it.
+
+ static void _remove_from_inventory(item_def* item);
+
+Functions use underscores_as_spaces, but there are currently a lot of
+mixedCase functions.
+
+ void destroy_item(item_def* item)
+ {
+ // - Variables use underscores too.
+ int item_weight = /* ... */;
+ }
+
+There's no convention for class/struct names (yet?)
+
+ class TextDB
+ {
+ public:
+ // - No rules for static member functions; they're not used often anyway.
+ static void whatever();
+
+ // - Public member functions: named like functions.
+ void* get_value();
+
+ private:
+ // - Internal member functions: also named like functions.
+ void _parse_text_file(const char*);
+
+ // - Member variables get a prefix.
+ DB* m_db;
+
+ // - Static member variables get a prefix, too.
+ std::vector<DB*> sm_all_dbs;
+ };
+
+
+But structures tend to use underscores
+
+ struct coord_def
+ {
+ // - Simple structures don't need the "m_" prefixes
+ int x, y;
+ };
+
+
+D) Braces
+---------
+
+Braces are always put on their own lines.
+
+ do
+ {
+ curse_an_item(false);
+ }
+ while ( !one_chance_in(3) );
+
+
+If many comparisons are necessary, this can result in a number of nested
+braces. These can sometimes be omitted, as long as the underlying logic isn't
+changed, of course. The following assumes that the conditions are followed by
+single statements.
+
+If both the condition itself and the conditional code are single line
+statements, the braces may be omitted.
+
+ if (item != NULL)
+ _remove_from_inventory(item);
+ else
+ _something_else();
+
+
+Otherwise, place braces.
+
+ if (tran == TRAN_STATUE || tran == TRAN_ICE_BEAST
+ || tran == TRAN_AIR || tran == TRAN_LICH
+ || tran == TRAN_SPIDER) // monster spiders don't bleed either
+ {
+ return (false);
+ }
+
+
+ for ( int i = 0; i < power_level * 5 + 2; ++i )
+ {
+ create_monster(result, std::min(power/50, 6),
+ friendly ? BEH_FRIENDLY : BEH_HOSTILE,
+ you.x_pos, you.y_pos, MHITYOU, MONS_PROGRAM_BUG);
+ }
+
+Also place braces if this is only the case because of one or more comment
+lines.
+
+ for (j = 0; j < num_to_make; j++)
+ {
+ // places items (eg darts), which will automatically stack
+ itrap(beam, i);
+ }
+
+
+In the case of nested if-conditionals, try to combine the conditions, e.g.
+instead of
+
+ if (A)
+ {
+ if (B)
+ do_something();
+ }
+
+use
+
+ if (A && B)
+ do_something();
+
+Place braces as per the conventions above.
+
+Else, whenever if-conditional nesting can't be avoided, always use braces. I
+could't find an example where that isn't already necessary for logical reasons,
+so these should be really rare.
+
+In a row of if-else if-statements or in a switch-case loop, the optional braces
+should be used if the bigger part of statements needs braces for logical
+reasons or because of one of the conventions above. Otherwise, they may be
+omitted.
+
+ if (mons_neutral(monster))
+ {
+ if (coinflip()) // neutrals speak half as often
+ return false;
+
+ prefixes.push_back("neutral");
+ }
+ else if (mons_friendly(monster))
+ prefixes.push_back("friendly");
+ else
+ prefixes.push_back("hostile");
+
+When for-loops are nested and the outer loop has no further statements, the
+braces may be omitted.
+
+ for (int x = 0; x < GXM; x++)
+ for (int y = 0; y < GYM; y++)
+ {
+ if (grd[x][y] == DNGN_LAVA)
+ lava_spaces++;
+ if (grd[x][y] == DNGN_DEEP_WATER || grd[x][y] == NGN_SHALLOW_WATER)
+ water_spaces++;
+ }
+
+The same is true for combined for- and if-conditionals as long as all
+statements fill less than four lines.
+
+ for (i = 0; i < MAX_SHOPS; i++)
+ if (env.shop[i].type == SHOP_UNASSIGNED)
+ break;
+
+If the order of if- and for-conditionals is reversed, however, place braces.
+
+ [...]
+ else if (enhanced < 0)
+ {
+ for (ndx = enhanced; ndx < 0; ndx++)
+ power /= 2;
+ }
+
+
+If there are more than three nested statements with optional bracing, use braces
+to roughly divide them into halves. (See example below.)
+
+Should such nested code be followed by code other than a closing brace,
+leave a free line between them.
+
+ for (int y = 1; y < GYM; ++y)
+ for (int x = 1; x < GXM; ++x)
+ {
+ if (grd[x][y] == feat)
+ return coord_def(x, y);
+ }
+
+ return coord_def(0, 0);
+
+
+E) Commenting
+-------------
+
+If you feel that a method is complicated enough to be difficult to understand,
+or has restrictions or effects that might not be obvious, add explanatory
+comments before it. You may sign your comments if you wish to.
+
+ // Note that this function *completely* blocks messaging for monsters
+ // distant or invisible to the player ... look elsewhere for a function
+ // permitting output of "It" messages for the invisible {dlb}
+ // Intentionally avoids info and str_pass now. -- bwr
+ bool simple_monster_message(const monsters *monster, const char *event,
+ msg_channel_type channel, int param,
+ description_level_type descrip)
+ [...]
+
+Adding explanatory comments to somewhat complicated, already existing methods
+is very much welcome, as long as said comments are correct. :)
+
+Suboptimal code should be marked for later revision using the keywords "XXX",
+"FIXME" or "TODO", so that other coders can easily find it by searching the
+source. Also, some editors will highlight such keywords. Don't forget to add
+a comment about what should be changed, or to remove said comment if you fix
+the issue.
+
+ // XXX Unbelievably hacky. And to think that my goal was to clean up the code.
+ // Identical to find_square, except that input (tx, ty) and output
+ // (mfp) are in grid coordinates rather than view coordinates.
+ static char find_square_wrapper( int tx, int ty,
+ [...]
+
+
+ if (death_type == KILLED_BY_LEAVING
+ || death_type == KILLED_BY_WINNING)
+ {
+ // TODO: strcat "after reaching level %d"; for LEAVING
+ [...]
+
+
+ // FIXME: implement this for tiles
+ void update_monster_pane() {}
diff --git a/crawl-ref/docs/develop/level_design.txt b/crawl-ref/docs/develop/level_design.txt
new file mode 100644
index 0000000000..6c973d6220
--- /dev/null
+++ b/crawl-ref/docs/develop/level_design.txt
@@ -0,0 +1,1916 @@
+-----------------------------------------------
+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. Portal vaults
+ I. Lua reference
+ J. Feature names
+ K. Map statistics
+
+
+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:
+
+ altar.des - minivaults containing altars
+ arena.des - arenas for the arena mode
+ bazaar.des - entrances to bazaar portal vaults, and bazaars proper
+ crypt.des - random vaults for Crypt, the Crypt:5 branch ends, and the
+ predefined maps for Tomb:1, Tomb:2 and Tomb:3
+ didact.des - lua and vaults for syntax checking - not used in-game
+ dummy.des - global dummy balancers
+ elf.des - arrival and random vaults for Elf, and Elf:7 branch ends
+ 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, random hive vaults, Hive:2
+ icecave.des - the ice cave portal vault
+ lab.des - labyrinths exits and flavour vaults
+ lair.des - lair entrances, random vaults for lair proper and sub-branches,
+ and the branch ends: Shoals:5, Swamp:5, Snake:5, Slime:6
+ large.des - all regular vaults which have ORIENT:encompass/northwest etc
+ layout.des - level layout code that has been moved from dungeon.cc and
+ rewritten in Lua.
+ mini.des - minivaults (no ORIENT line at all)
+ orc.des - orcish mine entrances, orc only vaults
+ ossuary.des - the ossuary portal vault
+ pan.des - vaults of the Pan demon lords, Pan minivaults
+ rooms.des - special monster rooms, such as orc, kobold and jelly rooms
+ sewer.des - the sewer portal vault
+ temple.des - Ecumenical Temples, and Temple entrances
+ vaults.des - entrances for the Vaults, Vaults-specific vaults, the
+ Hall of Blades, and Vaults:8
+ ziggurat.des - the ziggurat entry vaults, pillars and arenas
+ zot.des - vaults for the Zot branch and the maps for Zot:5
+
+Kinds of Vaults
+---------------
+The different kinds of vaults used by Crawl are described briefly below.
+
+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 by the absence of an
+ORIENT: declaration. Any map without a specified ORIENT: is a
+minivault. Minivaults are handled like floating vaults (ORIENT: float
+vaults) in most respects. The differences are:
+
+1. Floating vaults may be placed before the rest of the level layout
+ is generated, and the rest of the level may be built around the floating
+ vault. This is never the case for minivaults.
+
+2. Floating vaults may be placed anywhere in the map, including places
+ completely separated from the rest of the level by rock. The
+ dungeon builder will then connect the exits from the floating vault
+ to the rest of the level, usually producing obvious "passages" from
+ the floating vault to the main body of the level.
+
+ In contrast, minivaults are placed such that at least one square of
+ the minivault overlaps with an existing part of the level, and are
+ thus more likely to look like part of the level. Unlike floating
+ vaults, the dungeon builder assumes that any one square of overlap
+ is enough to connect the minivault to the rest of the level and
+ makes no effort to connect exits from the minivault to the level.
+ You can ask the dungeon builder to connect exits from your
+ minivault with the "mini_float" tag.
+
+
+
+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: useless_temple_entry
+# header section below:
+ORIENT: float # "ORIENT: float" tells the level builder that
+ # this entry can be anywhere on the level.
+TAGS: temple_entry # "TAGS: temple_entry" turns the 'O' on the
+MONS: butterfly, plant # map into stairs to the Temple.
+ITEM: stone
+# actual map below: # The symbols on the map:
+MAP # x - rock wall
+xx.d.xx # . - floor
+x..1..x # @ - entry point (
+@d2O2d. # O - stairs to the Temple
+x..1..x # 1 - first monster from list (here butterfly)
+xx.d.xx # 2 - second monster from list (here plant)
+ENDMAP # d - first item from the list (here stones)
+
+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 try to stick to this order for
+consistency).
+
+Lines starting with # are comments. The keywords available are explained
+in detail in the following sections.
+
+
+C. 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 (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.
+ Z - the Orb of Zot
+ 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 deprecated. You can
+ (and should) 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
+
+
+D. 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: <priority>:<roll> or <roll>
+
+ 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 <number> in 10000. If specified as a percentage,
+ the chance of selecting the vault is <perc> * 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(<priority>, <number>)
+
+ 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 an 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.
+
+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:<god> 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."
+ * "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.
+
+ 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 specific pluses or number of charges
+ or force a randart. 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. 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.
+
+ 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
+
+ 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.
+
+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.
+
+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.
+
+RTILE: x = wall_hive:15 / wall_lair / none
+ Identical to FTILE, but for rock walls. Not useful for anything
+ but the rock wall feature.
+
+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: 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'.
+
+ 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_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 lua:<marker_expr>
+
+ 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:<expr>
+ 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:<expr>
+
+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".
+
+
+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:
+
+ 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. :)
+
+ 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 very supportive for making a single map appear
+ in many versions. Use the SHUFFLE: and SUBST: and NSUBST: directives and
+ look at the existing entry vaults. Besides reducing tedium, this avoids
+ giving veterans a spoiled edge. As an 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 WEIGHT 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 (for me at least) to have a theme in mind before
+ making the actual level. For entry vaults, something simple like 'forest'
+ or 'fortress' 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 Traps & Doors or
+ necromancy) is even better.
+
+* Testing your maps.
+ This is easy for entry vaults. Temporarily introducing a WEIGHT: 50000
+ will make your entry appear almost always. For other vaults, you can
+ for the moment declare them as entry vaults with a huge WEIGHT: 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 WEIGHT: 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.
+
+ 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. Portal Vaults
+==================
+
+Portal vaults are vaults accessed by portals in the dungeon (labyrinths
+and bazaars are special cases of portal vaults). You can create custom
+portal vaults in the following steps (no compilation is necessary):
+
+* Create a new file name.des in the dat/ folder. Rules:
+ The "name" should be descriptive of the vault you're adding.
+ The "name" should not exceed eight letters.
+ The ending must be "des".
+* Add "name.des" to the list of local files in dat/clua/loadmaps.lua.
+* "name.des" should contain a comment at the top, explaining flavour and
+ gameplay goals of the portal vault (and perhaps additional ideas etc.)
+* Define at least one vault containing the portal (see below).
+* Define at least one destination map (see below).
+* Add a short in-game description for the string "desc" (see below) to
+ dat/descript/features.txt.
+
+Before going into the details of portal vault creation, some words about
+their uses: Portal vaults are different from branches in that they are
+not guaranteed. Also, there is only one go at a portal vault - if you
+leave, it's gone for good. You can apply special rules to a portal vault,
+like enforcing maprot.
+
+Portal vaults can be particulary thematic, using specialised monster
+sets, fitting loot, coloured dungeon features etc. Avoid death traps; it
+is no fun to enter a vault, being unable to leave and be killed outright.
+In order to provide fun and reduce spoiler effects, randomise. For portal
+vaults, it is desirable to have several different layouts (ideally each
+of the maps has some randomisation on its own). Often, it is a good idea
+to skew the map distribution: e.g. with four destination vaults, weights
+like 40,30,20,10 might be more interesting than 25,25,25,25.
+
+In order to test a portal vault, you can either use PLACE: D:2 for an
+entry vault, or use the wizard mode command &L for conjuring up the entry.
+
+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").
+
+In case you want to make sure that the portal vault entry is only used
+once, you add a TAGS: uniq_BAR line. It should be noted that the label
+BAR may *not* end in _entry (otherwise the level builder assumes that
+the vault is a branch entry).
+
+If you want the place name displayed while in the vault to be different
+than the destination name, then you can give one_way_stair() a "dstname"
+parameter. If you want the place origin for items in a character
+dump to be different than the default you can give one_way_stair a
+"dstorigin" parameter (i.e., dstname = "garden", dstorigin = "in the gardens").
+If you want the place name abbreviation used when displaying notes to be
+different than than the default you can use the "dstname_abbrev" parameter.
+
+You can dynamically change the origin string using the lua function
+dgn.set_level_type_origin(), and dynamically change the place name
+abbreviation with dgn.set_set_level_name_abbrev().
+
+Known portal vault entries will be displayed on the overmap. By default
+the name shown on the overmap will be the "dstname" parameter, or if
+that isn't present the "dst" paremeter. It can be set to something else
+with the "overmap" parameter. A note can be made to accompany the
+portal's position on the overmap with the "overmap_note" parameter.
+
+Bones files for characters killed in the portal vault will normally
+use an extension derived from the first three letters of the 'dst'
+property. You can override this by setting the 'dstext' property to
+your preferred extension.
+
+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:
+
+Define a destination map
+------------------------
+
+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.
+
+The MARKER parameters
+---------------------
+
+The lines
+ MARKER: O = lua:one_way_stair { desc = "A portal to places unknown", \
+ dst = "generic_portal" }
+ KFEAT: O = enter_portal_vault
+ensure that an 'O' glyph will be turned into a portal. Upon leaving the portal
+vault, you will be placed on its entry which has been turned into a floor. You
+can turn it into something different (usually an empty stone arch), by adding
+ floor = 'stone_arch'
+to the lua:one_way_stair parameters.
+
+Note that the desc string is what you will see upon examining the portal.
+The dst string is used for Crawl's right hand stat area; it will show
+ Place: generic portal
+in the above example. Here is a lost of the parameters that can be used
+within one_way_stair (taken from icecave.des):
+ desc = "A frozen archway", # description of the portal before entry
+ dst = "ice_cave", # label used for maps and entry vaults
+ dstname = "Ice Cave", # used for PLACE: on the main screen
+ dstname_abbrev = "IceCv", # used in the notes
+ dstorigin = "in an ice cave", # appendix for items picked up there
+ overmap = "frozen archway", # used on the overmap (X)
+ floor = "stone_arch" # feature left after escaping the portal
+
+The dst string is also used to link the destination maps to the entry maps.
+In case dstname is missing, dst will be used.
+
+You can replace lua:one_way_stair by lua:timed_marker in order to make timed
+portal vaults (which will disappear after some time). bazaar.des and lab.des
+contain examples. For timed portals, you may want to add messages to the file
+dat/clua/lm_tmsg.lua.
+
+Using lua functions as shortcuts
+--------------------------------
+
+If you are making several entry and destination vaults, you will note a
+lot of duplicated header statements. This can be lessened using lua.
+Define a lua block right at the top (after your comments) as follows:
+
+{{
+function generic_portal(e)
+ e.marker([[O = lua:one_way_stair { desc = "A portal to places unknown",
+ dst = "generic_portal",
+ floor = "stone_arch" }]])
+ e.kfeat("O = enter_portal_vault")
+ e.colour("O = magenta")
+end
+}}
+
+Instead of the MARKER and KFEAT lines introduced above you now just use
+ :generic_portal(_G)
+and the resulting portal glyphs will even be magenta!
+
+Defining a random monster set
+-----------------------------
+
+Portal vaults require a defined random monster set to make the Shadow
+Creatures spell work. This is done by calling dgn.set_random_mon_list()
+manually. Here's an example from ice_cave_small_02 in icecave.des:
+ : dgn.set_random_mon_list("ice beast w:90 / ice dragon / nothing")
+You can use "nothing" to have the spell fail sometimes.
+
+If you are using the same random monster list in several destination maps,
+you can define a lua block and call it from the destination map definition.
+This example is from sewer.des:
+
+{{
+function sewer_random_monster_list(e)
+ e.set_random_mon_list("giant bat w:20 / giant newt w:20 / small snake / \
+ ooze / worm / snake / giant mosquito w:15")
+end
+}}
+
+You can then use this line in the map definition to execute the lua block:
+ : sewer_random_monster_list(_G)
+
+You can also set env.spawn_random_rate() to have monsters generated from the
+list during play.
+
+Milestones for portal vaults
+----------------------------
+
+This example is from icecave.des, defined in the lua preludes:
+
+{{
+function ice_cave_milestone(e)
+ crawl.mark_milestone("br.enter", "entered an Ice Cave.")
+end
+}}
+
+The function is called from each of the destination map definitions:
+
+: ice_cave_milestone(_G)
+
+This marks down entering the portal vault in the milestones. When the portal
+is entered, the destination map is chosen and the call to crawl.mark_milestone
+is executed along with the rest of the map definition.
+
+Adding milestones in a .des does have the slight catch of creating multiple
+milestones if the map fails validation for some reason, so it's best used
+in maps that will never fail validation.
+
+I. Lua reference
+===================
+
+How maps are processed
+----------------------
+
+Under the hood, Crawl translates everything in a .des file to Lua. You
+don't need to know what the underlying Lua looks like to design
+levels, but it helps.
+
+Crawl uses Lua 5.1 from http://www.lua.org (the site has information
+on the Lua language). Let's examine how Crawl converts a map
+definition into Lua code with an example map:
+
+NAME: statue_in_pool
+TAGS: no_rotate no_pool_fixup
+: if you.absdepth() < 7 then
+MONS: plant
+: else
+MONS: oklob plant
+: end
+MAP
+1...1
+.www.
+.wGw.
+.www.
+1...1
+ENDMAP
+
+Crawl will convert this map into the following Lua code, wrapped in an
+anonymous function (this is called a Lua chunk):
+
+function ()
+ tags("no_rotate")
+ tags("no_pool_fixup")
+ if you.absdepth() < 7 then
+ mons("plant")
+ else
+ mons("oklob plant")
+ end
+ map(".....")
+ map(".www.")
+ map(".wGw.")
+ map(".www.")
+ map(".....")
+end
+
+If your level defines prelude or validation Lua code, such code is
+extracted into separate prelude and validation chunks. The prelude and
+validation chunks are empty unless specified.
+
+Apart from the special NAME map header, every map header translates to
+a Lua function with the same name in lowercase. For instance, KFEAT:
+<xyz> is translated into kfeat("<xyz>").
+
+If you have a space or comma separated list (such as TAGS, MONS, ITEM,
+etc.), then each space/comma separated item is passed into a separate
+call to the corresponding Lua function. For instance:
+
+TAGS: no_rotate no_pool_fixup
+->
+tags("no_rotate")
+tags("no_pool_fixup")
+
+MONS: orc, gnoll
+->
+mons("orc")
+mons("gnoll")
+
+Knowing what the generated Lua looks like under the hood is useful
+because it allows you to extract repeated boilerplate in similar
+vaults into a Lua function in the .des file's prelude. For instance,
+if you were planning to write a whole slew of vaults featuring statues
+in water guarded by plants, you could extract the common code into the
+top of the .des file as:
+
+# This block has to be placed before any other vault in the .des file.
+{{
+function statue_pool_map(e)
+ e.tags("no_rotate")
+ e.tags("no_pool_fixup")
+ if you.absdepth() < 7 then
+ e.mons("plant")
+ else
+ e.mons("oklob plant")
+ end
+end
+}}
+
+NAME: statue_in_pool
+# Pass in the Lua environment global _G to the prelude function.
+: statue_pool_map(_G)
+MAP
+1...1
+.www.
+.wGw.
+.www.
+1...1
+ENDMAP
+
+You can also use arbitrary Lua directly in vault definitions, which is
+handy when randomizing things:
+
+NAME: statue_in_pool
+: local plant_weight = crawl.random_range(1,10)
+: mons("plant w:" .. plant_weight ..
+: " / oklob plant w:" .. (10 - plant_weight))
+MAP
+1...1
+.www.
+.wGw.
+.www.
+1...1
+ENDMAP
+
+How Lua chunks are associated with a C++ map object
+---------------------------------------------------
+
+A map's Lua chunk consists of calls to functions such as tags(),
+mons(), etc. These functions are defined in the dgn table (see the Lua
+API reference below), and they expect to act on an instance of Crawl's
+C++ mapdef object. Given:
+
+tags("no_rotate")
+
+the actual Lua call needs to be:
+
+dgn.tags(<map>, "no_rotate")
+
+Where <map> is the C++ map object to which the tag should be added.
+Since calling dgn.<foo>(<map>, <xxx>) is tedious, dat/clua/dungeon.lua
+wraps the Lua chunk for the map into an environment that defines
+wrappers for all the functions in 'dgn' as:
+
+ function <xyz>(...)
+ dgn.<xyz>(<map>, ...)
+ end
+
+i.e. for every function <xyz> in the 'dgn' table, we define a new
+function <xyz> that just calls dgn.<xyz>() with the current map as the
+first parameter, and the other parameters as passed in. Thus Lua code
+that you write as:
+
+tags("no_rotate")
+
+is translated to the correct dgn.tags(<map>, "no_rotate").
+
+While this is done automatically for map code, if you need to call Lua
+code that was not defined in the scope of the map, as in the example
+statue_pool_map() function, you need to pass in the map environment to
+that function if you want it to modify the map. Thus the call to
+statue_pool_map looks like:
+
+: statue_pool_map(_G)
+
+Steps involved in processing .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 validation
+ and prelude 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>
+ }}
+ The "lua" word is optional; you can also use:
+ {{ <code> }}
+ and
+ {{
+ <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,
+set_random_mon_list
+
+
+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,
+mark_milestone
+
+
+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
+
+
+J. 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, escape_hatch_down, stone_stairs_up_i,
+stone_stairs_up_ii, stone_stairs_up_iii, escape_hatch_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, fountain_blue,
+fountain_sparkling, fountain_blood, dry_fountain_blue,
+dry_fountain_sparkling, dry_fountain_blood, permadry_fountain
+
+
+K. Map Statistics
+===================
+
+Full-debug Crawl builds (this does not include normal Crawl builds
+that have wizard-mode - you must build Crawl with "make debug", not
+"make wizard") 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 random map on each level, use:
+
+crawl -mapstat 1
diff --git a/crawl-ref/docs/develop/monster_speech.txt b/crawl-ref/docs/develop/monster_speech.txt
new file mode 100644
index 0000000000..d497fd2bbf
--- /dev/null
+++ b/crawl-ref/docs/develop/monster_speech.txt
@@ -0,0 +1,900 @@
+Overview
+========
+
+As of Dungeon Crawl Stone Soup 0.3 the previously hard-coded monster
+speech has been outsourced. This makes changing existing messages,
+or adding new ones really easy. This file will hopefully help you in
+this endeavour.
+
+The outsourced messages are used to create two databases out of which
+Crawl randomly draws the necessary speech text.
+
+* shout.db (handling speech when monsters first notice you), and
+* speak.db (for all other cases).
+
+Because of the amount of definitions necessary, they have been divided
+over a number of different files.
+
+The shout database is constructed from the following two files:
+
+* shout.txt handles message output for monsters noticing you
+* insult.txt handles insults thrown at you by imps and demons
+
+The speak database contains messages defined in these files:
+
+* monspeak.txt handles messages for monsters communicating with you
+* wpnnoise.txt handles randart weapons with the noises property
+* godspeak.txt handles randomized speech by the gods, as well as
+ speech used for some divine abilities
+* insult.txt Same file as above.
+
+The messages defined in insult.txt form a part of both databases.
+Apart from that, keywords and statements defined for one database
+cannot be automatically accessed from the other. Rather, they have to
+be defined a second time.
+
+Whenever Dungeon Crawl is started, the game checks whether any of the
+databases needs to be updated. If one of the underlying files has been
+changed since the last check, the database is automatically rerolled.
+That means that if you'd like to change one of the descriptions or add
+some new monster speech all you have to do is modify the file, save,
+and restart the game to test your changes.
+
+
+Contents:
+ A. Monster speech probabilities
+ B. A simple example
+ C. Key lookup in detail
+ D. Values in detail
+ E. Testing your changes
+ F. Publishing your changes
+ APPENDIX: List of monster glyphs
+
+
+A. Monster speech probabilities
+================================
+
+Not all monsters are equally likely to speak. Rather there are
+different chances involved, depending on several attributes, and most
+of the time the database lookup stage isn't even reached.
+
+First, the player will only ever hear monsters speak if they are in
+line of sight, and monsters will only ever speak if they are not
+asleep, not submerged in water, air or lava, and not wandering around
+aimlessly (unless neutral).
+
+Berserk monsters are too busy killing and maiming to speak. Also,
+invisible monsters the player can't see (for lack of see invisible)
+will always stay silent, unless confused.
+
+Monsters capable of speech (i.e. all intelligent humanoid monsters, as
+well as all uniques and some non-unique demons) have a base chance of
+1/21 of speaking, while humanoid monsters incapable of speech will
+never communicate with the player in any form.
+
+Non-humanoid monsters get a 1/84 probability of "speaking" per turn
+(non-verbal actions, more like). This chance is divided by another 10,
+if the monster in question was generated as a member of a group.
+Chances are again doubled if this non-humanoid monster is fleeing, and
+doubled again if confused.
+
+Neutral monsters only speak half as often, and for charmed monsters
+the probability is divided by 3. The same applies to silenced
+monsters, i.e. monsters that are not naturally silent will only get to
+even attempt to speak in one out of three tries where the above
+chances hold.
+
+Note that the definition of which monsters are capable of speech is
+entirely hardcoded. We think we made this apply to all sensible
+monsters, i.e. all intelligent humanoid monsters, but of course it is
+possible we've overlooked something, so if you find that your
+carefully constructed monster speech never gets printed, and this
+documentation also doesn't help you solve the problem, you might want
+to post a bug report on Dungeon Crawl's SourceForge site [1].
+
+The exception to the above is when the monster goes away due to dying, being
+banished, or a summoned monster being abjured or having it's time run out. In
+that case the monster always speaks if the player can see the grid the monster
+is on (assuming that there's a speech entry defined for that occasion, of
+course).
+
+B. A simple example
+====================
+
+If you have a look at some of the speech files, you'll see that all
+entries have basically the same structure: a key, followed by one or
+more values.
+Here is an example.
+
+ %%%%
+ # Friendly imps are very common so they speak very rarely
+ friendly '5'
+
+ w:1
+ @The_monster@ laughs.
+
+ w:1
+ @_friendly_imp_@
+
+ __NONE
+ %%%%
+
+Let's look at this entry's components in more detail.
+
+ %%%%
+
+Four percentage signs mark beginning and end of a database entry. If
+you forget to place these, you will get buggy monster speech.
+
+ # Friendly imps are very common so they speak very rarely
+
+A '#' sign at the beginning of a line causes it to be ignored; these
+are comment lines.
+
+ friendly '5'
+
+The first non-comment, non-blank line is interpreted as the key of an
+entry. Many keys are hardcoded, but there's place for user defined
+ones as well. More on that later, though.
+In this case, the key is "friendly '5'".
+
+'5' refers to the monster glyph, so the speech will not be entirely
+restricted to imps, though they are by far the most common type of
+minor demons.
+
+ w:1
+ @The_monster@ laughs.
+
+The rest of the entry consists of messages, separated by blank
+lines. This is one of them. Each may be prefixed with an optional
+weight ("w:1"). A message will be chosen with a probability of its
+weight out of the sum of weights for its entry. Weight defaults to 10
+if not specified. In this example, this particular message will be
+selected 1 time out of 12.
+
+ @The_monster@ laughs.
+
+This is the message that will be printed. The '@' markers indicate
+variables that will be substituted before printing. This particular
+variable "@The_monster@" is treated specially by the game; the
+substitution will change based on the monster giving the speech. See
+below for more details.
+
+ w:1
+ @_friendly_imp_@
+
+This is another case of a substitution. Here, "_friendly_imp_" is an
+entry in speak.txt. A random line from that entry will be substituted.
+
+ __NONE
+
+This is a special command; it prints no message. See below for more
+details on special commands.
+
+
+C. Key lookup in detail
+========================
+
+Key lookup is always case-insensitive. The game will make many
+different attempts when trying to find monster speech, all of which
+are explained in detail below. You'll find some examples at the end of
+this section.
+
+First, a monster may have one or more of a list of attributes that
+might influence its speech. We will henceforth refer to these
+attributes as prefixes.
+
+"friendly" is one of a couple of allowed prefixes, distinguishing the
+speech from "hostile" or "neutral". All prefixes are optional and
+tested in the following order:
+
+ default <attitude> fleeing silenced confused [related] <player god>
+
+where <attitude> can be any of friendly, neutral or hostile. Note that
+the game generally treats neutral monsters like hostiles since they
+still pose a danger to players.
+
+The prefix "related" is added if the player and the monster share the
+same genus, e.g. if you're playing a Sludge Elf, and the monster in
+question is a deep elf blademaster, you both are elves and the monster
+speech may reflect that. It's currently only used for friendly
+humanoids who will now sometimes mention that you're family, if you
+are. Stupid monsters, i.e. animals, will judge your relatedness status
+according to your transformed looks while smart monsters will see
+through that magic, so that e.g. vampires will recognise a vampire in
+bat form as one of their own but a giant bat would think the player
+really is a bat.
+
+The <player god> prefix is constructed according to the religious
+belief of the character. If the monster in question is a member of the
+orc species and the character worships Beogh, the prefix "beogh" gets
+added to the list, though not for charmed orcs who will simply use the
+generic friendly statements instead of the orcish followers' cheers.
+If you worship one of the good gods instead (Zin, the Shining One, or
+Elyvilon), the prefix "good god" is used. Conversely, worshippers of
+one of the evil gods (Yredelemnul, Makhleb, Kikubaaqudgha, Lugonu, or
+Beogh) will use the prefix "evil god".
+
+This allows fine-grained handling of monsters depending on your
+character's religion status, e.g. orcs will use special speech for
+Beogh worshippers, and neutral holy beings (Angel and Daeva) may
+shout messages of encouragement to followers of the good gods, while
+demons will attempt to slander the good gods.
+
+Once the entire set of prefixes has been determined, we only need
+to add the monster name and start the database search.
+
+First we search for the complete prefix string in combination with the
+monster name. Then we try omitting some very specific prefixes that
+might not be so important, first skipping on "hostile", then also
+ignoring religion status, then hostile and "related", then all three
+of them, and then finally adding "silenced" to the list of ignored
+prefixes, where applicable.
+
+If all of that didn't yield any results, next we'll take the complete
+prefix list again, then, reading from left to right, combinations are
+tested, beginning at three prefixes and ending at none. At this stage
+the list of prefixes is always prepended with "default". This ensures
+that, for example, fleeing uniques won't output their normal menacing
+speech but rather the default speech defined for fleeing humanoids in
+general.
+
+In practice this means that database keys starting with "default" are
+the fallback solution if the exact look-up has failed. As such, the
+messages should be generic enough to allow for all the possibly
+skipped prefixes, or else those cases should be caught earlier, e.g.
+if you have "default friendly humanoid", you should also define
+"default friendly fleeing humanoid" and "default friendly confused
+humanoid" (and possibly both combined) even if only with "__NONE"
+(stay silent), as the general friendly messages may look odd for a
+monster such afflicted.
+
+Only keys that match a search string perfectly (ignoring case) will
+be used. Once all prefixes have been exhausted and still no match has
+been found, the database lookup will try for a more general monster
+description. There are several possible ways this is attempted, in the
+following order:
+
+1. The actual monster name.
+ Examples: "crystal golem", "default confused moth of wrath"
+2. The monster genus.
+ Examples: If "friendly ogre-mage" wasn't found, try "friendly ogre"
+ instead. Same for "dragon" if "swamp drake" was
+ unsuccessful.
+3. Then the monster glyph, with prefix "cap-" for capital letters.
+ Examples: "default 'cap-J'", "default confused 'k'"
+4. A group description (such as 'insect' or 'humanoid') defined by the
+ monster's body shape (winged, tailed etc). The definition of the
+ latter is entirely hardcoded, though.
+ Examples: "default winged insect", "default confused humanoid"
+
+If you are playing with tiles, you may not know the monster glyphs,
+but internally the monsters are still treated the same, and even under
+tiles, the glyph keys used for step 3 are entirely valid. In case you
+need to know the monster glyphs for your speech definitions you'll
+find a list of monster glyphs at the end of this file. Also, for many
+monsters you can find out their glyph in-game by searching the
+database ('?/') and entering a vague enough monster name. For example,
+entering "drac" will tell you that all draconians use the symbol 'd'.
+
+Note that changing monster glyphs using the mon_glyph option may also
+affect speech of this kind.
+
+For the last round (shape comparison, e.g. "winged humanoid")
+occasionally an additional intelligence estimate ("stupid", "smart")
+is prefixed to the search string, depending on the monster type, e.g.
+a "stupid humanoid" may still be smarter than a "smart arachnid".
+
+Here's a list of allowed monster shapes that should hopefully be
+self-explanatory:
+
+ humanoid, winged humanoid (angels), tailed humanoid (draconians),
+ winged tailed humanoid (gargoyles), centaur, naga, quadruped,
+ tailless quadruped (frogs), winged quadruped (hippogriff), bat,
+ snake (also eels and worms), fish, insect, winged insect, arachnid,
+ centipede, snail, plant, fungus, orb (eyes), and blob (jellies).
+
+If no matching keys are found after all of these rounds, the monster
+definitely stays silent.
+
+
+Examples
+--------
+
+Example 1:
+ The monster we want to make "speak" is a "confused killer bee".
+
+ However, such an entry cannot be found in the database, so the game
+ tries first for "default confused killer bee", then "default killer
+ bee", neither of which yields any results.
+ The monster genus is also plain "killer bee", so that doesn't help
+ us any. For the next round we try again with "confused 'k'", which,
+ by itself, also can't be found in the database, but once the prefix
+ comparison tries it together with "default", we have a match:
+
+%%%%
+default confused 'k'
+
+SOUND:@The_monster@ buzzes around in tight circles.
+%%%%
+
+Example 2:
+ This time, we're interested in "friendly fleeing related beogh orc
+ wizard".
+
+ This obviously made up example also has no direct equivalent in the
+ database, so first we try to remove the less important prefixes, in
+ this case "related" and "beogh". Unfortunately, none of "friendly
+ fleeing related orc wizard", "friendly fleeing beogh orc wizard", or
+ "friendly fleeing orc wizard" has any corresponding entry in the
+ database, so that we now check for "default" in combination with,
+ one after another, all combinations of three or less prefixes.
+
+ Three prefixes: "default friendly fleeing related orc wizard",
+ "default friendly fleeing beogh orc wizard", "default friendly
+ related beogh orc wizard", "default fleeing related beogh orc
+ wizard".
+
+ Two prefixes: "default friendly fleeing orc wizard", "default
+ friendly related orc wizard", "default friendly beogh orc wizard",
+ "default fleeing related orc wizard", "default fleeing beogh orc
+ wizard", "default related beogh orc wizard".
+
+ One prefix: "default friendly orc wizard", "default fleeing orc
+ wizard", "default related orc wizard", "default beogh orc wizard".
+
+ No prefix: "default orc wizard".
+
+ Sadly, none of these is successful. The genus of orc wizards is
+ "orc", so we retry the above using "orc" instead of "orc wizard".
+ The same is repeated for "friendly fleeing beogh 'o'", and we still
+ haven't found anything.
+
+ This is starting to get ridiculous, so it's time for desperate
+ measures:
+
+ With the help of some rather complicated functions the game works
+ out that orcs can be described as humanoids of average intelligence.
+ Thus, in a final attempt of making this orc wizard speak, we search
+ the database for "friendly fleeing related beogh humanoid",
+ something that, not surprisingly (since Beogh and humanoid don't go
+ well together), doesn't exist. Annoyingly enough, neither do the
+ variants "friendly fleeing related humanoid", "friendly fleeing
+ beogh humanoid" or even "friendly fleeing humanoid".
+
+ Still, we haven't yet tried the prefix combinations: "default
+ friendly fleeing related humanoid" is still unsuccessful, as
+ are "default friendly fleeing beogh humanoid", "default friendly
+ related beogh humanoid", and "default fleeing related beogh
+ humanoid", but with "default friendly fleeing humanoid" we finally
+ strike gold:
+
+%%%%
+default friendly fleeing humanoid
+
+w:30
+VISUAL:@The_monster@ tries to hide somewhere.
+
+@The_monster@ @shouts@, "WAIT FOR ME, @player_name@! Could you help me?"
+
+...
+
+ We'll leave it at that, even though the database code still has work
+ to do, namely add up the weights of all the entries (and there are
+ several more), and randomly choose one of them.
+
+
+Weapon speech
+-------------
+For obvious reasons, weapon noises get by without any such prefixes,
+and the only hardcoded keywords are "noisy weapon" for weapons with
+the noises property, and "singing sword" for (who'd have guessed?) the
+Singing Sword.
+
+Death speech
+------------
+You can define messages for the monster to give for when it goes away in three
+different manners:
+
+* If it really died, then the game will look up a speech entry with the
+ same keys as usual, but with " killed" appended to all the keys.
+
+* If it was banished, then the game will append " banished" to all the
+ lookup keys.
+
+* If the monster was summoned and rather than being killed was abjured or
+ ran out of time, then the game will append " unsummoned" to all of the
+ lookup keys.
+
+The game will always do a lookup in these circumstances if the player can see
+the square the monster is on, so if you only want a death message to be given
+occasionally then make one of the messages "__NONE" and give it a high weight.
+
+Of course, if no keys with the given suffix are in the database then the
+monster will say nothing in that circumstance.
+
+Special monster speech
+----------------------
+Rarely, monster speech will also rely on hard-coded keys. If such a hard-coded
+key is changed or removed, the speech in question will simply not be printed.
+This may look odd in the game, but will have no other effect. Sometimes,
+default messages will be output instead.
+
+God speech
+----------
+The keys used to search for god speech are entirely hard-coded, though
+some local synonyms have been defined as well. Hopefully, the comments
+will explain what the different speech messages are used for.
+
+
+D. Values in detail
+====================
+
+Spacing
+-------
+
+There have to be blank lines between the different messages. If
+messages are placed directly one after another they will be printed as
+a block. This can be useful, e.g. for outputting first a "spell" and
+then its (fake) result.
+
+Note that this does not work for weapon noises. Here only the first
+part of a paragraph before a carriage return is parsed.
+
+The message entries themselves can be longer than a line, though Crawl
+will simply truncate it should it exceed the screen width (assuming 80
+columns or less). The actual message length will usually differ from
+the one defining an entry as parameters can be stripped from the entry
+or replaced by other values, as explained in the following section.
+
+Variables
+---------
+
+Values can contain variable references, which look like text
+surrounded by @@. These variables may be defined by entries in
+shout.txt for the shouting database, or monspeak.txt or one of the
+other files for the speech database, in which case they are replaced
+with a random value from the entry in question; or they may have
+hardcoded expansions defined by the game.
+
+Note that variable replacement is recursive, so be careful to avoid
+infinite loops. Though the game will abort after a number of
+replacement attempts, it will still look ugly in the monster speech.
+
+The following variables are hardcoded:
+
+@monster@ : Plain monster name, e.g. "rat" or "Sigmund"
+@a_monster@ : Indefinite article plus monster name,
+ or only the name if it is unique ("Sigmund").
+@the_monster@ : Definite article plus monster name ("the rat"),
+ or a possessive if it is friendly ("your rat"),
+ or only the name if it is unique ("Sigmund").
+@something@ : Like @monster@, with monster name replaced by
+ "something" if the monster is invisible and the
+ player cannot see invisible.
+@a_something@ : similar
+@the_something@ : similar
+@player_name@ : Player name.
+@player_species@: Player base species, with Draconian rather than the
+ actual subtype.
+@player_genus@ : Player genus, i.e. "Elf" rather than the exact type,
+ or "Ogre" instead of "Ogre-Mage".
+@player_genus_plural@ : pluralised genus form.
+@player_god@ : Player's god name, or "you" if non-religious.
+@Player_god@ : Player's god name, or "You" if non-religious.
+@god_is@ : replaced with "<god name> is" or "you are", if
+ non-religious.
+@God_is@ : replaced with "<god name> is" or "You are", if
+ non-religious.
+@surface@ : Whatever the monster is standing on.
+@feature@ : The monster's square's feature description.
+@pronoun@ : it, she, he, as appropriate
+@possessive@ : its, her, his, as appropriate
+@imp_taunt@ : imp type insults (see insult.txt)
+@demon_taunt@ : demon type insults (see insult.txt)
+@says@ : synonym of "say" that fits monsters' (hardcoded)
+ speech pattern and noise level.
+
+Capitalized forms (@Monster@, @A_something@, @Possessive@, @Pronoun@)
+are expanded with capitalized text.
+
+Also, in insult.txt you'll find the hardcoded variables
+@species_insult_adj1@, @species_insult_adj2@, and
+@species_insult_noun@. These are sometimes used in the construction of
+imps' or demons' generic insults, and allow for species-dependent
+handling. If the parser encounters such a variable, it will search the
+database for the corresponding specific entry, i.e. "insult <genus>
+adj1/adj2/noun" where <genus> is replaced with the actual genus name,
+that is "draconian", "elf" or "dwarf" instead of the more specific
+species name, "ogre" for "ogre-mage", or the actual species name in all
+other cases.
+
+If this specific search doesn't yield any results, i.e., such an
+entry hasn't been defined for the species in question, the general
+replacements are used instead.
+
+Weapon noises are handled differently in that most of the above
+replacements don't hold. Instead you can use @The_weapon@,
+@the_weapon@, @Your_weapon@, @your_weapon@ and @weapon@ which will get
+replaced by "The (weapon name)", "the (weapon name)", "Your (weapon
+name)", "your (weapon name)", and the plain weapon name,
+respectively.
+@player_name@ is expanded as above, as is @player_god@, though for
+atheists it returns "atheism".
+
+Note that the Singing Sword, being unique, cannot be referred to by
+the possessive variants, so they will be replaced with the appropriate
+definite article ones.
+
+Examples of pre-defined variables in the database include
+_high_priest_, _mercenary_guard_, _wizard_, _hostile_adventurer_,
+_friendly_imp_, _hostile_imp_, and _tormentor_, but more get added all
+the time. There are also a few synonyms defined at the beginning of
+monspeak.txt such as for @ATTACK@, @pointless@, @shouts@, @wails@, and
+others.
+
+Weapon noises also use a number of synonyms which are defined at the
+end of wpnnoise.txt.
+
+The best way to learn about how variables and other concepts can be
+used is probably to see how it has been done for existing messages.
+
+Speaking to the player vs to another monster
+--------------------------------------------
+
+If a message contains a variable starting with "@player", then that message
+will only be used by friendly/good-neutral monsters, or by hostile/neutral
+monsters which have the player as their foe (and it will never be used in the
+arena). Additionally, any message containing a line starting with "You" or
+ending in a bare "you." (but not a quoted "you.") will also be considered
+player centric. You can also make a message player-centric by appending
+"@player_only@" to the end of any of the lines in the message, which will be
+removed before displaying it to the player.
+
+If you want a message to be able to apply to a foe which is another monster in
+*addition* to the player, you can replace "@player" with "@foe" to have the
+variable filled out with a string appropriate for the foe being either the
+player or another monster. If "@foe_name@" is present then the message will
+only be used on monster foes which are named, and if "@foe_god@" or "@god_is@"
+is present then it will only be used on priestly monsters or god gift monsters.
+"@Foe@" or "@foe@" will be replaced with "You" or "you" if directed at the
+player, or if directed at another monster be the same as "@The_monster@" or
+"@the_monster@", but with the foe monster's name rather than the speaking
+monster's name. "@foe_possessive@" will be replaced with "your" if directed
+at the player, or expanded like "@foe@'s" if directed at a monster.
+
+If you want to indicate which monster a message is directed at, you can put in
+"@to_foe@" or "@at_foe@" to fill in the foe name when the message is directed
+at a monster; when directed at the player the variable will be removed. For
+example, with the message:
+
+ @The_monster@ says @to_foe@, "Defend yourself!"
+
+If directed at an orc will expand to:
+
+ @The_monster@ says to the orc, "Defend yourself!"
+
+but if directed at the player will expand to:
+
+ @The_monster@ says, "Defend yourself!"
+
+You can do something similar with "@foe,@" for asking questions and the like.
+For example:
+
+ @The_monster@ asks @foe,@ "Who are you?"
+
+when directed at an orc will expand to:
+
+ @The_monster@ asks the orc, "Who are you?"
+
+and when directed at the player will expand to:
+
+ @The_monster@ asks, "Who are you?"
+
+Channels
+--------
+
+An optional channel name at the beginning of a string causes messages
+to be sent to that channel. For example:
+
+ SPELL:@The_monster@ casts a spell.
+ WARN:Your equipment suddenly seems to weigh more.
+
+Spacing after the channel parameter won't get stripped, so it's a good
+idea to double check that the speech message directly follows the
+colon.
+
+Here are the defined channels:
+
+ TALK : MSGCH_TALK (Default value.)
+ DANGER : MSGCH_DANGER
+ ENCHANT : MSGCH_MONSTER_ENCHANT
+ PLAIN : MSGCH_PLAIN
+ SOUND : MSGCH_SOUND
+ SPELL : MSGCH_MONSTER_SPELL
+ VISUAL : MSGCH_TALK_VISUAL
+ WARN : MSGCH_WARN
+
+The channels have been assigned different colours and are sometimes
+treated differently, e.g. any of MSGCH_TALK, MSGCH_SOUND and
+MSGCH_TALK_VISUAL will never interrupt resting or travel unless
+specifically added in the options file.
+
+Note that MSGCH_SOUND and MSGCH_TALK get filtered out when you are
+silenced. For similar reasons monster speech of channel SPELL is muted
+under silence, along with ENCHANT and WARN, both of which currently
+only occur in combination with SPELL. To allow for silent spells along
+with fake warnings and enchantments, you can combine these with VISUAL
+and enforce output even when silenced.
+
+ VISUAL ENCHANT : MSGCH_MONSTER_ENCHANT
+ VISUAL SPELL : MSGCH_MONSTER_SPELL
+ VISUAL WARN : MSGCH_WARN
+
+Note, though, that these only will take effect if a VISUAL message
+just happens to be chosen. As stated above, the database search
+doesn't really care whether a monster is supposed to be silent, so it
+may pick any noisy monster speech, but the message output will care
+and refuse to print such nonsense, so that in this case the monster
+will actually stay silent after all.
+
+To summarize, chances of silent "speech" are overall lower (as is
+intended) but only VISUAL messages even have a chance to be printed
+under these circumstances.
+
+As explained earlier, "silenced" is one of the prefixes that are
+regarded as "less important" and can be ignored in the exact string
+search. So that both specially defined silenced messages for a
+particular monster and its normal VISUAL messages can sometimes take
+effect, chances for actually skipping on silenced in the direct string
+matching are 50:50.
+
+Example 3:
+ The player has just cast Silence when a Killer Klown wanders into
+ view. (Uh oh!) This "silenced Killer Klown" is now attempting to say
+ something. The exact look-up is unsuccessful, but now there's a 50%
+ chance of skipping on the "silenced" prefix. If this route is chosen
+ we may get results such as
+
+%%%%
+Killer Klown
+
+@The_monster@ giggles crazily.
+
+@The_monster@ laughs merrily.
+
+...
+
+ none of which, if chosen, would actually be printed, but luckily the
+ "Killer Klown" entry also contains VISUAL statements like the
+ following:
+
+...
+
+VISUAL:@The_monster@ beckons to you.
+
+VISUAL:@The_monster@ does a flip.
+
+...
+
+ If one of these is chosen, we get a non-verbal "speech" statement of
+ this silenced monster.
+
+ However, what happens if the other 50% take effect and we will *not*
+ ignore the "silenced" prefix? In this case, we'll simply continue
+ like in the earlier examples above, get no results for either of
+ "default silenced Killer Klown" or "default Killer Klown", and try
+ the genus next: human, which cannot be found in the database,
+ silenced or no. Neither will we find anything for the monster glyph
+ '@'. Now all that remains is to check the monster shape, which is
+ "humanoid" again. "silenced humanoid" won't get us any results, nor
+ will simply "humanoid", but "default silenced humanoid" has some
+ statements defined.
+
+%%%%
+default silenced humanoid
+
+w:30
+VISUAL:@The_monster@ says something but you don't hear anything.
+
+w:30
+VISUAL:@The_monster@ gestures.
+
+...
+
+ All of the statements in these predefined "silenced" entries have to
+ be of the type VISUAL; otherwise they'll never get printed.
+
+
+For shouts the default channel is also MSGCH_TALK, which is
+automatically changed to MSGCH_TALK_VISUAL for monsters that can't
+speak (animals, usually), and manually set to MSGCH_SOUND for all
+those variants of "You hear a shout!"
+
+Monster spells and enchantments will only interrupt resting/running
+if done by a non-friendly creature, and, as stated above, messages
+passed through the TALK or SOUND channels never will.
+
+For weapon noises only a subset of the above is relevant, as anything
+including VISUAL and the channel keys SPELL and ENCHANT is considered
+invalid and will trigger a default message instead. Again, the default
+channel is MSGCH_TALK.
+
+Special commands and variables
+------------------------------
+
+Message entries may also be one of several special commands. These
+aren't variables, so they aren't surrounded by @@. Accordingly, they
+are not expanded, but rather they produce special game behaviour.
+
+ __NONE : no message
+ __NEXT : try a more general monster description
+ __MORE : enforce a "--more--" prompt
+ __YOU_RESIST : print "You resist."
+ __NOTHING_HAPPENS : print "Nothing appears to happen."
+
+Some special keys are defined in monspeak.txt and shout.txt, such as
+__RESIST_OR_NOTHING and __SHOUT. These are normal variable expansions,
+and may be used as such. They are given special-looking names because
+Crawl looks up the noises a given monster can produce and looks for
+keys that match the string, i.e. __SHOUT, __BARK and so on.
+
+
+E. Testing your changes
+========================
+
+Get a version of Stone Soup that contains WIZARD mode. You can check
+whether this is the case by reading the in-game version information
+('?v'). If Wizard mode is not listed among the included features
+(likely, since WIZARD builds are generally not distributed), you will
+have to compile the game for yourself.
+
+To build Crawl yourself, download the source code from the Crawl
+homepage [1] and read the "INSTALL" file in the main directory for
+instructions. Should you still have any questions after reading the
+documentation and checking the archives of the Crawl newsgroup [2],
+ask away!
+
+If you have WIZARD mode compiled in, you can access special wizard
+commands by pressing '&'. First answer "yes" to the safety question
+and then you can test to your heart's content. Pressing '&' followed
+by a number of other keys will execute wizard mode commands that are
+all listed in the wizard help menu (press '&?').
+
+In particular, you can create a monster with '&M', and enforce
+behaviour on a monster by examining it (with 'x', as usual). In wizard
+mode, examining monsters offers several new sub-commands such as 'F'
+(make monster friendly/neutral/hostile) and 's' (make monster shout).
+These last two are of particular interest to monster speech designers.
+
+Also, the Singing Sword and other hardcoded artefacts can be created
+with '&o'. To create all artefacts at the same time, use '&|'. The
+Elemental Staff and the spear of Voo-Doo are examples of noisy weapons.
+
+You can also temporarily increase the likelihood of a given message by
+adding a high weight value before it, e.g. w:5000, or equally
+temporarily push it into another channel (e.g. MSGCH_WARN) to make it
+more noticeable.
+
+If you successfully got Crawl compiled, you can easily enable more
+detailed debug information. All you need to do is add
+
+ #define DEBUG_MONSPEAK
+
+somewhere in AppHdr.h, for example at the beginning of the section
+entitled "Debugging Defines", and then compile the game anew, first
+using "make clean", then "make wizard".
+If you play with DEBUG_MONSPEAK compiled in, whenever the game is
+searching the monspeak database you'll get extensive information on
+all keys and prefixes tried. Once you're done testing don't forget to
+remove (or comment out) the DEBUG_MONSPEAK setting as trying to
+actually play that way would sure be annoying.
+
+
+F. Publishing your changes
+===========================
+
+If you feel that your additions really add something to the game and
+would like to make them available to the general public, you can post
+them (in the form of a diff file, or in plain text) as a feature
+request on sourceforge.net [1] or in the newsgroup [2].
+
+
+.. [1] http://crawl-ref.sourceforge.net
+ http://sourceforge.net/projects/crawl-ref
+
+.. [2] rec.games.roguelike.misc
+ Since this newsgroup is being shared with a number of other
+ roguelike games, it is generally considered polite to flag
+ subjects of posts pertaining only to Crawl with "-crawl-" or
+ a similar marker.
+
+
+APPENDIX: List of monster glyphs
+================================
+
+Lowercase letters:
+------------------
+a giant cockroach, giant ant, soldier ant
+b giant bat, butterfly
+c centaur (warrior), yaktaur (captain)
+d all draconians
+e all elves
+f fungus, wandering mushroom
+g goblin, hobgoblin, gnoll, boggart
+h all hounds (jackal, hound, wolf, warg, war dog, hell hound)
+ and hogs (hog, hell-hog)
+j snails: elephant slug, giant slug, giant snail
+k winged insects: killer bee, bumblebee
+l lizards (giant newt/gecko/iguana/lizard, gila monster, komodo
+ dragon),
+ and drakes (swamp drake, firedrake, death drake, lindwurm)
+n ghouls: necrophage, ghoul, rotting hulk
+o all orcs
+p all ghosts, phantom, and insubstantial wisp
+r all rodents (rats of all colours, and quokka)
+s arachnides (giant mite, giant centipede, scorpion, wolf spider,
+ redback)
+t minotaur
+u (very) ugly thing
+v all vortices, and air elemental
+w all worms and larvae
+x unseen horror, small abomination
+y wasps, giant mosquito, giant blowfly, moth of wrath
+z small zombie/skeleton/simulacrum, skeletal warrior, flying skull,
+ curse skull, and curse toe
+
+Uppercase letters:
+------------------
+A Angel, Daeva
+B all beetles
+C all giants, ettin, cyclops, and titan
+D all dragons, wyvern, and hydra
+E efreet
+F all frogs
+G all eyes, giant spore, and giant orange brain
+H hippogriff, manticore, griffon, and sphinx
+I ice beast
+J all jellies, oozes, and slime creature, pulsating lump,
+ giant amoeba, jellyfish, and acid blob
+K all kobolds
+L all liches
+M all mummies
+N all naga
+O all ogres
+P all plants
+Q queen bee, and queen ant
+R (fake) rakshasa
+S all snakes, and salamander
+T all trolls
+U all bears
+V all vampires
+W all wraiths, wight, and spectral warrior/thing
+X abomination, tentacled monstrosity, and Orb Guardian
+Y all yaks, and sheep
+Z large zombie/skeleton/simulacrum
+
+Numbers:
+--------
+1 all Fiends, Executioner, Blue/Green Death, Balrug, Cacodemon
+2 sun demon, reaper, soul eater, ice devil, and Lorocyproca
+3 hellion, tormentor, blue/iron devil, neqoxec, orange/shadow demon,
+ hellwing, ynoxinul, and demonic crawler
+4 red/rotting/hairy devil, beast, and smoke demon
+5 all imps, and other minor demons (quasit, lemure, ufetubus, manes,
+ midge)
+8 all golems, and living statues
+9 all gargoyles
+
+Other symbols:
+--------------
+# earth elemental, fire elemental, and vapour
+{ water elemental
+; all fish, and electric eel
+@ all humans, (glowing) shapeshifter, and Killer Klown
+& all pandemonium lords
+* ball lightning, and orb of fire
+% death cob
+ shadow
+
+For uniques, see their monster description for their subtype.
diff --git a/crawl-ref/docs/develop/patch_guide.txt b/crawl-ref/docs/develop/patch_guide.txt
new file mode 100644
index 0000000000..2ecc4fab2e
--- /dev/null
+++ b/crawl-ref/docs/develop/patch_guide.txt
@@ -0,0 +1,134 @@
+How to Write a Patch
+====================
+
+The following is a rough guide on how to write patches to the code. It is
+meant to make writing patches easier to inexperienced programmers, but
+following these steps does not guarantee that any patch will actually be
+accepted - that depends entirely on content.
+
+Also, we're talking about Stonesoup here, but the principle could be applied to
+any other program as well. :)
+
+Required tools
+--------------
+At the very least you'll need the source code, and some helpful programs like
+diff and grep. The latter come preinstalled with Unix, whereas Windows users
+will have to download and install them. This may be a bit of work, but is
+totally worth it if you're programming a lot. You can get them at e.g.
+ http://gnuwin32.sourceforge.net/packages/diffutils.htm
+ http://gnuwin32.sourceforge.net/packages/grep.htm
+
+Main steps
+----------
+0.) If you're not interested in coding or have no intention of compiling the
+ game, you can still submit patches for the documentation, descriptions
+ or vaults. In that case, simply ignore the steps relating to compilation
+ and coding. You don't even need the source code for that, instead you can
+ simply use the binary distributation that also contains the relevant
+ text files.
+
+1.) Get the source code, either from the most recent release
+ (http://sourceforge.net/projects/crawl-ref/files/) or use SVN to get the
+ current trunk:
+ svn co https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk/crawl-ref trunk
+
+2.) Compile the code. To do this you might have to install a compiler and/or
+ additional libraries. See INSTALL.txt for details. If you have any
+ questions, you can ask for help on crawl-ref-discuss@lists.sourceforge.net.
+
+3.) Once you've got everything set up, you should copy the folder containing
+ the files you're going to change, i.e. docs/, dat/descript/ or the entire
+ source/ folder, as appropriate. This is done so you can later easily create
+ the patch against the original version.
+
+4.) Now you can start tweaking the code. Depending on your coding background
+ you may want to experiment with smaller changes first. If you intend to
+ submit the patch to the dev team, please skim coding_conventions.txt.
+ Following these guidelines will save us some time later when integrating
+ the patch.
+
+5.) Compile again to test your changes.
+
+6.) Once everything works as it should, you can use diff or git to create a
+ patch out of the differences between the two folders, e.g.
+ diff -ur trunk-orig trunk-new > mypatch.diff
+
+ You may want to apply the patch against the unmodified folder to test
+ whether everything worked correctly.
+
+7.) Upload the patch on the patch tracker of Sourceforge at
+ http://sourceforge.net/tracker/?group_id=143991&atid=757515.
+
+ Here it is immensely helpful if you give a summary of what the patch is
+ about. If you created it in response to a bug report or feature request,
+ mention the id, and you might also want to post a reply in said item
+ pointing out your new patch. Please also mention the revision/version you
+ used for patching, e.g. 0.5 or r10078, and anything you think may still
+ need to be improved or modified.
+
+ Thank you! :D
+
+
+Tips
+----
+Tip 1: The code is rougly divided into files according to functionality that
+ is reflected in the file names, so monstuff.cc, mon-util.cc and
+ mstuff2.cc all handle code relating to monsters, while spl-data.h,
+ spl-cast.cc and spells2.cc deal with spells. Note that related code can
+ still be found in other files, too, but these are a good starting point.
+
+Tip 2: Start out with the simple, generic stuff where you only have to copy
+ and minimally tweak existing code, and only once that works move on to
+ the more complicated implementations.
+
+Tip 3: Use grep to find all occurences of a similar instance of the same type
+ as the one you're implementing, e.g.
+ grep GOD_ELYVILON *.cc when adding a new god, or
+ grep SCR_FOG *.cc when adding a new scroll.
+
+ That way you'll be able to repurpose a lot of code for your new
+ implementation, and it also helps cut down on coding errors.
+
+
+Example
+-------
+I want to add a spell that creates some kind of clouds. The first similar spell
+I can think of is Mephitic Cloud. I know that this spell is defined as
+SPELL_MEPHITIC_CLOUD (and if I didn't know I could find out by grepping for
+"Mephitic Cloud"), so I type (within the source folder)
+ grep SPELL_MEPHITIC_CLOUD *.h and
+ grep SPELL_MEPHITIC_CLOUD *.cc
+
+... which tells me that code regarding this spell turns up in enum.h (its
+declaration), mon-spll.h (monsters "casting" the spell), spl-data.h (the
+definition), and ghost.cc (monster spell), it_use3.cc (some kind of misc.
+item, maybe), mstuff2.cc (helpfully with a comment mentioning swamp
+drakes), spl-book.cc (spellbooks that contain this spell), and spl-cast.cc
+(actually casting the spell).
+
+That gives me some ideas on where to start looking at code to duplicate
+for my new spell. I'd start out with the basics, the declaration and
+definition, copying all values from Mephitic Cloud and only changing the
+SPELL_xxxx tag. Then I add the new spell to the list in spl-cast.cc, at which
+point I'll also notice that Mephitic Cloud uses a function called
+stinking_cloud() and that various other cloud spells (helpfully sorted by
+effect type) use functions like cast_big_c() and others. Using grep I can
+quickly find out that both functions are declared in spells1.h, meaning their
+definitions can be found in spells1.cc.
+
+stinking_cloud() contains a definition of a beam that defines damage and
+such. The various properties are not self-explanatory but they're also not
+totally obscure, so you should be able to find out a lot about them by just
+fiddling with the values. In particular, beam.flavour is set to something
+called BEAM_POTION_STINKING_CLOUD which looks interesting enough to check
+out, so I grep the source (*.h and *.cc) for all occurences and have a look
+at all files this turns up. And so on.
+
+Evaluating and prioritising the findings takes some experience with the source
+code but even if you have no idea what the files are likely to contain, using
+grep still greatly reduces the number of files you have to look at. To find
+the code you're interested in, search the files for the same keyword you used
+for grepping.
+
+Good luck with your patch! If you have any questions, don't hesitate to ask.
+Thank you for your support!
diff --git a/crawl-ref/docs/develop/release.txt b/crawl-ref/docs/develop/release.txt
new file mode 100644
index 0000000000..e370a797af
--- /dev/null
+++ b/crawl-ref/docs/develop/release.txt
@@ -0,0 +1,122 @@
+Steps to a Successful Release
+-----------------------------
+The following is a step-by-step guide for how to preceed through the releasing
+process. For minor releases (0.X.y), steps 0 and 1 have already been done, so
+for those the list begins with step 2.
+
+0. Delay branching as long as possible
+ Try to delay additions that forseeably won't make it into the next version
+ until the release is not too far off. Once trunk has been branched, you
+ have to commit all important changes twice, and it's easy to forget one
+ of them.
+
+ At the same time if something big does get introduced it's better to branch
+ before doing so seeing how otherwise you'll have to later turn it off in
+ branch before the release.
+ Thus, you'll need to branch as early as necessary and as late as possible.
+
+1. Branch trunk into the new version
+ svn cp https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk
+ https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup-0.X
+
+2. Update version information
+ version.h: Set VER_NUM = 0.X, VER_QUAL = empty.
+ Undefine DISPLAY_BUILD_REVISION (not needed for official distributions).
+
+3. Modify branch as needed
+ Turn off all features that are not balanced or finished enough to make it
+ into the release. This can be a bit of a hassle, so do try to avoid this in
+ the first place. (See 0.)
+
+4. Wait and fix some bugs
+ Wait at least a week for some last minute bug reports. When fixing bugs
+ concentrate on the important ones (crashes and gamebreakers), but you
+ might also want to handle the trivial ones for extra polishing.
+ If you add any last minute feature or bug fixes doublecheck everything,
+ so you don't accidentally introduce new bugs, and wait at least another
+ day for potential bug reports to roll in.
+
+ Reread the entire documentation to make sure it's up to date.
+ Also update the change log!
+
+5. Sanity testing
+ Build the binaries (preferably on all platforms) to see if the code
+ compiles correctly, then run some basic sanity tests including at least
+ the following:
+ * start a new game (both prechosen and random)
+ * saving/loading
+ * being killed
+ * level creation for all branches/portal vaults (using &~, &L)
+ * accessing all help screens (including the ? submenus)
+
+ If you want to be thorough, play a tutorial for each of the three character
+ builds. This way, you get to test melee, spellcasting, and ranged combat,
+ and at the same time you can check that the information handed out during
+ the tutorial is up to date.
+
+6. Package the source tarball and zip
+ On Linux, run "make package-source" in the source tree to create the source
+ tarball and zip. Extract the resulting packages into different folders,
+ compile their source and run the basic sanity tests. Also check whether
+ the doc, settings and dat subfolders contain all relevant files.
+
+7. Tag the release
+ svn cp https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup-0.X
+ https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/tags/stone_soup-0.X
+
+ The tags are some sort of frozen state of the source for all releases, so
+ this is the last step you take before the actual release. All further
+ changes either make it into the next (minor) version, or, if they are
+ important bug fixes and happen before the release took place, have to be
+ merged into trunk AND branch AND the corresponding tag.
+
+8. Checkout the release tag
+ svn co https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/tags/stone_soup-0.X
+
+ Do a clean checkout into a new folder, so you don't get any compilation
+ stuff into the distribution. Package the source (as described in 6.) and
+ build the binaries. If you want you can do some more sanity testing but it
+ shouldn't be necessary anymore.
+
+9. Upload the files to Sourceforge
+ Probably requires SF permissions for file releases.
+
+ You could use for example rsync (on Linux) or FTP.
+ See https://sourceforge.net/apps/trac/sourceforge/wiki/File%20management%20service
+ for reference. Compare the file sizes to make sure the upload went
+ correctly.
+
+ If using rsync, the correct command is:
+ rsync -avP -e ssh FILENAME USERNAME,crawl-ref@frs.sourceforge.net:/home/frs/project/c/cr/crawl-ref/
+
+10. Create a new release in Sourceforge's file release system
+ Requires SF permissions for file releases.
+
+ * Click on Project Admin -> File Manager
+ * Create a new folder under "Stone Soup" named by version number -> 0.X.y
+ * Right-click on the uploaded files to Cut and later Paste them into the
+ newly created folder.
+ * Click on a file to change its settings.
+ * Mark a file as default for a given platform, so the "Download Now" link
+ can refer the user to the most fitting file for their system.
+
+ You can use an older release as a guideline (but don't actually modify it!)
+ See https://sourceforge.net/apps/trac/sourceforge/wiki/Release%20files%20for%20download
+ for some more detailed explanations.
+
+11. Update the homepage
+ ssh -t username,crawl-ref@shell.sourceforge.net create
+
+ Go to /home/groups/c/cr/crawl-ref/htdocs.
+ Paste the changelog into a newly created 0.X.txt
+ Modify index.html to update the version number (the link will always point
+ to the most recent release) and add a new news item. For the latter, use
+ <a href="0.X.txt">text</a> as a link to the change log.
+
+12. Announce the release
+ Post a release announcement to rec.games.roguelike.misc and
+ rec.games.roguelike.announce. Also send an email over crawl-ref-discuss.
+ If you want you can also write a news item on Sourceforge.
+
+13. Lean back and enjoy the excitement
+ -- until the first bug reports roll in. ;)
diff --git a/crawl-ref/docs/develop/tiles_creation.txt b/crawl-ref/docs/develop/tiles_creation.txt
new file mode 100644
index 0000000000..1c86d59ca4
--- /dev/null
+++ b/crawl-ref/docs/develop/tiles_creation.txt
@@ -0,0 +1,106 @@
+A short guide to Tiles creation
+===============================
+
+This is a short guide to creating tiles. We assume that you've got some kind of
+image editing software (such as Photoshop or the GIMP) as well as some basic
+knowledge of how to use it. While the fancier functions can occasionally come
+in useful, the simple tools for drawing, selection and erasing of pixels will
+usually suffice.
+
+You may want to download the latest source or even the trunk version. Either
+way, the source/rltiles/ directory contains all tiles used in the game, and
+some more that are currently unused. While you can create new tiles without
+having access to existing ones, it can be useful to have them around for
+comparison. Also, you'll probably want to compile them into the game to test
+your creations. (You don't have to, though.) For compiling the game, see
+INSTALL.txt.
+If you're going to change anything in the main code you'll probably want to
+create a patch. See docs/patch_guide.txt for help with that.
+
+Crawl's tiles are png files in a format of 32x32 pixels. Larger tiles such
+as for the pandemonium demons are possible, but require additional coding and
+should be used sparingly. The tile background should be transparent, but if
+your image software doesn't support png files with transparent background you
+can also submit a png or bmp with the background coloured differently from the
+rest of the tile, so we can easily remove it later.
+
+
+1.) Before setting out to draw a new tile, you may want to check out the
+ UNUSED/ directory in case there's already a tile that could be used for
+ this purpose.
+
+2.) When creating new tiles you often don't need to start from zero. A lot of
+ the time existing tiles can be repurposed to other uses. If you tweak them
+ enough no-one will even notice you cheated.
+ For example, the spell tile deaths_door.png is basically a modified version
+ of the reaper, with the hour glass copied over from the slowing potion's
+ i-slowing.png that was then changed significantly.
+
+3.) For items and monsters don't forget to add a shadow. You can use standard
+ black for this.
+
+4.) New randart weapons and armour items need not only a tile for the item
+ itself but also a smaller variant for the player doll to wield or wear.
+ To define the new artefact tiles, you'll need to modify two files:
+ source/art-data.txt, and rltiles/dc-player.txt, with the details nicely
+ described in art-data.txt.
+ If you have perl installed, run "perl art-data.pl" from source/util. If you
+ made any mistakes in modifying the two files the script will complain.
+
+ If an artefact doesn't get a special equipment tile the base type's tile
+ will be used instead.
+
+5.) Otherwise, add the tile to the relevant dc-xxxx.txt file and use the same
+ (uppercase) definition in the matching tileidx_xxxx() function in
+ tilepick.cc. Note that the latter is not necessary if you are adding tiles
+ for the player doll.
+
+ Tiles are assumed to have been placed within the rltiles/ directory
+ structure. You can use a relative path for the tile definition, or you can
+ use the %sdir command to change the current default relative path.
+
+ Use the %rim property to control whether Crawl needs to draw a black
+ outline around your tile or whether it already has one. To change the rim
+ property for your tile, use e.g.:
+ %rim 1
+ new_tile NEW_TILE
+ %rim 0
+
+6.) For humanoid monsters' tiles you may want to add a line in
+ get_weapon_offset() in tilemcache.cc to allow it to be drawn with a wielded
+ weapon.
+
+7.) New monsters may also need a unique corpse tile. In that case you'll also
+ need to modify dc-corpse.txt and add a tile in _tileidx_corpse() of
+ tilepick.cc.
+
+
+When compiling the game you may need to delete or rename the relevant tile
+section's png file, i.e. main.png (for items), player.png (for player, doll
+equipment, and monsters), dngn.png (for dungeon features) or gui.png (for
+spells), to make the changes take effect. The first step during the compilation
+will be to rebuild this file, so you can check right away whether your new tile
+was added correctly. Changes in dc-xxxx.txt automatically cause the relevant
+image files to be recreated.
+
+
+In case you'd like to draw some tiles but have run out of ideas, here's an
+incomplete (and possibly outdated) list of suggestions:
+
+* tiles of the various runes
+* zombie/skeleton tiles taking into account the monster type
+* tiles for abilities
+* alternative tiles for dungeon features to allow for "animations"
+* equipment tiles for the player doll
+* improvement of existing tiles
+etc.
+
+You can also check the SourceForge Feature Requests for tracker items
+containing the "\o/" emblem in the title. At least one of them will be a call
+for more tiles.
+
+Please submit your new tiles as a new item on our feature request or patches
+tracker, or send one of the tiles developers (ennewalker, evktalo, j-p-e-g) an
+email containing your tiles.
+
+Thanks a lot for your support!