X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Ftrap.c;h=590f4db3c845fe67486d2bd129837d438b47ffc2;hb=bd519d53bf8418cc2225f944092684de915be365;hp=e75729f8962cccadf2415ebc51ce21dd029b7554;hpb=188488293d5afb53a6c20dda31feafb844af35d9;p=hengband%2Fhengband.git diff --git a/src/trap.c b/src/trap.c index e75729f89..590f4db3c 100644 --- a/src/trap.c +++ b/src/trap.c @@ -6,6 +6,8 @@ #include "player-damage.h" #include "player-move.h" #include "player-effects.h" +#include "player-class.h" +#include "player-personality.h" #include "spells-summon.h" #include "quest.h" #include "artifact.h" @@ -19,6 +21,7 @@ #include "files.h" #include "dungeon.h" #include "world.h" +#include "realm-song.h" static s16b normal_traps[MAX_NORMAL_TRAPS]; @@ -141,12 +144,12 @@ void init_normal_traps(void) * Actually, it is not this routine, but the "trap instantiation"\n * code, which should also check for "trap doors" on quest levels.\n */ -FEAT_IDX choose_random_trap(void) +FEAT_IDX choose_random_trap(floor_type *floor_ptr) { FEAT_IDX feat; /* Pick a trap */ - while (1) + while (TRUE) { /* Hack -- pick a trap */ feat = normal_traps[randint0(MAX_NORMAL_TRAPS)]; @@ -155,10 +158,10 @@ FEAT_IDX choose_random_trap(void) if (!have_flag(f_info[feat].flags, FF_MORE)) break; /* Hack -- no trap doors on special levels */ - if (p_ptr->inside_arena || quest_number(current_floor_ptr->dun_level)) continue; + if (floor_ptr->inside_arena || quest_number(floor_ptr->dun_level)) continue; /* Hack -- no trap doors on the deepest level */ - if (current_floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) continue; + if (floor_ptr->dun_level >= d_info[floor_ptr->dungeon_idx].maxdepth) continue; break; } @@ -166,21 +169,23 @@ FEAT_IDX choose_random_trap(void) return feat; } + /*! -* @brief マスに存在するトラップを秘匿する / +* @brief マスに存在する隠しトラップを公開する / * Disclose an invisible trap +* @param player * @param y 秘匿したいマスのY座標 * @param x 秘匿したいマスのX座標 * @return なし */ -void disclose_grid(POSITION y, POSITION x) +void disclose_grid(player_type *trapped_ptr, POSITION y, POSITION x) { - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; + grid_type *g_ptr = &trapped_ptr->current_floor_ptr->grid_array[y][x]; if (cave_have_flag_grid(g_ptr, FF_SECRET)) { /* No longer hidden */ - cave_alter_feat(y, x, FF_SECRET); + cave_alter_feat(trapped_ptr, y, x, FF_SECRET); } else if (g_ptr->mimic) { @@ -192,6 +197,7 @@ void disclose_grid(POSITION y, POSITION x) } } + /*! * @brief マスをトラップを配置する / * The location must be a legal, naked, floor grid. @@ -202,19 +208,19 @@ void disclose_grid(POSITION y, POSITION x) * when they are "discovered" (by detecting them or setting them off),\n * the trap is "instantiated" as a visible, "typed", trap.\n */ -void place_trap(POSITION y, POSITION x) +void place_trap(floor_type *floor_ptr, POSITION y, POSITION x) { - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; + grid_type *g_ptr = &floor_ptr->grid_array[y][x]; /* Paranoia -- verify location */ - if (!in_bounds(y, x)) return; + if (!in_bounds(floor_ptr, y, x)) return; /* Require empty, clean, floor grid */ - if (!cave_clean_bold(y, x)) return; + if (!cave_clean_bold(floor_ptr, y, x)) return; /* Place an invisible trap */ g_ptr->mimic = g_ptr->feat; - g_ptr->feat = choose_random_trap(); + g_ptr->feat = choose_random_trap(floor_ptr); } @@ -228,7 +234,7 @@ void place_trap(POSITION y, POSITION x) * Always miss 5% of the time, Always hit 5% of the time. * Otherwise, match trap power against player armor. */ -static int check_hit(int power) +static int check_hit(player_type *target_ptr, int power) { int k; ARMOUR_CLASS ac; @@ -239,20 +245,20 @@ static int check_hit(int power) /* Hack -- 5% hit, 5% miss */ if (k < 10) return (k < 5); - if (p_ptr->pseikaku == SEIKAKU_NAMAKE) - if (one_in_(20)) return (TRUE); + if (target_ptr->pseikaku == SEIKAKU_NAMAKE) + if (one_in_(20)) return TRUE; /* Paranoia -- No power */ - if (power <= 0) return (FALSE); + if (power <= 0) return FALSE; /* Total armor */ - ac = p_ptr->ac + p_ptr->to_a; + ac = target_ptr->ac + target_ptr->to_a; /* Power competes against Armor */ - if (randint1(power) > ((ac * 3) / 4)) return (TRUE); + if (randint1(power) > ((ac * 3) / 4)) return TRUE; /* Assume miss */ - return (FALSE); + return FALSE; } @@ -261,7 +267,7 @@ static int check_hit(int power) * @param trap_feat_type トラップの種別ID * @return なし */ -static void hit_trap_pit(int trap_feat_type) +static void hit_trap_pit(player_type *trapped_ptr, int trap_feat_type) { HIT_POINT dam; concptr trap_name = ""; @@ -284,7 +290,7 @@ static void hit_trap_pit(int trap_feat_type) return; } - if (p_ptr->levitation) + if (trapped_ptr->levitation) { msg_format(_("%sを飛び越えた。", "You fly over %s."), trap_name); return; @@ -302,37 +308,37 @@ static void hit_trap_pit(int trap_feat_type) msg_format(_("%sが刺さった!", "You are impaled on %s!"), spike_name); dam = dam * 2; - (void)set_cut(p_ptr->cut + randint1(dam)); + (void)set_cut(trapped_ptr,trapped_ptr->cut + randint1(dam)); if (trap_feat_type == TRAP_POISON_PIT) { - if (p_ptr->resist_pois || IS_OPPOSE_POIS()) + if (trapped_ptr->resist_pois || IS_OPPOSE_POIS()) { msg_print(_("しかし毒の影響はなかった!", "The poison does not affect you!")); } else { dam = dam * 2; - (void)set_poisoned(p_ptr->poisoned + randint1(dam)); + (void)set_poisoned(trapped_ptr, trapped_ptr->poisoned + randint1(dam)); } } } - take_hit(DAMAGE_NOESCAPE, dam, trap_name, -1); + take_hit(trapped_ptr, DAMAGE_NOESCAPE, dam, trap_name, -1); } /*! * @brief ダーツ系トラップ(通常ダメージ)の判定とプレイヤーの被害処理 * @return ダーツが命中した場合TRUEを返す */ -static bool hit_trap_dart(void) +static bool hit_trap_dart(player_type *target_ptr) { bool hit = FALSE; - if (check_hit(125)) + if (check_hit(target_ptr, 125)) { msg_print(_("小さなダーツが飛んできて刺さった!", "A small dart hits you!")); - take_hit(DAMAGE_ATTACK, damroll(1, 4), _("ダーツの罠", "a dart trap"), -1); - if (!CHECK_MULTISHADOW()) hit = TRUE; + take_hit(target_ptr, DAMAGE_ATTACK, damroll(1, 4), _("ダーツの罠", "a dart trap"), -1); + if (!CHECK_MULTISHADOW(target_ptr)) hit = TRUE; } else { @@ -347,11 +353,11 @@ static bool hit_trap_dart(void) * @param stat 低下する能力値ID * @return なし */ -static void hit_trap_lose_stat(int stat) +static void hit_trap_lose_stat(player_type *target_ptr, int stat) { - if (hit_trap_dart()) + if (hit_trap_dart(target_ptr)) { - do_dec_stat(stat); + do_dec_stat(target_ptr, stat); } } @@ -359,11 +365,11 @@ static void hit_trap_lose_stat(int stat) * @brief ダーツ系トラップ(通常ダメージ+減速)の判定とプレイヤーの被害処理 * @return なし */ -static void hit_trap_slow(void) +static void hit_trap_slow(player_type *target_ptr) { - if (hit_trap_dart()) + if (hit_trap_dart(target_ptr)) { - set_slow(p_ptr->slow + randint0(20) + 20, FALSE); + set_slow(target_ptr, target_ptr->slow + randint0(20) + 20, FALSE); } } @@ -372,7 +378,7 @@ static void hit_trap_slow(void) * @param trap_message メッセージの補完文字列 * @param resist 状態異常に抵抗する判定が出たならTRUE * @param set_status 状態異常を指定する関数ポインタ -* @param current_world_ptr->game_turn 状態異常の追加ターン量 +* @param turn_aux 状態異常の追加ターン量 * @return なし */ static void hit_trap_set_abnormal_status(concptr trap_message, bool resist, bool(*set_status)(IDX), IDX turn_aux) @@ -384,40 +390,49 @@ static void hit_trap_set_abnormal_status(concptr trap_message, bool resist, bool } } +static void hit_trap_set_abnormal_status_p(concptr trap_message, bool resist, bool(*set_status)(player_type *, IDX), IDX turn_aux) +{ + msg_print(trap_message); + if (!resist) + { + set_status(p_ptr, turn_aux); + } +} + /*! * @brief プレイヤーへのトラップ作動処理メインルーチン / * Handle player hitting a real trap * @param break_trap 作動後のトラップ破壊が確定しているならばTRUE * @return なし */ -void hit_trap(bool break_trap) +void hit_trap(player_type *trapped_ptr, bool break_trap) { int i, num, dam; - POSITION x = p_ptr->x, y = p_ptr->y; - grid_type *g_ptr = ¤t_floor_ptr->grid_array[y][x]; + POSITION x = trapped_ptr->x, y = trapped_ptr->y; + grid_type *g_ptr = &trapped_ptr->current_floor_ptr->grid_array[y][x]; feature_type *f_ptr = &f_info[g_ptr->feat]; int trap_feat_type = have_flag(f_ptr->flags, FF_TRAP) ? f_ptr->subtype : NOT_TRAP; concptr name = _("トラップ", "a trap"); - disturb(FALSE, TRUE); + disturb(trapped_ptr, FALSE, TRUE); - cave_alter_feat(y, x, FF_HIT_TRAP); + cave_alter_feat(trapped_ptr, y, x, FF_HIT_TRAP); /* Analyze */ switch (trap_feat_type) { case TRAP_TRAPDOOR: { - if (p_ptr->levitation) + if (trapped_ptr->levitation) { msg_print(_("落とし戸を飛び越えた。", "You fly over a trap door.")); } else { msg_print(_("落とし戸に落ちた!", "You have fallen through a trap door!")); - if ((p_ptr->pseikaku == SEIKAKU_COMBAT) || (p_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON)) + if ((trapped_ptr->pseikaku == SEIKAKU_COMBAT) || (trapped_ptr->inventory_list[INVEN_BOW].name1 == ART_CRIMSON)) msg_print(_("くっそ~!", "")); - else if((p_ptr->pseikaku == SEIKAKU_CHARGEMAN)) + else if((trapped_ptr->pseikaku == SEIKAKU_CHARGEMAN)) msg_print(_("ジュラル星人の仕業に違いない!", "")); @@ -425,15 +440,15 @@ void hit_trap(bool break_trap) dam = damroll(2, 8); name = _("落とし戸", "a trap door"); - take_hit(DAMAGE_NOESCAPE, dam, name, -1); + take_hit(trapped_ptr, DAMAGE_NOESCAPE, dam, name, -1); /* Still alive and autosave enabled */ - if (autosave_l && (p_ptr->chp >= 0)) - do_cmd_save_game(TRUE); + if (autosave_l && (trapped_ptr->chp >= 0)) + do_cmd_save_game(trapped_ptr, TRUE); - do_cmd_write_nikki(NIKKI_BUNSHOU, 0, _("落とし戸に落ちた", "You have fallen through a trap door!")); - prepare_change_floor_mode(CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT); - p_ptr->leaving = TRUE; + exe_write_diary(trapped_ptr, NIKKI_BUNSHOU, 0, _("落とし戸に落ちた", "You have fallen through a trap door!")); + prepare_change_floor_mode(trapped_ptr, CFM_SAVE_FLOORS | CFM_DOWN | CFM_RAND_PLACE | CFM_RAND_CONNECT); + trapped_ptr->leaving = TRUE; } break; } @@ -442,7 +457,7 @@ void hit_trap(bool break_trap) case TRAP_SPIKED_PIT: case TRAP_POISON_PIT: { - hit_trap_pit(trap_feat_type); + hit_trap_pit(trapped_ptr, trap_feat_type); break; } @@ -452,17 +467,17 @@ void hit_trap(bool break_trap) num = 2 + randint1(3); for (i = 0; i < num; i++) { - (void)summon_specific(0, y, x, current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET), '\0'); + (void)summon_specific(0, y, x, trapped_ptr->current_floor_ptr->dun_level, 0, (PM_ALLOW_GROUP | PM_ALLOW_UNIQUE | PM_NO_PET)); } - if (current_floor_ptr->dun_level > randint1(100)) /* No nasty effect for low levels */ + if (trapped_ptr->current_floor_ptr->dun_level > randint1(100)) /* No nasty effect for low levels */ { bool stop_ty = FALSE; int count = 0; do { - stop_ty = activate_ty_curse(stop_ty, &count); + stop_ty = activate_ty_curse(trapped_ptr, stop_ty, &count); } while (one_in_(6)); } break; @@ -471,7 +486,7 @@ void hit_trap(bool break_trap) case TRAP_TELEPORT: { msg_print(_("テレポート・トラップにひっかかった!", "You hit a teleport trap!")); - teleport_player(100, TELEPORT_PASSIVE); + teleport_player(trapped_ptr, 100, TELEPORT_PASSIVE); break; } @@ -479,7 +494,7 @@ void hit_trap(bool break_trap) { msg_print(_("炎に包まれた!", "You are enveloped in flames!")); dam = damroll(4, 6); - (void)fire_dam(dam, _("炎のトラップ", "a fire trap"), -1, FALSE); + (void)fire_dam(trapped_ptr, dam, _("炎のトラップ", "a fire trap"), -1, FALSE); break; } @@ -487,65 +502,65 @@ void hit_trap(bool break_trap) { msg_print(_("酸が吹きかけられた!", "You are splashed with acid!")); dam = damroll(4, 6); - (void)acid_dam(dam, _("酸のトラップ", "an acid trap"), -1, FALSE); + (void)acid_dam(trapped_ptr, dam, _("酸のトラップ", "an acid trap"), -1, FALSE); break; } case TRAP_SLOW: { - hit_trap_slow(); + hit_trap_slow(trapped_ptr); break; } case TRAP_LOSE_STR: { - hit_trap_lose_stat(A_STR); + hit_trap_lose_stat(trapped_ptr, A_STR); break; } case TRAP_LOSE_DEX: { - hit_trap_lose_stat(A_DEX); + hit_trap_lose_stat(trapped_ptr, A_DEX); break; } case TRAP_LOSE_CON: { - hit_trap_lose_stat(A_CON); + hit_trap_lose_stat(trapped_ptr, A_CON); break; } case TRAP_BLIND: { - hit_trap_set_abnormal_status( + hit_trap_set_abnormal_status_p( _("黒いガスに包み込まれた!", "A black gas surrounds you!"), - p_ptr->resist_blind, - set_blind, p_ptr->blind + (TIME_EFFECT)randint0(50) + 25); + trapped_ptr->resist_blind, + set_blind, trapped_ptr->blind + (TIME_EFFECT)randint0(50) + 25); break; } case TRAP_CONFUSE: { - hit_trap_set_abnormal_status( + hit_trap_set_abnormal_status_p( _("きらめくガスに包み込まれた!", "A gas of scintillating colors surrounds you!"), - p_ptr->resist_conf, - set_confused, p_ptr->confused + (TIME_EFFECT)randint0(20) + 10); + trapped_ptr->resist_conf, + set_confused, trapped_ptr->confused + (TIME_EFFECT)randint0(20) + 10); break; } case TRAP_POISON: { - hit_trap_set_abnormal_status( + hit_trap_set_abnormal_status_p( _("刺激的な緑色のガスに包み込まれた!", "A pungent green gas surrounds you!"), - p_ptr->resist_pois || IS_OPPOSE_POIS(), - set_poisoned, p_ptr->poisoned + (TIME_EFFECT)randint0(20) + 10); + trapped_ptr->resist_pois || IS_OPPOSE_POIS(), + set_poisoned, trapped_ptr->poisoned + (TIME_EFFECT)randint0(20) + 10); break; } case TRAP_SLEEP: { msg_print(_("奇妙な白い霧に包まれた!", "A strange white mist surrounds you!")); - if (!p_ptr->free_act) + if (!trapped_ptr->free_act) { msg_print(_("あなたは眠りに就いた。", "You fall asleep.")); @@ -554,10 +569,10 @@ void hit_trap(bool break_trap) msg_print(_("身の毛もよだつ光景が頭に浮かんだ。", "A horrible vision enters your mind.")); /* Have some nightmares */ - sanity_blast(NULL, FALSE); + sanity_blast(trapped_ptr, NULL, FALSE); } - (void)set_paralyzed(p_ptr->paralyzed + randint0(10) + 5); + (void)set_paralyzed(trapped_ptr, trapped_ptr->paralyzed + randint0(10) + 5); } break; } @@ -566,7 +581,7 @@ void hit_trap(bool break_trap) { msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!")); /* Make some new traps */ - project(0, 1, y, x, 0, GF_MAKE_TRAP, PROJECT_HIDE | PROJECT_JUMP | PROJECT_GRID, -1); + project(trapped_ptr, 0, 1, y, x, 0, GF_MAKE_TRAP, PROJECT_HIDE | PROJECT_JUMP | PROJECT_GRID, -1); break; } @@ -575,7 +590,7 @@ void hit_trap(bool break_trap) { msg_print(_("けたたましい音が鳴り響いた!", "An alarm sounds!")); - aggravate_monsters(0); + aggravate_monsters(trapped_ptr, 0); break; } @@ -583,10 +598,10 @@ void hit_trap(bool break_trap) case TRAP_OPEN: { msg_print(_("大音響と共にまわりの壁が崩れた!", "Suddenly, surrounding walls are opened!")); - (void)project(0, 3, y, x, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1); - (void)project(0, 3, y, x - 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1); - (void)project(0, 3, y, x + 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1); - aggravate_monsters(0); + (void)project(trapped_ptr, 0, 3, y, x, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1); + (void)project(trapped_ptr, 0, 3, y, x - 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1); + (void)project(trapped_ptr, 0, 3, y, x + 4, 0, GF_DISINTEGRATE, PROJECT_GRID | PROJECT_HIDE, -1); + aggravate_monsters(trapped_ptr, 0); break; } @@ -600,7 +615,7 @@ void hit_trap(bool break_trap) msg_print(_("突然天界の戦争に巻き込まれた!", "Suddenly, you are surrounded by immotal beings!")); /* Summon Demons and Angels */ - for (lev = current_floor_ptr->dun_level; lev >= 20; lev -= 1 + lev / 16) + for (lev = trapped_ptr->current_floor_ptr->dun_level; lev >= 20; lev -= 1 + lev / 16) { num = levs[MIN(lev / 10, 9)]; for (i = 0; i < num; i++) @@ -608,16 +623,15 @@ void hit_trap(bool break_trap) POSITION x1 = rand_spread(x, 7); POSITION y1 = rand_spread(y, 5); - /* Skip illegal grids */ - if (!in_bounds(y1, x1)) continue; + if (!in_bounds(trapped_ptr->current_floor_ptr, y1, x1)) continue; /* Require line of projection */ - if (!projectable(p_ptr->y, p_ptr->x, y1, x1)) continue; + if (!projectable(trapped_ptr->current_floor_ptr, trapped_ptr->y, trapped_ptr->x, y1, x1)) continue; - if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_EVIL, (PM_NO_PET), '\0')) + if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_EVIL, (PM_NO_PET))) evil_idx = hack_m_idx_ii; - if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_GOOD, (PM_NO_PET), '\0')) + if (summon_specific(0, y1, x1, lev, SUMMON_ARMAGE_GOOD, (PM_NO_PET))) { good_idx = hack_m_idx_ii; } @@ -625,8 +639,8 @@ void hit_trap(bool break_trap) /* Let them fight each other */ if (evil_idx && good_idx) { - monster_type *evil_ptr = ¤t_floor_ptr->m_list[evil_idx]; - monster_type *good_ptr = ¤t_floor_ptr->m_list[good_idx]; + monster_type *evil_ptr = &trapped_ptr->current_floor_ptr->m_list[evil_idx]; + monster_type *good_ptr = &trapped_ptr->current_floor_ptr->m_list[good_idx]; evil_ptr->target_y = good_ptr->fy; evil_ptr->target_x = good_ptr->fx; good_ptr->target_y = evil_ptr->fy; @@ -642,13 +656,13 @@ void hit_trap(bool break_trap) msg_print(_("突然壁から水が溢れ出した!ピラニアがいる!", "Suddenly, the room is filled with water with piranhas!")); /* Water fills room */ - fire_ball_hide(GF_WATER_FLOW, 0, 1, 10); + fire_ball_hide(trapped_ptr, GF_WATER_FLOW, 0, 1, 10); /* Summon Piranhas */ - num = 1 + current_floor_ptr->dun_level / 20; + num = 1 + trapped_ptr->current_floor_ptr->dun_level / 20; for (i = 0; i < num; i++) { - (void)summon_specific(0, y, x, current_floor_ptr->dun_level, SUMMON_PIRANHAS, (PM_ALLOW_GROUP | PM_NO_PET), '\0'); + (void)summon_specific(0, y, x, trapped_ptr->current_floor_ptr->dun_level, SUMMON_PIRANHAS, (PM_ALLOW_GROUP | PM_NO_PET)); } break; } @@ -656,7 +670,7 @@ void hit_trap(bool break_trap) if (break_trap && is_trap(g_ptr->feat)) { - cave_alter_feat(y, x, FF_DISARM); + cave_alter_feat(trapped_ptr, y, x, FF_DISARM); msg_print(_("トラップを粉砕した。", "You destroyed the trap.")); } }