summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/misc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/misc.cc')
-rw-r--r--crawl-ref/source/misc.cc1358
1 files changed, 10 insertions, 1348 deletions
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 3811cb6a61..4b3a6a8f4a 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -35,48 +35,42 @@
#endif
#include "externs.h"
+#include "misc.h"
#include "abyss.h"
#include "branch.h"
-#include "chardump.h"
-#include "cloud.h"
#include "clua.h"
+#include "cloud.h"
#include "delay.h"
#include "dgnevent.h"
-#include "fight.h"
+#include "direct.h"
+#include "dungeon.h"
#include "files.h"
#include "food.h"
-#include "hiscores.h"
#include "it_use2.h"
-#include "items.h"
#include "itemprop.h"
+#include "items.h"
#include "lev-pand.h"
-#include "macro.h"
-#include "makeitem.h"
-#include "mapmark.h"
-#include "monplace.h"
+#include "message.h"
#include "mon-util.h"
#include "monstuff.h"
-#include "mstuff2.h"
-#include "notes.h"
#include "ouch.h"
-#include "overmap.h"
+#include "place.h"
#include "player.h"
#include "religion.h"
#include "shopping.h"
#include "skills.h"
#include "skills2.h"
#include "spells3.h"
-#include "spl-cast.h"
+#include "stash.h"
#include "stuff.h"
+#include "terrain.h"
#include "transfor.h"
+#include "traps.h"
#include "travel.h"
#include "tutorial.h"
#include "view.h"
-bool scramble(void);
-static void dart_trap(bool trap_known, int trapped, bolt &pbolt, bool poison);
-
// void place_chunks(int mcls, unsigned char rot_status, unsigned char chx,
// unsigned char chy, unsigned char ch_col)
void turn_corpse_into_chunks( item_def &item )
@@ -151,246 +145,6 @@ void turn_corpse_into_chunks( item_def &item )
}
} // end place_chunks()
-bool grid_is_wall( dungeon_feature_type grid )
-{
- return (grid == DNGN_ROCK_WALL
- || grid == DNGN_STONE_WALL
- || grid == DNGN_METAL_WALL
- || grid == DNGN_GREEN_CRYSTAL_WALL
- || grid == DNGN_WAX_WALL
- || grid == DNGN_PERMAROCK_WALL);
-}
-
-bool grid_is_stone_stair(dungeon_feature_type grid)
-{
- switch (grid)
- {
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- return (true);
- default:
- return (false);
- }
-}
-
-bool grid_is_rock_stair(dungeon_feature_type grid)
-{
- switch (grid)
- {
- case DNGN_ROCK_STAIRS_UP:
- case DNGN_ROCK_STAIRS_DOWN:
- return (true);
- default:
- return (false);
- }
-}
-
-bool grid_sealable_portal(dungeon_feature_type grid)
-{
- switch (grid)
- {
- case DNGN_ENTER_HELL:
- case DNGN_ENTER_ABYSS:
- case DNGN_ENTER_PANDEMONIUM:
- case DNGN_ENTER_LABYRINTH:
- case DNGN_ENTER_PORTAL_VAULT:
- return (true);
- default:
- return (false);
- }
-}
-
-bool grid_is_portal(dungeon_feature_type grid)
-{
- return (grid == DNGN_ENTER_PORTAL_VAULT || grid == DNGN_EXIT_PORTAL_VAULT);
-}
-
-command_type grid_stair_direction(dungeon_feature_type grid)
-{
- switch (grid)
- {
- case DNGN_STONE_STAIRS_UP_I:
- case DNGN_STONE_STAIRS_UP_II:
- case DNGN_STONE_STAIRS_UP_III:
- case DNGN_ROCK_STAIRS_UP:
- case DNGN_RETURN_FROM_ORCISH_MINES:
- case DNGN_RETURN_FROM_HIVE:
- case DNGN_RETURN_FROM_LAIR:
- case DNGN_RETURN_FROM_SLIME_PITS:
- case DNGN_RETURN_FROM_VAULTS:
- case DNGN_RETURN_FROM_CRYPT:
- case DNGN_RETURN_FROM_HALL_OF_BLADES:
- case DNGN_RETURN_FROM_ZOT:
- case DNGN_RETURN_FROM_TEMPLE:
- case DNGN_RETURN_FROM_SNAKE_PIT:
- case DNGN_RETURN_FROM_ELVEN_HALLS:
- case DNGN_RETURN_FROM_TOMB:
- case DNGN_RETURN_FROM_SWAMP:
- case DNGN_RETURN_FROM_SHOALS:
- case DNGN_RETURN_RESERVED_2:
- case DNGN_RETURN_RESERVED_3:
- case DNGN_RETURN_RESERVED_4:
- case DNGN_ENTER_SHOP:
- case DNGN_EXIT_HELL:
- case DNGN_EXIT_PORTAL_VAULT:
- return (CMD_GO_UPSTAIRS);
-
- case DNGN_ENTER_PORTAL_VAULT:
- case DNGN_ENTER_HELL:
- case DNGN_ENTER_LABYRINTH:
- case DNGN_STONE_STAIRS_DOWN_I:
- case DNGN_STONE_STAIRS_DOWN_II:
- case DNGN_STONE_STAIRS_DOWN_III:
- case DNGN_ROCK_STAIRS_DOWN:
- case DNGN_ENTER_DIS:
- case DNGN_ENTER_GEHENNA:
- case DNGN_ENTER_COCYTUS:
- case DNGN_ENTER_TARTARUS:
- case DNGN_ENTER_ABYSS:
- case DNGN_EXIT_ABYSS:
- case DNGN_ENTER_PANDEMONIUM:
- case DNGN_EXIT_PANDEMONIUM:
- case DNGN_TRANSIT_PANDEMONIUM:
- case DNGN_ENTER_ORCISH_MINES:
- case DNGN_ENTER_HIVE:
- case DNGN_ENTER_LAIR:
- case DNGN_ENTER_SLIME_PITS:
- case DNGN_ENTER_VAULTS:
- case DNGN_ENTER_CRYPT:
- case DNGN_ENTER_HALL_OF_BLADES:
- case DNGN_ENTER_ZOT:
- case DNGN_ENTER_TEMPLE:
- case DNGN_ENTER_SNAKE_PIT:
- case DNGN_ENTER_ELVEN_HALLS:
- case DNGN_ENTER_TOMB:
- case DNGN_ENTER_SWAMP:
- case DNGN_ENTER_SHOALS:
- case DNGN_ENTER_RESERVED_2:
- case DNGN_ENTER_RESERVED_3:
- case DNGN_ENTER_RESERVED_4:
- return (CMD_GO_DOWNSTAIRS);
-
- default:
- return (CMD_NO_CMD);
- }
-}
-
-bool grid_is_opaque( dungeon_feature_type grid )
-{
- return (grid < DNGN_MINSEE && grid != DNGN_ORCISH_IDOL);
-}
-
-bool grid_is_solid( dungeon_feature_type grid )
-{
- return (grid < DNGN_MINMOVE);
-}
-
-bool grid_is_solid( int x, int y )
-{
- return (grid_is_solid(grd[x][y]));
-}
-
-bool grid_is_solid(const coord_def &c)
-{
- return (grid_is_solid(grd(c)));
-}
-
-bool grid_is_trap(dungeon_feature_type grid)
-{
- return (grid == DNGN_TRAP_MECHANICAL || grid == DNGN_TRAP_MAGICAL
- || grid == DNGN_TRAP_III);
-}
-
-bool grid_is_water( dungeon_feature_type grid )
-{
- return (grid == DNGN_SHALLOW_WATER || grid == DNGN_DEEP_WATER);
-}
-
-bool grid_is_watery( dungeon_feature_type grid )
-{
- return (grid_is_water(grid) || grid == DNGN_BLUE_FOUNTAIN);
-}
-
-bool grid_destroys_items( dungeon_feature_type grid )
-{
- return (grid == DNGN_LAVA || grid == DNGN_DEEP_WATER);
-}
-
-// returns 0 if grid is not an altar, else it returns the GOD_* type
-god_type grid_altar_god( dungeon_feature_type grid )
-{
- if (grid >= DNGN_ALTAR_ZIN && grid <= DNGN_ALTAR_BEOGH)
- return (static_cast<god_type>( grid - DNGN_ALTAR_ZIN + 1 ));
-
- return (GOD_NO_GOD);
-}
-
-// returns DNGN_FLOOR for non-gods, otherwise returns the altar for
-// the god.
-dungeon_feature_type altar_for_god( god_type god )
-{
- if (god == GOD_NO_GOD || god >= NUM_GODS)
- return (DNGN_FLOOR); // Yeah, lame. Tell me about it.
-
- return static_cast<dungeon_feature_type>(DNGN_ALTAR_ZIN + god - 1);
-}
-
-bool grid_is_branch_stairs( dungeon_feature_type grid )
-{
- return ((grid >= DNGN_ENTER_ORCISH_MINES && grid <= DNGN_ENTER_RESERVED_4)
- || (grid >= DNGN_ENTER_DIS && grid <= DNGN_ENTER_TARTARUS));
-}
-
-int grid_secret_door_appearance( int gx, int gy )
-{
- int ret = DNGN_FLOOR;
-
- for (int dx = -1; dx <= 1; dx++)
- {
- for (int dy = -1; dy <= 1; dy++)
- {
- // only considering orthogonal grids
- if ((abs(dx) + abs(dy)) % 2 == 0)
- continue;
-
- const dungeon_feature_type targ = grd[gx + dx][gy + dy];
-
- if (!grid_is_wall( targ ))
- continue;
-
- if (ret == DNGN_FLOOR)
- ret = targ;
- else if (ret != targ)
- ret = ((ret < targ) ? ret : targ);
- }
- }
-
- return ((ret == DNGN_FLOOR) ? DNGN_ROCK_WALL
- : ret);
-}
-
-const char *grid_item_destruction_message( dungeon_feature_type grid )
-{
- return grid == DNGN_DEEP_WATER? "You hear a splash."
- : grid == DNGN_LAVA ? "You hear a sizzling splash."
- : "You hear a crunching noise.";
-}
-
-// Returns true if exits from this type of level involve going upstairs.
-bool level_type_exits_up(level_area_type type)
-{
- return (type == LEVEL_LABYRINTH || type == LEVEL_PORTAL_VAULT);
-}
-
-bool level_type_exits_down(level_area_type type)
-{
- return (type == LEVEL_PANDEMONIUM || type == LEVEL_ABYSS);
-}
-
void search_around( bool only_adjacent )
{
int i;
@@ -454,181 +208,6 @@ void search_around( bool only_adjacent )
return;
} // end search_around()
-static coord_def dgn_find_nearest_square(
- const coord_def &pos,
- bool (*acceptable)(const coord_def &),
- bool (*traversable)(const coord_def &) = NULL)
-{
- memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));
-
- std::list<coord_def> points[2];
- int iter = 0;
- points[iter].push_back(pos);
-
- while (!points[iter].empty())
- {
- for (std::list<coord_def>::iterator i = points[iter].begin();
- i != points[iter].end(); ++i)
- {
- const coord_def &p = *i;
-
- if (p != pos && acceptable(p))
- return (p);
-
- travel_point_distance[p.x][p.y] = 1;
- for (int yi = -1; yi <= 1; ++yi)
- {
- for (int xi = -1; xi <= 1; ++xi)
- {
- if (!xi && !yi)
- continue;
-
- const coord_def np = p + coord_def(xi, yi);
- if (!in_bounds(np) || travel_point_distance[np.x][np.y])
- continue;
-
- if (traversable && !traversable(np))
- continue;
-
- points[!iter].push_back(np);
- }
- }
- }
-
- points[iter].clear();
- iter = !iter;
- }
-
- coord_def unfound;
- return (unfound);
-}
-
-static bool item_safe_square(const coord_def &pos)
-{
- const dungeon_feature_type feat = grd(pos);
- return (is_traversable(feat) && !grid_destroys_items(feat));
-}
-
-// Moves an item on the floor to the nearest adjacent floor-space.
-static bool dgn_shift_item(const coord_def &pos, item_def &item)
-{
- const coord_def np = dgn_find_nearest_square(pos, item_safe_square);
- if (in_bounds(np) && np != pos)
- {
- int index = item.index();
- move_item_to_grid(&index, np.x, np.y);
- return (true);
- }
- return (false);
-}
-
-static bool is_critical_feature(dungeon_feature_type feat)
-{
- return (grid_stair_direction(feat) != CMD_NO_CMD
- || grid_altar_god(feat) != GOD_NO_GOD);
-}
-
-static bool is_feature_shift_target(const coord_def &pos)
-{
- return (grd(pos) == DNGN_FLOOR && !dungeon_events.has_listeners_at(pos));
-}
-
-static bool dgn_shift_feature(const coord_def &pos)
-{
- const dungeon_feature_type dfeat = grd(pos);
- if (!is_critical_feature(dfeat) && !env.markers.find(pos, MAT_ANY))
- return (false);
-
- const coord_def dest =
- dgn_find_nearest_square(pos, is_feature_shift_target);
- if (in_bounds(dest) && dest != pos)
- {
- grd(dest) = dfeat;
-
- if (dfeat == DNGN_ENTER_SHOP)
- {
- if (shop_struct *s = get_shop(pos.x, pos.y))
- {
- s->x = dest.x;
- s->y = dest.y;
- }
- }
- env.markers.move(pos, dest);
- dungeon_events.move_listeners(pos, dest);
- }
- return (true);
-}
-
-static void dgn_check_terrain_items(const coord_def &pos, bool preserve_items)
-{
- const dungeon_feature_type grid = grd(pos);
- if (grid_is_solid(grid) || grid_destroys_items(grid))
- {
- int item = igrd(pos);
- bool did_destroy = false;
- while (item != NON_ITEM)
- {
- const int curr = item;
- item = mitm[item].link;
-
- // Game-critical item.
- if (preserve_items || item_is_critical(mitm[curr]))
- dgn_shift_item(pos, mitm[curr]);
- else
- {
- destroy_item(curr);
- did_destroy = true;
- }
- }
- if (did_destroy && player_can_hear(pos))
- mprf(MSGCH_SOUND, grid_item_destruction_message(grid));
- }
-}
-
-static void dgn_check_terrain_monsters(const coord_def &pos)
-{
- const int mindex = mgrd(pos);
- if (mindex != NON_MONSTER)
- {
- monsters *mons = &menv[mindex];
- if (grid_is_solid(grd(pos)))
- monster_teleport(mons, true, false);
- else
- mons_check_pool(mons, KILL_MISC, -1);
- }
-}
-
-void dungeon_terrain_changed(const coord_def &pos,
- dungeon_feature_type nfeat,
- bool affect_player,
- bool preserve_features,
- bool preserve_items)
-{
- if (nfeat != DNGN_UNSEEN)
- {
- if (preserve_features)
- dgn_shift_feature(pos);
- unnotice_feature(level_pos(level_id::current(), pos));
- grd(pos) = nfeat;
- env.grid_colours(pos) = BLACK;
- if (is_notable_terrain(nfeat) && see_grid(pos))
- seen_notable_thing(nfeat, pos.x, pos.y);
- }
-
- dgn_check_terrain_items(pos, preserve_items);
- if (affect_player && pos == you.pos())
- {
- if (!grid_is_solid(grd(pos)))
- {
- if (!you.flies())
- move_player_to_grid(pos.x, pos.y, false, true, false);
- }
- else
- you_teleport_now(true, false);
- }
- dgn_check_terrain_monsters(pos);
-}
-
void in_a_cloud()
{
int cl = env.cgrid[you.x_pos][you.y_pos];
@@ -817,133 +396,6 @@ void curare_hits_player(int agent, int degree)
}
}
-// returns the number of a net on a given square
-// if trapped only stationary ones are counted
-// otherwise the first net found is returned
-int get_trapping_net(int x, int y, bool trapped)
-{
- int net, next;
-
- for (net = igrd[x][y]; net != NON_ITEM; net = next)
- {
- next = mitm[net].link;
-
- if (mitm[net].base_type == OBJ_MISSILES
- && mitm[net].sub_type == MI_THROWING_NET
- && (!trapped || item_is_stationary(mitm[net])))
- {
- return (net);
- }
- }
- return (NON_ITEM);
-}
-
-// if there are more than one net on this square
-// split off one of them for checking/setting values
-static void maybe_split_nets(item_def &item, int x, int y)
-{
- if (item.quantity == 1)
- {
- set_item_stationary(item);
- return;
- }
-
- item_def it;
-
- it.base_type = item.base_type;
- it.sub_type = item.sub_type;
- it.plus = item.plus;
- it.plus2 = item.plus2;
- it.flags = item.flags;
- it.special = item.special;
- it.quantity = --item.quantity;
- item_colour(it);
-
- item.quantity = 1;
- set_item_stationary(item);
-
- copy_item_to_grid( it, x, y );
-}
-
-void mark_net_trapping(int x, int y)
-{
- int net = get_trapping_net(x,y);
- if (net == NON_ITEM)
- {
- net = get_trapping_net(x,y, false);
- if (net != NON_ITEM)
- maybe_split_nets(mitm[net], x, y);
- }
-}
-
-void monster_caught_in_net(monsters *mon, bolt &pbolt)
-{
- if (mon->body_size(PSIZE_BODY) >= SIZE_GIANT)
- return;
-
- if (mons_is_insubstantial(mon->type))
- {
- if (mons_near(mon) && player_monster_visible(mon))
- mprf("The net passes right through %s!", mon->name(DESC_NOCAP_THE).c_str());
- return;
- }
-
- const monsters* mons = static_cast<const monsters*>(mon);
- bool mon_flies = mons->flies();
- if (mon_flies && !mons_is_confused(mons))
- {
- simple_monster_message(mon, " darts out from under the net!");
- return;
- }
-
- if (mons->type == MONS_OOZE || mons->type == MONS_PULSATING_LUMP)
- {
- simple_monster_message(mon, " oozes right through the net!");
- return;
- }
-
- if (!mons_is_caught(mon) && mon->add_ench(ENCH_HELD))
- {
- if (mons_near(mon) && !player_monster_visible(mon))
- mpr("Something gets caught in the net!");
- else
- simple_monster_message(mon, " is caught in the net!");
-
- if (mon_flies)
- {
- simple_monster_message(mon, " falls like a stone!");
- mons_check_pool(mon, pbolt.killer(), pbolt.beam_source);
- }
- }
-}
-
-void player_caught_in_net()
-{
- if (you.body_size(PSIZE_BODY) >= SIZE_GIANT)
- return;
-
- if (you.flies() && !you.confused())
- {
- mpr("You dart out from under the net!");
- return;
- }
-
- if (!you.attribute[ATTR_HELD])
- {
- you.attribute[ATTR_HELD] = 10;
- mpr("You become entangled in the net!");
-
- // I guess levitation works differently, keeping both you
- // and the net hovering above the floor
- if (you.flies())
- {
- mpr("You fall like a stone!");
- fall_into_a_pool(you.x_pos, you.y_pos, false, grd[you.x_pos][you.y_pos]);
- }
- }
-
-}
-
void merfolk_start_swimming(void)
{
if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE)
@@ -1619,449 +1071,6 @@ void new_level(void)
#endif
}
-static void dart_trap(bool trap_known, int trapped, bolt &pbolt, bool poison)
-{
- int damage_taken = 0;
- int trap_hit, your_dodge;
-
- if (one_chance_in(5) || (trap_known && !one_chance_in(4)))
- {
- mprf( "You avoid triggering a%s trap.", pbolt.name.c_str() );
- return;
- }
-
- if (you.equip[EQ_SHIELD] != -1 && one_chance_in(3))
- exercise( SK_SHIELDS, 1 );
-
- std::string msg = "A" + pbolt.name + " shoots out and ";
-
- if (random2( 20 + 5 * you.shield_blocks * you.shield_blocks )
- < player_shield_class())
- {
- you.shield_blocks++;
- msg += "hits your shield.";
- mpr(msg.c_str());
- }
- else
- {
- // note that this uses full ( not random2limit(foo,40) )
- // player_evasion.
- trap_hit = (20 + (you.your_level * 2)) * random2(200) / 100;
-
- your_dodge = player_evasion() + random2(you.dex) / 3
- - 2 + (you.duration[DUR_REPEL_MISSILES] * 10);
-
- if (trap_hit >= your_dodge && you.duration[DUR_DEFLECT_MISSILES] == 0)
- {
- msg += "hits you!";
- mpr(msg.c_str());
-
- if (poison && random2(100) < 50 - (3 * player_AC()) / 2
- && !player_res_poison())
- {
- poison_player( 1 + random2(3) );
- }
-
- damage_taken = roll_dice( pbolt.damage );
- damage_taken -= random2( player_AC() + 1 );
-
- if (damage_taken > 0)
- ouch( damage_taken, 0, KILLED_BY_TRAP, pbolt.name.c_str() );
- }
- else
- {
- msg += "misses you.";
- mpr(msg.c_str());
- }
-
- if (player_light_armour(true) && coinflip())
- exercise( SK_DODGING, 1 );
- }
-
- pbolt.target_x = you.x_pos;
- pbolt.target_y = you.y_pos;
-
- if (coinflip())
- itrap( pbolt, trapped );
-} // end dart_trap()
-
-//
-// itrap takes location from target_x, target_y of bolt strcture.
-//
-
-void itrap( struct bolt &pbolt, int trapped )
-{
- object_class_type base_type = OBJ_MISSILES;
- int sub_type = MI_DART;
-
- switch (env.trap[trapped].type)
- {
- case TRAP_DART:
- base_type = OBJ_MISSILES;
- sub_type = MI_DART;
- break;
- case TRAP_ARROW:
- base_type = OBJ_MISSILES;
- sub_type = MI_ARROW;
- break;
- case TRAP_BOLT:
- base_type = OBJ_MISSILES;
- sub_type = MI_BOLT;
- break;
- case TRAP_SPEAR:
- base_type = OBJ_WEAPONS;
- sub_type = WPN_SPEAR;
- break;
- case TRAP_AXE:
- base_type = OBJ_WEAPONS;
- sub_type = WPN_HAND_AXE;
- break;
- case TRAP_NEEDLE:
- base_type = OBJ_MISSILES;
- sub_type = MI_NEEDLE;
- break;
- case TRAP_NET:
- base_type = OBJ_MISSILES;
- sub_type = MI_THROWING_NET;
- break;
- default:
- return;
- }
-
- trap_item( base_type, sub_type, pbolt.target_x, pbolt.target_y );
-
- return;
-} // end itrap()
-
-void handle_traps(char trt, int i, bool trap_known)
-{
- struct bolt beam;
-
- switch (trt)
- {
- case TRAP_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.damage = dice_def( 1, 0 );
- dart_trap(trap_known, i, beam, true);
- break;
-
- case TRAP_ARROW:
- beam.name = "n 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.damage = dice_def( 1, 13 + you.your_level );
- dart_trap(trap_known, i, beam, false);
- break;
-
- case TRAP_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.damage = dice_def( 1, 15 + you.your_level );
- dart_trap(trap_known, i, beam, false);
- break;
-
- case TRAP_TELEPORT:
- mpr("You enter a teleport trap!");
-
- if (scan_randarts(RAP_PREVENT_TELEPORTATION))
- mpr("You feel a weird sense of stasis.");
- else
- you_teleport_now( true );
- break;
-
- case TRAP_AMNESIA:
- mpr("You feel momentarily disoriented.");
- if (!wearing_amulet(AMU_CLARITY))
- forget_map(random2avg(100, 2));
- break;
-
- case TRAP_BLADE:
- if (trap_known && one_chance_in(3))
- mpr("You avoid triggering a blade trap.");
- else if (random2limit(player_evasion(), 40)
- + (random2(you.dex) / 3) + (trap_known ? 3 : 0) > 8)
- {
- mpr("A huge blade swings just past you!");
- }
- else
- {
- mpr("A huge blade swings out and slices into you!");
- ouch( (you.your_level * 2) + random2avg(29, 2)
- - random2(1 + player_AC()), 0, KILLED_BY_TRAP, " blade" );
- }
- break;
-
- case TRAP_NET:
-
- if (trap_known && one_chance_in(3))
- mpr("A net swings high above you.");
- else
- {
- if (random2limit(player_evasion(), 40)
- + (random2(you.dex) / 3) + (trap_known ? 3 : 0) > 12)
- {
- mpr("A net drops to the ground!");
- }
- else
- {
- mpr("A large net falls onto you!");
- player_caught_in_net();
- }
-
- trap_item( OBJ_MISSILES, MI_THROWING_NET, env.trap[i].x, env.trap[i].y );
- if (you.attribute[ATTR_HELD])
- mark_net_trapping(you.x_pos, you.y_pos);
-
- grd[env.trap[i].x][env.trap[i].y] = DNGN_FLOOR;
- env.trap[i].type = TRAP_UNASSIGNED;
- }
- break;
-
- case TRAP_ZOT:
- default:
- mpr((trap_known) ? "You enter the Zot trap."
- : "Oh no! You have blundered into a Zot trap!");
- miscast_effect( SPTYP_RANDOM, random2(30) + you.your_level,
- 75 + random2(100), 3, "a Zot trap" );
- break;
- }
- learned_something_new(TUT_SEEN_TRAP, you.x_pos, you.y_pos);
-} // end handle_traps()
-
-void disarm_trap( struct dist &disa )
-{
- if (you.duration[DUR_BERSERKER])
- {
- canned_msg(MSG_TOO_BERSERK);
- return;
- }
-
- int i, j;
-
- for (i = 0; i < MAX_TRAPS; i++)
- {
- if (env.trap[i].x == you.x_pos + disa.dx
- && env.trap[i].y == you.y_pos + disa.dy)
- {
- break;
- }
-
- if (i == MAX_TRAPS - 1)
- {
- mpr("Error - couldn't find that trap.");
- return;
- }
- }
-
- if (trap_category(env.trap[i].type) == DNGN_TRAP_MAGICAL)
- {
- mpr("You can't disarm that trap.");
- return;
- }
-
- if (random2(you.skills[SK_TRAPS_DOORS] + 2) <= random2(you.your_level + 5))
- {
- mpr("You failed to disarm the trap.");
-
- you.turn_is_over = true;
-
- if (random2(you.dex) > 5 + random2(5 + you.your_level))
- exercise(SK_TRAPS_DOORS, 1 + random2(you.your_level / 5));
- else
- {
- if (env.trap[i].type == TRAP_NET &&
- (env.trap[i].x != you.x_pos || env.trap[i].y != you.y_pos))
- {
- if (coinflip())
- return;
-
- mpr("You stumble into the trap!");
- move_player_to_grid( env.trap[i].x, env.trap[i].y, true, false, true);
- }
- else
- handle_traps(env.trap[i].type, i, false);
-
- if (coinflip())
- exercise(SK_TRAPS_DOORS, 1);
- }
-
- return;
- }
-
- mpr("You have disarmed the trap.");
-
- struct bolt beam;
-
- beam.target_x = you.x_pos + disa.dx;
- beam.target_y = you.y_pos + disa.dy;
-
- if (env.trap[i].type == TRAP_NET)
- trap_item( OBJ_MISSILES, MI_THROWING_NET, beam.target_x, beam.target_y );
- else if (env.trap[i].type != TRAP_BLADE
- && trap_category(env.trap[i].type) == DNGN_TRAP_MECHANICAL)
- {
- const int num_to_make = 10 + random2(you.skills[SK_TRAPS_DOORS]);
- for (j = 0; j < num_to_make; j++)
- {
- // places items (eg darts), which will automatically stack
- itrap(beam, i);
- }
- }
-
- grd[you.x_pos + disa.dx][you.y_pos + disa.dy] = DNGN_FLOOR;
- env.trap[i].type = TRAP_UNASSIGNED;
- you.turn_is_over = true;
-
- // reduced from 5 + random2(5)
- exercise(SK_TRAPS_DOORS, 1 + random2(5) + (you.your_level / 5));
-} // end disarm_trap()
-
-// attempts to take a net off a given monster
-// Do not expect gratitude for this!
-// ----------------------------------
-void remove_net_from(monsters *mon)
-{
- you.turn_is_over = true;
-
- int net = get_trapping_net(mon->x, mon->y);
-
- if (net == NON_ITEM)
- {
- mon->del_ench(ENCH_HELD, true);
- return;
- }
-
- // factor in whether monster is paralysed or invisible
- int paralys = 0;
- if (mons_is_paralysed(mon)) // makes this easier
- paralys = random2(5);
-
- int invis = 0;
- if (!player_monster_visible(mon)) // makes this harder
- invis = 3 + random2(5);
-
- bool net_destroyed = false;
- if ( random2(you.skills[SK_TRAPS_DOORS] + 2) + paralys
- <= random2( 2*mon->body_size(PSIZE_BODY) + 3 ) + invis)
- {
- if (one_chance_in(you.skills[SK_TRAPS_DOORS] + you.dex/2))
- {
- mitm[net].plus--;
- mpr("You tear at the net.");
- if (mitm[net].plus < -7)
- {
- mpr("Whoops! The net comes apart in your hands!");
- mon->del_ench(ENCH_HELD, true);
- destroy_item(net);
- net_destroyed = true;
- }
- }
-
- if (!net_destroyed)
- {
- if (player_monster_visible(mon))
- {
- mprf("You fail to remove the net from %s.",
- mon->name(DESC_NOCAP_THE).c_str());
- }
- else
- mpr("You fail to remove the net.");
- }
-
- if (random2(you.dex) > 5 + random2( 2*mon->body_size(PSIZE_BODY) ))
- exercise(SK_TRAPS_DOORS, 1 + random2(mon->body_size(PSIZE_BODY)/2));
- return;
- }
-
- mon->del_ench(ENCH_HELD, true);
- remove_item_stationary(mitm[net]);
-
- if (player_monster_visible(mon))
- mprf("You free %s.", mon->name(DESC_NOCAP_THE).c_str());
- else
- mpr("You loosen the net.");
-
-}
-
-void free_self_from_net(bool damage_net)
-{
- int net = get_trapping_net(you.x_pos, you.y_pos);
-
- if (net == NON_ITEM) // really shouldn't happen!
- {
- you.attribute[ATTR_HELD] = 0;
- return;
- }
- int hold = mitm[net].plus;
-
- if (damage_net)
- {
- mpr("You struggle against the net.");
- int damage = 1;
-
- // extra damage for cutting weapons
- if (you.equip[EQ_WEAPON] != -1
- && can_cut_meat(you.inv[you.equip[EQ_WEAPON]]))
- {
- damage++;
- }
-
- if (you.body_size(PSIZE_BODY) > SIZE_MEDIUM)
- damage++;
-
- if (hold < 0 && !one_chance_in(-hold/2))
- damage++;
-
- if (you.duration[DUR_BERSERKER])
- damage *= 2;
-
- mitm[net].plus -= damage;
-
- if (mitm[net].plus < -7)
- {
- mpr("You rip the net and break free!");
- dec_mitm_item_quantity( net, 1 );
-
- you.attribute[ATTR_HELD] = 0;
- return;
- }
- }
- else // you try to escape
- {
- mpr("You struggle to escape from the net.");
- you.attribute[ATTR_HELD]--;
-
- if (you.body_size(PSIZE_BODY) < SIZE_MEDIUM)
- you.attribute[ATTR_HELD]--;
-
- if (hold < 0 && !one_chance_in(-hold/2))
- you.attribute[ATTR_HELD]--;
-
- if (you.attribute[ATTR_HELD] <= 0)
- {
- mpr("You break free from the net!");
- you.attribute[ATTR_HELD] = 0;
- remove_item_stationary(mitm[net]);
- return;
- }
- }
-}
-
std::string weird_writing()
{
int temp_rand; // for probability determinations {dlb}
@@ -2121,114 +1130,6 @@ std::string weird_writing()
return result;
}
-// returns true if we manage to scramble free.
-bool fall_into_a_pool( int entry_x, int entry_y, bool allow_shift,
- unsigned char terrain )
-{
- bool escape = false;
- FixedVector< char, 2 > empty;
-
- if (you.species == SP_MERFOLK && terrain == DNGN_DEEP_WATER)
- {
- // These can happen when we enter deep water directly -- bwr
- merfolk_start_swimming();
- return (false);
- }
-
- // sanity check
- if (terrain != DNGN_LAVA && beogh_water_walk())
- return (false);
-
- mprf("You fall into the %s!",
- (terrain == DNGN_LAVA) ? "lava" :
- (terrain == DNGN_DEEP_WATER) ? "water"
- : "programming rift");
-
- more();
- mesclr();
-
- if (terrain == DNGN_LAVA)
- {
- const int resist = player_res_fire();
-
- if (resist <= 0)
- {
- mpr( "The lava burns you to a cinder!" );
- ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
- }
- else
- {
- // should boost # of bangs per damage in the future {dlb}
- mpr( "The lava burns you!" );
- ouch( (10 + roll_dice(2,50)) / resist, 0, KILLED_BY_LAVA );
- }
-
- expose_player_to_element( BEAM_LAVA, 14 );
- }
-
- // a distinction between stepping and falling from you.duration[DUR_LEVITATION]
- // prevents stepping into a thin stream of lava to get to the other side.
- if (scramble())
- {
- if (allow_shift)
- {
- if (empty_surrounds( you.x_pos, you.y_pos, DNGN_FLOOR, 1,
- false, empty ))
- {
- escape = true;
- }
- else
- {
- escape = false;
- }
- }
- else
- {
- // back out the way we came in, if possible
- if (grid_distance( you.x_pos, you.y_pos, entry_x, entry_y ) == 1
- && (entry_x != empty[0] || entry_y != empty[1])
- && mgrd[entry_x][entry_y] == NON_MONSTER)
- {
- escape = true;
- empty[0] = entry_x;
- empty[1] = entry_y;
- }
- else // zero or two or more squares away, with no way back
- {
- escape = false;
- }
- }
- }
- else
- {
- mpr("You try to escape, but your burden drags you down!");
- }
-
- if (escape)
- {
- const coord_def pos(empty[0], empty[1]);
- if (in_bounds(pos) && !is_grid_dangerous(grd(pos)))
- {
- mpr("You manage to scramble free!");
- move_player_to_grid( empty[0], empty[1], false, false, true );
-
- if (terrain == DNGN_LAVA)
- expose_player_to_element( BEAM_LAVA, 14 );
-
- return (true);
- }
- }
-
- mpr("You drown...");
-
- if (terrain == DNGN_LAVA)
- ouch( INSTANT_DEATH, 0, KILLED_BY_LAVA );
- else if (terrain == DNGN_DEEP_WATER)
- ouch( INSTANT_DEATH, 0, KILLED_BY_WATER );
-
- return (false);
-} // end fall_into_a_pool()
-
bool scramble(void)
{
int max_carry = carrying_capacity();
@@ -2316,101 +1217,6 @@ bool go_berserk(bool intentional)
return true;
} // end go_berserk()
-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;
- item.plus2 = 0;
- item.flags = 0;
- item.special = 0;
- item.quantity = 1;
-
- if (base_type == OBJ_MISSILES)
- {
- if (sub_type == MI_NEEDLE)
- set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED );
- else
- set_item_ego_type( item, OBJ_MISSILES, SPMSL_NORMAL );
- }
- else
- {
- set_item_ego_type( item, OBJ_WEAPONS, SPWPN_NORMAL );
- }
-
- item_colour(item);
-
- if (igrd[beam_x][beam_y] != NON_ITEM)
- {
- if (items_stack( item, mitm[ igrd[beam_x][beam_y] ] ))
- {
- inc_mitm_item_quantity( igrd[beam_x][beam_y], 1 );
- return (false);
- }
-
- // don't want to go overboard here. Will only generate up to three
- // separate trap items, or less if there are other items present.
- if (mitm[ igrd[beam_x][beam_y] ].link != NON_ITEM
- && (item.base_type != OBJ_MISSILES || item.sub_type != MI_THROWING_NET))
- {
- if (mitm[ mitm[ igrd[beam_x][beam_y] ].link ].link != NON_ITEM)
- return (false);
- }
- } // end of if igrd != NON_ITEM
-
- return (!copy_item_to_grid( item, beam_x, beam_y, 1 ));
-} // end trap_item()
-
-// returns appropriate trap symbol for a given trap type {dlb}
-dungeon_feature_type trap_category(trap_type type)
-{
- switch (type)
- {
- case TRAP_TELEPORT:
- case TRAP_AMNESIA:
- case TRAP_ZOT:
- return (DNGN_TRAP_MAGICAL);
-
- case TRAP_DART:
- case TRAP_ARROW:
- case TRAP_SPEAR:
- case TRAP_AXE:
- case TRAP_BLADE:
- case TRAP_BOLT:
- case TRAP_NEEDLE:
- case TRAP_NET:
- default: // what *would* be the default? {dlb}
- return (DNGN_TRAP_MECHANICAL);
- }
-} // end trap_category()
-
-// returns index of the trap for a given (x,y) coordinate pair {dlb}
-int trap_at_xy(int which_x, int which_y)
-{
-
- for (int which_trap = 0; which_trap < MAX_TRAPS; which_trap++)
- {
- if (env.trap[which_trap].x == which_x &&
- env.trap[which_trap].y == which_y &&
- env.trap[which_trap].type != TRAP_UNASSIGNED)
- {
- return (which_trap);
- }
- }
-
- // no idea how well this will be handled elsewhere: {dlb}
- return (-1);
-} // end trap_at_xy()
-
-trap_type trap_type_at_xy(int x, int y)
-{
- const int idx = trap_at_xy(x, y);
- return (idx == -1? NUM_TRAPS : env.trap[idx].type);
-}
-
bool is_damaging_cloud(cloud_type type)
{
switch (type)
@@ -2559,150 +1365,6 @@ bool i_feel_safe(bool announce, bool want_move)
return true;
}
-// Do not attempt to use level_id if level_type != LEVEL_DUNGEON
-std::string short_place_name(level_id id)
-{
- return id.describe();
-}
-
-int place_branch(unsigned short place)
-{
- const unsigned branch = (unsigned) ((place >> 8) & 0xFF);
- const int lev = place & 0xFF;
- return lev == 0xFF? -1 : (int) branch;
-}
-
-int place_depth(unsigned short place)
-{
- const int lev = place & 0xFF;
- return lev == 0xFF? -1 : lev;
-}
-
-unsigned short get_packed_place( branch_type branch, int subdepth,
- level_area_type level_type )
-{
- unsigned short place = (unsigned short)
- ( (static_cast<int>(branch) << 8) | (subdepth & 0xFF) );
- if (level_type != LEVEL_DUNGEON)
- place = (unsigned short) ( (static_cast<int>(level_type) << 8) | 0xFF );
- return place;
-}
-
-unsigned short get_packed_place()
-{
- return get_packed_place( you.where_are_you,
- subdungeon_depth(you.where_are_you, you.your_level),
- you.level_type );
-}
-
-bool single_level_branch( branch_type branch )
-{
- return
- branch >= 0 && branch < NUM_BRANCHES
- && branches[branch].depth == 1;
-}
-
-std::string place_name( unsigned short place, bool long_name,
- bool include_number )
-{
-
- unsigned char branch = (unsigned char) ((place >> 8) & 0xFF);
- int lev = place & 0xFF;
-
- std::string result;
- if (lev == 0xFF)
- {
- switch (branch)
- {
- case LEVEL_ABYSS:
- return ( long_name ? "The Abyss" : "Abyss" );
- case LEVEL_PANDEMONIUM:
- return ( long_name ? "Pandemonium" : "Pan" );
- case LEVEL_LABYRINTH:
- return ( long_name ? "a Labyrinth" : "Lab" );
- case LEVEL_PORTAL_VAULT:
- return ( long_name ? "a Portal Chamber" : "Port" );
- default:
- return ( long_name ? "Buggy Badlands" : "Bug" );
- }
- }
-
- result = (long_name ?
- branches[branch].longname : branches[branch].abbrevname);
-
- if ( include_number && branches[branch].depth != 1 )
- {
- char buf[200];
- if ( long_name )
- {
- // decapitalize 'the'
- if ( result.find("The") == 0 )
- result[0] = 't';
- snprintf( buf, sizeof buf, "Level %d of %s",
- lev, result.c_str() );
- }
- else if (lev)
- snprintf( buf, sizeof buf, "%s:%d", result.c_str(), lev );
- else
- snprintf( buf, sizeof buf, "%s:$", result.c_str() );
-
- result = buf;
- }
- return result;
-}
-
-// Takes a packed 'place' and returns a compact stringified place name.
-// XXX: This is done in several other places; a unified function to
-// describe places would be nice.
-std::string short_place_name(unsigned short place)
-{
- return place_name( place, false, true );
-}
-
-// Prepositional form of branch level name. For example, "in the
-// Abyss" or "on level 3 of the Main Dungeon".
-std::string prep_branch_level_name(unsigned short packed_place)
-{
- std::string place = place_name( packed_place, true, true );
- if (place.length() && place != "Pandemonium")
- place[0] = tolower(place[0]);
- return (place.find("level") == 0?
- "on " + place
- : "in " + place);
-}
-
-// Use current branch and depth
-std::string prep_branch_level_name()
-{
- return prep_branch_level_name( get_packed_place() );
-}
-
-int absdungeon_depth(branch_type branch, int subdepth)
-{
- if (branch >= BRANCH_VESTIBULE_OF_HELL && branch <= BRANCH_THE_PIT)
- return subdepth + 27 - (branch == BRANCH_VESTIBULE_OF_HELL);
- else
- {
- --subdepth;
- while ( branch != BRANCH_MAIN_DUNGEON )
- {
- subdepth += branches[branch].startdepth;
- branch = branches[branch].parent_branch;
- }
- }
- return subdepth;
-}
-
-int subdungeon_depth(branch_type branch, int depth)
-{
- return depth - absdungeon_depth(branch, 0);
-}
-
-int player_branch_depth()
-{
- return subdungeon_depth(you.where_are_you, you.your_level);
-}
-
static const char *shop_types[] = {
"weapon",
"armour",