2 * @brief モンスターの移動に関する処理
7 #include "monster/monster-move.h"
8 #include "cmd/cmd-pet.h"
9 #include "monster-status.h"
10 #include "player-move.h"
12 static bool check_hp_for_feat_destruction(feature_type *f_ptr, monster_type *m_ptr)
14 return !have_flag(f_ptr->flags, FF_GLASS) ||
15 (r_info[m_ptr->r_idx].flags2 & RF2_STUPID) ||
16 (m_ptr->hp >= MAX(m_ptr->maxhp / 3, 200));
21 * @brief モンスターによる壁の透過・破壊を行う
22 * @param target_ptr プレーヤーへの参照ポインタ
23 * @param m_ptr モンスターへの参照ポインタ
26 * @param can_cross モンスターが地形を踏破できるならばTRUE
27 * @return 透過も破壊もしなかった場合はFALSE、それ以外はTRUE
29 bool process_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx, bool can_cross)
31 monster_race *r_ptr = &r_info[m_ptr->r_idx];
33 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
35 f_ptr = &f_info[g_ptr->feat];
36 if (player_bold(target_ptr, ny, nx))
38 turn_flags_ptr->do_move = TRUE;
44 turn_flags_ptr->do_move = TRUE;
48 if (((r_ptr->flags2 & RF2_KILL_WALL) != 0) &&
49 (can_cross ? !have_flag(f_ptr->flags, FF_LOS) : !turn_flags_ptr->is_riding_mon) &&
50 have_flag(f_ptr->flags, FF_HURT_DISI) && !have_flag(f_ptr->flags, FF_PERMANENT) &&
51 check_hp_for_feat_destruction(f_ptr, m_ptr))
53 turn_flags_ptr->do_move = TRUE;
54 if (!can_cross) turn_flags_ptr->must_alter_to_move = TRUE;
56 turn_flags_ptr->did_kill_wall = TRUE;
60 if (!can_cross) return FALSE;
62 turn_flags_ptr->do_move = TRUE;
63 if (((r_ptr->flags2 & RF2_PASS_WALL) != 0) && (!turn_flags_ptr->is_riding_mon || target_ptr->pass_wall) &&
64 have_flag(f_ptr->flags, FF_CAN_PASS))
66 turn_flags_ptr->did_pass_wall = TRUE;
74 * @brief モンスターが普通のドアを開ける処理
75 * @param target_ptr プレーヤーへの参照ポインタ
76 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
77 * @param m_ptr モンスターへの参照ポインタ
80 * @return ここではドアを開けず、ガラスのドアを開ける可能性があるならTRUE
82 static bool bash_normal_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
84 monster_race *r_ptr = &r_info[m_ptr->r_idx];
86 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
88 f_ptr = &f_info[g_ptr->feat];
89 turn_flags_ptr->do_move = FALSE;
90 if (((r_ptr->flags2 & RF2_OPEN_DOOR) == 0) || !have_flag(f_ptr->flags, FF_OPEN) ||
91 (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
94 if (f_ptr->power == 0)
96 turn_flags_ptr->did_open_door = TRUE;
97 turn_flags_ptr->do_turn = TRUE;
101 if (randint0(m_ptr->hp / 10) > f_ptr->power)
103 cave_alter_feat(target_ptr, ny, nx, FF_DISARM);
104 turn_flags_ptr->do_turn = TRUE;
113 * @brief モンスターがガラスのドアを開ける処理
114 * @param target_ptr プレーヤーへの参照ポインタ
115 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
116 * @param m_ptr モンスターへの参照ポインタ
117 * @param g_ptr グリッドへの参照ポインタ
118 * @param f_ptr 地形への参照ポインタ
121 static void bash_glass_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, feature_type *f_ptr, bool may_bash)
123 monster_race *r_ptr = &r_info[m_ptr->r_idx];
124 if (!may_bash || ((r_ptr->flags2 & RF2_BASH_DOOR) == 0) || !have_flag(f_ptr->flags, FF_BASH) ||
125 (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
128 if (!check_hp_for_feat_destruction(f_ptr, m_ptr) || (randint0(m_ptr->hp / 10) <= f_ptr->power))
131 if (have_flag(f_ptr->flags, FF_GLASS))
132 msg_print(_("ガラスが砕ける音がした!", "You hear glass breaking!"));
134 msg_print(_("ドアを叩き開ける音がした!", "You hear a door burst open!"));
136 if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
138 turn_flags_ptr->did_bash_door = TRUE;
139 turn_flags_ptr->do_move = TRUE;
140 turn_flags_ptr->must_alter_to_move = TRUE;
145 * @brief モンスターによるドアの開放・破壊を行う
146 * @param target_ptr プレーヤーへの参照ポインタ
147 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
148 * @param m_ptr モンスターへの参照ポインタ
149 * @param ny モンスターのY座標
150 * @param nx モンスターのX座標
151 * @return モンスターが死亡した場合のみFALSE
153 bool process_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
155 monster_race *r_ptr = &r_info[m_ptr->r_idx];
157 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
158 if (!is_closed_door(target_ptr, g_ptr->feat)) return TRUE;
161 f_ptr = &f_info[g_ptr->feat];
162 bool may_bash = bash_normal_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx);
163 bash_glass_door(target_ptr, turn_flags_ptr, m_ptr, f_ptr, may_bash);
165 if (!turn_flags_ptr->did_open_door && !turn_flags_ptr->did_bash_door) return TRUE;
167 if (turn_flags_ptr->did_bash_door &&
168 ((randint0(100) < 50) || (feat_state(target_ptr, g_ptr->feat, FF_OPEN) == g_ptr->feat) || have_flag(f_ptr->flags, FF_GLASS)))
170 cave_alter_feat(target_ptr, ny, nx, FF_BASH);
171 if (!monster_is_valid(m_ptr))
173 target_ptr->update |= (PU_FLOW);
174 target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
175 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
182 cave_alter_feat(target_ptr, ny, nx, FF_OPEN);
185 f_ptr = &f_info[g_ptr->feat];
186 turn_flags_ptr->do_view = TRUE;
192 * @brief モンスターが壁を掘った後続処理を実行する
193 * @param target_ptr プレーヤーへの参照ポインタ
194 * @turn_flags_ptr ターン経過処理フラグへの参照ポインタ
195 * @param m_ptr モンスターへの参照ポインタ
196 * @param ny モンスターのY座標
197 * @param nx モンスターのX座標
198 * @return モンスターが死亡した場合のみFALSE
200 bool process_post_dig_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
202 monster_race *r_ptr = &r_info[m_ptr->r_idx];
204 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
206 f_ptr = &f_info[g_ptr->feat];
207 if (!turn_flags_ptr->did_kill_wall || !turn_flags_ptr->do_move) return TRUE;
209 if (one_in_(GRINDNOISE))
211 if (have_flag(f_ptr->flags, FF_GLASS))
212 msg_print(_("何かの砕ける音が聞こえる。", "There is a crashing sound."));
214 msg_print(_("ギシギシいう音が聞こえる。", "There is a grinding sound."));
217 cave_alter_feat(target_ptr, ny, nx, FF_HURT_DISI);
219 if (!monster_is_valid(m_ptr))
221 target_ptr->update |= (PU_FLOW);
222 target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
223 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_KILL_WALL);
228 f_ptr = &f_info[g_ptr->feat];
229 turn_flags_ptr->do_view = TRUE;
230 turn_flags_ptr->do_turn = TRUE;
236 * @brief 守りのルーンによるモンスターの移動制限を処理する
237 * @param target_ptr プレーヤーへの参照ポインタ
238 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
239 * @param m_ptr モンスターへの参照ポインタ
240 * @param ny モンスターのY座標
241 * @param nx モンスターのX座標
244 bool process_protection_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
247 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
248 monster_race *r_ptr = &r_info[m_ptr->r_idx];
249 if (!turn_flags_ptr->do_move || !is_glyph_grid(g_ptr) ||
250 (((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) && player_bold(target_ptr, ny, nx)))
253 turn_flags_ptr->do_move = FALSE;
254 if (is_pet(m_ptr) || (randint1(BREAK_GLYPH) >= r_ptr->level))
257 if (g_ptr->info & CAVE_MARK)
259 msg_print(_("守りのルーンが壊れた!", "The rune of protection is broken!"));
262 g_ptr->info &= ~(CAVE_MARK);
263 g_ptr->info &= ~(CAVE_OBJECT);
265 turn_flags_ptr->do_move = TRUE;
266 note_spot(target_ptr, ny, nx);
273 * @param target_ptr プレーヤーへの参照ポインタ
274 * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
275 * @param m_ptr モンスターへの参照ポインタ
276 * @param ny モンスターのY座標
277 * @param nx モンスターのX座標
278 * @return モンスターが死亡した場合のみFALSE
280 bool process_explosive_rune(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
283 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
284 monster_race *r_ptr = &r_info[m_ptr->r_idx];
285 if (!turn_flags_ptr->do_move || !is_explosive_rune_grid(g_ptr) ||
286 (((r_ptr->flags1 & RF1_NEVER_BLOW) != 0) && player_bold(target_ptr, ny, nx)))
289 turn_flags_ptr->do_move = FALSE;
290 if (is_pet(m_ptr)) return TRUE;
292 if (randint1(BREAK_MINOR_GLYPH) > r_ptr->level)
294 if (g_ptr->info & CAVE_MARK)
296 msg_print(_("ルーンが爆発した!", "The rune explodes!"));
297 BIT_FLAGS project_flags = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI;
298 project(target_ptr, 0, 2, ny, nx, 2 * (target_ptr->lev + damroll(7, 7)), GF_MANA, project_flags, -1);
303 msg_print(_("爆発のルーンは解除された。", "An explosive rune was disarmed."));
306 g_ptr->info &= ~(CAVE_MARK);
307 g_ptr->info &= ~(CAVE_OBJECT);
310 note_spot(target_ptr, ny, nx);
311 lite_spot(target_ptr, ny, nx);
313 if (!monster_is_valid(m_ptr)) return FALSE;
315 turn_flags_ptr->do_move = TRUE;