void monk_double_attack_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Double Attack"); break; case SPELL_DESC: var_set_string(res, "Attack twice at an adjacent enemy. This action consumes double the normal energy."); break; case SPELL_CAST: var_set_bool(res, FALSE); if (_monk_check_spell()) { int x, y, dir = 0; if (!get_rep_dir(&dir, FALSE)) return; y = py + ddy[dir]; x = px + ddx[dir]; if (cave[y][x].m_idx) { if (one_in_(2)) msg_print("Ahhhtatatatatatatatatatatatatatataatatatatattaaaaa!!!!"); else msg_print("Oraoraoraoraoraoraoraoraoraoraoraoraoraoraoraoraora!!!!"); py_attack(y, x, 0); if (cave[y][x].m_idx) { handle_stuff(); py_attack(y, x, 0); } } else { msg_print("You don't see any monster in this direction"); msg_print(NULL); } var_set_bool(res, TRUE); } break; case SPELL_ENERGY: var_set_int(res, 100 + ENERGY_NEED()); break; default: default_spell(cmd, res); break; } }
void _scatter_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Scatter"); break; case SPELL_DESC: var_set_string(res, "Attack all adjacent monsters with a single strike. If landed, your enemies will be scattered away from you."); break; case SPELL_CAST: { int dir, x, y; cave_type *c_ptr; monster_type *m_ptr; for (dir = 0; dir < 8; dir++) { y = py + ddy_ddd[dir]; x = px + ddx_ddd[dir]; c_ptr = &cave[y][x]; m_ptr = &m_list[c_ptr->m_idx]; if (c_ptr->m_idx && (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT))) py_attack(y, x, MAULER_SCATTER); } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/* * Tunnel through "walls" (including rubble and secret doors) * * Digging is very difficult without a "digger" weapon, but can be * accomplished by strong players using heavy weapons. */ void do_cmd_tunnel(cmd_code code, cmd_arg args[]) { int y, x, dir; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Oops */ if (!do_cmd_tunnel_test(y, x)) { /* Cancel repeat */ disturb(0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave_m_idx[y][x] > 0) { if (mon_list[cave_m_idx[y][x]].align & (AL_PET_MASK)) { msg_print("There is a friendly monster in the way!"); } else { /* Message */ msg_print("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } /* Walls */ else { /* Tunnel through walls */ more = do_cmd_tunnel_aux(y, x); } /* Cancel repetition unless we can continue */ if (!more) disturb(0, 0); }
/* * Close an open door. */ void do_cmd_close(cmd_code code, cmd_arg args[]) { int y, x, dir; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Verify legality */ if (!do_cmd_close_test(y, x)) { /* Cancel repeat */ disturb(0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave_m_idx[y][x] > 0) { if (mon_list[cave_m_idx[y][x]].align & (AL_PET_MASK)) msg_print("There is a friendly monster in the way!"); else { /* Message */ msg_print("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } /* Door */ else { /* Close door */ more = do_cmd_close_aux(y, x); } /* Cancel repeat unless told not to */ if (!more) disturb(0, 0); }
/** * Close an open door. */ void do_cmd_close(struct command *cmd) { int y, x, dir; int err; bool more = false; /* Get arguments */ err = cmd_get_arg_direction(cmd, "direction", &dir); if (err || dir == DIR_UNKNOWN) { int y2, x2; /* Count open doors */ if (count_feats(&y2, &x2, square_isopendoor, false) == 1) { dir = coords_to_dir(y2, x2); cmd_set_arg_direction(cmd, "direction", dir); } else if (cmd_get_direction(cmd, "direction", &dir, false)) { return; } } /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Verify legality */ if (!do_cmd_close_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; } /* Monster - alert, then attack */ if (cave->squares[y][x].mon > 0) { msg("There is a monster in the way!"); py_attack(y, x); } else /* Door - close it */ more = do_cmd_close_aux(y, x); /* Cancel repeat unless told not to */ if (!more) disturb(player, 0); }
/* * Tunnel through "walls" (including rubble and secret doors) * * Digging is very difficult without a "digger" weapon, but can be * accomplished by strong players using heavy weapons. */ void do_cmd_tunnel(cmd_code code, cmd_arg args[]) { int y, x, dir; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Oops */ if (!do_cmd_tunnel_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave->m_idx[y][x] > 0) { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Walls */ else { /* Tunnel through walls */ more = do_cmd_tunnel_aux(y, x); } /* Cancel repetition unless we can continue */ if (!more) disturb(p_ptr, 0, 0); }
static void _charge_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Charge"); break; case SPELL_DESC: var_set_string(res, "Attacks monster with your weapons normally, then move through counter side of the monster."); break; case SPELL_CAST: { int dir, x, y; var_set_bool(res, FALSE); if (p_ptr->riding) { msg_print("You cannot do it when riding."); return; } if (!get_rep_dir2(&dir)) return; if (dir == 5) return; y = py + ddy[dir]; x = px + ddx[dir]; if (!cave[y][x].m_idx) { msg_print("There is no monster there."); return; } py_attack(y, x, 0); if (player_can_enter(cave[y][x].feat, 0) && !is_trap(cave[y][x].feat)) { y += ddy[dir]; x += ddx[dir]; if (player_can_enter(cave[y][x].feat, 0) && !is_trap(cave[y][x].feat) && !cave[y][x].m_idx) { msg_print(NULL); move_player_effect(y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); } } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/* * Close an open door. */ void do_cmd_close(cmd_code code, cmd_arg args[]) { int y, x, dir; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Verify legality */ if (!do_cmd_close_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave->m_idx[y][x] > 0) { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Door */ else { /* Close door */ more = do_cmd_close_aux(y, x); } /* Cancel repeat unless told not to */ if (!more) disturb(p_ptr, 0, 0); }
bool do_blow(int type) { int x = 0, y = 0; int dir; int m_idx = 0; /* For ergonomics sake, use currently targeted monster. This allows a macro of \e*tmaa or similar to pick an adjacent foe, while \emaa*t won't work, since get_rep_dir2() won't allow a target. */ if (use_old_target && target_okay()) { y = target_row; x = target_col; m_idx = cave[y][x].m_idx; if (m_idx) { if (m_list[m_idx].cdis > 1) m_idx = 0; else dir = 5; } } if (!m_idx) { if (!get_rep_dir2(&dir)) return FALSE; if (dir == 5) return FALSE; y = py + ddy[dir]; x = px + ddx[dir]; m_idx = cave[y][x].m_idx; if (!m_idx) { msg_print("There is no monster there."); return FALSE; } } if (m_idx) py_attack(y, x, type); return TRUE; }
/* * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter_aux(int dir) { int y, x; bool more = FALSE; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Attack monsters */ if (cave->m_idx[y][x] > 0) py_attack(y, x); /* Tunnel through walls and rubble */ else if (cave_isdiggable(cave, y, x)) more = do_cmd_tunnel_aux(y, x); /* Open closed doors */ else if (cave_iscloseddoor(cave, y, x)) more = do_cmd_open_aux(y, x); /* Disarm traps */ else if (cave_isknowntrap(cave, y, x)) more = do_cmd_disarm_aux(y, x); /* Oops */ else msg("You spin around."); /* Cancel repetition unless we can continue */ if (!more) disturb(p_ptr, 0, 0); }
/** * Tunnel through "walls" (including rubble and doors, secret or otherwise) * * Digging is very difficult without a "digger" weapon, but can be * accomplished by strong players using heavy weapons. */ void do_cmd_tunnel(struct command *cmd) { int y, x, dir; bool more = false; /* Get arguments */ if (cmd_get_direction(cmd, "direction", &dir, false)) return; /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Oops */ if (!do_cmd_tunnel_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; } /* Attack any monster we run into */ if (cave->squares[y][x].mon > 0) { msg("There is a monster in the way!"); py_attack(y, x); } else { /* Tunnel through walls */ more = do_cmd_tunnel_aux(y, x); } /* Cancel repetition unless we can continue */ if (!more) disturb(player, 0); }
/** * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter_aux(int dir) { int y, x; bool more = false; /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; } /* Action depends on what's there */ if (cave->squares[y][x].mon > 0) /* Attack monsters */ py_attack(y, x); else if (square_isdiggable(cave, y, x)) /* Tunnel through walls and rubble */ more = do_cmd_tunnel_aux(y, x); else if (square_iscloseddoor(cave, y, x)) /* Open closed doors */ more = do_cmd_open_aux(y, x); else if (square_isknowntrap(cave, y, x)) /* Disarm traps */ more = do_cmd_disarm_aux(y, x); else /* Oops */ msg("You spin around."); /* Cancel repetition unless we can continue */ if (!more) disturb(player, 0); }
void awesome_blow_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Awesome Blow"); break; case SPELL_DESC: var_set_string(res, "Attack a monster with a single melee blow. If blow hits, does normal melee damage and propels the monster backwards."); break; case SPELL_CAST: { int y, x, dir; var_set_bool(res, FALSE); if (!get_rep_dir2(&dir)) return; if (dir == 5) return; y = py + ddy[dir]; x = px + ddx[dir]; if (cave[y][x].m_idx) { py_attack(y, x, MELEE_AWESOME_BLOW); } else { msg_print("There is no monster."); return; } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/* * Open a closed/locked/jammed door or a closed/locked chest. * * Unlocking a locked door/chest is worth one experience point. */ void do_cmd_open(cmd_code code, cmd_arg args[]) { int y, x, dir; s16b o_idx; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_open_test(y, x)) { /* Cancel repeat */ disturb(0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chest */ o_idx = chest_check(y, x); } /* Monster */ if (cave_m_idx[y][x] > 0) { if (mon_list[cave_m_idx[y][x]].align & (AL_PET_MASK)) msg_print("There is a friendly monster in the way!"); else { /* Message */ msg_print("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } /* Chest */ else if (o_idx) { /* Open the chest */ more = do_cmd_open_chest(y, x, o_idx); } /* Door */ else { /* Open the door */ more = do_cmd_open_aux(y, x); } /* Cancel repeat unless we may continue */ if (!more) disturb(0, 0); }
/* * Bash open a door, success based on character strength * * For a closed door, pval is positive if locked; negative if stuck. * * For an open door, pval is positive for a broken door. * * A closed door can be opened - harder if locked. Any door might be * bashed open (and thereby broken). Bashing a door is (potentially) * faster! You move into the door way. To open a stuck door, it must * be bashed. A closed door can be jammed (see do_cmd_spike()). * * Creatures can also open or bash doors, see elsewhere. */ void do_cmd_bash(void) { int py = p_ptr->py; int px = p_ptr->px; int y, x, dir; bool more = FALSE; /* Get a direction (or abort) */ if (!get_rep_dir(&dir)) return; /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; /* Verify legality */ if (!do_cmd_bash_test(y, x)) return; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; } /* Allow repeated command */ if (p_ptr->command_arg) { /* Set repeat count */ p_ptr->command_rep = p_ptr->command_arg - 1; /* Redraw the state */ p_ptr->redraw |= (PR_STATE); /* Cancel the arg */ p_ptr->command_arg = 0; } /* Monster */ if (cave_m_idx[y][x] > 0) { /* Message */ msg_print("There is a monster in the way!"); /* Attack */ py_attack(y, x); /* Done */ return; } /* Door */ else { /* Bash the door */ more = do_cmd_bash_aux(y, x); } /* Cancel repeat unless told not to */ if (!more) disturb(0, 0); }
/** * Open a closed/locked/jammed door or a closed/locked chest. * * Unlocking a locked chest is worth one experience point; since doors are * player lockable, there is no experience for unlocking doors. */ void do_cmd_open(struct command *cmd) { int y, x, dir; struct object *obj; bool more = false; int err; struct monster *m; /* Get arguments */ err = cmd_get_arg_direction(cmd, "direction", &dir); if (err || dir == DIR_UNKNOWN) { int y2, x2; int n_closed_doors, n_locked_chests; n_closed_doors = count_feats(&y2, &x2, square_iscloseddoor, false); n_locked_chests = count_chests(&y2, &x2, CHEST_OPENABLE); if (n_closed_doors + n_locked_chests == 1) { dir = coords_to_dir(y2, x2); cmd_set_arg_direction(cmd, "direction", dir); } else if (cmd_get_direction(cmd, "direction", &dir, false)) { return; } } /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chest */ obj = chest_check(y, x, CHEST_OPENABLE); /* Check for door */ if (!obj && !do_cmd_open_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chest */ obj = chest_check(y, x, CHEST_OPENABLE); } /* Monster */ m = square_monster(cave, y, x); if (m) { /* Mimics surprise the player */ if (is_mimicking(m)) { become_aware(m); /* Mimic wakes up */ mon_clear_timed(m, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false); } else { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } else if (obj) { /* Chest */ more = do_cmd_open_chest(y, x, obj); } else { /* Door */ more = do_cmd_open_aux(y, x); } /* Cancel repeat unless we may continue */ if (!more) disturb(player, 0); }
/* * Move player in the given direction. * * 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/rubble/etc. */ void move_player(int dir, bool disarm) { int py = p_ptr->py; int px = p_ptr->px; int y = py + ddy[dir]; int x = px + ddx[dir]; int m_idx = cave->m_idx[y][x]; /* Attack monsters */ if (m_idx > 0) { /* Mimics surprise the player */ if (is_mimicking(m_idx)) { become_aware(m_idx); /* Mimic wakes up */ mon_clear_timed(m_idx, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE); } else { py_attack(y, x); } } /* Optionally alter traps/doors on movement */ else if (disarm && (cave->info[y][x] & CAVE_MARK) && (cave_isknowntrap(cave, y, x) || cave_iscloseddoor(cave, y, x))) { /* Auto-repeat if not already repeating */ if (cmd_get_nrepeats() == 0) cmd_set_repeat(99); do_cmd_alter_aux(dir); } /* Cannot walk through walls */ else if (!cave_floor_bold(y, x)) { /* Disturb the player */ disturb(p_ptr, 0, 0); /* Notice unknown obstacles */ if (!(cave->info[y][x] & CAVE_MARK)) { /* Rubble */ if (cave->feat[y][x] == FEAT_RUBBLE) { msgt(MSG_HITWALL, "You feel a pile of rubble blocking your way."); cave->info[y][x] |= (CAVE_MARK); cave_light_spot(cave, y, x); } /* Closed door */ else if (cave->feat[y][x] < FEAT_SECRET) { msgt(MSG_HITWALL, "You feel a door blocking your way."); cave->info[y][x] |= (CAVE_MARK); cave_light_spot(cave, y, x); } /* Wall (or secret door) */ else { msgt(MSG_HITWALL, "You feel a wall blocking your way."); cave->info[y][x] |= (CAVE_MARK); cave_light_spot(cave, y, x); } } /* Mention known obstacles */ else { if (cave->feat[y][x] == FEAT_RUBBLE) msgt(MSG_HITWALL, "There is a pile of rubble blocking your way."); else if (cave->feat[y][x] < FEAT_SECRET) msgt(MSG_HITWALL, "There is a door blocking your way."); else msgt(MSG_HITWALL, "There is a wall blocking your way."); } } /* Normal movement */ else { /* See if trap detection status will change */ bool old_dtrap = ((cave->info2[py][px] & (CAVE2_DTRAP)) != 0); bool new_dtrap = ((cave->info2[y][x] & (CAVE2_DTRAP)) != 0); /* Note the change in the detect status */ if (old_dtrap != new_dtrap) p_ptr->redraw |= (PR_DTRAP); /* Disturb player if the player is about to leave the area */ if (OPT(disturb_detect) && p_ptr->running && !p_ptr->running_firststep && old_dtrap && !new_dtrap) { disturb(p_ptr, 0, 0); return; } /* Move player */ monster_swap(py, px, y, x); /* New location */ y = py = p_ptr->py; x = px = p_ptr->px; /* Searching */ if (p_ptr->searching || (p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] >= 50) || one_in_(50 - p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) search(FALSE); /* Handle "store doors" */ if ((cave->feat[p_ptr->py][p_ptr->px] >= FEAT_SHOP_HEAD) && (cave->feat[p_ptr->py][p_ptr->px] <= FEAT_SHOP_TAIL)) { /* Disturb */ disturb(p_ptr, 0, 0); cmd_insert(CMD_ENTER_STORE); } /* All other grids (including traps) */ else { /* Handle objects (later) */ p_ptr->notice |= (PN_PICKUP); } /* Discover invisible traps */ if (cave->feat[y][x] == FEAT_INVIS) { /* Disturb */ disturb(p_ptr, 0, 0); /* Message */ msg("You found a trap!"); /* Pick a trap */ pick_trap(y, x); /* Hit the trap */ hit_trap(y, x); } /* Set off an visible trap */ else if (cave_isknowntrap(cave, y, x)) { /* Disturb */ disturb(p_ptr, 0, 0); /* Hit the trap */ hit_trap(y, x); } } p_ptr->running_firststep = FALSE; }
/* * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors, * or, for rogues, set traps and steal money. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter(void) { int py = p_ptr->py; int px = p_ptr->px; int y, x, dir; int feat; bool did_nothing = TRUE; bool more = FALSE; monster_type *m_ptr; /* Get a direction */ if (!get_rep_dir(&dir)) return; /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; /* Original feature */ feat = cave_feat[y][x]; /* Must have knowledge to know feature XXX XXX */ if (!(cave_info[y][x] & (CAVE_MARK))) feat = FEAT_NONE; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; } /* Allow repeated command */ if (p_ptr->command_arg) { /* Set repeat count */ p_ptr->command_rep = p_ptr->command_arg - 1; /* Redraw the state */ p_ptr->redraw |= (PR_STATE); /* Cancel the arg */ p_ptr->command_arg = 0; } /* If a monster is present, and visible, Rogues may steal from it. * Otherwise, the player will simply attack. -LM- */ if (cave_m_idx[y][x] > 0) { if ((check_ability(SP_STEAL)) && (!SCHANGE)) { m_ptr = &m_list[cave_m_idx[y][x]]; if (m_ptr->ml) py_steal(y, x); else py_attack(y, x); } else py_attack(y, x); did_nothing = FALSE; } /* * Some players can set traps. Total number is checked in py_set_trap. */ else if ((check_ability(SP_TRAP)) && (cave_naked_bold(y, x))) { py_set_trap(y, x); did_nothing = FALSE; } /* Disarm advanced monster traps */ else if (feat > FEAT_MTRAP_HEAD) { /* Disarm */ more = do_cmd_disarm_aux(y, x); } /* Modify basic monster traps */ else if (feat == FEAT_MTRAP_HEAD) { /* Modify */ py_modify_trap(y, x); } /* Tunnel through walls */ else if (feat >= FEAT_SECRET) { /* Tunnel */ more = do_cmd_tunnel_aux(y, x); } /* Bash jammed doors */ else if (feat >= FEAT_DOOR_HEAD + 0x08) { /* Bash */ more = do_cmd_bash_aux(y, x); } /* Open closed doors */ else if (feat >= FEAT_DOOR_HEAD) { /* Close */ more = do_cmd_open_aux(y, x); } /* Disarm traps */ else if (feat >= FEAT_TRAP_HEAD) { /* Disarm */ more = do_cmd_disarm_aux(y, x); } /* Oops */ else if (did_nothing) { /* Oops */ msg_print("You spin around."); } /* Cancel repetition unless we can continue */ if (!more) disturb(0, 0); }
/* * Open a closed/locked/jammed door or a closed/locked chest. * * Unlocking a locked door/chest is worth one experience point. */ void do_cmd_open(cmd_code code, cmd_arg args[]) { int y, x, dir; s16b o_idx; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_open_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chest */ o_idx = chest_check(y, x); } /* Monster */ if (cave->m_idx[y][x] > 0) { int m_idx = cave->m_idx[y][x]; /* Mimics surprise the player */ if (is_mimicking(m_idx)) { become_aware(m_idx); /* Mimic wakes up */ mon_clear_timed(m_idx, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE); } else { /* Message */ msg("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } /* Chest */ else if (o_idx) { /* Open the chest */ more = do_cmd_open_chest(y, x, o_idx); } /* Door */ else { /* Open the door */ more = do_cmd_open_aux(y, x); } /* Cancel repeat unless we may continue */ if (!more) disturb(p_ptr, 0, 0); }
/** * Move player in the given direction. * * 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/rubble/etc. */ void move_player(int dir, bool disarm) { int y = player->py + ddy[dir]; int x = player->px + ddx[dir]; int m_idx = cave->squares[y][x].mon; struct monster *mon = cave_monster(cave, m_idx); bool alterable = (square_isknowntrap(cave, y, x) || square_iscloseddoor(cave, y, x)); /* Attack monsters, alter traps/doors on movement, hit obstacles or move */ if (m_idx > 0) { /* Mimics surprise the player */ if (is_mimicking(mon)) { become_aware(mon); /* Mimic wakes up */ mon_clear_timed(mon, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, false); } else { py_attack(y, x); } } else if (disarm && square_isknown(cave, y, x) && alterable) { /* Auto-repeat if not already repeating */ if (cmd_get_nrepeats() == 0) cmd_set_repeat(99); do_cmd_alter_aux(dir); } else if (player->upkeep->running && square_isknowntrap(cave, y, x)) { /* Stop running before known traps */ disturb(player, 0); } else if (!square_ispassable(cave, y, x)) { disturb(player, 0); /* Notice unknown obstacles, mention known obstacles */ if (!square_isknown(cave, y, x)) { if (square_isrubble(cave, y, x)) { msgt(MSG_HITWALL, "You feel a pile of rubble blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } else if (square_iscloseddoor(cave, y, x)) { msgt(MSG_HITWALL, "You feel a door blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } else { msgt(MSG_HITWALL, "You feel a wall blocking your way."); square_memorize(cave, y, x); square_light_spot(cave, y, x); } } else { if (square_isrubble(cave, y, x)) msgt(MSG_HITWALL, "There is a pile of rubble blocking your way."); else if (square_iscloseddoor(cave, y, x)) msgt(MSG_HITWALL, "There is a door blocking your way."); else msgt(MSG_HITWALL, "There is a wall blocking your way."); } } else { /* Move player */ monster_swap(player->py, player->px, y, x); /* Handle store doors, or notice objects */ if (square_isshop(cave, y, x)) { disturb(player, 0); event_signal(EVENT_ENTER_STORE); event_remove_handler_type(EVENT_ENTER_STORE); event_signal(EVENT_USE_STORE); event_remove_handler_type(EVENT_USE_STORE); event_signal(EVENT_LEAVE_STORE); event_remove_handler_type(EVENT_LEAVE_STORE); } else { square_know_pile(cave, y, x); cmdq_push(CMD_AUTOPICKUP); } /* Discover invisible traps, set off visible ones */ if (square_issecrettrap(cave, y, x)) { disturb(player, 0); hit_trap(y, x); } else if (square_isknowntrap(cave, y, x)) { disturb(player, 0); hit_trap(y, x); } /* Update view and search */ update_view(cave, player); search(); } player->upkeep->running_firststep = false; }
/** * 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."); } } } }
/** * Disarms a trap, or a chest * * Traps must be visible, chests must be known trapped */ void do_cmd_disarm(struct command *cmd) { int y, x, dir; int err; struct object *obj; bool more = false; /* Get arguments */ err = cmd_get_arg_direction(cmd, "direction", &dir); if (err || dir == DIR_UNKNOWN) { int y2, x2; int n_traps, n_chests; n_traps = count_feats(&y2, &x2, square_isknowntrap, true); n_chests = count_chests(&y2, &x2, CHEST_TRAPPED); if (n_traps + n_chests == 1) { dir = coords_to_dir(y2, x2); cmd_set_arg_direction(cmd, "direction", dir); } else if (cmd_get_direction(cmd, "direction", &dir, n_chests > 0)) { /* If there are chests to disarm, 5 is allowed as a direction */ return; } } /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chests */ obj = chest_check(y, x, CHEST_TRAPPED); /* Verify legality */ if (!obj && !do_cmd_disarm_test(y, x)) { /* Cancel repeat */ disturb(player, 0); return; } /* Take a turn */ player->upkeep->energy_use = z_info->move_energy; /* Apply confusion */ if (player_confuse_dir(player, &dir, false)) { /* Get location */ y = player->py + ddy[dir]; x = player->px + ddx[dir]; /* Check for chests */ obj = chest_check(y, x, CHEST_TRAPPED); } /* Monster */ if (cave->squares[y][x].mon > 0) { msg("There is a monster in the way!"); py_attack(y, x); } else if (obj) /* Chest */ more = do_cmd_disarm_chest(y, x, obj); else if (square_iscloseddoor(cave, y, x) && !square_islockeddoor(cave, y, x)) /* Door to lock */ more = do_cmd_lock_door(y, x); else /* Disarm trap */ more = do_cmd_disarm_aux(y, x); /* Cancel repeat unless told not to */ if (!more) disturb(player, 0); }
/* * Disarms a trap, a glyph, or a chest. */ void do_cmd_disarm(void) { int py = p_ptr->py; int px = p_ptr->px; int y, x, dir; s16b o_idx; bool more = FALSE; /* Option: Pick a direction -TNB- */ if (easy_disarm) { int num_traps, num_chests; /* Count visible traps */ num_traps = count_feats(&y, &x, is_trap, TRUE); /* Count chests (trapped) */ num_chests = count_chests(&y, &x, TRUE); /* See if there's only one target */ if (num_traps || num_chests) { if (num_traps + num_chests <= 1) p_ptr->command_dir = coords_to_dir(y, x); } } /* Get a direction (or abort) */ if (!get_rep_dir(&dir)) return; /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_disarm_test(y, x)) return; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); } /* Allow repeated command */ if (p_ptr->command_arg) { /* Set repeat count */ p_ptr->command_rep = p_ptr->command_arg - 1; /* Redraw the state */ p_ptr->redraw |= (PR_STATE); /* Cancel the arg */ p_ptr->command_arg = 0; } /* Monster */ if (cave_m_idx[y][x] > 0) { /* Message */ msg_print("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Chest */ else if (o_idx) { /* Disarm the chest */ more = do_cmd_disarm_chest(y, x, o_idx); } /* Disarm trap */ else { /* Disarm the trap */ more = do_cmd_disarm_aux(y, x); } /* Cancel repeat unless told not to */ if (!more) disturb(0, 0); }
/* * Manipulate an adjacent grid in some way * * Attack monsters, tunnel through walls, disarm traps, open doors. * * This command must always take energy, to prevent free detection * of invisible monsters. * * The "semantics" of this command must be chosen before the player * is confused, and it must be verified against the new grid. */ void do_cmd_alter_aux(int dir) { int y, x; int feat; bool more = FALSE; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Original feature */ feat = cave_feat[y][x]; /* Must have knowledge to know feature XXX XXX */ if (!(cave_info[y][x] & (CAVE_MARK))) feat = FEAT_NONE; /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Attack monsters */ if (cave_m_idx[y][x] > 0) { if (mon_list[cave_m_idx[y][x]].align & (AL_PET_MASK)) { msg_print("There is a friendly monster in the way!"); } else { /* Attack */ py_attack(y, x); } } /* Tunnel through walls */ else if (feat >= FEAT_SECRET) { more = do_cmd_tunnel_aux(y, x); } #if 0 /* Bash jammed doors */ else if (feat >= FEAT_DOOR_HEAD + 0x08) { more = do_cmd_bash_aux(y, x); } #endif /* Open closed doors */ else if (feat >= FEAT_DOOR_HEAD) { more = do_cmd_open_aux(y, x); } /* Disarm traps */ else if (feat >= FEAT_TRAP_HEAD) { more = do_cmd_disarm_aux(y, x); } #if 0 /* Close open doors */ else if (feat == FEAT_OPEN) { more = do_cmd_close_aux(y, x); } #endif /* Oops */ else { msg_print("You spin around."); } /* Cancel repetition unless we can continue */ if (!more) disturb(0, 0); }
/* * Disarms a trap, or a chest */ void do_cmd_disarm(cmd_code code, cmd_arg args[]) { int y, x, dir; s16b o_idx; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_disarm_test(y, x)) { /* Cancel repeat */ disturb(0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (confuse_dir(&dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); } /* Monster */ if (cave_m_idx[y][x] > 0) { /* Message */ msg_print("There is a monster in the way!"); /* Attack */ py_attack(y, x); } /* Chest */ else if (o_idx) { /* Disarm the chest */ more = do_cmd_disarm_chest(y, x, o_idx); } /* Disarm trap */ else { /* Disarm the trap */ more = do_cmd_disarm_aux(y, x); } /* Cancel repeat unless told not to */ if (!more) disturb(0, 0); }
/** * Rogues may steal gold from monsters. The monster needs to have * something to steal (it must drop some form of loot), and should * preferably be asleep. Humanoids and dragons are a rogue's favorite * targets. Steal too often on a level, and monsters will be more wary, * and the hue and cry will be eventually be raised. Having every * monster on the level awake and aggravated is not pleasant. -LM- */ extern void py_steal(int y, int x) { cptr act = NULL; monster_type *m_ptr = &m_list[cave_m_idx[y][x]]; monster_race *r_ptr = &r_info[m_ptr->r_idx]; char m_name[80]; int i; int effect, theft_protection; int filching_power = 0; int purse = 0; bool thief = FALSE; bool success = FALSE; /* Check intent */ if ((m_ptr->hostile != -1) && !get_check("Do you want to steal from this being?")) { py_attack(y, x, FALSE); return; } /* Hard limit on theft. */ if (number_of_thefts_on_level > 4) { msg_print ("Everyone is keeping a lookout for you. You can steal nothing here."); return; } /* Determine the cunning of the thief. */ filching_power = 2 * p_ptr->lev; /* Penalize some conditions */ if (p_ptr->timed[TMD_BLIND] || no_light()) filching_power = filching_power / 10; if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) filching_power = filching_power / 10; /* Determine how much protection the monster has. */ theft_protection = (7 * (r_ptr->level + 2) / 4); theft_protection += (m_ptr->mspeed - p_ptr->state.pspeed); if (theft_protection < 1) theft_protection = 1; /* Send a thief to catch a thief. */ for (i = 0; i < 4; i++) { /* Extract infomation about the blow effect */ effect = r_ptr->blow[i].effect; if (effect == RBE_EAT_GOLD) thief = TRUE; if (effect == RBE_EAT_ITEM) thief = TRUE; } if (thief) theft_protection += 30; if (m_ptr->csleep) theft_protection = 3 * theft_protection / 5; /* Special player stealth magics aid stealing, but are lost in the process */ if (p_ptr->timed[TMD_SSTEALTH]) { theft_protection = 3 * theft_protection / 5; (void) clear_timed(TMD_SSTEALTH, TRUE); } /* The more you steal on a level, the more wary the monsters. */ theft_protection += number_of_thefts_on_level * 15; /* Did the theft succeed? */ if (randint1(theft_protection) < filching_power) success = TRUE; /* If the theft succeeded, determine the value of the purse. */ if (success) { purse = (r_ptr->level + 1) + randint1(3 * (r_ptr->level + 1) / 2); /* Uniques are juicy targets. */ if (rf_has(r_ptr->flags, RF_UNIQUE)) purse *= 3; /* But some monsters are dirt poor. */ if (!(rf_has(r_ptr->flags, RF_DROP_60)) || rf_has(r_ptr->flags, RF_DROP_90) || rf_has(r_ptr->flags, RF_DROP_1D2) || rf_has(r_ptr->flags, RF_DROP_2D2) || rf_has(r_ptr->flags, RF_DROP_3D2) || rf_has(r_ptr->flags, RF_DROP_4D2)) purse = 0; /* Some monster races are far better to steal from than others. */ if ((r_ptr->d_char == 'D') || (r_ptr->d_char == 'd') || (r_ptr->d_char == 'p') || (r_ptr->d_char == 'h')) purse *= 2 + randint1(3) + randint1(r_ptr->level / 20); else if ((r_ptr->d_char == 'P') || (r_ptr->d_char == 'o') || (r_ptr->d_char == 'O') || (r_ptr->d_char == 'T') || (r_ptr->d_char == 'n') || (r_ptr->d_char == 'W') || (r_ptr->d_char == 'k') || (r_ptr->d_char == 'L') || (r_ptr->d_char == 'V') || (r_ptr->d_char == 'y')) purse *= 1 + randint1(3) + randint1(r_ptr->level / 30); /* Pickings are scarce in a land of many thieves. */ purse = purse * (p_ptr->depth + 5) / (p_ptr->recall[0] + 5); /* Increase player gold. */ p_ptr->au += purse; /* Limit to avoid buffer overflow */ if (p_ptr->au > PY_MAX_GOLD) p_ptr->au = PY_MAX_GOLD; /* Redraw gold */ p_ptr->redraw |= (PR_GOLD); /* Announce the good news. */ if (purse) msg_format("You burgle %d gold.", purse); /* Pockets are empty. */ else msg_print("You burgle only dust."); } /* The victim normally, but not always, wakes up and is aggravated. */ if (randint1(4) != 1) { m_ptr->csleep = 0; m_ptr->mflag |= (MFLAG_ACTV); if (m_ptr->mspeed < r_ptr->speed + 3) m_ptr->mspeed += 10; /* Become hostile */ m_ptr->hostile = -1; /* Occasionally, amuse the player with a message. */ if ((randint1(5) == 1) && (purse) && (rf_has(r_ptr->flags, RF_SMART))) { monster_desc(m_name, sizeof(m_name), m_ptr, 0); act = desc_victim_outcry[randint0(20)]; msg_format("%^s cries out %s", m_name, act); } /* Otherwise, simply explain what happened. */ else { monster_desc(m_name, sizeof(m_name), m_ptr, 0); msg_format("You have aroused %s.", m_name); } } /* The thief also speeds up, but only for just long enough to escape. */ if (!p_ptr->timed[TMD_FAST]) p_ptr->timed[TMD_FAST] += 2; /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); /* Handle stuff */ handle_stuff(); /* Increment the number of thefts, and possibly raise the hue and cry. */ number_of_thefts_on_level++; if (number_of_thefts_on_level > 4) { /* Notify the player of the trouble he's in. */ msg_print("All the level is in an uproar over your misdeeds!"); /* Aggravate and speed up all monsters on level. */ (void) aggravate_monsters(1, TRUE); } else if ((number_of_thefts_on_level > 2) || (randint1(8) == 1)) { msg_print ("You hear hunting parties scouring the area for a notorious burgler."); /* Aggravate monsters nearby. */ (void) aggravate_monsters(1, FALSE); } /* Rogue "Hit and Run" attack. */ if (p_ptr->special_attack & (ATTACK_FLEE)) { /* Cancel the fleeing spell */ p_ptr->special_attack &= ~(ATTACK_FLEE); /* Message */ msg_print("You escape into the shadows!"); /* Teleport. */ teleport_player(6 + p_ptr->lev / 5, TRUE); /* Redraw the state */ p_ptr->redraw |= (PR_STATUS); } }
/* * Jam a closed door with a spike. Now takes only 4/10ths normal energy * if no monster is in the way. -LM- * * This command may NOT be repeated */ void do_cmd_spike(void) { int py = p_ptr->py; int px = p_ptr->px; int y, x, dir, item; /* Get a spike */ if (!get_spike(&item)) { /* Message */ msg_print("You have no spikes!"); /* Done */ return; } /* Get a direction (or abort) */ if (!get_rep_dir(&dir)) return; /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; /* Verify legality */ if (!do_cmd_spike_test(y, x)) return; /* Take a partial turn. Now jamming is more useful. */ p_ptr->energy_use = 40; /* Confuse direction */ if (confuse_dir(&dir)) { /* Get location */ y = py + ddy[dir]; x = px + ddx[dir]; } /* Monster. Make the action now take a full turn */ if (cave_m_idx[y][x] > 0) { /* Message */ msg_print("There is a monster in the way!"); p_ptr->energy_use += 60; /* Attack */ py_attack(y, x); } /* Go for it */ else { /* Verify legality */ if (!do_cmd_spike_test(y, x)) return; /* Successful jamming */ msg_print("You jam the door with a spike."); /* Convert "locked" to "stuck" XXX XXX XXX */ if (cave_feat[y][x] < FEAT_DOOR_HEAD + 0x08) { cave_feat[y][x] += 0x08; } /* Add one spike to the door */ if (cave_feat[y][x] < FEAT_DOOR_TAIL) { cave_feat[y][x] += 0x01; } /* Use up, and describe, a single spike, from the bottom */ inven_item_increase(item, -1); inven_item_describe(item); inven_item_optimize(item); } }
static void _double_crack_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Double Crack"); break; case SPELL_DESC: var_set_string(res, "Attack a monster normally with your whip, and then randomly attack an adjacent monster."); break; case SPELL_CAST: if (_whip_check()) { int dir = 5; bool b = FALSE; if ( get_rep_dir2(&dir) && dir != 5 ) { int x, y; int num = 1; int attempts = 0; /* First we attack where the player selected */ y = py + ddy[dir]; x = px + ddx[dir]; if (in_bounds(y, x) && cave[y][x].m_idx) py_attack(y, x, 0); else msg_print("Your whip cracks in empty air."); /* Now the whip cracks randomly! Note that we favor fighting in hallways, or with ones back up against the wall. */ while (num > 0) { if (attempts > 3 * num) { while (num > 0) { msg_print("Your whip cracks in empty air."); num--; } break; } /* random direction, but we don't penalize for choosing the player (5) */ dir = randint0(9); if (dir == 5) continue; attempts++; y = py + ddy[dir]; x = px + ddx[dir]; if ( !in_bounds(y, x) || cave_have_flag_bold(y, x, FF_WALL) || cave_have_flag_bold(y, x, FF_TREE) || cave_have_flag_bold(y, x, FF_CAN_DIG) ) { continue; } if (cave[y][x].m_idx) py_attack(y, x, 0); else msg_print("Your whip cracks in empty air."); num--; } b = TRUE; } var_set_bool(res, b); } else { msg_print("Whip techniques can only be used if you are fighting with whips."); var_set_bool(res, FALSE); } break; default: default_spell(cmd, res); break; } }
/* * Jam a closed door with a spike * * This command may NOT be repeated */ void do_cmd_spike(cmd_code code, cmd_arg args[]) { int y, x, dir, item = 0; dir = args[0].direction; /* Get a spike */ if (!get_spike(&item)) { /* Message */ msg_print("You have no spikes!"); /* Done */ return; } /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Verify legality */ if (!do_cmd_spike_test(y, x)) return; /* Take a turn */ p_ptr->energy_use = 100; /* Confuse direction */ if (confuse_dir(&dir)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; } /* Monster */ if (cave_m_idx[y][x] > 0) { if (mon_list[cave_m_idx[y][x]].align & (AL_PET_MASK)) { msg_print("There is a friendly monster in the way!"); } else { /* Message */ msg_print("There is a monster in the way!"); /* Attack */ py_attack(y, x); } } /* Go for it */ else { /* Verify legality */ if (!do_cmd_spike_test(y, x)) return; /* Successful jamming */ msg_print("You jam the door with a spike."); /* Convert "locked" to "stuck" XXX XXX XXX */ if (cave_feat[y][x] < FEAT_DOOR_HEAD + 0x08) { cave_feat[y][x] += 0x08; } /* Add one spike to the door */ if (cave_feat[y][x] < FEAT_DOOR_TAIL) { cave_feat[y][x] += 0x01; } /* Use up, and describe, a single spike, from the bottom */ inven_item_increase(item, -1); inven_item_describe(item); inven_item_optimize(item); } }
/* * Disarms a trap, or a chest */ void do_cmd_disarm(cmd_code code, cmd_arg args[]) { int y, x, dir; s16b o_idx; bool more = FALSE; dir = args[0].direction; /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); /* Verify legality */ if (!o_idx && !do_cmd_disarm_test(y, x)) { /* Cancel repeat */ disturb(p_ptr, 0, 0); return; } /* Take a turn */ p_ptr->energy_use = 100; /* Apply confusion */ if (player_confuse_dir(p_ptr, &dir, FALSE)) { /* Get location */ y = p_ptr->py + ddy[dir]; x = p_ptr->px + ddx[dir]; /* Check for chests */ o_idx = chest_check(y, x); } /* Monster */ if (cave->m_idx[y][x] > 0) { msg("There is a monster in the way!"); py_attack(y, x); } /* Chest */ else if (o_idx) more = do_cmd_disarm_chest(y, x, o_idx); /* Door to lock */ else if (cave->feat[y][x] == FEAT_DOOR_HEAD) more = do_cmd_lock_door(y, x); /* Disarm trap */ else more = do_cmd_disarm_aux(y, x); /* Cancel repeat unless told not to */ if (!more) disturb(p_ptr, 0, 0); }