/* * Determine if a given grid may be "walked" */ static bool do_cmd_walk_test(int y, int x) { /* Assume no monster. */ monster_type *m_ptr = 0; /* Access the monster, if any is present. */ if (cave_m_idx[y][x] != 0) m_ptr = &m_list[cave_m_idx[y][x]]; /* If a monster can be seen, it can be attacked normally. Code in cmd1.c * controls whether a player can actually move to the destination grid. */ if ((m_ptr) && (m_ptr->ml)) return (TRUE); /* Hack -- walking obtains knowledge XXX XXX */ if (!(cave_info[y][x] & (CAVE_MARK))) return (TRUE); /* Require open space */ if (!cave_passable_bold(y, x)) { /* Door */ if (cave_feat[y][x] < FEAT_SECRET) { /* If easy_open_door option is on, doors are legal. */ if (easy_open) return (TRUE); /* Otherwise, let the player know of the door. */ else msg_print("There is a door in the way!"); } /* Wall */ else { /* Message */ msg_print("There is a wall in the way!"); } /* Nope */ return (FALSE); } /* Okay */ return (TRUE); }
/* * Determine is a monster makes a reasonable target * * The concept of "targetting" was stolen from "Morgul" (?) * * The player can target any location, or any "target-able" monster. * * Currently, a monster is "target_able" if it is visible, and if * the player can hit it with a projection, and the player is not * hallucinating. This allows use of "use closest target" macros. * * Future versions may restrict the ability to target "trappers" * and "mimics", but the semantics is a little bit weird. */ bool target_able(int m_idx) { monster_type *m_ptr; /* No monster */ if (m_idx <= 0) return (FALSE); /* Get monster */ m_ptr = &mon_list[m_idx]; /* Monster must be alive */ if (!m_ptr->r_idx) return (FALSE); /* Monster must be visible */ if (!m_ptr->ml) return (FALSE); /*monster is an undiscovered mimic*/ if (m_ptr->mimic_k_idx) return (FALSE); /* Monster must be projectable */ if (!m_ptr->project) return (FALSE); /* Walls protect monsters */ if (!cave_project_bold(m_ptr->fy, m_ptr->fx) && !cave_passable_bold(m_ptr->fy, m_ptr->fx)) return (FALSE); /* Hack -- no targeting hallucinations */ if (p_ptr->timed[TMD_IMAGE]) return (FALSE); /* Hack -- Never target trappers XXX XXX XXX */ /* if (CLEAR_ATTR && (CLEAR_CHAR)) return (FALSE); */ /* Hidden monsters cannot be targets */ if (m_ptr->mflag & (MFLAG_HIDE)) return (FALSE); /* Assume okay */ return (TRUE); }
/** * Hack -- Teleport to the target. Oangband asks for a target after * the command. */ static void do_cmd_wiz_bamf(void) { /* target starts at player. */ s16b ny = 0; s16b nx = 0; /* Use the targeting function. */ if (!target_set_interactive(TARGET_LOOK, -1, -1)) return; /* grab the target coords. */ target_get(&nx, &ny); /* Test for passable terrain. */ if (!cave_passable_bold(ny, nx)) { msg_print("The square you are aiming for is impassable."); } /* The simple act of controlled teleport. */ else teleport_player_to(ny, nx, TRUE); }
/** * Move player in the given direction, with the given "pickup" flag. * * This routine should only be called when energy has been expended. * * Note that this routine handles monsters in the destination grid, * and also handles attempting to move into walls/doors/etc. */ void move_player(int dir) { int py = p_ptr->py; int px = p_ptr->px; byte str_escape, dex_escape; /* Permit the player to move? */ bool can_move = FALSE; /* Player is jumping off a cliff */ bool falling = FALSE; /* Player hits a trap (always unless flying) */ bool trapped = TRUE; int temp; int y, x; /* Find the result of moving */ y = py + ddy[dir]; x = px + ddx[dir]; /* Hack -- attack monsters */ if (cave_m_idx[y][x] > 0) { /* Attack */ if (py_attack(y, x, TRUE)) return; } /* It takes some dexterity, or failing that strength, to get out of pits */ if (cave_feat[p_ptr->py][p_ptr->px] == (FEAT_TRAP_HEAD + 0x01)) { str_escape = adj_dex_dis[p_ptr->state.stat_ind[A_STR]]; dex_escape = adj_dex_dis[p_ptr->state.stat_ind[A_DEX]]; /* First attempt to leap out of the pit, */ if ((dex_escape + 1) * 2 < randint1(16)) { /* then attempt to climb out of the pit. */ if (str_escape + 3 < randint1(16)) { /* Failure costs a turn. */ msg_print("You remain stuck in the pit."); return; } else msg_print("You clamber out of the pit."); } else msg_print("You leap out of the pit."); } /* Option to disarm a visible trap. -TNB- */ /* Hack - Rogues can walk over their own trap - BR */ if (OPT(easy_alter) && (cave_feat[y][x] >= FEAT_TRAP_HEAD) && (cave_feat[y][x] <= FEAT_TRAP_TAIL)) { bool more = FALSE; /* Auto-repeat if not already repeating */ if (cmd_get_nrepeats() == 0) cmd_set_repeat(99); more = do_cmd_disarm_aux(y, x); /* Cancel repeat unless we may continue */ if (!more) disturb(0, 0); return; } /* Some terrain is impassable for the player, such as stone walls. */ else if (!cave_passable_bold(y, x)) { /* Disturb the player */ disturb(0, 0); /* Notice unknown obstacles */ if (!(cave_info[y][x] & (CAVE_MARK))) { /* Closed door */ if (cave_feat[y][x] < FEAT_SECRET) { message(MSG_HITWALL, 0, "You feel a door blocking your way."); cave_info[y][x] |= (CAVE_MARK); light_spot(y, x); } /* Wall (or secret door) */ else { message(MSG_HITWALL, 0, "You feel a wall blocking your way."); cave_info[y][x] |= (CAVE_MARK); light_spot(y, x); } } /* Mention known obstacles */ else { /* Closed door */ if (cave_feat[y][x] < FEAT_SECRET) { /* Option to automatically open doors. -TNB- */ if (OPT(easy_alter)) { bool more = FALSE; /* Auto-repeat if not already repeating */ if (cmd_get_nrepeats() == 0) cmd_set_repeat(99); /* Open the door */ more = do_cmd_open_aux(y, x); /* Cancel repeat unless we may continue */ if (!more) disturb(0, 0); return; } /* Otherwise, a message. */ message(MSG_HITWALL, 0, "There is a door blocking your way."); } /* Wall (or secret door) */ else { message(MSG_HITWALL, 0, "There is a wall blocking your way."); } } /* Sound */ sound(MSG_HITWALL); } /* Normal movement */ else { /*** Handle traversable terrain. ***/ switch (cave_feat[y][x]) { case FEAT_RUBBLE: { /* Dwarves move easily through rubble */ if (player_has(PF_DWARVEN)) can_move = TRUE; /* Bats, dragons can fly */ else if ((p_ptr->schange == SHAPE_BAT) || (p_ptr->schange == SHAPE_WYRM)) can_move = TRUE; else if (player_is_crossing == dir) { can_move = TRUE; player_is_crossing = 0; } else { player_is_crossing = dir; cmd_insert(CMD_WALK); } break; } case FEAT_TREE: case FEAT_TREE2: { /* Druids, rangers, elves and ents (SJGU) slip easily under * trees */ if (((player_has(PF_WOODSMAN)) || (player_has(PF_ELVEN))) || (player_has(PF_WOODEN))) can_move = TRUE; /* Bats, dragons can fly */ else if ((p_ptr->schange == SHAPE_BAT) || (p_ptr->schange == SHAPE_WYRM)) can_move = TRUE; /* Allow movement only if partway through already. */ else if (player_is_crossing == dir) { can_move = TRUE; player_is_crossing = 0; } else { player_is_crossing = dir; cmd_insert(CMD_WALK); } break; } case FEAT_WATER: /* Water now slows rather than stopping -NRM- */ { /* Stop any run. */ disturb(0, 0); can_move = TRUE; /* Speed will need updating */ p_ptr->update |= PU_BONUS; break; } case FEAT_LAVA: { /* Assume player will continue. */ temp = TRUE; /* Smart enough to stop running. */ if (p_ptr->running) { if (!get_check("Lava blocks your path. Step into it? ")) { temp = FALSE; p_ptr->running = 0; } } /* Smart enough to sense trouble. */ else if ((!p_resist_pos(P_RES_FIRE)) || (!p_resist_strong(P_RES_FIRE) && (p_ptr->chp <= 100)) || (!p_immune(P_RES_FIRE) && (p_ptr->chp <= 30))) { if (!get_check ("The heat of the lava scalds you! Really enter? ")) { temp = FALSE; } } /* Enter if OK or confirmed. */ if (temp) { /* Can always cross. */ can_move = TRUE; /* Feather fall makes one lightfooted. */ if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); temp = 49 + randint1(51); } else temp = 124 + randint1(126); /* Will take serious fire damage. */ fire_dam(temp, "burnt to a cinder in molten lava"); } break; } case FEAT_VOID: { /* Bats, dragons can fly */ if ((p_ptr->schange == SHAPE_BAT) || (p_ptr->schange == SHAPE_WYRM)) can_move = TRUE; else { /* Assume player will continue. */ temp = TRUE; /* Smart enough to stop running. */ if (p_ptr->running) { if (!get_check ("You have come to a cliff. Step off it? ")) { temp = FALSE; p_ptr->running = 0; } } /* Smart enough to sense trouble. */ else if (!p_ptr->timed[TMD_BLIND]) { if (!get_check("It's a cliff! Really step off it? ")) { temp = FALSE; } } /* Step off if confirmed. */ if (temp) { /* Can always jump. */ can_move = TRUE; /* Will take serious damage. */ falling = TRUE; } } break; } default: { /* All other terrain can be traversed normally. */ can_move = TRUE; } } /* If the player can move, handle various things. */ if (can_move) { /* Move player */ monster_swap(py, px, y, x); /* Update speed if stepping out of water */ if (cave_feat[py][px] == FEAT_WATER) p_ptr->update |= PU_BONUS; /* Update stealth for Unlight */ if (player_has(PF_UNLIGHT)) p_ptr->update |= PU_BONUS; /* Superstealth for ents in trees SJGU */ if ((player_has(PF_WOODEN)) && (tf_has (f_info[cave_feat[p_ptr->py][p_ptr->px]].flags, TF_TREE))) { if (!(tf_has(f_info[cave_feat[py][px]].flags, TF_TREE)) || !(p_ptr->timed[TMD_SSTEALTH])) { (void) inc_timed(TMD_SSTEALTH, 1, FALSE); p_ptr->update |= (PU_BONUS); } } else if ((player_has(PF_WOODEN)) && (tf_has(f_info[cave_feat[py][px]].flags, TF_TREE))) { if (p_ptr->timed[TMD_SSTEALTH]) { (void) dec_timed(TMD_SSTEALTH, 1, FALSE); p_ptr->update |= (PU_BONUS); } } /* New location */ y = py = p_ptr->py; x = px = p_ptr->px; /* No longer traversing. */ player_is_crossing = 0; /* Fall off a cliff */ if (falling) fall_off_cliff(); /* Spontaneous Searching */ if (p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] > 49) { (void) search(FALSE); } else if (0 == randint0(50 - p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) { (void) search(FALSE); } /* Continuous Searching */ if (p_ptr->searching) { (void) search(FALSE); } /* Handle "store doors" */ if ((cave_feat[y][x] >= FEAT_SHOP_HEAD) && (cave_feat[y][x] <= FEAT_SHOP_TAIL)) { /* Disturb */ disturb(0, 0); cmd_insert(CMD_ENTER_STORE); } /* All other grids (including traps) */ else { /* Handle objects (later) */ p_ptr->notice |= (PN_PICKUP); } /* Flying players have a chance to miss traps */ if ((p_ptr->schange == SHAPE_BAT) || (p_ptr->schange == SHAPE_WYRM)) { if (((cave_feat[y][x] == FEAT_INVIS) || (cave_feat[y][x] == FEAT_GRASS_INVIS)) && (randint0(3) != 0)) trapped = FALSE; else if ((cave_feat[y][x] >= FEAT_TRAP_HEAD) && (cave_feat[y][x] <= FEAT_TRAP_TAIL) && (randint0(10) != 0)) trapped = FALSE; } /* Discover invisible traps */ else if (((cave_feat[y][x] == FEAT_INVIS) || (cave_feat[y][x] == FEAT_GRASS_INVIS) || (cave_feat[y][x] == FEAT_TREE_INVIS) || (cave_feat[y][x] == FEAT_TREE2_INVIS)) && trapped) { /* Disturb */ disturb(0, 0); /* Message */ msg_print("You stumble upon a trap!"); /* Pick a trap */ pick_trap(y, x); /* Hit the floor trap. */ hit_trap(y, x); } /* Set off a visible trap */ else if ((cave_feat[y][x] >= FEAT_TRAP_HEAD) && (cave_feat[y][x] <= FEAT_TRAP_TAIL) && trapped) { /* Disturb */ disturb(0, 0); /* Hit the floor trap. */ hit_trap(y, x); } /* Walk on a monster trap */ else if ((cave_feat[y][x] >= FEAT_MTRAP_HEAD) && (cave_feat[y][x] <= FEAT_MTRAP_TAIL)) { msg_print("You inspect your cunning trap."); } } } }
/** * Handle player hitting a real trap. Rewritten in Oangband to allow a * greater variety of traps, with effects controlled by dungeon level. * To allow a trap to choose one of a variety of effects consistantly, * the quick RNG is often used, and xy coordinates input as a seed value. */ extern void hit_trap(int y, int x) { int i, j, k, num; int dam = 0; int nastyness, selection; feature_type *f_ptr = &f_info[cave_feat[y][x]]; cptr name = f_ptr->name; /* Use the "simple" RNG to insure that traps are consistant. */ Rand_quick = TRUE; /* Use the coordinates of the trap to seed the RNG. */ Rand_value = y * x; /* Disturb the player */ disturb(0, 0); /* Analyze XXX XXX XXX */ switch (cave_feat[y][x]) { /* trap door. */ case FEAT_TRAP_HEAD + 0x00: { Rand_quick = FALSE; /* Paranoia -NRM- */ if (((stage_map[p_ptr->stage][STAGE_TYPE] == CAVE) || (stage_map[p_ptr->stage][STAGE_TYPE] == VALLEY)) && (!stage_map[p_ptr->stage][DOWN])) { cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); msg_print("The trap fails!"); break; } msg_print("You fall through a trap door!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently down to the next level."); } else { dam = damroll(2, 8); take_hit(dam, name); } /* Remember where we came from */ p_ptr->last_stage = p_ptr->stage; if (!stage_map[p_ptr->stage][DOWN]) { /* Set the ways forward and back */ stage_map[255][UP] = p_ptr->stage; stage_map[p_ptr->stage][DOWN] = 255; stage_map[255][DEPTH] = p_ptr->depth + 1; } /* New stage */ p_ptr->stage = stage_map[p_ptr->stage][DOWN]; /* New depth */ p_ptr->depth = stage_map[p_ptr->stage][DEPTH]; /* Leaving */ p_ptr->leaving = TRUE; Rand_quick = TRUE; break; } /* pits. */ case FEAT_TRAP_HEAD + 0x01: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); if (randint1(20) == 1) nastyness += 20; else if (randint1(5) == 1) nastyness += 10; /* Player is now in pit. */ monster_swap(p_ptr->py, p_ptr->px, y, x); /* Center on player. */ y = p_ptr->py; x = p_ptr->px; /* pit of daggers. */ if ((nastyness > 80) && (randint1(3) != 3)) { msg_print("You fall into a pit of daggers!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the floor of the pit."); msg_print("You carefully avoid setting off the daggers."); } else { /* a trap of morgul. */ if (randint1(6) == 1) { Rand_quick = FALSE; msg_print ("A single coldly gleaming dagger pierces you deeply!"); msg_print ("You feel a deadly chill slowly withering your soul."); /* activate the Black Breath. */ p_ptr->black_breath = TRUE; /* lots of damage. */ dam = damroll(20, 15); /* undead may be attracted. */ if (randint1(2) == 1) { msg_print ("Undead suddenly appear and call you to them!"); k = randint1(3) + 2; for (i = 0; i < k; i++) { summon_specific(y, x, FALSE, p_ptr->depth, SUMMON_UNDEAD); } } /* morgul-traps are one-time only. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); Rand_quick = TRUE; } else { Rand_quick = FALSE; /* activate the ordinary daggers. */ msg_print("Daggers pierce you everywhere!"); k = randint1(10) + 5; for (i = 0; i < k; i++) { dam += damroll(3, 4); } Rand_quick = TRUE; } /* cut the player. */ (void) inc_timed(TMD_CUT, randint1(dam), TRUE); /* Take the damage. */ take_hit(dam, name); } } /* poisoned spiked pit. */ else if ((nastyness > 55) && (randint1(3) != 3)) { msg_print("You fall into a spiked pit!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the floor of the pit."); msg_print("You carefully avoid touching the spikes."); } else { Rand_quick = FALSE; /* Base damage */ dam = damroll(2, 6); /* Extra spike damage */ if (randint0(100) < 85) { bool was_poisoned; msg_print("You are impaled on poisonous spikes!"); dam = dam * (randint1(6) + 3); (void) inc_timed(TMD_CUT, randint1(dam), TRUE); was_poisoned = pois_hit(dam); if (!was_poisoned) msg_print("The poison does not affect you!"); } /* Take the damage */ take_hit(dam, name); Rand_quick = TRUE; } } /* spiked pit. */ else if ((nastyness > 30) && (randint1(3) != 3)) { msg_print("You fall into a spiked pit!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the floor of the pit."); msg_print("You carefully avoid touching the spikes."); } else { Rand_quick = FALSE; /* Base damage */ dam = damroll(2, 6); /* Extra spike damage */ if (randint0(100) < 85) { msg_print("You are impaled!"); dam = dam * (2 + randint1(4)); (void) inc_timed(TMD_CUT, randint1(dam), TRUE); } /* Take the damage */ take_hit(dam, name); Rand_quick = TRUE; } } /* ordinary pit in all other cases. */ else { msg_print("You fall into a pit!"); if (p_ptr->state.ffall) { notice_obj(OF_FEATHER, 0); msg_print("You float gently to the bottom of the pit."); } else { Rand_quick = FALSE; dam = damroll(2, 6); take_hit(dam, name); Rand_quick = TRUE; } } break; } /* stat-reducing dart traps. */ case FEAT_TRAP_HEAD + 0x02: { /* decide if the dart hits. */ if (check_trap_hit(50 + p_ptr->depth)) { /* select a stat to drain. */ selection = randint0(6); Rand_quick = FALSE; msg_print("A small dart hits you!"); dam = damroll(1, 4); take_hit(dam, name); /* Determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); /* decide how much to drain the stat by. */ if ((nastyness > 50) && (randint1(3) == 1)) { num = randint1(4); } else num = 1; /* drain the stat. */ for (i = 0; i < num; i++) { (void) do_dec_stat(selection); } Rand_quick = TRUE; } else { msg_print("A small dart barely misses you."); } break; } /* discolored spots. */ case FEAT_TRAP_HEAD + 0x03: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); if (randint1(5) == 1) nastyness += 10; /* pick a elemental attack type. */ selection = randint1(4); /* electicity trap. */ if (selection == 1) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("You are struck by lightning!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You get zapped!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; elec_dam(dam, "an electricity trap"); Rand_quick = TRUE; } /* frost trap. */ if (selection == 2) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("You are lost within a blizzard!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You are coated in frost!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; cold_dam(dam, "a frost trap"); Rand_quick = TRUE; } /* fire trap. */ if (selection == 3) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("You are enveloped in a column of fire!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You are surrounded by flames!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; fire_dam(dam, "a fire trap"); Rand_quick = TRUE; } /* acid trap. */ if (selection == 4) { if ((nastyness >= 50) && (randint1(2) == 1)) { Rand_quick = FALSE; msg_print("A cauldron of acid is tipped over your head!"); dam = damroll(6, 30); Rand_quick = TRUE; } else { Rand_quick = FALSE; msg_print("You are splashed with acid!"); dam = damroll(4, 8); Rand_quick = TRUE; } Rand_quick = FALSE; acid_dam(dam, "an acid trap"); Rand_quick = TRUE; } break; } /* gas traps. */ case FEAT_TRAP_HEAD + 0x04: { selection = randint1(4); /* blinding trap. */ if (selection == 1) { msg_print("You are surrounded by a black gas!"); if (!p_ptr->state.no_blind) { Rand_quick = FALSE; (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE); Rand_quick = TRUE; } } else notice_obj(OF_SEEING, 0); /* confusing trap. */ if (selection == 2) { msg_print ("You are surrounded by a gas of scintillating colors!"); if (!p_resist_good(P_RES_CONFU)) { Rand_quick = FALSE; (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE); Rand_quick = TRUE; } else notice_other(IF_RES_CONFU, 0); } /* poisoning trap. */ if (selection == 3) { msg_print("You are surrounded by a pungent green gas!"); Rand_quick = FALSE; pois_hit(25); Rand_quick = TRUE; } /* sleeping trap. */ if (selection == 4) { msg_print("You are surrounded by a strange white mist!"); if (!p_ptr->state.free_act) { (void) inc_timed(TMD_PARALYZED, randint0(10) + 5, TRUE); } else notice_obj(OF_FREE_ACT, 0); } break; } /* summoning traps. */ case FEAT_TRAP_HEAD + 0x05: { sound(MSG_SUM_MONSTER); /* sometimes summon thieves. */ if ((p_ptr->depth > 8) && (randint1(5) == 1)) { msg_print("You have aroused a den of thieves!"); Rand_quick = FALSE; num = 2 + randint1(3); for (i = 0; i < num; i++) { (void) summon_specific(y, x, FALSE, p_ptr->depth, SUMMON_THIEF); } Rand_quick = TRUE; } /* sometimes summon a nasty unique. */ else if (randint1(8) == 1) { msg_print("You are enveloped in a cloud of smoke!"); Rand_quick = FALSE; (void) summon_specific(y, x, FALSE, p_ptr->depth + 5, SUMMON_UNIQUE); Rand_quick = TRUE; } /* otherwise, the ordinary summon monsters. */ else { msg_print("You are enveloped in a cloud of smoke!"); Rand_quick = FALSE; num = 2 + randint1(3); for (i = 0; i < num; i++) { (void) summon_specific(y, x, FALSE, p_ptr->depth, 0); } Rand_quick = TRUE; } /* these are all one-time traps. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); break; } /* dungeon alteration traps. */ case FEAT_TRAP_HEAD + 0x06: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint1(p_ptr->depth); if (randint1(5) == 1) nastyness += 10; /* make room for alterations. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); /* Everything truely random from here on. */ Rand_quick = FALSE; /* dungeon destruction trap. */ if ((nastyness > 60) && (randint1(12) == 1)) { msg_print ("A ear-splitting howl shatters your mind as the dungeon is smashed by hammer blows!"); (void) destroy_level(FALSE); /* the player is hard-hit. */ (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE); (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE); (void) inc_timed(TMD_STUN, randint1(50) + 50, TRUE); dam = damroll(15, 15); take_hit(dam, name); } /* earthquake trap. */ else if ((nastyness > 20) && (randint1(4) == 1)) { msg_print("A tremor shakes the earth around you"); earthquake(y, x, 10, FALSE); } /* falling rock trap. */ else if ((nastyness > 4) && (randint1(2) == 1)) { msg_print("A rock falls on your head."); dam = damroll(2, 10); take_hit(dam, name); (void) inc_timed(TMD_STUN, randint1(10) + 10, TRUE); } /* a few pebbles. */ else { msg_print("A bunch of pebbles rain down on you."); dam = damroll(1, 8); take_hit(dam, name); } Rand_quick = TRUE; break; } /* various char and equipment-alteration traps, lumped together to * avoid any one effect being too common (some of them can be rather * nasty). */ case FEAT_TRAP_HEAD + 0x07: { /* determine how dangerous the trap is allowed to be. */ nastyness = randint0(100); /* these are all one-time traps. */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); /* Everything truely random from here on. */ Rand_quick = FALSE; /* trap of drain wands. */ if (nastyness < 15) { /* Hold the object information. */ object_type *o_ptr; /* Find an item */ for (i = 0; i < 20; i++) { /* Pick an item */ i = randint0(INVEN_PACK - p_ptr->pack_size_reduce); /* Obtain the item */ o_ptr = &p_ptr->inventory[i]; /* use "num" to decide if a item can be uncharged. By * default, assume it can't. */ num = 0; /* Skip non-objects */ if (!o_ptr->k_idx) continue; /* Drain charged wands/staffs/rods */ if ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_ROD)) { /* case of charged wands/staffs. */ if (((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND)) && (o_ptr->pval)) num = 1; /* case of charged rods. */ if ((o_ptr->tval == TV_ROD) && (o_ptr->timeout < randcalc(o_ptr->time, 0, MINIMISE))) num = 1; if (num == 1) { /* Message */ msg_print("Energy drains from your pack!"); /* Uncharge */ if ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND)) o_ptr->pval = 0; if (o_ptr->tval == TV_ROD) o_ptr->timeout = randcalc(o_ptr->time, 0, RANDOMISE) * o_ptr->number * 2; /* Combine / Reorder the pack */ p_ptr->notice |= (PN_COMBINE | PN_REORDER); /* not more than one inventory slot effected. */ break; } else continue; } } } /* trap of forgetting. */ else if (nastyness < 35) { if (check_save(100)) { msg_print("You hang on to your memories!"); } else if (lose_all_info()) { msg_print("Your memories fade away."); } } /* trap of alter reality. */ else if (nastyness < 50) { if (OPT(adult_ironman)) msg_print("Nothing happens."); else { msg_print("The world changes!"); /* Leaving */ p_ptr->leaving = TRUE; } } /* trap of remold player. */ else if (nastyness < 75) { int max1, cur1, max2, cur2, ii, jj; msg_print("You feel yourself being twisted by wild magic!"); if (check_save(100)) { msg_print("You resist the effects!"); } else { msg_print("Your body starts to scramble..."); /* Pick a pair of stats */ ii = randint0(6); for (jj = ii; jj == ii; jj = randint0(6)) /* loop */ ; max1 = p_ptr->stat_max[ii]; cur1 = p_ptr->stat_cur[ii]; max2 = p_ptr->stat_max[jj]; cur2 = p_ptr->stat_cur[jj]; p_ptr->stat_max[ii] = max2; p_ptr->stat_cur[ii] = cur2; p_ptr->stat_max[jj] = max1; p_ptr->stat_cur[jj] = cur1; p_ptr->update |= (PU_BONUS); } } /* time ball trap. */ else if (nastyness < 90) { msg_print("You feel time itself assault you!"); /* Target the player with a radius 0 ball attack. */ fire_meteor(0, GF_TIME, p_ptr->py, p_ptr->px, 75, 0, TRUE); } /* trap of bugs gone berserk. */ else { /* explain what the dickens is going on. */ msg_print("GRUESOME Gnawing Bugs leap out at you!"); if (!p_resist_good(P_RES_CONFU)) { (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE); } else notice_other(IF_RES_CONFU, 0); if (!p_resist_good(P_RES_CHAOS)) { (void) inc_timed(TMD_IMAGE, randint1(40), TRUE); } else notice_other(IF_RES_CHAOS, 0); /* XXX (hard coded) summon 3-6 bugs. */ k = randint1(4) + 2; for (i = 0; i < k; ++i) { /* Look for a location */ for (j = 0; j < 20; ++j) { /* Pick a (scattered) distance. */ int d = (j / 10) + randint1(3); /* Pick a location */ scatter(&y, &x, y, x, d, 0); /* Require passable terrain */ if (!cave_passable_bold(y, x)) continue; /* Hack -- no summon on glyph of warding */ if (cave_feat[y][x] == FEAT_RUNE_PROTECT) continue; /* Okay */ break; } /* Attempt to place the awake bug */ place_monster_aux(y, x, 453, FALSE, TRUE); } /* herald the arrival of bugs. */ msg_print("AAAAAAAHHHH! THEY'RE EVERYWHERE!"); } Rand_quick = TRUE; break; } /* teleport trap */ case FEAT_TRAP_HEAD + 0x08: { if (stage_map[p_ptr->stage][STAGE_TYPE] >= CAVE) msg_print("You teleport across the dungeon."); else msg_print("You teleport across the wilderness."); Rand_quick = FALSE; teleport_player(250, FALSE); Rand_quick = TRUE; break; } /* murder holes. */ case FEAT_TRAP_HEAD + 0x09: { /* hold the object info. */ object_type *o_ptr; object_type object_type_body; /* hold the missile type and name. */ int sval = 0; int tval = 0; cptr missile_name = ""; /* Determine the missile type and base damage. */ if (randint1(3) == 1) { if (p_ptr->depth < 40) { missile_name = "shot"; dam = damroll(2, 3); tval = TV_SHOT; sval = SV_AMMO_NORMAL; } else { missile_name = "seeker shot"; dam = damroll(3, 7); tval = TV_SHOT; sval = SV_AMMO_HEAVY; } } else if (randint1(2) == 1) { if (p_ptr->depth < 55) { missile_name = "arrow"; dam = damroll(2, 4); tval = TV_ARROW; sval = SV_AMMO_NORMAL; } else { missile_name = "seeker arrow"; dam = damroll(3, 9); tval = TV_ARROW; sval = SV_AMMO_HEAVY; } } else { if (p_ptr->depth < 65) { missile_name = "bolt"; dam = damroll(2, 5); tval = TV_BOLT; sval = SV_AMMO_NORMAL; } else { missile_name = "seeker bolt"; dam = damroll(3, 11); tval = TV_BOLT; sval = SV_AMMO_HEAVY; } } /* determine if the missile hits. */ if (check_trap_hit(75 + p_ptr->depth)) { msg_format("A %s hits you from above.", missile_name); Rand_quick = FALSE; /* critical hits. */ if (randint1(2) == 1) { msg_print("It was well-aimed!"); dam *= 1 + randint1(2); } if (randint1(2) == 1) { msg_print("It gouges you!"); dam = 3 * dam / 2; /* cut the player. */ (void) inc_timed(TMD_CUT, randint1(dam), TRUE); } Rand_quick = TRUE; take_hit(dam, name); } /* Explain what just happened. */ else msg_format("A %s wizzes by your head.", missile_name); /* these will eventually run out of ammo. */ Rand_quick = FALSE; if (randint0(8) == 0) { cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_FLOOR); } Rand_quick = TRUE; /* Get local object */ o_ptr = &object_type_body; /* Make a missile, identify it, and drop it near the player. */ object_prep(o_ptr, lookup_kind(tval, sval), MINIMISE); object_aware(o_ptr); object_known(o_ptr); drop_near(o_ptr, -1, y, x, TRUE); break; } /* falling tree branch */ case FEAT_TRAP_HEAD + 0x0A: { /* determine if the missile hits. */ if (check_trap_hit(75 + p_ptr->depth)) { /* Take damage */ dam = damroll(3, 5); msg_print("A branch hits you from above."); Rand_quick = FALSE; /* critical hits. */ if (randint1(2) == 1) { msg_print("It was heavy!"); dam = 3 * dam / 2; /* stun the player. */ (void) inc_timed(TMD_STUN, randint1(dam), TRUE); } Rand_quick = TRUE; take_hit(dam, name); } /* Explain what just happened. */ else msg_print("A falling branch just misses you."); /* No more */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_TREE); break; } /* falling tree branch */ case FEAT_TRAP_HEAD + 0x0B: { /* determine if the missile hits. */ if (check_trap_hit(75 + p_ptr->depth)) { /* Take damage */ dam = damroll(3, 5); msg_print("A branch hits you from above."); Rand_quick = FALSE; /* critical hits. */ if (randint1(2) == 1) { msg_print("It was heavy!"); dam = 3 * dam / 2; /* stun the player. */ (void) inc_timed(TMD_STUN, randint1(dam), TRUE); } Rand_quick = TRUE; take_hit(dam, name); } /* Explain what just happened. */ else msg_print("A falling branch just misses you."); /* No more */ cave_info[y][x] &= ~(CAVE_MARK); cave_set_feat(y, x, FEAT_TREE2); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0C: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0D: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0E: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } /* undefined trap. */ case FEAT_TRAP_HEAD + 0x0F: { msg_print("A dagger is thrown at you from the shadows!"); dam = damroll(3, 4); take_hit(dam, name); break; } } /* Revert to usage of the complex RNG. */ Rand_quick = FALSE; }