summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/traps.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/traps.cc')
-rw-r--r--crawl-ref/source/traps.cc310
1 files changed, 292 insertions, 18 deletions
diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc
index d8e1043695..db6d7b1f49 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"
@@ -285,44 +287,64 @@ void itrap( struct bolt &pbolt, int trapped )
return;
} // end itrap()
-void handle_traps(char trt, int i, bool trap_known)
+void handle_traps(trap_type trt, int i, bool trap_known)
{
struct bolt beam;
+
+ bool branchtype = false;
+ if (trap_category(trt) == DNGN_TRAP_MECHANICAL && trt != TRAP_NET
+ && trt != TRAP_BLADE)
+ {
+ if (you.where_are_you == BRANCH_ORCISH_MINES)
+ {
+ beam.name = "n orcish";
+ branchtype = true;
+ }
+ else if (you.where_are_you == BRANCH_ELVEN_HALLS)
+ {
+ beam.name = "n elven";
+ branchtype = true;
+ }
+ else
+ beam.name = "";
+ }
switch (trt)
{
case TRAP_DART:
- beam.name = " dart";
+ beam.name += " dart";
beam.damage = dice_def( 1, 4 + (you.your_level / 2) );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_NEEDLE:
- beam.name = " needle";
+ beam.name += " needle";
beam.damage = dice_def( 1, 0 );
dart_trap(trap_known, i, beam, true);
break;
case TRAP_ARROW:
- beam.name = "n arrow";
+ beam.name += (branchtype? "" : "n");
+ beam.name += " arrow";
beam.damage = dice_def( 1, 7 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_BOLT:
- beam.name = " bolt";
+ beam.name += " bolt";
beam.damage = dice_def( 1, 13 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_SPEAR:
- beam.name = " spear";
+ beam.name += " spear";
beam.damage = dice_def( 1, 10 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
case TRAP_AXE:
- beam.name = "n axe";
+ beam.name += (branchtype? "" : "n");
+ beam.name += " axe";
beam.damage = dice_def( 1, 15 + you.your_level );
dart_trap(trap_known, i, beam, false);
break;
@@ -336,10 +358,18 @@ void handle_traps(char trt, int i, bool trap_known)
you_teleport_now( true );
break;
- case TRAP_AMNESIA:
- mpr("You feel momentarily disoriented.");
- if (!wearing_amulet(AMU_CLARITY))
- forget_map(random2avg(100, 2));
+ case TRAP_ALARM:
+ if (silenced(you.x_pos, you.y_pos))
+ {
+ if (trap_known)
+ mpr("The alarm is silenced.");
+ else
+ grd[you.x_pos][you.y_pos] = DNGN_UNDISCOVERED_TRAP;
+ return;
+ }
+
+ noisy(12, you.x_pos, you.y_pos, "An alarm trap emits a blaring wail!");
+
break;
case TRAP_BLADE:
@@ -359,7 +389,6 @@ void handle_traps(char trt, int i, bool trap_known)
break;
case TRAP_NET:
-
if (trap_known && one_chance_in(3))
mpr("A net swings high above you.");
else
@@ -383,6 +412,42 @@ void handle_traps(char trt, int i, bool trap_known)
env.trap[i].type = TRAP_UNASSIGNED;
}
break;
+
+ // If we don't trigger the shaft, and the player doesn't
+ // already know about it, don't let him/her notice it.
+ case TRAP_SHAFT:
+ {
+ // Paranoia
+ if (!is_valid_shaft_level())
+ {
+ if (trap_known)
+ mpr("The shaft disappears in a puff of logic!");
+
+ grd[env.trap[i].x][env.trap[i].y] = DNGN_FLOOR;
+ env.trap[i].type = TRAP_UNASSIGNED;
+ return;
+ }
+
+ if (!you.will_trigger_shaft())
+ {
+ if (trap_known && !you.airborne())
+ mpr("You don't fall through the shaft..");
+
+ if (!trap_known)
+ grd[you.x_pos][you.y_pos] = DNGN_UNDISCOVERED_TRAP;
+
+ return;
+ }
+
+ if (!you.do_shaft())
+ if (!trap_known)
+ {
+ grd[you.x_pos][you.y_pos] = DNGN_UNDISCOVERED_TRAP;
+ return;
+ }
+
+ break;
+ }
case TRAP_ZOT:
default:
@@ -579,12 +644,11 @@ static int damage_or_escape_net(int hold)
damage += 2;
else if (you.has_usable_claws())
{
- if (you.species == SP_TROLL || you.species == SP_GHOUL)
- damage += 2;
- else if (you.mutation[MUT_CLAWS] == 1)
+ int level = you.has_claws();
+ if (level == 1)
damage += coinflip();
else
- damage += you.mutation[MUT_CLAWS] - 1;
+ damage += level - 1;
}
// Berserkers get a fighting bonus
@@ -759,7 +823,6 @@ bool trap_item(object_class_type base_type, char sub_type,
char beam_x, char beam_y)
{
item_def item;
-
item.base_type = base_type;
item.sub_type = sub_type;
item.plus = 0;
@@ -801,6 +864,15 @@ bool trap_item(object_class_type base_type, char sub_type,
}
} // end of if igrd != NON_ITEM
+ // give appropriate racial flag for Orcish Mines and Elven Halls
+ // should we ever allow properties of dungeon features, we could use that
+ if ( item.sub_type != MI_THROWING_NET )
+ {
+ if (you.where_are_you == BRANCH_ORCISH_MINES)
+ set_equip_race( item, ISFLAG_ORCISH );
+ else if (you.where_are_you == BRANCH_ELVEN_HALLS)
+ set_equip_race( item, ISFLAG_ELVEN );
+ }
return (!copy_item_to_grid( item, beam_x, beam_y, 1 ));
} // end trap_item()
@@ -809,8 +881,11 @@ dungeon_feature_type trap_category(trap_type type)
{
switch (type)
{
+ case TRAP_SHAFT:
+ return (DNGN_TRAP_NATURAL);
+
case TRAP_TELEPORT:
- case TRAP_AMNESIA:
+ case TRAP_ALARM:
case TRAP_ZOT:
return (DNGN_TRAP_MAGICAL);
@@ -851,3 +926,202 @@ 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);
+
+ // disallow shafts on the first two levels
+ if (place.branch == BRANCH_MAIN_DUNGEON
+ && you.your_level < 2)
+ {
+ 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));
+}