summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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