diff options
author | peterb12 <peterb12@c06c8d41-db1a-0410-9941-cceddc491573> | 2005-07-21 02:34:44 +0000 |
---|---|---|
committer | peterb12 <peterb12@c06c8d41-db1a-0410-9941-cceddc491573> | 2005-07-21 02:34:44 +0000 |
commit | 673bdae75485d14f759af597c3c62b99601f9a43 (patch) | |
tree | 368103f29fe0ce5dcf98060d9b5faa04590085fb /trunk/source/misc.cc | |
parent | 7e900be770db24b0405fd2162491c405a425873e (diff) | |
download | crawl-ref-673bdae75485d14f759af597c3c62b99601f9a43.tar.gz crawl-ref-673bdae75485d14f759af597c3c62b99601f9a43.zip |
Initial revision
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'trunk/source/misc.cc')
-rw-r--r-- | trunk/source/misc.cc | 1767 |
1 files changed, 1767 insertions, 0 deletions
diff --git a/trunk/source/misc.cc b/trunk/source/misc.cc new file mode 100644 index 0000000000..85ebb311b7 --- /dev/null +++ b/trunk/source/misc.cc @@ -0,0 +1,1767 @@ +/* + * File: misc.cc + * Summary: Misc functions. + * Written by: Linley Henzell + * + * Change History (most recent first): + * + * <3> 11/14/99 cdl evade with random40(ev) vice random2(ev) + * <2> 5/20/99 BWR Multi-user support, new berserk code. + * <1> -/--/-- LRH Created + */ + + +#include "AppHdr.h" +#include "misc.h" + +#include <string.h> +#if !(defined(__IBMCPP__) || defined(__BCPLUSPLUS__)) +#include <unistd.h> +#endif +#include <stdlib.h> +#include <stdio.h> + +#ifdef DOS +#include <conio.h> +#endif + +#include "externs.h" + +#include "cloud.h" +#include "delay.h" +#include "fight.h" +#include "files.h" +#include "food.h" +#include "it_use2.h" +#include "items.h" +#include "itemname.h" +#include "lev-pand.h" +#include "macro.h" +#include "monplace.h" +#include "mon-util.h" +#include "monstuff.h" +#include "ouch.h" +#include "player.h" +#include "shopping.h" +#include "skills.h" +#include "skills2.h" +#include "spells3.h" +#include "spl-cast.h" +#include "stuff.h" +#include "transfor.h" +#include "view.h" + + +bool scramble(void); +bool trap_item(char base_type, char sub_type, char beam_x, char beam_y); +static void dart_trap(bool trap_known, int trapped, struct 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 ) +{ + const int mons_class = item.plus; + const int max_chunks = mons_weight( mons_class ) / 150; + + ASSERT( item.base_type == OBJ_CORPSES ); + + item.base_type = OBJ_FOOD; + item.sub_type = FOOD_CHUNK; + item.quantity = 1 + random2( max_chunks ); + + item.quantity = stepdown_value( item.quantity, 4, 4, 12, 12 ); + + // seems to me that this should come about only + // after the corpse has been butchered ... {dlb} + if (monster_descriptor( mons_class, MDSC_LEAVES_HIDE ) && !one_chance_in(3)) + { + int o = get_item_slot( 100 + random2(200) ); + if (o == NON_ITEM) + return; + + mitm[o].quantity = 1; + + // these values are common to all: {dlb} + mitm[o].base_type = OBJ_ARMOUR; + mitm[o].plus = 0; + mitm[o].plus2 = 0; + mitm[o].special = 0; + mitm[o].flags = 0; + mitm[o].colour = mons_colour( mons_class ); + + // these values cannot be set by a reasonable formula: {dlb} + switch (mons_class) + { + case MONS_DRAGON: + mitm[o].sub_type = ARM_DRAGON_HIDE; + break; + case MONS_TROLL: + mitm[o].sub_type = ARM_TROLL_HIDE; + break; + case MONS_ICE_DRAGON: + mitm[o].sub_type = ARM_ICE_DRAGON_HIDE; + break; + case MONS_STEAM_DRAGON: + mitm[o].sub_type = ARM_STEAM_DRAGON_HIDE; + break; + case MONS_MOTTLED_DRAGON: + mitm[o].sub_type = ARM_MOTTLED_DRAGON_HIDE; + break; + case MONS_STORM_DRAGON: + mitm[o].sub_type = ARM_STORM_DRAGON_HIDE; + break; + case MONS_GOLDEN_DRAGON: + mitm[o].sub_type = ARM_GOLD_DRAGON_HIDE; + break; + case MONS_SWAMP_DRAGON: + mitm[o].sub_type = ARM_SWAMP_DRAGON_HIDE; + break; + default: + // future implementation {dlb} + mitm[o].sub_type = ARM_ANIMAL_SKIN; + break; + } + + move_item_to_grid( &o, item.x, item.y ); + } +} // end place_chunks() + +void search_around(void) +{ + char srx = 0; + char sry = 0; + int i; + + // Never if doing something else... this prevents a slight asymetry + // where using autopickup was giving free searches in comparison to + // not using autopickup. -- bwr + if (you_are_delayed()) + return; + + for (srx = you.x_pos - 1; srx < you.x_pos + 2; srx++) + { + for (sry = you.y_pos - 1; sry < you.y_pos + 2; sry++) + { + // don't exclude own square; may be levitating + if (grd[srx][sry] == DNGN_SECRET_DOOR + && random2(17) <= 1 + you.skills[SK_TRAPS_DOORS]) + { + grd[srx][sry] = DNGN_CLOSED_DOOR; + mpr("You found a secret door!"); + exercise(SK_TRAPS_DOORS, ((coinflip())? 2 : 1)); + } + + if (grd[srx][sry] == DNGN_UNDISCOVERED_TRAP + && random2(17) <= 1 + you.skills[SK_TRAPS_DOORS]) + { + i = trap_at_xy(srx, sry); + + if (i != -1) + grd[srx][sry] = trap_category(env.trap[i].type); + + mpr("You found a trap!"); + } + } + } + + return; +} // end search_around() + +void in_a_cloud(void) +{ + int cl = env.cgrid[you.x_pos][you.y_pos]; + int hurted = 0; + int resist; + + if (you.duration[DUR_CONDENSATION_SHIELD] > 0) + { + mpr("Your icy shield dissipates!", MSGCH_DURATION); + you.duration[DUR_CONDENSATION_SHIELD] = 0; + you.redraw_armour_class = 1; + } + + switch (env.cloud[cl].type) + { + case CLOUD_FIRE: + case CLOUD_FIRE_MON: + if (you.fire_shield) + return; + + mpr("You are engulfed in roaring flames!"); + + resist = player_res_fire(); + + if (resist <= 0) + { + hurted += ((random2avg(23, 3) + 10) * you.time_taken) / 10; + + if (resist < 0) + hurted += ((random2avg(14, 2) + 3) * you.time_taken) / 10; + + hurted -= random2(player_AC()); + + if (hurted < 1) + hurted = 0; + else + ouch( hurted, cl, KILLED_BY_CLOUD, "flame" ); + } + else + { + canned_msg(MSG_YOU_RESIST); + hurted += ((random2avg(23, 3) + 10) * you.time_taken) / 10; + hurted /= (1 + resist * resist); + ouch( hurted, cl, KILLED_BY_CLOUD, "flame" ); + } + scrolls_burn(7, OBJ_SCROLLS); + break; + + case CLOUD_STINK: + case CLOUD_STINK_MON: + // If you don't have to breathe, unaffected + mpr("You are engulfed in noxious fumes!"); + if (player_res_poison()) + break; + + hurted += (random2(3) * you.time_taken) / 10; + if (hurted < 1) + hurted = 0; + else + ouch( (hurted * you.time_taken) / 10, cl, KILLED_BY_CLOUD, + "noxious fumes" ); + + if (1 + random2(27) >= you.experience_level) + { + mpr("You choke on the stench!"); + confuse_player( (coinflip() ? 3 : 2) ); + } + break; + + case CLOUD_COLD: + case CLOUD_COLD_MON: + mpr("You are engulfed in freezing vapours!"); + + resist = player_res_cold(); + + if (resist <= 0) + { + hurted += ((random2avg(23, 3) + 10) * you.time_taken) / 10; + + if (resist < 0) + hurted += ((random2avg(14, 2) + 3) * you.time_taken) / 10; + + hurted -= random2(player_AC()); + if (hurted < 0) + hurted = 0; + + ouch( (hurted * you.time_taken) / 10, cl, KILLED_BY_CLOUD, + "freezing vapour" ); + } + else + { + canned_msg(MSG_YOU_RESIST); + hurted += ((random2avg(23, 3) + 10) * you.time_taken) / 10; + hurted /= (1 + resist * resist); + ouch( hurted, cl, KILLED_BY_CLOUD, "freezing vapour" ); + } + scrolls_burn(7, OBJ_POTIONS); + break; + + case CLOUD_POISON: + case CLOUD_POISON_MON: + // If you don't have to breathe, unaffected + mpr("You are engulfed in poison gas!"); + if (!player_res_poison()) + { + ouch( (random2(10) * you.time_taken) / 10, cl, KILLED_BY_CLOUD, + "poison gas" ); + poison_player(1); + } + break; + + case CLOUD_GREY_SMOKE: + case CLOUD_BLUE_SMOKE: + case CLOUD_PURP_SMOKE: + case CLOUD_BLACK_SMOKE: + case CLOUD_GREY_SMOKE_MON: + case CLOUD_BLUE_SMOKE_MON: + case CLOUD_PURP_SMOKE_MON: + case CLOUD_BLACK_SMOKE_MON: + mpr("You are engulfed in a cloud of smoke!"); + break; + + case CLOUD_STEAM: + case CLOUD_STEAM_MON: + mpr("You are engulfed in a cloud of scalding steam!"); + if (you.species == SP_PALE_DRACONIAN && you.experience_level > 5) + { + mpr("It doesn't seem to affect you."); + return; + } + + if (!player_equip( EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR )) + { + mpr("It doesn't seem to affect you."); + return; + } + + hurted += (random2(6) * you.time_taken) / 10; + if (hurted < 0 || player_res_fire() > 0) + hurted = 0; + + ouch( (hurted * you.time_taken) / 10, cl, KILLED_BY_CLOUD, "poison gas" ); + break; + + case CLOUD_MIASMA: + case CLOUD_MIASMA_MON: + mpr("You are engulfed in a dark miasma."); + + if (player_prot_life() > random2(3)) + return; + + poison_player(1); + + hurted += (random2avg(12, 3) * you.time_taken) / 10; // 3 + + if (hurted < 0) + hurted = 0; + + ouch( hurted, cl, KILLED_BY_CLOUD, "foul pestilence" ); + potion_effect(POT_SLOWING, 5); + + if (you.hp_max > 4 && coinflip()) + rot_hp(1); + + break; + } + + return; +} // end in_a_cloud() + + +void merfolk_start_swimming(void) +{ + FixedVector < char, 8 > removed; + + if (you.attribute[ATTR_TRANSFORMATION] != TRAN_NONE) + untransform(); + + for (int i = EQ_WEAPON; i < EQ_RIGHT_RING; i++) + { + removed[i] = 0; + } + + if (you.equip[EQ_BOOTS] != -1) + removed[EQ_BOOTS] = 1; + + // Perhaps a bit to easy for the player, but we allow merfolk + // to slide out of heavy body armour freely when entering water, + // rather than handling emcumbered swimming. -- bwr + if (!player_light_armour()) + { + // Can't slide out of just the body armour, cloak comes off -- bwr + if (you.equip[EQ_CLOAK]) + removed[EQ_CLOAK] = 1; + + removed[EQ_BODY_ARMOUR] = 1; + } + + remove_equipment(removed); +} + +void up_stairs(void) +{ + unsigned char stair_find = grd[you.x_pos][you.y_pos]; + char old_where = you.where_are_you; + bool was_a_labyrinth = false; + + if (stair_find == DNGN_ENTER_SHOP) + { + shop(); + return; + } + + // probably still need this check here (teleportation) -- bwr + if ((stair_find < DNGN_STONE_STAIRS_UP_I + || stair_find > DNGN_ROCK_STAIRS_UP) + && (stair_find < DNGN_RETURN_FROM_ORCISH_MINES || stair_find >= 150)) + { + mpr("You can't go up here."); + return; + } + + // Since the overloaded message set turn_is_over, I'm assuming that + // the overloaded character makes an attempt... so we're doing this + // check before that one. -- bwr + if (!player_is_levitating() + && you.conf + && (stair_find >= DNGN_STONE_STAIRS_UP_I + && stair_find <= DNGN_ROCK_STAIRS_UP) + && random2(100) > you.dex) + { + mpr("In your confused state, you trip and fall back down the stairs."); + + ouch( roll_dice( 3 + you.burden_state, 5 ), 0, + KILLED_BY_FALLING_DOWN_STAIRS ); + + you.turn_is_over = 1; + return; + } + + if (you.burden_state == BS_OVERLOADED) + { + mpr("You are carrying too much to climb upwards."); + you.turn_is_over = 1; + return; + } + + if (you.your_level == 0 + && !yesno("Are you sure you want to leave the Dungeon?", false)) + { + mpr("Alright, then stay!"); + return; + } + + unsigned char old_level = you.your_level; + + // Make sure we return to our main dungeon level... labyrinth entrances + // in the abyss or pandemonium a bit trouble (well the labyrinth does + // provide a way out of those places, its really not that bad I suppose) + if (you.level_type == LEVEL_LABYRINTH) + { + you.level_type = LEVEL_DUNGEON; + was_a_labyrinth = true; + } + + you.your_level--; + + int i = 0; + + if (you.your_level < 0) + { + mpr("You have escaped!"); + + for (i = 0; i < ENDOFPACK; i++) + { + if (is_valid_item( you.inv[i] ) + && you.inv[i].base_type == OBJ_ORBS) + { + ouch(-9999, 0, KILLED_BY_WINNING); + } + } + + ouch(-9999, 0, KILLED_BY_LEAVING); + } + + mpr("Entering..."); + you.prev_targ = MHITNOT; + you.pet_target = MHITNOT; + + if (player_in_branch( BRANCH_VESTIBULE_OF_HELL )) + { + mpr("Thank you for visiting Hell. Please come again soon."); + you.where_are_you = BRANCH_MAIN_DUNGEON; + you.your_level = you.hell_exit; + stair_find = DNGN_STONE_STAIRS_UP_I; + } + + if (player_in_hell()) + { + you.where_are_you = BRANCH_VESTIBULE_OF_HELL; + you.your_level = 27; + } + + switch (stair_find) + { + case DNGN_RETURN_FROM_ORCISH_MINES: + case DNGN_RETURN_FROM_HIVE: + case DNGN_RETURN_FROM_LAIR: + case DNGN_RETURN_FROM_VAULTS: + case DNGN_RETURN_FROM_TEMPLE: + case DNGN_RETURN_FROM_ZOT: + mpr("Welcome back to the Dungeon!"); + you.where_are_you = BRANCH_MAIN_DUNGEON; + break; + case DNGN_RETURN_FROM_SLIME_PITS: + case DNGN_RETURN_FROM_SNAKE_PIT: + case DNGN_RETURN_FROM_SWAMP: + mpr("Welcome back to the Lair of Beasts!"); + you.where_are_you = BRANCH_LAIR; + break; + case DNGN_RETURN_FROM_CRYPT: + case DNGN_RETURN_FROM_HALL_OF_BLADES: + mpr("Welcome back to the Vaults!"); + you.where_are_you = BRANCH_VAULTS; + break; + case DNGN_RETURN_FROM_TOMB: + mpr("Welcome back to the Crypt!"); + you.where_are_you = BRANCH_CRYPT; + break; + case DNGN_RETURN_FROM_ELVEN_HALLS: + mpr("Welcome back to the Orcish Mines!"); + you.where_are_you = BRANCH_ORCISH_MINES; + break; + } + + unsigned char stair_taken = stair_find; + + if (player_is_levitating()) + { + if (you.duration[DUR_CONTROLLED_FLIGHT]) + mpr("You fly upwards."); + else + mpr("You float upwards... And bob straight up to the ceiling!"); + } + else + mpr("You climb upwards."); + + load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth, old_level, old_where); + + you.turn_is_over = 1; + + save_game(false); + + new_level(); + + viewwindow(1, true); + + + if (you.skills[SK_TRANSLOCATIONS] > 0 && !allow_control_teleport( true )) + mpr( "You sense a powerful magical force warping space.", MSGCH_WARN ); +} // end up_stairs() + +void down_stairs( bool remove_stairs, int old_level ) +{ + int i; + char old_level_type = you.level_type; + bool was_a_labyrinth = false; + const unsigned char stair_find = grd[you.x_pos][you.y_pos]; + + //int old_level = you.your_level; + bool leave_abyss_pan = false; + char old_where = you.where_are_you; + +#ifdef SHUT_LABYRINTH + if (stair_find == DNGN_ENTER_LABYRINTH) + { + mpr("Sorry, this section of the dungeon is closed for fumigation."); + mpr("Try again next release."); + return; + } +#endif + + // probably still need this check here (teleportation) -- bwr + if ((stair_find < DNGN_ENTER_LABYRINTH + || stair_find > DNGN_ROCK_STAIRS_DOWN) + && stair_find != DNGN_ENTER_HELL + && ((stair_find < DNGN_ENTER_DIS + || stair_find > DNGN_TRANSIT_PANDEMONIUM) + && stair_find != DNGN_STONE_ARCH) + && !(stair_find >= DNGN_ENTER_ORCISH_MINES + && stair_find < DNGN_RETURN_FROM_ORCISH_MINES)) + { + mpr( "You can't go down here!" ); + return; + } + + if (stair_find >= DNGN_ENTER_LABYRINTH + && stair_find <= DNGN_ROCK_STAIRS_DOWN + && player_in_branch( BRANCH_VESTIBULE_OF_HELL )) + { + mpr("A mysterious force prevents you from descending the staircase."); + return; + } /* down stairs in vestibule are one-way */ + + if (stair_find == DNGN_STONE_ARCH) + { + mpr("You can't go down here!"); + return; + } + + if (player_is_levitating() && !wearing_amulet(AMU_CONTROLLED_FLIGHT)) + { + mpr("You're floating high up above the floor!"); + return; + } + + if (stair_find == DNGN_ENTER_ZOT) + { + int num_runes = 0; + + for (i = 0; i < ENDOFPACK; i++) + { + if (is_valid_item( you.inv[i] ) + && you.inv[i].base_type == OBJ_MISCELLANY + && you.inv[i].sub_type == MISC_RUNE_OF_ZOT) + { + num_runes += you.inv[i].quantity; + } + } + + if (num_runes < NUMBER_OF_RUNES_NEEDED) + { + switch (NUMBER_OF_RUNES_NEEDED) + { + case 1: + mpr("You need a Rune to enter this place."); + break; + + default: + snprintf( info, INFO_SIZE, + "You need at least %d Runes to enter this place.", + NUMBER_OF_RUNES_NEEDED ); + + mpr(info); + } + return; + } + } + + if (you.level_type == LEVEL_PANDEMONIUM + && stair_find == DNGN_TRANSIT_PANDEMONIUM) + { + was_a_labyrinth = true; + } + else + { + if (you.level_type != LEVEL_DUNGEON) + was_a_labyrinth = true; + + you.level_type = LEVEL_DUNGEON; + } + + mpr("Entering..."); + you.prev_targ = MHITNOT; + you.pet_target = MHITNOT; + + if (stair_find == DNGN_ENTER_HELL) + { + you.where_are_you = BRANCH_VESTIBULE_OF_HELL; + you.hell_exit = you.your_level; + + mpr("Welcome to Hell!"); + mpr("Please enjoy your stay."); + + more(); + + you.your_level = 26; // = 59; + } + + if ((stair_find >= DNGN_ENTER_DIS + && stair_find <= DNGN_ENTER_TARTARUS) + || (stair_find >= DNGN_ENTER_ORCISH_MINES + && stair_find < DNGN_RETURN_FROM_ORCISH_MINES)) + { + // no idea why such a huge switch and not 100-grd[][] + // planning ahead for re-organizaing grd[][] values - 13jan2000 {dlb} + strcpy( info, "Welcome to " ); + switch (stair_find) + { + case DNGN_ENTER_DIS: + strcat(info, "the Iron City of Dis!"); + you.where_are_you = BRANCH_DIS; + you.your_level = 26; + break; + case DNGN_ENTER_GEHENNA: + strcat(info, "Gehenna!"); + you.where_are_you = BRANCH_GEHENNA; + you.your_level = 26; + break; + case DNGN_ENTER_COCYTUS: + strcat(info, "Cocytus!"); + you.where_are_you = BRANCH_COCYTUS; + you.your_level = 26; + break; + case DNGN_ENTER_TARTARUS: + strcat(info, "Tartarus!"); + you.where_are_you = BRANCH_TARTARUS; + you.your_level = 26; + break; + case DNGN_ENTER_ORCISH_MINES: + strcat(info, "the Orcish Mines!"); + you.where_are_you = BRANCH_ORCISH_MINES; + break; + case DNGN_ENTER_HIVE: + strcpy(info, "You hear a buzzing sound coming from all directions."); + you.where_are_you = BRANCH_HIVE; + break; + case DNGN_ENTER_LAIR: + strcat(info, "the Lair of Beasts!"); + you.where_are_you = BRANCH_LAIR; + break; + case DNGN_ENTER_SLIME_PITS: + strcat(info, "the Pits of Slime!"); + you.where_are_you = BRANCH_SLIME_PITS; + break; + case DNGN_ENTER_VAULTS: + strcat(info, "the Vaults!"); + you.where_are_you = BRANCH_VAULTS; + break; + case DNGN_ENTER_CRYPT: + strcat(info, "the Crypt!"); + you.where_are_you = BRANCH_CRYPT; + break; + case DNGN_ENTER_HALL_OF_BLADES: + strcat(info, "the Hall of Blades!"); + you.where_are_you = BRANCH_HALL_OF_BLADES; + break; + case DNGN_ENTER_ZOT: + strcat(info, "the Hall of Zot!"); + you.where_are_you = BRANCH_HALL_OF_ZOT; + break; + case DNGN_ENTER_TEMPLE: + strcat(info, "the Ecumenical Temple!"); + you.where_are_you = BRANCH_ECUMENICAL_TEMPLE; + break; + case DNGN_ENTER_SNAKE_PIT: + strcat(info, "the Snake Pit!"); + you.where_are_you = BRANCH_SNAKE_PIT; + break; + case DNGN_ENTER_ELVEN_HALLS: + strcat(info, "the Elven Halls!"); + you.where_are_you = BRANCH_ELVEN_HALLS; + break; + case DNGN_ENTER_TOMB: + strcat(info, "the Tomb!"); + you.where_are_you = BRANCH_TOMB; + break; + case DNGN_ENTER_SWAMP: + strcat(info, "the Swamp!"); + you.where_are_you = BRANCH_SWAMP; + break; + } + + mpr(info); + } + else if (stair_find == DNGN_ENTER_LABYRINTH) + { + you.level_type = LEVEL_LABYRINTH; + grd[you.x_pos][you.y_pos] = DNGN_FLOOR; + } + else if (stair_find == DNGN_ENTER_ABYSS) + { + you.level_type = LEVEL_ABYSS; + } + else if (stair_find == DNGN_ENTER_PANDEMONIUM) + { + you.level_type = LEVEL_PANDEMONIUM; + } + + if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS + || you.level_type == LEVEL_PANDEMONIUM) + { + char glorpstr[kFileNameSize]; + char del_file[kFileNameSize]; + int sysg; + +#ifdef SAVE_DIR_PATH + snprintf( glorpstr, sizeof(glorpstr), + SAVE_DIR_PATH "%s%d", you.your_name, (int) getuid() ); +#else + strncpy(glorpstr, you.your_name, kFileNameLen); + + // glorpstr [strlen(glorpstr)] = 0; + // This is broken. Length is not valid yet! We have to check if we got + // a trailing NULL; if not, write one: + /* is name 6 chars or more? */ + if (strlen(you.your_name) > kFileNameLen - 1) + glorpstr[kFileNameLen] = '\0'; +#endif + + strcpy(del_file, glorpstr); + strcat(del_file, ".lab"); + +#ifdef DOS + strupr(del_file); +#endif + sysg = unlink(del_file); + +#if DEBUG_DIAGNOSTICS + strcpy( info, "Deleting: " ); + strcat( info, del_file ); + mpr( info, MSGCH_DIAGNOSTICS ); + more(); +#endif + } + + if (stair_find == DNGN_EXIT_ABYSS || stair_find == DNGN_EXIT_PANDEMONIUM) + { + leave_abyss_pan = true; + mpr("You pass through the gate, and find yourself at the top of a staircase."); + more(); + } + + if (!player_is_levitating() + && you.conf + && (stair_find >= DNGN_STONE_STAIRS_DOWN_I + && stair_find <= DNGN_ROCK_STAIRS_DOWN) + && random2(100) > you.dex) + { + mpr("In your confused state, you trip and fall down the stairs."); + + // Nastier than when climbing stairs, but you'll aways get to + // your destination, -- bwr + ouch( roll_dice( 6 + you.burden_state, 10 ), 0, + KILLED_BY_FALLING_DOWN_STAIRS ); + } + + if (you.level_type == LEVEL_DUNGEON) + you.your_level++; + + int stair_taken = stair_find; + + //unsigned char save_old = 1; + + if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_ABYSS) + stair_taken = DNGN_FLOOR; //81; + + if (you.level_type == LEVEL_PANDEMONIUM) + stair_taken = DNGN_TRANSIT_PANDEMONIUM; + + if (remove_stairs) + grd[you.x_pos][you.y_pos] = DNGN_FLOOR; + + switch (you.level_type) + { + case LEVEL_LABYRINTH: + mpr("You enter a dark and forbidding labyrinth."); + break; + + case LEVEL_ABYSS: + mpr("You enter the Abyss!"); + mpr("To return, you must find a gate leading back."); + break; + + case LEVEL_PANDEMONIUM: + if (old_level_type == LEVEL_PANDEMONIUM) + mpr("You pass into a different region of Pandemonium."); + else + { + mpr("You enter the halls of Pandemonium!"); + mpr("To return, you must find a gate leading back."); + } + break; + + default: + mpr("You climb downwards."); + break; + } + + load(stair_taken, LOAD_ENTER_LEVEL, was_a_labyrinth, old_level, old_where); + + unsigned char pc = 0; + unsigned char pt = random2avg(28, 3); + + switch (you.level_type) + { + case LEVEL_LABYRINTH: + you.your_level++; + break; + + case LEVEL_ABYSS: + grd[you.x_pos][you.y_pos] = DNGN_FLOOR; + + if (old_level_type != LEVEL_PANDEMONIUM) + you.your_level--; // Linley-suggested addition 17jan2000 {dlb} + + init_pandemonium(); /* colours only */ + + if (player_in_hell()) + { + you.where_are_you = BRANCH_MAIN_DUNGEON; + you.your_level = you.hell_exit - 1; + } + break; + + case LEVEL_PANDEMONIUM: + if (old_level_type == LEVEL_PANDEMONIUM) + { + init_pandemonium(); + for (pc = 0; pc < pt; pc++) + pandemonium_mons(); + } + else + { + // Linley-suggested addition 17jan2000 {dlb} + if (old_level_type != LEVEL_ABYSS) + you.your_level--; + + init_pandemonium(); + + for (pc = 0; pc < pt; pc++) + pandemonium_mons(); + + if (player_in_hell()) + { + you.where_are_you = BRANCH_MAIN_DUNGEON; + you.hell_exit = 26; + you.your_level = 26; + } + } + break; + + default: + break; + } + + you.turn_is_over = 1; + + save_game(false); + + new_level(); + + viewwindow(1, true); + + if (you.skills[SK_TRANSLOCATIONS] > 0 && !allow_control_teleport( true )) + mpr( "You sense a powerful magical force warping space.", MSGCH_WARN ); +} // end down_stairs() + +void new_level(void) +{ + int curr_subdungeon_level = you.your_level + 1; + + textcolor(LIGHTGREY); + + // maybe last part better expresssed as <= PIT {dlb} + if (player_in_hell() || player_in_branch( BRANCH_VESTIBULE_OF_HELL )) + curr_subdungeon_level = you.your_level - 26; + + /* Remember, must add this to the death_string in ouch */ + if (you.where_are_you >= BRANCH_ORCISH_MINES + && you.where_are_you <= BRANCH_SWAMP) + { + curr_subdungeon_level = you.your_level + - you.branch_stairs[you.where_are_you - 10]; + } + + gotoxy(46, 12); + +#if DEBUG_DIAGNOSTICS + cprintf( "(%d) ", you.your_level + 1 ); +#endif + + env.floor_colour = LIGHTGREY; + env.rock_colour = BROWN; + + if (you.level_type == LEVEL_PANDEMONIUM) + { + cprintf("- Pandemonium "); + + env.floor_colour = (mcolour[env.mons_alloc[9]] == BLACK) + ? LIGHTGREY : mcolour[env.mons_alloc[9]]; + + env.rock_colour = (mcolour[env.mons_alloc[8]] == BLACK) + ? LIGHTGREY : mcolour[env.mons_alloc[8]]; + } + else if (you.level_type == LEVEL_ABYSS) + { + cprintf("- The Abyss "); + + env.floor_colour = (mcolour[env.mons_alloc[9]] == BLACK) + ? LIGHTGREY : mcolour[env.mons_alloc[9]]; + + env.rock_colour = (mcolour[env.mons_alloc[8]] == BLACK) + ? LIGHTGREY : mcolour[env.mons_alloc[8]]; + } + else if (you.level_type == LEVEL_LABYRINTH) + { + cprintf("- a Labyrinth "); + } + else + { + // level_type == LEVEL_DUNGEON + if (!player_in_branch( BRANCH_VESTIBULE_OF_HELL )) + cprintf( "%d", curr_subdungeon_level ); + + switch (you.where_are_you) + { + case BRANCH_MAIN_DUNGEON: + cprintf(" of the Dungeon "); + break; + case BRANCH_DIS: + env.floor_colour = CYAN; + env.rock_colour = CYAN; + cprintf(" of Dis "); + break; + case BRANCH_GEHENNA: + env.floor_colour = DARKGREY; + env.rock_colour = RED; + cprintf(" of Gehenna "); + break; + case BRANCH_VESTIBULE_OF_HELL: + env.floor_colour = LIGHTGREY; + env.rock_colour = LIGHTGREY; + cprintf("- the Vestibule of Hell "); + break; + case BRANCH_COCYTUS: + env.floor_colour = LIGHTBLUE; + env.rock_colour = LIGHTCYAN; + cprintf(" of Cocytus "); + break; + case BRANCH_TARTARUS: + env.floor_colour = DARKGREY; + env.rock_colour = DARKGREY; + cprintf(" of Tartarus "); + break; + case BRANCH_INFERNO: + env.floor_colour = LIGHTRED; + env.rock_colour = RED; + cprintf(" of the Inferno "); + break; + case BRANCH_THE_PIT: + env.floor_colour = RED; + env.rock_colour = DARKGREY; + cprintf(" of the Pit "); + break; + case BRANCH_ORCISH_MINES: + env.floor_colour = BROWN; + env.rock_colour = BROWN; + cprintf(" of the Orcish Mines "); + break; + case BRANCH_HIVE: + env.floor_colour = YELLOW; + env.rock_colour = BROWN; + cprintf(" of the Hive "); + break; + case BRANCH_LAIR: + env.floor_colour = GREEN; + env.rock_colour = BROWN; + cprintf(" of the Lair "); + break; + case BRANCH_SLIME_PITS: + env.floor_colour = GREEN; + env.rock_colour = LIGHTGREEN; + cprintf(" of the Slime Pits "); + break; + case BRANCH_VAULTS: + env.floor_colour = LIGHTGREY; + env.rock_colour = BROWN; + cprintf(" of the Vaults "); + break; + case BRANCH_CRYPT: + env.floor_colour = LIGHTGREY; + env.rock_colour = LIGHTGREY; + cprintf(" of the Crypt "); + break; + case BRANCH_HALL_OF_BLADES: + env.floor_colour = LIGHTGREY; + env.rock_colour = LIGHTGREY; + cprintf(" of the Hall of Blades "); + break; + + case BRANCH_HALL_OF_ZOT: + if (you.your_level - you.branch_stairs[7] <= 1) + { + env.floor_colour = LIGHTGREY; + env.rock_colour = LIGHTGREY; + } + else + { + switch (you.your_level - you.branch_stairs[7]) + { + case 2: + env.rock_colour = LIGHTGREY; + env.floor_colour = BLUE; + break; + case 3: + env.rock_colour = BLUE; + env.floor_colour = LIGHTBLUE; + break; + case 4: + env.rock_colour = LIGHTBLUE; + env.floor_colour = MAGENTA; + break; + case 5: + env.rock_colour = MAGENTA; + env.floor_colour = LIGHTMAGENTA; + break; + } + } + cprintf(" of the Realm of Zot "); + break; + + case BRANCH_ECUMENICAL_TEMPLE: + env.floor_colour = LIGHTGREY; + env.rock_colour = LIGHTGREY; + cprintf(" of the Temple "); + break; + case BRANCH_SNAKE_PIT: + env.floor_colour = LIGHTGREEN; + env.rock_colour = YELLOW; + cprintf(" of the Snake Pit "); + break; + case BRANCH_ELVEN_HALLS: + env.floor_colour = DARKGREY; + env.rock_colour = LIGHTGREY; + cprintf(" of the Elven Halls "); + break; + case BRANCH_TOMB: + env.floor_colour = YELLOW; + env.rock_colour = LIGHTGREY; + cprintf(" of the Tomb "); + break; + case BRANCH_SWAMP: + env.floor_colour = BROWN; + env.rock_colour = BROWN; + cprintf(" of the Swamp "); + break; + } + } // end else +} // end new_level() + +static void dart_trap( bool trap_known, int trapped, struct bolt &pbolt, + bool poison ) +{ + int damage_taken = 0; + int trap_hit, your_dodge; + + if (random2(10) < 2 || (trap_known && !one_chance_in(4))) + { + snprintf( info, INFO_SIZE, "You avoid triggering a%s trap.", + pbolt.beam_name ); + mpr(info); + return; + } + + if (you.equip[EQ_SHIELD] != -1 && one_chance_in(3)) + exercise( SK_SHIELDS, 1 ); + + snprintf( info, INFO_SIZE, "A%s shoots out and ", pbolt.beam_name ); + + if (random2( 50 + 10 * you.shield_blocks * you.shield_blocks ) + < player_shield_class()) + { + you.shield_blocks++; + strcat( info, "hits your shield." ); + mpr(info); + goto out_of_trap; + } + + // 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) + { + strcat( info, "hits you!" ); + mpr(info); + + 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.beam_name ); + } + else + { + strcat( info, "misses you." ); + mpr(info); + } + + if (player_light_armour() && coinflip()) + exercise( SK_DODGING, 1 ); + + out_of_trap: + + 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 ) +{ + int 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; + 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: + strcpy(beam.beam_name, " dart"); + beam.damage = dice_def( 1, 4 + (you.your_level / 2) ); + dart_trap(trap_known, i, beam, false); + break; + + case TRAP_NEEDLE: + strcpy(beam.beam_name, " needle"); + beam.damage = dice_def( 1, 0 ); + dart_trap(trap_known, i, beam, true); + break; + + case TRAP_ARROW: + strcpy(beam.beam_name, "n arrow"); + beam.damage = dice_def( 1, 7 + you.your_level ); + dart_trap(trap_known, i, beam, false); + break; + + case TRAP_BOLT: + strcpy(beam.beam_name, " bolt"); + beam.damage = dice_def( 1, 13 + you.your_level ); + dart_trap(trap_known, i, beam, false); + break; + + case TRAP_SPEAR: + strcpy(beam.beam_name, " spear"); + beam.damage = dice_def( 1, 10 + you.your_level ); + dart_trap(trap_known, i, beam, false); + break; + + case TRAP_AXE: + strcpy(beam.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_teleport2( 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_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; + } +} // end handle_traps() + +void disarm_trap( struct dist &disa ) +{ + if (you.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 = 1; + + if (random2(you.dex) > 5 + random2(5 + you.your_level)) + exercise(SK_TRAPS_DOORS, 1 + random2(you.your_level / 5)); + 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_BLADE + && trap_category(env.trap[i].type) == DNGN_TRAP_MECHANICAL) + { + for (j = 0; j < 20; j++) + { + // places items (eg darts), which will automatically stack + itrap(beam, i); + + if (j > 10 && one_chance_in(3)) + break; + } + } + + grd[you.x_pos + disa.dx][you.y_pos + disa.dy] = DNGN_FLOOR; + env.trap[i].type = TRAP_UNASSIGNED; + you.turn_is_over = 1; + + // reduced from 5 + random2(5) + exercise(SK_TRAPS_DOORS, 1 + random2(5) + (you.your_level / 5)); +} // end disarm_trap() + +void manage_clouds(void) +{ + // amount which cloud dissipates - must be unsigned! {dlb} + unsigned int dissipate = 0; + + for (unsigned char cc = 0; cc < MAX_CLOUDS; cc++) + { + if (env.cloud[cc].type == CLOUD_NONE) // no cloud -> next iteration + continue; + + dissipate = you.time_taken; + + // water -> flaming clouds: + // lava -> freezing clouds: + if ((env.cloud[cc].type == CLOUD_FIRE + || env.cloud[cc].type == CLOUD_FIRE_MON) + && grd[env.cloud[cc].x][env.cloud[cc].y] == DNGN_DEEP_WATER) + { + dissipate *= 4; + } + else if ((env.cloud[cc].type == CLOUD_COLD + || env.cloud[cc].type == CLOUD_COLD_MON) + && grd[env.cloud[cc].x][env.cloud[cc].y] == DNGN_LAVA) + { + dissipate *= 4; + } + + // double the amount when slowed - must be applied last(!): + if (you.slow) + dissipate *= 2; + + // apply calculated rate to the actual cloud: + env.cloud[cc].decay -= dissipate; + + // check for total dissipatation and handle accordingly: + if (env.cloud[cc].decay < 1) + delete_cloud( cc ); + } + + return; +} // end manage_clouds() + +void weird_writing(char stringy[40]) +{ + int temp_rand = 0; // for probability determinations {dlb} + + temp_rand = random2(15); + + // you'll see why later on {dlb} + strcpy(stringy, (temp_rand == 0) ? "writhing" : + (temp_rand == 1) ? "bold" : + (temp_rand == 2) ? "faint" : + (temp_rand == 3) ? "spidery" : + (temp_rand == 4) ? "blocky" : + (temp_rand == 5) ? "angular" : + (temp_rand == 6) ? "shimmering" : + (temp_rand == 7) ? "glowing" : ""); + + if (temp_rand < 8) + strcat(stringy, " "); // see above for reasoning {dlb} + + temp_rand = random2(14); + + strcat(stringy, (temp_rand == 0) ? "yellow" : + (temp_rand == 1) ? "brown" : + (temp_rand == 2) ? "black" : + (temp_rand == 3) ? "purple" : + (temp_rand == 4) ? "orange" : + (temp_rand == 5) ? "lime-green" : + (temp_rand == 6) ? "blue" : + (temp_rand == 7) ? "grey" : + (temp_rand == 8) ? "silver" : + (temp_rand == 9) ? "gold" : + (temp_rand == 10) ? "umber" : + (temp_rand == 11) ? "charcoal" : + (temp_rand == 12) ? "pastel" : + (temp_rand == 13) ? "mauve" + : "colourless"); + + strcat(stringy, " "); + + temp_rand = random2(14); + + strcat(stringy, (temp_rand == 0) ? "writing" : + (temp_rand == 1) ? "scrawl" : + (temp_rand == 2) ? "sigils" : + (temp_rand == 3) ? "runes" : + (temp_rand == 4) ? "hieroglyphics" : + (temp_rand == 5) ? "scrawl" : + (temp_rand == 6) ? "print-out" : + (temp_rand == 7) ? "binary code" : + (temp_rand == 8) ? "glyphs" : + (temp_rand == 9) ? "symbols" + : "text"); + + return; +} // end weird_writing() + +// must be a better name than 'place' for the first parameter {dlb} +void fall_into_a_pool(bool place, 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; + } + + strcpy(info, "You fall into the "); + + strcat(info, (terrain == DNGN_LAVA) ? "lava" : + (terrain == DNGN_DEEP_WATER) ? "water" + : "programming rift"); + + strcat(info, "!"); + mpr(info); + + more(); + mesclr(); + + if (terrain == DNGN_LAVA) + { + const int resist = player_res_fire(); + + if (resist <= 0) + { + mpr( "The lava burns you to a cinder!" ); + ouch( -9999, 0, KILLED_BY_LAVA ); + } + else + { + // should boost # of bangs per damage in the future {dlb} + mpr( "The lava burns you!" ); + ouch( (10 + random2avg(100, 2)) / resist, 0, KILLED_BY_LAVA ); + } + + if (you.duration[DUR_CONDENSATION_SHIELD] > 0) + { + mpr("Your icy shield dissipates!", MSGCH_DURATION); + you.duration[DUR_CONDENSATION_SHIELD] = 0; + you.redraw_armour_class = 1; + } + } + + // a distinction between stepping and falling from you.levitation + // prevents stepping into a thin stream of lava to get to the other side. + if (scramble()) + { + if (place) + { + if (empty_surrounds(you.x_pos, you.y_pos, DNGN_FLOOR, false, empty)) + { + you.x_pos = empty[0]; + you.y_pos = empty[1]; + escape = true; + } + else + escape = false; + } + else + escape = true; + } + else + { + // that is, don't display following when fall from levitating + if (!place) + mpr("You try to escape, but your burden drags you down!"); + } + + if (escape) + { + mpr("You manage to scramble free!"); + + if (terrain == DNGN_LAVA) + scrolls_burn(10, OBJ_SCROLLS); + + return; + } + + mpr("You drown..."); + + if (terrain == DNGN_LAVA) + ouch(-9999, 0, KILLED_BY_LAVA); + else if (terrain == DNGN_DEEP_WATER) + ouch(-9999, 0, KILLED_BY_WATER); + + // Okay, so you don't trigger a trap when you scramble onto it. + //I really can't be bothered right now. +} // end fall_into_a_pool() + +bool scramble(void) +{ + int max_carry = carrying_capacity(); + + if ((max_carry / 2) + random2(max_carry / 2) <= you.burden) + return false; + else + return true; +} // end scramble() + +void weird_colours(unsigned char coll, char wc[30]) +{ + unsigned char coll_div16 = coll / 16; // conceivable max is then 16 {dlb} + + // Must start with a consonant! + strcpy(wc, (coll_div16 == 0 || coll_div16 == 7) ? "brilliant" : + (coll_div16 == 1 || coll_div16 == 8) ? "pale" : + (coll_div16 == 2 || coll_div16 == 9) ? "mottled" : + (coll_div16 == 3 || coll_div16 == 10) ? "shimmering" : + (coll_div16 == 4 || coll_div16 == 11) ? "bright" : + (coll_div16 == 5 || coll_div16 == 12) ? "dark" : + (coll_div16 == 6 || coll_div16 == 13) ? "shining" + : "faint"); + + strcat(wc, " "); + + while (coll > 17) + coll -= 10; + + strcat(wc, (coll == 0) ? "red" : + (coll == 1) ? "purple" : + (coll == 2) ? "green" : + (coll == 3) ? "orange" : + (coll == 4) ? "magenta" : + (coll == 5) ? "black" : + (coll == 6) ? "grey" : + (coll == 7) ? "silver" : + (coll == 8) ? "gold" : + (coll == 9) ? "pink" : + (coll == 10) ? "yellow" : + (coll == 11) ? "white" : + (coll == 12) ? "brown" : + (coll == 13) ? "aubergine" : + (coll == 14) ? "ochre" : + (coll == 15) ? "leaf green" : + (coll == 16) ? "mauve" : + (coll == 17) ? "azure" + : "colourless"); + + return; +} // end weird_colours() + +bool go_berserk(bool intentional) +{ + if (you.berserker) + { + if (intentional) + mpr("You're already berserk!"); + // or else you won't notice -- no message here. + return false; + } + + if (you.exhausted) + { + if (intentional) + mpr("You're too exhausted to go berserk."); + // or else they won't notice -- no message here + return false; + } + + if (you.is_undead) + { + if (intentional) + mpr("You cannot raise a blood rage in your lifeless body."); + // or else you won't notice -- no message here + return false; + } + + mpr("A red film seems to cover your vision as you go berserk!"); + mpr("You feel yourself moving faster!"); + mpr("You feel mighty!"); + + you.berserker += 20 + random2avg(19, 2); + + calc_hp(); + you.hp *= 15; + you.hp /= 10; + + deflate_hp(you.hp_max, false); + + if (!you.might) + modify_stat( STAT_STRENGTH, 5, true ); + + you.might += you.berserker; + haste_player( you.berserker ); + + if (you.berserk_penalty != NO_BERSERK_PENALTY) + you.berserk_penalty = 0; + + return true; +} // end go_berserk() + +bool trap_item(char 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; + item.colour = LIGHTCYAN; + + if (base_type == OBJ_MISSILES) + { + if (sub_type == MI_NEEDLE) + { + set_item_ego_type( item, OBJ_MISSILES, SPMSL_POISONED ); + item.colour = WHITE; + } + else + { + set_item_ego_type( item, OBJ_MISSILES, SPMSL_NORMAL ); + } + } + else + { + set_item_ego_type( item, OBJ_WEAPONS, SPWPN_NORMAL ); + } + + 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) + { + 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} +unsigned char trap_category(unsigned char trap_type) +{ + switch (trap_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: + 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) + { + return (which_trap); + } + } + + // no idea how well this will be handled elsewhere: {dlb} + return (-1); +} // end trap_at_xy() |