summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-11-13 12:33:41 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2007-11-13 12:33:41 +0000
commitf19ffb0cf2b7db6897674d73191525cb54831723 (patch)
treeeb83c1180bd1f6137e4566b45d5d414def477e7d /crawl-ref
parent2ce8ccfa9ec7125c1519f2b9efbe1fe25aa5ad48 (diff)
downloadcrawl-ref-f19ffb0cf2b7db6897674d73191525cb54831723.tar.gz
crawl-ref-f19ffb0cf2b7db6897674d73191525cb54831723.zip
The number of traps randomly generated on a level, and which types of
traps are randomly selected, can now easily be controlled on a branch by branch basis (and for Pan and the Abyss), similar to how monster level and rarity is controlled (via function pointers in the Branch data structure). The same can be done for fog machines (though this feature isn't being used as of yet). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@2846 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/branch.cc25
-rw-r--r--crawl-ref/source/branch.h10
-rw-r--r--crawl-ref/source/cloud.cc161
-rw-r--r--crawl-ref/source/cloud.h27
-rw-r--r--crawl-ref/source/dungeon.cc98
-rw-r--r--crawl-ref/source/misc.cc27
-rw-r--r--crawl-ref/source/misc.h3
-rw-r--r--crawl-ref/source/traps.cc194
-rw-r--r--crawl-ref/source/traps.h19
9 files changed, 483 insertions, 81 deletions
diff --git a/crawl-ref/source/branch.cc b/crawl-ref/source/branch.cc
index d8e36f1a6c..26411173ef 100644
--- a/crawl-ref/source/branch.cc
+++ b/crawl-ref/source/branch.cc
@@ -4,10 +4,12 @@
#include "AppHdr.h"
#include "branch.h"
+#include "cloud.h"
#include "externs.h"
#include "mon-pick.h"
#include "player.h"
#include "spells3.h"
+#include "traps.h"
Branch& your_branch()
{
@@ -115,6 +117,7 @@ Branch branches[] = {
NULL,
true, true, LIGHTGREY, BROWN,
mons_standard_rare, mons_standard_level,
+ NULL, NULL, NULL, NULL,
8, 'D', false, false },
{ BRANCH_ECUMENICAL_TEMPLE, BRANCH_MAIN_DUNGEON, 1, 5, 0, 0,
@@ -123,6 +126,7 @@ Branch branches[] = {
NULL,
false, false, LIGHTGREY, LIGHTGREY,
mons_standard_rare, mons_standard_level,
+ traps_zero_number, NULL, NULL, NULL, // No traps in temple
0, 'T', false, false },
{ BRANCH_ORCISH_MINES, BRANCH_MAIN_DUNGEON, 4, 6, 0, 0,
@@ -131,6 +135,7 @@ Branch branches[] = {
NULL,
true, false, BROWN, BROWN,
mons_mineorc_rare, mons_mineorc_level,
+ NULL, NULL, NULL, NULL,
20, 'O', false, false },
{ BRANCH_ELVEN_HALLS, BRANCH_ORCISH_MINES, 7, 4, 0, 0,
@@ -139,6 +144,7 @@ Branch branches[] = {
NULL,
true, true, DARKGREY, LIGHTGREY,
mons_hallelf_rare, mons_hallelf_level,
+ NULL, NULL, NULL, NULL,
8, 'E', false, true },
{ BRANCH_LAIR, BRANCH_MAIN_DUNGEON, 10, 8, 0, 0,
@@ -147,6 +153,7 @@ Branch branches[] = {
NULL,
true, false, GREEN, BROWN,
mons_lair_rare, mons_lair_level,
+ NULL, NULL, NULL, NULL,
5, 'L', false, false },
{ BRANCH_SWAMP, BRANCH_LAIR, 5, 3, 0, 0,
@@ -155,6 +162,7 @@ Branch branches[] = {
NULL,
true, true, BROWN, BROWN,
mons_swamp_rare, mons_swamp_level,
+ NULL, NULL, NULL, NULL,
0, 'S', false, true },
{ BRANCH_SHOALS, BRANCH_LAIR, 5, 4, 0, 0,
@@ -163,6 +171,7 @@ Branch branches[] = {
NULL,
true, true, BROWN, BROWN,
mons_shoals_rare, mons_shoals_level,
+ NULL, NULL, NULL, NULL,
0, 'A', false, true },
{ BRANCH_SLIME_PITS, BRANCH_LAIR, 6, 4, 0, 0,
@@ -171,6 +180,7 @@ Branch branches[] = {
NULL,
false, false, GREEN, LIGHTGREEN,
mons_pitslime_rare, mons_pitslime_level,
+ NULL, NULL, NULL, NULL,
5, 'M', false, true },
{ BRANCH_SNAKE_PIT, BRANCH_LAIR, 5, 7, 0, 0,
@@ -179,6 +189,7 @@ Branch branches[] = {
NULL,
true, true, LIGHTGREEN, YELLOW,
mons_pitsnake_rare, mons_pitsnake_level,
+ NULL, NULL, NULL, NULL,
10, 'P', false, true },
{ BRANCH_HIVE, BRANCH_MAIN_DUNGEON, 4, 15, 0, 0,
@@ -187,6 +198,7 @@ Branch branches[] = {
"You hear a buzzing sound coming from all directions.",
false, false, YELLOW, BROWN,
mons_hive_rare, mons_hive_level,
+ NULL, NULL, NULL, NULL,
0, 'H', false, true },
{ BRANCH_VAULTS, BRANCH_MAIN_DUNGEON, 8, 17, 0, 0,
@@ -195,6 +207,7 @@ Branch branches[] = {
NULL,
true, true, LIGHTGREY, BROWN,
mons_standard_rare, mons_standard_level,
+ NULL, NULL, NULL, NULL,
5, 'V', false, true },
@@ -204,6 +217,7 @@ Branch branches[] = {
NULL,
false, true, LIGHTGREY, LIGHTGREY,
mons_hallblade_rare, mons_hallblade_level,
+ NULL, NULL, NULL, NULL,
0, 'B', false, false },
{ BRANCH_CRYPT, BRANCH_VAULTS, 5, 3, 0, 0,
@@ -212,6 +226,7 @@ Branch branches[] = {
NULL,
false, true, LIGHTGREY, LIGHTGREY,
mons_crypt_rare, mons_crypt_level,
+ NULL, NULL, NULL, NULL,
5, 'C', false, false },
{ BRANCH_TOMB, BRANCH_CRYPT, 3, 5, 0, 0,
@@ -220,6 +235,7 @@ Branch branches[] = {
NULL,
false, true, YELLOW, LIGHTGREY,
mons_tomb_rare, mons_tomb_level,
+ NULL, NULL, NULL, NULL,
0, 'G', false, true },
{ BRANCH_VESTIBULE_OF_HELL, BRANCH_MAIN_DUNGEON, 1, -1, 0, 0,
@@ -228,6 +244,7 @@ Branch branches[] = {
NULL,
false, true, LIGHTGREY, LIGHTGREY,
mons_standard_rare, mons_standard_level,
+ NULL, NULL, NULL, NULL,
0, 'U', false, false },
{ BRANCH_DIS, BRANCH_VESTIBULE_OF_HELL, 7, -1, 0, 0,
@@ -236,6 +253,7 @@ Branch branches[] = {
NULL,
false, false, CYAN, CYAN,
mons_dis_rare, mons_dis_level,
+ NULL, NULL, NULL, NULL,
0, 'I', true, true },
{ BRANCH_GEHENNA, BRANCH_VESTIBULE_OF_HELL, 7, -1, 0, 0,
@@ -244,6 +262,7 @@ Branch branches[] = {
NULL,
false, false, DARKGREY, RED,
mons_gehenna_rare, mons_gehenna_level,
+ NULL, NULL, NULL, NULL,
0, 'N', true, true },
{ BRANCH_COCYTUS, BRANCH_VESTIBULE_OF_HELL, 7, -1, 0, 0,
@@ -252,6 +271,7 @@ Branch branches[] = {
NULL,
false, false, LIGHTBLUE, LIGHTCYAN,
mons_cocytus_rare, mons_cocytus_level,
+ NULL, NULL, NULL, NULL,
0, 'X', true, true },
{ BRANCH_TARTARUS, BRANCH_VESTIBULE_OF_HELL, 7, -1, 0, 0,
@@ -260,6 +280,7 @@ Branch branches[] = {
NULL,
false, false, DARKGREY, DARKGREY,
mons_tartarus_rare, mons_tartarus_level,
+ NULL, NULL, NULL, NULL,
0, 'Y', true, true },
{ BRANCH_INFERNO, BRANCH_MAIN_DUNGEON, -1, -1, 0, 0,
@@ -268,6 +289,7 @@ Branch branches[] = {
NULL,
false, false, BLACK, BLACK,
NULL, NULL,
+ NULL, NULL, NULL, NULL,
0, 'R', false, false },
{ BRANCH_THE_PIT, BRANCH_MAIN_DUNGEON, -1, -1, 0, 0,
@@ -276,6 +298,7 @@ Branch branches[] = {
NULL,
false, false, BLACK, BLACK,
NULL, NULL,
+ NULL, NULL, NULL, NULL,
0, '0', false, false },
{ BRANCH_HALL_OF_ZOT, BRANCH_MAIN_DUNGEON, 5, 27, BFLAG_HAS_ORB, 0,
@@ -284,6 +307,7 @@ Branch branches[] = {
NULL,
false, true, BLACK, BLACK,
mons_hallzot_rare, mons_hallzot_level,
+ NULL, NULL, NULL, NULL,
1, 'Z', false, true },
{ BRANCH_CAVERNS, BRANCH_MAIN_DUNGEON, -1, -1, 0, 0,
@@ -292,5 +316,6 @@ Branch branches[] = {
NULL,
false, false, BLACK, BLACK,
NULL, NULL,
+ NULL, NULL, NULL, NULL,
0, 0, false, false }
};
diff --git a/crawl-ref/source/branch.h b/crawl-ref/source/branch.h
index 404c40d6b9..0598f31247 100644
--- a/crawl-ref/source/branch.h
+++ b/crawl-ref/source/branch.h
@@ -12,6 +12,8 @@
#include "enum.h"
+struct fog_machine_data;
+
enum branch_flag_type
{
BFLAG_NONE = 0,
@@ -41,8 +43,12 @@ struct Branch
bool has_uniques;
char floor_colour; // Zot needs special handling
char rock_colour;
- int (*mons_rarity_function)(int);
- int (*mons_level_function)(int);
+ int (*mons_rarity_function)(int);
+ int (*mons_level_function)(int);
+ int (*num_traps_function)(int);
+ trap_type (*rand_trap_function)(int);
+ int (*num_fogs_function)(int);
+ void (*rand_fog_function)(int,fog_machine_data&);
int altar_chance; // in percent
int travel_shortcut; // which key to press for travel
bool any_upstair_exits; // any upstair exits the branch (Hell branches)
diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc
index ae7b614045..3d471f41ee 100644
--- a/crawl-ref/source/cloud.cc
+++ b/crawl-ref/source/cloud.cc
@@ -15,9 +15,11 @@
#include "AppHdr.h"
#include "externs.h"
+#include "branch.h"
#include "cloud.h"
#include "mapmark.h"
#include "misc.h"
+#include "place.h"
#include "stuff.h"
#include "terrain.h"
@@ -310,6 +312,12 @@ cloud_type random_smoke_type()
void place_fog_machine(fog_machine_type fm_type, cloud_type cl_type,
int x, int y, int size, int power)
{
+ ASSERT(fm_type >= FM_GEYSER && fm_type < NUM_FOG_MACHINE_TYPES);
+ ASSERT(cl_type > CLOUD_NONE && (cl_type < CLOUD_RANDOM
+ || cl_type == CLOUD_DEBUGGING));
+ ASSERT(size >= 1);
+ ASSERT(power >= 1);
+
const char* fog_types[] = {
"geyser",
"spread",
@@ -342,6 +350,159 @@ void place_fog_machine(fog_machine_type fm_type, cloud_type cl_type,
}
}
+void place_fog_machine(fog_machine_data data, int x, int y)
+{
+ place_fog_machine(data.fm_type, data.cl_type, x, y, data.size,
+ data.power);
+}
+
+bool valid_fog_machine_data(fog_machine_data data)
+{
+ if (data.fm_type < FM_GEYSER || data.fm_type >= NUM_FOG_MACHINE_TYPES)
+ return false;
+
+ if (data.cl_type <= CLOUD_NONE || (data.cl_type >= CLOUD_RANDOM
+ && data.cl_type != CLOUD_DEBUGGING))
+ return false;
+
+ if (data.size < 1 || data.power < 1)
+ return false;
+
+ return true;
+}
+
+int num_fogs_for_place(int level_number, const level_id &place)
+{
+ if (level_number == -1)
+ {
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ level_number = absdungeon_depth(place.branch, place.depth);
+ break;
+ case LEVEL_ABYSS:
+ level_number = 51;
+ break;
+ case LEVEL_PANDEMONIUM:
+ level_number = 52;
+ break;
+ default:
+ level_number = you.your_level;
+ }
+ }
+
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ {
+ Branch &branch = branches[place.branch];
+ ASSERT((branch.num_fogs_function == NULL
+ && branch.rand_fog_function == NULL)
+ || (branch.num_fogs_function != NULL
+ && branch.rand_fog_function != NULL));
+
+ if (branch.num_fogs_function == NULL)
+ return 0;
+
+ return branch.num_fogs_function(level_number);
+ }
+ case LEVEL_ABYSS:
+ return fogs_abyss_number(level_number);
+ case LEVEL_PANDEMONIUM:
+ return fogs_pan_number(level_number);
+ case LEVEL_LABYRINTH:
+ return fogs_lab_number(level_number);
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+fog_machine_data random_fog_for_place(int level_number, const level_id &place)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ if (level_number == -1)
+ {
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ level_number = absdungeon_depth(place.branch, place.depth);
+ break;
+ case LEVEL_ABYSS:
+ level_number = 51;
+ break;
+ case LEVEL_PANDEMONIUM:
+ level_number = 52;
+ break;
+ default:
+ level_number = you.your_level;
+ }
+ }
+
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ {
+ Branch &branch = branches[place.branch];
+ ASSERT(branch.num_fogs_function != NULL
+ && branch.rand_fog_function != NULL);
+ fog_machine_data data;
+
+ branch.rand_fog_function(level_number, data);
+ return data;
+ }
+ case LEVEL_ABYSS:
+ return fogs_abyss_type(level_number);
+ case LEVEL_PANDEMONIUM:
+ return fogs_pan_type(level_number);
+ case LEVEL_LABYRINTH:
+ return fogs_lab_type(level_number);
+ default:
+ ASSERT(false);
+ return data;
+ }
+
+ ASSERT(false);
+ return data;
+}
+
+int fogs_pan_number(int level_number)
+{
+ return 0;
+}
+
+fog_machine_data fogs_pan_type(int level_number)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ return data;
+}
+
+int fogs_abyss_number(int level_number)
+{
+ return 0;
+}
+
+fog_machine_data fogs_abyss_type(int level_number)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ return data;
+}
+
+int fogs_lab_number(int level_number)
+{
+ return 0;
+}
+
+fog_machine_data fogs_lab_type(int level_number)
+{
+ fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1};
+
+ return data;
+}
////////////////////////////////////////////////////////////////////////
// cloud_struct
diff --git a/crawl-ref/source/cloud.h b/crawl-ref/source/cloud.h
index 157aa1932c..0cee66ca0d 100644
--- a/crawl-ref/source/cloud.h
+++ b/crawl-ref/source/cloud.h
@@ -13,6 +13,7 @@
#define CLOUD_H
#include "externs.h"
+#include "travel.h"
enum fog_machine_type
{
@@ -22,6 +23,14 @@ enum fog_machine_type
NUM_FOG_MACHINE_TYPES
};
+struct fog_machine_data
+{
+ fog_machine_type fm_type;
+ cloud_type cl_type;
+ int size;
+ int power;
+};
+
cloud_type random_smoke_type();
void delete_cloud( int cloud );
@@ -40,4 +49,22 @@ int steam_cloud_damage(const cloud_struct &cloud);
void place_fog_machine(fog_machine_type fm_type, cloud_type cl_type,
int x, int y, int size, int power);
+void place_fog_machine(fog_machine_data data, int x, int y);
+
+bool valid_fog_machine_data(fog_machine_data data);
+
+int num_fogs_for_place(int level_number = -1,
+ const level_id &place = level_id::current());
+fog_machine_data random_fog_for_place(int level_number = -1,
+ const level_id &place = level_id::current());
+
+int fogs_pan_number(int level_number = -1);
+fog_machine_data fogs_pan_type(int level_number = -1);
+
+int fogs_abyss_number(int level_number = -1);
+fog_machine_data fogs_abyss_type(int level_number = -1);
+
+int fogs_lab_number(int level_number = -1);
+fog_machine_data fogs_lab_type(int level_number = -1);
+
#endif
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index abeb5e4ad5..7a124183fe 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -34,6 +34,7 @@
#include "AppHdr.h"
#include "abyss.h"
#include "branch.h"
+#include "cloud.h"
#include "defines.h"
#include "enum.h"
#include "externs.h"
@@ -137,6 +138,7 @@ static void place_minivaults(const std::string &tag = "",
int fewest = -1, int most = -1,
bool force = false);
static void place_traps( int level_number );
+static void place_fog_machines( int level_number );
static void prepare_swamp();
static void prepare_shoals( int level_number );
static void prepare_water( int level_number );
@@ -982,8 +984,8 @@ static void build_dungeon_level(int level_number, int level_type)
if (dgn_level_vetoed)
return;
- if (!player_in_branch( BRANCH_ECUMENICAL_TEMPLE ))
- place_traps(level_number);
+ place_traps(level_number);
+ place_fog_machines(level_number);
// place items
builder_items(level_number, level_type, num_items_wanted(level_number));
@@ -2057,53 +2059,13 @@ static void builder_extras( int level_number, int level_type )
}
}
-// Also checks you.where_are_you!
-static trap_type random_trap_for_level(int level_number)
-{
- trap_type type = TRAP_DART;
-
- if ((random2(1 + level_number) > 1) && one_chance_in(4))
- type = TRAP_NEEDLE;
- if (random2(1 + level_number) > 3)
- type = TRAP_SPEAR;
- if (random2(1 + level_number) > 5)
- type = TRAP_AXE;
-
- // Note we're boosting arrow trap numbers by moving it
- // down the list, and making spear and axe traps rarer.
- if (type == TRAP_DART?
- random2(1 + level_number) > 2
- : one_chance_in(7))
- type = TRAP_ARROW;
-
- if ((type == TRAP_DART || type == TRAP_ARROW) && one_chance_in(15))
- type = TRAP_NET;
-
- if (random2(1 + level_number) > 7)
- type = TRAP_BOLT;
- if (random2(1 + level_number) > 11)
- type = TRAP_BLADE;
-
- if ((random2(1 + level_number) > 14 && one_chance_in(3))
- || (player_in_branch( BRANCH_HALL_OF_ZOT ) && coinflip()))
- {
- type = TRAP_ZOT;
- }
-
- if (one_chance_in(50) && is_valid_shaft_level())
- type = TRAP_SHAFT;
- if (one_chance_in(20))
- type = TRAP_TELEPORT;
- if (one_chance_in(40))
- type = TRAP_ALARM;
-
- return (type);
-}
-
static void place_traps(int level_number)
{
int i;
- int num_traps = random2avg(9, 2);
+ int num_traps = num_traps_for_place(level_number);
+
+ ASSERT(num_traps >= 0);
+ ASSERT(num_traps <= MAX_TRAPS);
for (i = 0; i < num_traps; i++)
{
@@ -2120,13 +2082,51 @@ static void place_traps(int level_number)
while (grd[env.trap[i].x][env.trap[i].y] != DNGN_FLOOR
&& --tries > 0);
+ if (tries <= 0)
+ break;
+
trap_type &trap_type = env.trap[i].type;
- trap_type = random_trap_for_level(level_number);
+ trap_type = random_trap_for_place(level_number);
grd[env.trap[i].x][env.trap[i].y] = DNGN_UNDISCOVERED_TRAP;
} // end "for i"
} // end place_traps()
+static void place_fog_machines(int level_number)
+{
+ int i;
+ int num_fogs = num_fogs_for_place(level_number);
+
+ ASSERT(num_fogs >= 0);
+
+ for (i = 0; i < num_fogs; i++)
+ {
+ fog_machine_data data = random_fog_for_place(level_number);
+
+ if (!valid_fog_machine_data(data))
+ {
+ mpr("Invalid fog machine data, bailing.", MSGCH_DIAGNOSTICS);
+ return;
+ }
+
+ int tries = 200;
+ int x, y;
+ dungeon_feature_type feat;
+ do
+ {
+ x = random2(GXM);
+ y = random2(GYM);
+ feat = grd[x][y];
+ }
+ while (feat <= DNGN_MAXWALL && --tries > 0);
+
+ if (tries <= 0)
+ break;
+
+ place_fog_machine(data, x, y);
+ } // end "for i"
+} // end place_traps()
+
static void place_specific_feature(dungeon_feature_type feat)
{
int sx, sy;
@@ -4265,7 +4265,7 @@ static int vault_grid( vault_placement &place,
else if (f.trap >= 0)
{
const trap_type trap =
- f.trap == TRAP_INDEPTH? random_trap_for_level(level_number)
+ f.trap == TRAP_INDEPTH? random_trap_for_place(level_number)
: static_cast<trap_type>(f.trap);
place_specific_trap(vx, vy, trap);
@@ -4341,7 +4341,7 @@ static int vault_grid( vault_placement &place,
place_specific_trap(vx, vy, TRAP_RANDOM);
break;
case '~':
- place_specific_trap(vx, vy, random_trap_for_level(level_number));
+ place_specific_trap(vx, vy, random_trap_for_place(level_number));
break;
}
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 24e3d1737a..8604af903b 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -1494,33 +1494,6 @@ bool go_berserk(bool intentional)
return true;
} // end go_berserk()
-bool is_valid_shaft_level()
-{
- if (you.level_type != LEVEL_DUNGEON)
- return (false);
-
- // Don't generate shafts in branches where teleport control
- // is prevented. Prevents player from going down levels without
- // reaching stairs, and also keeps player from getting stuck
- // on lower levels with the innability to use teleport control to
- // get back up.
- if (testbits(get_branch_flags(), LFLAG_NO_TELE_CONTROL))
- {
- return (false);
- }
-
- int depth = subdungeon_depth(you.where_are_you, you.your_level);
-
- // When generating levels, don't place a shaft on the level
- // immediately above the bottom of a branch if that branch is
- // significantly more dangerous than normal.
- int min_delta = 1;
- if (env.turns_on_level == -1 && your_branch().dangerous_bottom_level)
- min_delta = 2;
-
- return ((your_branch().depth - depth) >= min_delta);
-}
-
bool is_damaging_cloud(cloud_type type)
{
switch (type)
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 0dee017b67..460c76e403 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -123,7 +123,4 @@ bool scramble(void);
bool interrupt_cmd_repeat( activity_interrupt_type ai,
const activity_interrupt_data &at );
-//////////////////////////////////////////////////////////////////////
-bool is_valid_shaft_level();
-
#endif
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index 299f5d277b..b44543425f 100644
--- a/crawl-ref/source/traps.cc
+++ b/crawl-ref/source/traps.cc
@@ -16,6 +16,7 @@
#include "traps.h"
#include "beam.h"
+#include "branch.h"
#include "direct.h"
#include "it_use2.h"
#include "items.h"
@@ -25,6 +26,7 @@
#include "mon-util.h"
#include "monstuff.h"
#include "ouch.h"
+#include "place.h"
#include "player.h"
#include "randart.h"
#include "skills.h"
@@ -925,3 +927,195 @@ trap_type trap_type_at_xy(int x, int y)
return (idx == -1? NUM_TRAPS : env.trap[idx].type);
}
+bool is_valid_shaft_level(const level_id &place)
+{
+ if (place.level_type != LEVEL_DUNGEON)
+ return (false);
+
+ // Don't generate shafts in branches where teleport control
+ // is prevented. Prevents player from going down levels without
+ // reaching stairs, and also keeps player from getting stuck
+ // on lower levels with the innability to use teleport control to
+ // get back up.
+ if (testbits(get_branch_flags(place.branch), LFLAG_NO_TELE_CONTROL))
+ {
+ return (false);
+ }
+
+ const Branch &branch = branches[place.branch];
+
+ // When generating levels, don't place a shaft on the level
+ // immediately above the bottom of a branch if that branch is
+ // significantly more dangerous than normal.
+ int min_delta = 1;
+ if (env.turns_on_level == -1 && branch.dangerous_bottom_level)
+ min_delta = 2;
+
+ return ((branch.depth - place.depth) >= min_delta);
+}
+
+static int num_traps_default(int level_number, const level_id &place)
+{
+ return random2avg(9, 2);
+}
+
+int num_traps_for_place(int level_number, const level_id &place)
+{
+ if (level_number == -1)
+ {
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ level_number = absdungeon_depth(place.branch, place.depth);
+ break;
+ case LEVEL_ABYSS:
+ level_number = 51;
+ break;
+ case LEVEL_PANDEMONIUM:
+ level_number = 52;
+ break;
+ default:
+ level_number = you.your_level;
+ }
+ }
+
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ if (branches[place.branch].num_traps_function != NULL)
+ return branches[place.branch].num_traps_function(level_number);
+ else
+ return num_traps_default(level_number, place);
+ case LEVEL_ABYSS:
+ return traps_abyss_number(level_number);
+ case LEVEL_PANDEMONIUM:
+ return traps_pan_number(level_number);
+ case LEVEL_LABYRINTH:
+ case LEVEL_PORTAL_VAULT:
+ ASSERT(false);
+ break;
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static trap_type random_trap_default(int level_number, const level_id &place)
+{
+ trap_type type = TRAP_DART;
+
+ if ((random2(1 + level_number) > 1) && one_chance_in(4))
+ type = TRAP_NEEDLE;
+ if (random2(1 + level_number) > 3)
+ type = TRAP_SPEAR;
+ if (random2(1 + level_number) > 5)
+ type = TRAP_AXE;
+
+ // Note we're boosting arrow trap numbers by moving it
+ // down the list, and making spear and axe traps rarer.
+ if (type == TRAP_DART?
+ random2(1 + level_number) > 2
+ : one_chance_in(7))
+ type = TRAP_ARROW;
+
+ if ((type == TRAP_DART || type == TRAP_ARROW) && one_chance_in(15))
+ type = TRAP_NET;
+
+ if (random2(1 + level_number) > 7)
+ type = TRAP_BOLT;
+ if (random2(1 + level_number) > 11)
+ type = TRAP_BLADE;
+
+ if ((random2(1 + level_number) > 14 && one_chance_in(3))
+ || (place.branch == BRANCH_HALL_OF_ZOT &&
+ place.level_type == LEVEL_DUNGEON && coinflip()))
+ {
+ type = TRAP_ZOT;
+ }
+
+ if (one_chance_in(50) && is_valid_shaft_level(place))
+ type = TRAP_SHAFT;
+ if (one_chance_in(20))
+ type = TRAP_TELEPORT;
+ if (one_chance_in(40))
+ type = TRAP_ALARM;
+
+ return (type);
+}
+
+trap_type random_trap_for_place(int level_number, const level_id &place)
+{
+ if (level_number == -1)
+ {
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ level_number = absdungeon_depth(place.branch, place.depth);
+ break;
+ case LEVEL_ABYSS:
+ level_number = 51;
+ break;
+ case LEVEL_PANDEMONIUM:
+ level_number = 52;
+ break;
+ default:
+ level_number = you.your_level;
+ }
+ }
+
+ switch(place.level_type)
+ {
+ case LEVEL_DUNGEON:
+ if (branches[place.branch].rand_trap_function != NULL)
+ return branches[place.branch].rand_trap_function(level_number);
+ else
+ return random_trap_default(level_number, place);
+ case LEVEL_ABYSS:
+ return traps_abyss_type(level_number);
+ case LEVEL_PANDEMONIUM:
+ return traps_pan_type(level_number);
+ case LEVEL_LABYRINTH:
+ case LEVEL_PORTAL_VAULT:
+ ASSERT(false);
+ break;
+ default:
+ return random_trap_default(level_number, place);
+ }
+ return NUM_TRAPS;
+}
+
+int traps_zero_number(int level_number)
+{
+ return 0;
+}
+
+int traps_pan_number(int level_number)
+{
+ return num_traps_default(level_number, level_id(LEVEL_PANDEMONIUM));
+}
+
+trap_type traps_pan_type(int level_number)
+{
+ return random_trap_default(level_number, level_id(LEVEL_PANDEMONIUM));
+}
+
+int traps_abyss_number(int level_number)
+{
+ return num_traps_default(level_number, level_id(LEVEL_ABYSS));
+}
+
+trap_type traps_abyss_type(int level_number)
+{
+ return random_trap_default(level_number, level_id(LEVEL_ABYSS));
+}
+
+int traps_lab_number(int level_number)
+{
+ return num_traps_default(level_number, level_id(LEVEL_LABYRINTH));
+}
+
+trap_type traps_lab_type(int level_number)
+{
+ return random_trap_default(level_number, level_id(LEVEL_LABYRINTH));
+}
diff --git a/crawl-ref/source/traps.h b/crawl-ref/source/traps.h
index c86041840e..1853cf5313 100644
--- a/crawl-ref/source/traps.h
+++ b/crawl-ref/source/traps.h
@@ -14,6 +14,7 @@
#define TRAPS_H
#include "enum.h"
+#include "travel.h"
struct dist;
struct bolt;
@@ -63,4 +64,22 @@ dungeon_feature_type trap_category(trap_type type);
int trap_at_xy(int x, int y);
trap_type trap_type_at_xy(int x, int y);
+bool is_valid_shaft_level(const level_id &place = level_id::current());
+
+int num_traps_for_place(int level_number = -1,
+ const level_id &place = level_id::current());
+trap_type random_trap_for_place(int level_number = -1,
+ const level_id &place = level_id::current());
+
+int traps_zero_number(int level_number = -1);
+
+int traps_pan_number(int level_number = -1);
+trap_type traps_pan_type(int level_number = -1);
+
+int traps_abyss_number(int level_number = -1);
+trap_type traps_abyss_type(int level_number = -1);
+
+int traps_lab_number(int level_number = -1);
+trap_type traps_lab_type(int level_number = -1);
+
#endif