OSDN Git Service

[Refactor] #40030 Separated monster-move.c/h from monster-process.c
[hengband/hengband.git] / src / monster-process.c
1 /*!
2  * @file monster-process.c
3  * @brief モンスターの特殊技能とターン経過処理 (移動等)/ Monster spells and movement for passaging a turn
4  * @date 2014/01/17
5  * @author
6  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke\n
7  * This software may be copied and distributed for educational, research,\n
8  * and not for profit purposes provided that this copyright and statement\n
9  * are included in all such copies.  Other copyrights may also apply.\n
10  * 2014 Deskull rearranged comment for Doxygen.\n
11  * @details
12  * This file has several additions to it by Keldon Jones (keldon@umr.edu)
13  * to improve the general quality of the AI (version 0.1.1).
14  */
15
16 #include "angband.h"
17 #include "util.h"
18 #include "monster/monster-attack.h"
19 #include "monster/monster-object.h"
20 #include "monster/monster-move.h"
21 #include "monster/monster-util.h"
22 #include "monster/quantum-effect.h"
23
24 #include "cmd-dump.h"
25 #include "cmd-pet.h"
26 #include "creature.h"
27 #include "melee.h"
28 #include "spells.h"
29 #include "spells-floor.h"
30 #include "spells-summon.h"
31 #include "quest.h"
32 #include "avatar.h"
33 #include "realm-hex.h"
34 #include "feature.h"
35 #include "grid.h"
36 #include "player-move.h"
37 #include "monster-status.h"
38 #include "monster-spell.h"
39 #include "monster-process.h"
40 #include "monster-dist-offsets.h"
41 #include "monsterrace-hook.h"
42 #include "floor.h"
43 #include "files.h"
44 #include "view-mainwindow.h"
45
46 bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm);
47 void decide_enemy_approch_direction(player_type *target_ptr, MONSTER_IDX m_idx, int start, int plus, POSITION *y, POSITION *x);
48 bool decide_pet_approch_direction(player_type *target_ptr, monster_type *m_ptr, monster_type *t_ptr);
49
50 bool find_safety(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp);
51 coordinate_candidate sweep_safe_coordinate(player_type *target_ptr, MONSTER_IDX m_idx, const POSITION *y_offsets, const POSITION *x_offsets, int d);
52
53 bool find_hiding(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp);
54 void sweep_hiding_candidate(player_type *target_ptr, monster_type *m_ptr, const POSITION *y_offsets, const POSITION *x_offsets, coordinate_candidate *candidate);
55
56 void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon);
57 bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx);
58 bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
59 void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx);
60 void process_angar(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
61 bool explode_grenade(player_type *target_ptr, MONSTER_IDX m_idx);
62 bool decide_monster_multiplication(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox);
63 bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware);
64 bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr);
65 bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx);
66 bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx);
67 void escape_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, GAME_TEXT *m_name);
68 void process_special(player_type *target_ptr, MONSTER_IDX m_idx);
69 void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware);
70 bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware);
71
72 bool process_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx, bool can_cross);
73 bool process_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
74 bool bash_normal_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
75 void bash_glass_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, feature_type *f_ptr, bool may_bash);
76
77 bool process_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, DIRECTION *mm, POSITION oy, POSITION ox, int *count);
78 bool process_post_dig_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
79 bool update_riding_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx);
80
81 void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr);
82 void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr);
83 bool process_monster_fear(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx);
84
85 void sweep_monster_process(player_type *target_ptr);
86 bool decide_process_continue(player_type *target_ptr, monster_type *m_ptr);
87
88 /*!
89  * @brief モンスターが敵に接近するための方向を計算するメインルーチン
90  * Calculate the direction to the next enemy
91  * @param target_ptr プレーヤーへの参照ポインタ
92  * @param m_idx モンスターの参照ID
93  * @param mm 移動するべき方角IDを返す参照ポインタ
94  * @return 方向が確定した場合TRUE、接近する敵がそもそもいない場合FALSEを返す
95  */
96 bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm)
97 {
98         floor_type *floor_ptr = target_ptr->current_floor_ptr;
99         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
100
101         POSITION x = 0, y = 0;
102         if (target_ptr->riding_t_m_idx && player_bold(target_ptr, m_ptr->fy, m_ptr->fx))
103         {
104                 y = floor_ptr->m_list[target_ptr->riding_t_m_idx].fy;
105                 x = floor_ptr->m_list[target_ptr->riding_t_m_idx].fx;
106         }
107         else if (is_pet(m_ptr) && target_ptr->pet_t_m_idx)
108         {
109                 y = floor_ptr->m_list[target_ptr->pet_t_m_idx].fy;
110                 x = floor_ptr->m_list[target_ptr->pet_t_m_idx].fx;
111         }
112         else
113         {
114                 int start;
115                 int plus = 1;
116                 if (target_ptr->phase_out)
117                 {
118                         start = randint1(floor_ptr->m_max - 1) + floor_ptr->m_max;
119                         if (randint0(2)) plus = -1;
120                 }
121                 else
122                 {
123                         start = floor_ptr->m_max + 1;
124                 }
125
126                 decide_enemy_approch_direction(target_ptr, m_idx, start, plus, &y, &x);
127
128                 if ((x == 0) && (y == 0)) return FALSE;
129         }
130
131         x -= m_ptr->fx;
132         y -= m_ptr->fy;
133
134         store_enemy_approch_direction(mm, y, x);
135         return TRUE;
136 }
137
138
139 /*!
140  * @brief モンスターが敵に接近するための方向を決定する
141  * @param target_ptr プレーヤーへの参照ポインタ
142  * @param m_idx モンスターID
143  * @param start モンスターIDの開始
144  * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
145  * @param y モンスターの移動方向Y
146  * @param x モンスターの移動方向X
147  * @return なし
148  */
149 void decide_enemy_approch_direction(player_type *target_ptr, MONSTER_IDX m_idx, int start, int plus, POSITION *y, POSITION *x)
150 {
151         floor_type *floor_ptr = target_ptr->current_floor_ptr;
152         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
153         monster_race *r_ptr = &r_info[m_ptr->r_idx];
154         for (int i = start; ((i < start + floor_ptr->m_max) && (i > start - floor_ptr->m_max)); i += plus)
155         {
156                 MONSTER_IDX dummy = (i % floor_ptr->m_max);
157                 if (dummy == 0) continue;
158
159                 MONSTER_IDX t_idx = dummy;
160                 monster_type *t_ptr;
161                 t_ptr = &floor_ptr->m_list[t_idx];
162                 if (t_ptr == m_ptr) continue;
163                 if (!monster_is_valid(t_ptr)) continue;
164                 if (decide_pet_approch_direction(target_ptr, m_ptr, t_ptr)) continue;
165                 if (!are_enemies(target_ptr, m_ptr, t_ptr)) continue;
166
167                 if (((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) ||
168                         ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)))
169                 {
170                         if (!in_disintegration_range(floor_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
171                 }
172                 else
173                 {
174                         if (!projectable(target_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
175                 }
176
177                 *y = t_ptr->fy;
178                 *x = t_ptr->fx;
179                 return;
180         }
181 }
182
183
184 /*!
185  * @brief ペットが敵に接近するための方向を決定する
186  * @param target_ptr プレーヤーへの参照ポインタ
187  * @param m_ptr 移動を試みているモンスターへの参照ポインタ
188  * @param t_ptr 移動先モンスターへの参照ポインタ
189  * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
190  * @return ペットがモンスターに近づくならばTRUE
191  */
192 bool decide_pet_approch_direction(player_type *target_ptr, monster_type *m_ptr, monster_type *t_ptr)
193 {
194         monster_race *r_ptr = &r_info[m_ptr->r_idx];
195         if (!is_pet(m_ptr)) return FALSE;
196
197         if (target_ptr->pet_follow_distance < 0)
198         {
199                 if (t_ptr->cdis <= (0 - target_ptr->pet_follow_distance))
200                 {
201                         return TRUE;
202                 }
203         }
204         else if ((m_ptr->cdis < t_ptr->cdis) && (t_ptr->cdis > target_ptr->pet_follow_distance))
205         {
206                 return TRUE;
207         }
208
209         return (r_ptr->aaf < t_ptr->cdis);
210 }
211
212
213 /*!
214  * @brief モンスターがプレイヤーから逃走するかどうかを返す /
215  * Returns whether a given monster will try to run from the player.
216  * @param m_idx 逃走するモンスターの参照ID
217  * @return モンスターがプレイヤーから逃走するならばTRUEを返す。
218  * @details
219  * Monsters will attempt to avoid very powerful players.  See below.\n
220  *\n
221  * Because this function is called so often, little details are important\n
222  * for efficiency.  Like not using "mod" or "div" when possible.  And\n
223  * attempting to check the conditions in an optimal order.  Note that\n
224  * "(x << 2) == (x * 4)" if "x" has enough bits to hold the result.\n
225  *\n
226  * Note that this function is responsible for about one to five percent\n
227  * of the processor use in normal conditions...\n
228  */
229 static bool mon_will_run(player_type *target_ptr, MONSTER_IDX m_idx)
230 {
231         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
232         monster_race *r_ptr = &r_info[m_ptr->r_idx];
233
234         if (is_pet(m_ptr))
235         {
236                 return ((target_ptr->pet_follow_distance < 0) &&
237                         (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
238         }
239
240         if (m_ptr->cdis > MAX_SIGHT + 5) return FALSE;
241         if (MON_MONFEAR(m_ptr)) return TRUE;
242         if (m_ptr->cdis <= 5) return FALSE;
243
244         PLAYER_LEVEL p_lev = target_ptr->lev;
245         DEPTH m_lev = r_ptr->level + (m_idx & 0x08) + 25;
246         if (m_lev > p_lev + 4) return FALSE;
247         if (m_lev + 4 <= p_lev) return TRUE;
248
249         HIT_POINT p_chp = target_ptr->chp;
250         HIT_POINT p_mhp = target_ptr->mhp;
251         HIT_POINT m_chp = m_ptr->hp;
252         HIT_POINT m_mhp = m_ptr->maxhp;
253         u32b p_val = (p_lev * p_mhp) + (p_chp << 2);
254         u32b m_val = (m_lev * m_mhp) + (m_chp << 2);
255         if (p_val * m_mhp > m_val * p_mhp) return TRUE;
256
257         return FALSE;
258 }
259
260
261 /*!
262  * @brief モンスターがプレイヤーに向けて遠距離攻撃を行うことが可能なマスを走査する /
263  * Search spell castable grid
264  * @param target_ptr プレーヤーへの参照ポインタ
265  * @param m_idx モンスターの参照ID
266  * @param yp 適したマスのY座標を返す参照ポインタ
267  * @param xp 適したマスのX座標を返す参照ポインタ
268  * @return 有効なマスがあった場合TRUEを返す
269  */
270 static bool get_moves_aux2(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
271 {
272         floor_type *floor_ptr = target_ptr->current_floor_ptr;
273         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
274         monster_race *r_ptr = &r_info[m_ptr->r_idx];
275
276         POSITION y1 = m_ptr->fy;
277         POSITION x1 = m_ptr->fx;
278
279         if (projectable(target_ptr, y1, x1, target_ptr->y, target_ptr->x)) return FALSE;
280
281         int now_cost = floor_ptr->grid_array[y1][x1].cost;
282         if (now_cost == 0) now_cost = 999;
283
284         bool can_open_door = FALSE;
285         if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
286         {
287                 can_open_door = TRUE;
288         }
289
290         int best = 999;
291         for (int i = 7; i >= 0; i--)
292         {
293                 POSITION y = y1 + ddy_ddd[i];
294                 POSITION x = x1 + ddx_ddd[i];
295                 if (!in_bounds2(floor_ptr, y, x)) continue;
296                 if (player_bold(target_ptr, y, x)) return FALSE;
297
298                 grid_type *g_ptr;
299                 g_ptr = &floor_ptr->grid_array[y][x];
300                 int cost = g_ptr->cost;
301                 if (!(((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) || ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding))))
302                 {
303                         if (cost == 0) continue;
304                         if (!can_open_door && is_closed_door(target_ptr, g_ptr->feat)) continue;
305                 }
306
307                 if (cost == 0) cost = 998;
308
309                 if (now_cost < cost) continue;
310                 if (!projectable(target_ptr, y, x, target_ptr->y, target_ptr->x)) continue;
311                 if (best < cost) continue;
312
313                 best = cost;
314                 *yp = y1 + ddy_ddd[i];
315                 *xp = x1 + ddx_ddd[i];
316         }
317
318         if (best == 999) return FALSE;
319
320         return TRUE;
321 }
322
323
324 /*!
325  * @brief モンスターがプレイヤーに向けて接近することが可能なマスを走査する /
326  * Choose the "best" direction for "flowing"
327  * @param m_idx モンスターの参照ID
328  * @param yp 移動先のマスのY座標を返す参照ポインタ
329  * @param xp 移動先のマスのX座標を返す参照ポインタ
330  * @param no_flow モンスターにFLOWフラグが経っていない状態でTRUE
331  * @return 有効なマスがあった場合TRUEを返す
332  * @details
333  * Note that ghosts and rock-eaters are never allowed to "flow",\n
334  * since they should move directly towards the player.\n
335  *\n
336  * Prefer "non-diagonal" directions, but twiddle them a little\n
337  * to angle slightly towards the player's actual location.\n
338  *\n
339  * Allow very perceptive monsters to track old "spoor" left by\n
340  * previous locations occupied by the player.  This will tend\n
341  * to have monsters end up either near the player or on a grid\n
342  * recently occupied by the player (and left via "teleport").\n
343  *\n
344  * Note that if "smell" is turned on, all monsters get vicious.\n
345  *\n
346  * Also note that teleporting away from a location will cause\n
347  * the monsters who were chasing you to converge on that location\n
348  * as long as you are still near enough to "annoy" them without\n
349  * being close enough to chase directly.  I have no idea what will\n
350  * happen if you combine "smell" with low "aaf" values.\n
351  */
352 static bool get_moves_aux(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp, bool no_flow)
353 {
354         grid_type *g_ptr;
355         floor_type *floor_ptr = target_ptr->current_floor_ptr;
356         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
357         monster_race *r_ptr = &r_info[m_ptr->r_idx];
358
359         if (r_ptr->flags4 & (RF4_ATTACK_MASK) ||
360                 r_ptr->a_ability_flags1 & (RF5_ATTACK_MASK) ||
361                 r_ptr->a_ability_flags2 & (RF6_ATTACK_MASK))
362         {
363                 if (get_moves_aux2(target_ptr, m_idx, yp, xp)) return TRUE;
364         }
365
366         if (no_flow) return FALSE;
367         if ((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) return FALSE;
368         if ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)) return FALSE;
369
370         POSITION y1 = m_ptr->fy;
371         POSITION x1 = m_ptr->fx;
372         if (player_has_los_bold(target_ptr, y1, x1) && projectable(target_ptr, target_ptr->y, target_ptr->x, y1, x1)) return FALSE;
373
374         g_ptr = &floor_ptr->grid_array[y1][x1];
375
376         int best;
377         bool use_scent = FALSE;
378         if (g_ptr->cost)
379         {
380                 best = 999;
381         }
382         else if (g_ptr->when)
383         {
384                 if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].when - g_ptr->when > 127) return FALSE;
385
386                 use_scent = TRUE;
387                 best = 0;
388         }
389         else
390         {
391                 return FALSE;
392         }
393
394         for (int i = 7; i >= 0; i--)
395         {
396                 POSITION y = y1 + ddy_ddd[i];
397                 POSITION x = x1 + ddx_ddd[i];
398
399                 if (!in_bounds2(floor_ptr, y, x)) continue;
400
401                 g_ptr = &floor_ptr->grid_array[y][x];
402                 if (use_scent)
403                 {
404                         int when = g_ptr->when;
405                         if (best > when) continue;
406
407                         best = when;
408                 }
409                 else
410                 {
411                         int cost;
412                         if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
413                         {
414                                 cost = g_ptr->dist;
415                         }
416                         else
417                         {
418                                 cost = g_ptr->cost;
419                         }
420
421                         if ((cost == 0) || (best < cost)) continue;
422
423                         best = cost;
424                 }
425
426                 *yp = target_ptr->y + 16 * ddy_ddd[i];
427                 *xp = target_ptr->x + 16 * ddx_ddd[i];
428         }
429
430         if (best == 999 || best == 0) return FALSE;
431
432         return TRUE;
433 }
434
435
436 /*!
437  * @brief モンスターがプレイヤーから逃走することが可能なマスを走査する /
438  * Provide a location to flee to, but give the player a wide berth.
439  * @param m_idx モンスターの参照ID
440  * @param yp 移動先のマスのY座標を返す参照ポインタ
441  * @param xp 移動先のマスのX座標を返す参照ポインタ
442  * @return 有効なマスがあった場合TRUEを返す
443  * @details
444  * A monster may wish to flee to a location that is behind the player,\n
445  * but instead of heading directly for it, the monster should "swerve"\n
446  * around the player so that he has a smaller chance of getting hit.\n
447  */
448 static bool get_fear_moves_aux(floor_type *floor_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
449 {
450         POSITION gy = 0, gx = 0;
451
452         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
453         POSITION fy = m_ptr->fy;
454         POSITION fx = m_ptr->fx;
455
456         POSITION y1 = fy - (*yp);
457         POSITION x1 = fx - (*xp);
458
459         int score = -1;
460         for (int i = 7; i >= 0; i--)
461         {
462                 POSITION y = fy + ddy_ddd[i];
463                 POSITION x = fx + ddx_ddd[i];
464                 if (!in_bounds2(floor_ptr, y, x)) continue;
465
466                 POSITION dis = distance(y, x, y1, x1);
467                 POSITION s = 5000 / (dis + 3) - 500 / (floor_ptr->grid_array[y][x].dist + 1);
468                 if (s < 0) s = 0;
469
470                 if (s < score) continue;
471
472                 score = s;
473                 gy = y;
474                 gx = x;
475         }
476
477         if (score == -1) return FALSE;
478
479         (*yp) = fy - gy;
480         (*xp) = fx - gx;
481
482         return TRUE;
483 }
484
485
486 /*!
487  * @brief モンスターが逃げ込める安全な地点を返す /
488  * Choose a "safe" location near a monster for it to run toward.
489  * @param target_ptr プレーヤーへの参照ポインタ
490  * @param m_idx モンスターの参照ID
491  * @param yp 移動先のマスのY座標を返す参照ポインタ
492  * @param xp 移動先のマスのX座標を返す参照ポインタ
493  * @return 有効なマスがあった場合TRUEを返す
494  * @details
495  * A location is "safe" if it can be reached quickly and the player\n
496  * is not able to fire into it (it isn't a "clean shot").  So, this will\n
497  * cause monsters to "duck" behind walls.  Hopefully, monsters will also\n
498  * try to run towards corridor openings if they are in a room.\n
499  *\n
500  * This function may take lots of CPU time if lots of monsters are\n
501  * fleeing.\n
502  *\n
503  * Return TRUE if a safe location is available.\n
504  */
505 bool find_safety(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
506 {
507         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
508         for (POSITION d = 1; d < 10; d++)
509         {
510                 const POSITION *y_offsets;
511                 y_offsets = dist_offsets_y[d];
512
513                 const POSITION *x_offsets;
514                 x_offsets = dist_offsets_x[d];
515
516                 coordinate_candidate candidate = sweep_safe_coordinate(target_ptr, m_idx, y_offsets, x_offsets, d);
517
518                 if (candidate.gdis <= 0) continue;
519
520                 *yp = m_ptr->fy - candidate.gy;
521                 *xp = m_ptr->fx - candidate.gx;
522
523                 return TRUE;
524         }
525
526         return FALSE;
527 }
528
529
530 /*!
531  * @brief モンスターが逃げ込める地点を走査する
532  * @param target_ptr プレーヤーへの参照ポインタ
533  * @param m_idx モンスターID
534  * @param y_offsets
535  * @param x_offsets
536  * @param d モンスターがいる地点からの距離
537  * @return 逃げ込める地点の候補地
538  */
539 coordinate_candidate sweep_safe_coordinate(player_type *target_ptr, MONSTER_IDX m_idx, const POSITION *y_offsets, const POSITION *x_offsets, int d)
540 {
541         coordinate_candidate candidate = init_coordinate_candidate();
542         floor_type *floor_ptr = target_ptr->current_floor_ptr;
543         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
544         for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0];
545                 dx != 0 || dy != 0;
546                 i++, dx = x_offsets[i], dy = y_offsets[i])
547         {
548                 POSITION y = m_ptr->fy + dy;
549                 POSITION x = m_ptr->fx + dx;
550                 if (!in_bounds(floor_ptr, y, x)) continue;
551
552                 grid_type *g_ptr;
553                 g_ptr = &floor_ptr->grid_array[y][x];
554
555                 BIT_FLAGS16 riding_mode = (m_idx == target_ptr->riding) ? CEM_RIDING : 0;
556                 if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, &r_info[m_ptr->r_idx], riding_mode))
557                         continue;
558
559                 if (!(m_ptr->mflag2 & MFLAG2_NOFLOW))
560                 {
561                         if (g_ptr->dist == 0) continue;
562                         if (g_ptr->dist > floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist + 2 * d) continue;
563                 }
564
565                 if (projectable(target_ptr, target_ptr->y, target_ptr->x, y, x)) continue;
566
567                 POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
568                 if (dis <= candidate.gdis) continue;
569
570                 candidate.gy = y;
571                 candidate.gx = x;
572                 candidate.gdis = dis;
573         }
574
575         return candidate;
576 }
577
578
579 /*!
580  * @brief モンスターが隠れ潜める地点を返す /
581  * Choose a good hiding place near a monster for it to run toward.
582  * @param target_ptr プレーヤーへの参照ポインタ
583  * @param m_idx モンスターの参照ID
584  * @param yp 移動先のマスのY座標を返す参照ポインタ
585  * @param xp 移動先のマスのX座標を返す参照ポインタ
586  * @return 有効なマスがあった場合TRUEを返す
587  * @details
588  * Pack monsters will use this to "ambush" the player and lure him out\n
589  * of corridors into open space so they can swarm him.\n
590  *\n
591  * Return TRUE if a good location is available.\n
592  */
593 bool find_hiding(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
594 {
595         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
596         coordinate_candidate candidate = init_coordinate_candidate();
597         candidate.gdis = 999;
598
599         for (POSITION d = 1; d < 10; d++)
600         {
601                 const POSITION *y_offsets;
602                 y_offsets = dist_offsets_y[d];
603
604                 const POSITION *x_offsets;
605                 x_offsets = dist_offsets_x[d];
606
607                 sweep_hiding_candidate(target_ptr, m_ptr, y_offsets, x_offsets, &candidate);
608                 if (candidate.gdis >= 999) continue;
609
610                 *yp = m_ptr->fy - candidate.gy;
611                 *xp = m_ptr->fx - candidate.gx;
612                 return TRUE;
613         }
614
615         return FALSE;
616 }
617
618
619 /*!
620  * @brief モンスターが隠れられる地点を走査する
621  * @param target_ptr プレーヤーへの参照ポインタ
622  * @param m_idx モンスターID
623  * @param y_offsets
624  * @param x_offsets
625  * @param candidate 隠れられる地点の候補地
626  * @return なし
627  */
628 void sweep_hiding_candidate(player_type *target_ptr, monster_type *m_ptr, const POSITION *y_offsets, const POSITION *x_offsets, coordinate_candidate *candidate)
629 {
630         monster_race *r_ptr = &r_info[m_ptr->r_idx];
631         for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0];
632                 dx != 0 || dy != 0;
633                 i++, dx = x_offsets[i], dy = y_offsets[i])
634         {
635                 POSITION y = m_ptr->fy + dy;
636                 POSITION x = m_ptr->fx + dx;
637                 if (!in_bounds(target_ptr->current_floor_ptr, y, x)) continue;
638                 if (!monster_can_enter(target_ptr, y, x, r_ptr, 0)) continue;
639                 if (projectable(target_ptr, target_ptr->y, target_ptr->x, y, x) && clean_shot(target_ptr, m_ptr->fy, m_ptr->fx, y, x, FALSE))
640                         continue;
641
642                 POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
643                 if (dis < candidate->gdis && dis >= 2)
644                 {
645                         candidate->gy = y;
646                         candidate->gx = x;
647                         candidate->gdis = dis;
648                 }
649         }
650 }
651
652
653 /*!
654  * todo 分割したいが条件が多すぎて適切な関数名と詳細処理を追いきれない……
655  * @brief モンスターの移動方向を返す /
656  * Choose "logical" directions for monster movement
657  * @param target_ptr プレーヤーへの参照ポインタ
658  * @param m_idx モンスターの参照ID
659  * @param mm 移動方向を返す方向IDの参照ポインタ
660  * @return 有効方向があった場合TRUEを返す
661  */
662 static bool get_moves(player_type *target_ptr, MONSTER_IDX m_idx, DIRECTION *mm)
663 {
664         floor_type *floor_ptr = target_ptr->current_floor_ptr;
665         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
666         monster_race *r_ptr = &r_info[m_ptr->r_idx];
667         POSITION y = 0, ay, x = 0, ax;
668         POSITION y2 = target_ptr->y;
669         POSITION x2 = target_ptr->x;
670         bool done = FALSE;
671         bool will_run = mon_will_run(target_ptr, m_idx);
672         grid_type *g_ptr;
673         bool no_flow = ((m_ptr->mflag2 & MFLAG2_NOFLOW) != 0) && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].cost > 2);
674         bool can_pass_wall = ((r_ptr->flags2 & RF2_PASS_WALL) != 0) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall);
675
676         if (!will_run && m_ptr->target_y)
677         {
678                 int t_m_idx = floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
679                 if ((t_m_idx > 0) &&
680                         are_enemies(target_ptr, m_ptr, &floor_ptr->m_list[t_m_idx]) &&
681                         los(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x) &&
682                         projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
683                 {
684                         y = m_ptr->fy - m_ptr->target_y;
685                         x = m_ptr->fx - m_ptr->target_x;
686                         done = TRUE;
687                 }
688         }
689
690         if (!done && !will_run && is_hostile(m_ptr) &&
691                 (r_ptr->flags1 & RF1_FRIENDS) &&
692                 ((los(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x) && projectable(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x)) ||
693                 (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < MAX_SIGHT / 2)))
694         {
695                 if ((r_ptr->flags3 & RF3_ANIMAL) && !can_pass_wall &&
696                         !(r_ptr->flags2 & RF2_KILL_WALL))
697                 {
698                         int room = 0;
699                         for (int i = 0; i < 8; i++)
700                         {
701                                 int xx = target_ptr->x + ddx_ddd[i];
702                                 int yy = target_ptr->y + ddy_ddd[i];
703
704                                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
705
706                                 g_ptr = &floor_ptr->grid_array[yy][xx];
707                                 if (monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, 0))
708                                 {
709                                         room++;
710                                 }
711                         }
712
713                         if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].info & CAVE_ROOM) room -= 2;
714                         if (!r_ptr->flags4 && !r_ptr->a_ability_flags1 && !r_ptr->a_ability_flags2) room -= 2;
715
716                         if (room < (8 * (target_ptr->chp + target_ptr->csp)) /
717                                 (target_ptr->mhp + target_ptr->msp))
718                         {
719                                 if (find_hiding(target_ptr, m_idx, &y, &x)) done = TRUE;
720                         }
721                 }
722
723                 if (!done && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < 3))
724                 {
725                         for (int i = 0; i < 8; i++)
726                         {
727                                 y2 = target_ptr->y + ddy_ddd[(m_idx + i) & 7];
728                                 x2 = target_ptr->x + ddx_ddd[(m_idx + i) & 7];
729                                 if ((m_ptr->fy == y2) && (m_ptr->fx == x2))
730                                 {
731                                         y2 = target_ptr->y;
732                                         x2 = target_ptr->x;
733                                         break;
734                                 }
735
736                                 if (!in_bounds2(floor_ptr, y2, x2)) continue;
737                                 if (!monster_can_enter(target_ptr, y2, x2, r_ptr, 0)) continue;
738
739                                 break;
740                         }
741
742                         y = m_ptr->fy - y2;
743                         x = m_ptr->fx - x2;
744                         done = TRUE;
745                 }
746         }
747
748         if (!done)
749         {
750                 (void)get_moves_aux(target_ptr, m_idx, &y2, &x2, no_flow);
751                 y = m_ptr->fy - y2;
752                 x = m_ptr->fx - x2;
753         }
754
755         if (is_pet(m_ptr) && will_run)
756         {
757                 y = (-y), x = (-x);
758         }
759         else
760         {
761                 if (!done && will_run)
762                 {
763                         int tmp_x = (-x);
764                         int tmp_y = (-y);
765                         if (find_safety(target_ptr, m_idx, &y, &x) && !no_flow)
766                         {
767                                 if (get_fear_moves_aux(target_ptr->current_floor_ptr, m_idx, &y, &x))
768                                         done = TRUE;
769                         }
770
771                         if (!done)
772                         {
773                                 y = tmp_y;
774                                 x = tmp_x;
775                         }
776                 }
777         }
778
779         if (!x && !y) return FALSE;
780
781         ax = ABS(x);
782         ay = ABS(y);
783
784         int move_val = 0;
785         if (y < 0) move_val += 8;
786         if (x > 0) move_val += 4;
787
788         if (ay > (ax << 1)) move_val += 2;
789         else if (ax > (ay << 1)) move_val++;
790
791         switch (move_val)
792         {
793         case 0:
794                 mm[0] = 9;
795                 if (ay > ax)
796                 {
797                         mm[1] = 8;
798                         mm[2] = 6;
799                         mm[3] = 7;
800                         mm[4] = 3;
801                 }
802                 else
803                 {
804                         mm[1] = 6;
805                         mm[2] = 8;
806                         mm[3] = 3;
807                         mm[4] = 7;
808                 }
809                 break;
810         case 1:
811         case 9:
812                 mm[0] = 6;
813                 if (y < 0)
814                 {
815                         mm[1] = 3;
816                         mm[2] = 9;
817                         mm[3] = 2;
818                         mm[4] = 8;
819                 }
820                 else
821                 {
822                         mm[1] = 9;
823                         mm[2] = 3;
824                         mm[3] = 8;
825                         mm[4] = 2;
826                 }
827                 break;
828         case 2:
829         case 6:
830                 mm[0] = 8;
831                 if (x < 0)
832                 {
833                         mm[1] = 9;
834                         mm[2] = 7;
835                         mm[3] = 6;
836                         mm[4] = 4;
837                 }
838                 else
839                 {
840                         mm[1] = 7;
841                         mm[2] = 9;
842                         mm[3] = 4;
843                         mm[4] = 6;
844                 }
845                 break;
846         case 4:
847                 mm[0] = 7;
848                 if (ay > ax)
849                 {
850                         mm[1] = 8;
851                         mm[2] = 4;
852                         mm[3] = 9;
853                         mm[4] = 1;
854                 }
855                 else
856                 {
857                         mm[1] = 4;
858                         mm[2] = 8;
859                         mm[3] = 1;
860                         mm[4] = 9;
861                 }
862                 break;
863         case 5:
864         case 13:
865                 mm[0] = 4;
866                 if (y < 0)
867                 {
868                         mm[1] = 1;
869                         mm[2] = 7;
870                         mm[3] = 2;
871                         mm[4] = 8;
872                 }
873                 else
874                 {
875                         mm[1] = 7;
876                         mm[2] = 1;
877                         mm[3] = 8;
878                         mm[4] = 2;
879                 }
880                 break;
881         case 8:
882                 mm[0] = 3;
883                 if (ay > ax)
884                 {
885                         mm[1] = 2;
886                         mm[2] = 6;
887                         mm[3] = 1;
888                         mm[4] = 9;
889                 }
890                 else
891                 {
892                         mm[1] = 6;
893                         mm[2] = 2;
894                         mm[3] = 9;
895                         mm[4] = 1;
896                 }
897                 break;
898         case 10:
899         case 14:
900                 mm[0] = 2;
901                 if (x < 0)
902                 {
903                         mm[1] = 3;
904                         mm[2] = 1;
905                         mm[3] = 6;
906                         mm[4] = 4;
907                 }
908                 else
909                 {
910                         mm[1] = 1;
911                         mm[2] = 3;
912                         mm[3] = 4;
913                         mm[4] = 6;
914                 }
915                 break;
916         case 12:
917                 mm[0] = 1;
918                 if (ay > ax)
919                 {
920                         mm[1] = 2;
921                         mm[2] = 4;
922                         mm[3] = 3;
923                         mm[4] = 7;
924                 }
925                 else
926                 {
927                         mm[1] = 4;
928                         mm[2] = 2;
929                         mm[3] = 7;
930                         mm[4] = 3;
931                 }
932                 break;
933         }
934
935         return TRUE;
936 }
937
938
939 static bool check_hp_for_feat_destruction(feature_type *f_ptr, monster_type *m_ptr)
940 {
941         return !have_flag(f_ptr->flags, FF_GLASS) ||
942                 (r_info[m_ptr->r_idx].flags2 & RF2_STUPID) ||
943                 (m_ptr->hp >= MAX(m_ptr->maxhp / 3, 200));
944 }
945
946
947 /*!
948  * @brief モンスター単体の1ターン行動処理メインルーチン /
949  * Process a monster
950  * @param target_ptr プレーヤーへの参照ポインタ
951  * @param m_idx 行動モンスターの参照ID
952  * @return なし
953  * @details
954  * The monster is known to be within 100 grids of the player\n
955  *\n
956  * In several cases, we directly update the monster lore\n
957  *\n
958  * Note that a monster is only allowed to "reproduce" if there\n
959  * are a limited number of "reproducing" monsters on the current\n
960  * level.  This should prevent the level from being "swamped" by\n
961  * reproducing monsters.  It also allows a large mass of mice to\n
962  * prevent a louse from multiplying, but this is a small price to\n
963  * pay for a simple multiplication method.\n
964  *\n
965  * XXX Monster fear is slightly odd, in particular, monsters will\n
966  * fixate on opening a door even if they cannot open it.  Actually,\n
967  * the same thing happens to normal monsters when they hit a door\n
968  *\n
969  * In addition, monsters which *cannot* open or bash\n
970  * down a door will still stand there trying to open it...\n
971  *\n
972  * XXX Technically, need to check for monster in the way\n
973  * combined with that monster being in a wall (or door?)\n
974  *\n
975  * A "direction" of "5" means "pick a random direction".\n
976  */
977 void process_monster(player_type *target_ptr, MONSTER_IDX m_idx)
978 {
979         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
980         monster_race *r_ptr = &r_info[m_ptr->r_idx];
981         turn_flags tmp_flags;
982         turn_flags *turn_flags_ptr = init_turn_flags(target_ptr->riding, m_idx, &tmp_flags);
983         turn_flags_ptr->see_m = is_seen(m_ptr);
984
985         decide_drop_from_monster(target_ptr, m_idx, turn_flags_ptr->is_riding_mon);
986         if ((m_ptr->mflag2 & MFLAG2_CHAMELEON) && one_in_(13) && !MON_CSLEEP(m_ptr))
987         {
988                 choose_new_monster(target_ptr, m_idx, FALSE, 0);
989                 r_ptr = &r_info[m_ptr->r_idx];
990         }
991
992         turn_flags_ptr->aware = process_stealth(target_ptr, m_idx);
993         if (vanish_summoned_children(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
994         if (process_quantum_effect(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
995         if (explode_grenade(target_ptr, m_idx)) return;
996         if (runaway_monster(target_ptr, turn_flags_ptr, m_idx)) return;
997
998         awake_monster(target_ptr, m_idx);
999         if (MON_STUNNED(m_ptr))
1000         {
1001                 if (one_in_(2)) return;
1002         }
1003
1004         if (turn_flags_ptr->is_riding_mon)
1005         {
1006                 target_ptr->update |= (PU_BONUS);
1007         }
1008
1009         process_angar(target_ptr, m_idx, turn_flags_ptr->see_m);
1010
1011         POSITION oy = m_ptr->fy;
1012         POSITION ox = m_ptr->fx;
1013         if (decide_monster_multiplication(target_ptr, m_idx, oy, ox)) return;
1014
1015         process_special(target_ptr, m_idx);
1016         process_speak_sound(target_ptr, m_idx, oy, ox, turn_flags_ptr->aware);
1017         if (cast_spell(target_ptr, m_idx, turn_flags_ptr->aware)) return;
1018
1019         DIRECTION mm[8];
1020         mm[0] = mm[1] = mm[2] = mm[3] = 0;
1021         mm[4] = mm[5] = mm[6] = mm[7] = 0;
1022
1023         if (!decide_monster_movement_direction(target_ptr, mm, m_idx, turn_flags_ptr->aware)) return;
1024
1025         int count = 0;
1026         if (!process_monster_movement(target_ptr, turn_flags_ptr, m_idx, mm, oy, ox, &count)) return;
1027
1028         /*
1029          *  Forward movements failed, but now received LOS attack!
1030          *  Try to flow by smell.
1031          */
1032         if (target_ptr->no_flowed && count > 2 && m_ptr->target_y)
1033                 m_ptr->mflag2 &= ~MFLAG2_NOFLOW;
1034
1035         if (!turn_flags_ptr->do_turn && !turn_flags_ptr->do_move && !MON_MONFEAR(m_ptr) && !turn_flags_ptr->is_riding_mon && turn_flags_ptr->aware)
1036         {
1037                 if (r_ptr->freq_spell && randint1(100) <= r_ptr->freq_spell)
1038                 {
1039                         if (make_attack_spell(m_idx, target_ptr)) return;
1040                 }
1041         }
1042
1043         update_player_type(target_ptr, turn_flags_ptr, r_ptr);
1044         update_monster_race_flags(target_ptr, turn_flags_ptr, m_ptr);
1045
1046         if (!process_monster_fear(target_ptr, turn_flags_ptr, m_idx)) return;
1047
1048         if (m_ptr->ml) chg_virtue(target_ptr, V_COMPASSION, -1);
1049 }
1050
1051
1052 /*!
1053  * @brief 超隠密処理
1054  * @param target_ptr プレーヤーへの参照ポインタ
1055  * @param m_idx モンスターID
1056  * @return モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1057  */
1058 bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx)
1059 {
1060         if ((target_ptr->special_defense & NINJA_S_STEALTH) == 0) return TRUE;
1061
1062         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1063         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1064         int tmp = target_ptr->lev * 6 + (target_ptr->skill_stl + 10) * 4;
1065         if (target_ptr->monlite) tmp /= 3;
1066         if (target_ptr->cursed & TRC_AGGRAVATE) tmp /= 2;
1067         if (r_ptr->level > (target_ptr->lev * target_ptr->lev / 20 + 10)) tmp /= 3;
1068         return (randint0(tmp) <= (r_ptr->level + 20));
1069 }
1070
1071
1072 /*!
1073  * @brief 死亡したモンスターが乗馬中のモンスターだった場合に落馬処理を行う
1074  * @param target_ptr プレーヤーへの参照ポインタ
1075  * @param m_idx モンスターID
1076  * @param is_riding_mon 騎乗中であればTRUE
1077  * @return なし
1078  */
1079 void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon)
1080 {
1081         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1082         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1083         if (!is_riding_mon || ((r_ptr->flags7 & RF7_RIDING) != 0)) return;
1084
1085         if (rakuba(target_ptr, 0, TRUE))
1086         {
1087 #ifdef JP
1088                 msg_print("地面に落とされた。");
1089 #else
1090                 GAME_TEXT m_name[MAX_NLEN];
1091                 monster_desc(target_ptr, m_name, &target_ptr->current_floor_ptr->m_list[target_ptr->riding], 0);
1092                 msg_format("You have fallen from %s.", m_name);
1093 #endif
1094         }
1095 }
1096
1097
1098 /*!
1099  * @brief 召喚の親元が消滅した時、子供も消滅させる
1100  * @param target_ptr プレーヤーへの参照ポインタ
1101  * @param m_idx モンスターID
1102  * @param see_m モンスターが視界内にいたらTRUE
1103  * @return 召喚モンスターが消滅したらTRUE
1104  */
1105 bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
1106 {
1107         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1108         if ((m_ptr->parent_m_idx == 0) || (target_ptr->current_floor_ptr->m_list[m_ptr->parent_m_idx].r_idx > 0))
1109                 return FALSE;
1110
1111         if (see_m)
1112         {
1113                 GAME_TEXT m_name[MAX_NLEN];
1114                 monster_desc(target_ptr, m_name, m_ptr, 0);
1115                 msg_format(_("%sは消え去った!", "%^s disappears!"), m_name);
1116         }
1117
1118         if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
1119         {
1120                 GAME_TEXT m_name[MAX_NLEN];
1121                 monster_desc(target_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
1122                 exe_write_diary(target_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_LOSE_PARENT, m_name);
1123         }
1124
1125         delete_monster_idx(target_ptr, m_idx);
1126         return TRUE;
1127 }
1128
1129
1130 /*!
1131  * @brief 寝ているモンスターの起床を判定する
1132  * @param target_ptr プレーヤーへの参照ポインタ
1133  * @param m_idx モンスターID
1134  * @return なし
1135  */
1136 void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx)
1137 {
1138         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1139         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1140         if (!MON_CSLEEP(m_ptr)) return;
1141         if (!(target_ptr->cursed & TRC_AGGRAVATE)) return;
1142
1143         (void)set_monster_csleep(target_ptr, m_idx, 0);
1144         if (m_ptr->ml)
1145         {
1146                 GAME_TEXT m_name[MAX_NLEN];
1147                 monster_desc(target_ptr, m_name, m_ptr, 0);
1148                 msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
1149         }
1150
1151         if (is_original_ap_and_seen(target_ptr, m_ptr) && (r_ptr->r_wake < MAX_UCHAR))
1152         {
1153                 r_ptr->r_wake++;
1154         }
1155 }
1156
1157
1158 /*!
1159  * @brief モンスターの怒り状態を判定する (起こっていたら敵に回す)
1160  * @param target_ptr プレーヤーへの参照ポインタ
1161  * @param m_idx モンスターID
1162  * @param see_m モンスターが視界内にいたらTRUE
1163  * @return なし
1164  */
1165 void process_angar(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
1166 {
1167         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1168         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1169         bool gets_angry = FALSE;
1170         if (is_friendly(m_ptr) && (target_ptr->cursed & TRC_AGGRAVATE))
1171                 gets_angry = TRUE;
1172
1173         if (is_pet(m_ptr) && ((((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) &&
1174                 monster_has_hostile_align(target_ptr, NULL, 10, -10, r_ptr)) || (r_ptr->flagsr & RFR_RES_ALL)))
1175         {
1176                 gets_angry = TRUE;
1177         }
1178
1179         if (target_ptr->phase_out || !gets_angry) return;
1180
1181         if (is_pet(m_ptr) || see_m)
1182         {
1183                 GAME_TEXT m_name[MAX_NLEN];
1184                 monster_desc(target_ptr, m_name, m_ptr, is_pet(m_ptr) ? MD_ASSUME_VISIBLE : 0);
1185                 msg_format(_("%^sは突然敵にまわった!", "%^s suddenly becomes hostile!"), m_name);
1186         }
1187
1188         set_hostile(target_ptr, m_ptr);
1189 }
1190
1191
1192 /*!
1193  * @brief 手榴弾の爆発処理
1194  * @param target_ptr プレーヤーへの参照ポインタ
1195  * @param m_idx モンスターID
1196  * @return 爆死したらTRUE
1197  */
1198 bool explode_grenade(player_type *target_ptr, MONSTER_IDX m_idx)
1199 {
1200         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1201         if (m_ptr->r_idx != MON_GRENADE) return FALSE;
1202
1203         bool fear, dead;
1204         mon_take_hit_mon(target_ptr, m_idx, 1, &dead, &fear, _("は爆発して粉々になった。", " explodes into tiny shreds."), m_idx);
1205         return dead;
1206 }
1207
1208
1209 /*!
1210  * @brief モンスター依存の特別な行動を取らせる
1211  * @param target_ptr プレーヤーへの参照ポインタ
1212  * @param m_idx モンスターID
1213  * @return なし
1214  */
1215 void process_special(player_type *target_ptr, MONSTER_IDX m_idx)
1216 {
1217         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1218         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1219         if ((r_ptr->a_ability_flags2 & RF6_SPECIAL) == 0) return;
1220         if (m_ptr->r_idx != MON_OHMU) return;
1221         if (target_ptr->current_floor_ptr->inside_arena || target_ptr->phase_out) return;
1222         if ((r_ptr->freq_spell == 0) || !(randint1(100) <= r_ptr->freq_spell)) return;
1223
1224         int count = 0;
1225         DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
1226         BIT_FLAGS p_mode = is_pet(m_ptr) ? PM_FORCE_PET : 0L;
1227
1228         for (int k = 0; k < A_MAX; k++)
1229         {
1230                 if (summon_specific(target_ptr, m_idx, m_ptr->fy, m_ptr->fx, rlev, SUMMON_MOLD, (PM_ALLOW_GROUP | p_mode)))
1231                 {
1232                         if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml) count++;
1233                 }
1234         }
1235
1236         if (count && is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags6 |= (RF6_SPECIAL);
1237 }
1238
1239
1240 /*!
1241  * @brief モンスターを喋らせたり足音を立てたりする
1242  * @param target_ptr プレーヤーへの参照ポインタ
1243  * @param m_idx モンスターID
1244  * @param oy モンスターが元々いたY座標
1245  * @param ox モンスターが元々いたX座標
1246  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1247  * @return なし
1248  */
1249 void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware)
1250 {
1251         if (target_ptr->phase_out) return;
1252
1253         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1254         monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
1255         if (m_ptr->ap_r_idx == MON_CYBER &&
1256                 one_in_(CYBERNOISE) &&
1257                 !m_ptr->ml && (m_ptr->cdis <= MAX_SIGHT))
1258         {
1259                 if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
1260                 msg_print(_("重厚な足音が聞こえた。", "You hear heavy steps."));
1261         }
1262
1263         if (((ap_r_ptr->flags2 & RF2_CAN_SPEAK) == 0) || !aware ||
1264                 !one_in_(SPEAK_CHANCE) ||
1265                 !player_has_los_bold(target_ptr, oy, ox) ||
1266                 !projectable(target_ptr, oy, ox, target_ptr->y, target_ptr->x))
1267                 return;
1268
1269         GAME_TEXT m_name[MAX_NLEN];
1270         char monmessage[1024];
1271         concptr filename;
1272
1273         if (m_ptr->ml)
1274                 monster_desc(target_ptr, m_name, m_ptr, 0);
1275         else
1276                 strcpy(m_name, _("それ", "It"));
1277
1278         if (MON_MONFEAR(m_ptr))
1279                 filename = _("monfear_j.txt", "monfear.txt");
1280         else if (is_pet(m_ptr))
1281                 filename = _("monpet_j.txt", "monpet.txt");
1282         else if (is_friendly(m_ptr))
1283                 filename = _("monfrien_j.txt", "monfrien.txt");
1284         else
1285                 filename = _("monspeak_j.txt", "monspeak.txt");
1286
1287         if (get_rnd_line(filename, m_ptr->ap_r_idx, monmessage) == 0)
1288         {
1289                 msg_format(_("%^s%s", "%^s %s"), m_name, monmessage);
1290         }
1291 }
1292
1293
1294 /*!
1295  * @brief モンスターを分裂させるかどうかを決定する (分裂もさせる)
1296  * @param target_ptr プレーヤーへの参照ポインタ
1297  * @param m_idx モンスターID
1298  * @param oy 分裂元モンスターのY座標
1299  * @param ox 分裂元モンスターのX座標
1300  * @return 実際に分裂したらTRUEを返す
1301  */
1302 bool decide_monster_multiplication(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox)
1303 {
1304         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1305         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1306         if (((r_ptr->flags2 & RF2_MULTIPLY) == 0) || (target_ptr->current_floor_ptr->num_repro >= MAX_REPRO))
1307                 return FALSE;
1308
1309         int k = 0;
1310         for (POSITION y = oy - 1; y <= oy + 1; y++)
1311         {
1312                 for (POSITION x = ox - 1; x <= ox + 1; x++)
1313                 {
1314                         if (!in_bounds2(target_ptr->current_floor_ptr, y, x)) continue;
1315                         if (target_ptr->current_floor_ptr->grid_array[y][x].m_idx) k++;
1316                 }
1317         }
1318
1319         if (multiply_barrier(target_ptr, m_idx)) k = 8;
1320
1321         if ((k < 4) && (!k || !randint0(k * MON_MULT_ADJ)))
1322         {
1323                 if (multiply_monster(target_ptr, m_idx, FALSE, (is_pet(m_ptr) ? PM_FORCE_PET : 0)))
1324                 {
1325                         if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml && is_original_ap_and_seen(target_ptr, m_ptr))
1326                         {
1327                                 r_ptr->r_flags2 |= (RF2_MULTIPLY);
1328                         }
1329
1330                         return TRUE;
1331                 }
1332         }
1333
1334         return FALSE;
1335 }
1336
1337
1338 /*!
1339  * @brief モンスターの移動パターンを決定する
1340  * @param target_ptr プレーヤーへの参照ポインタ
1341  * @param mm 移動方向
1342  * @param m_idx モンスターID
1343  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1344  * @return 移動先が存在すればTRUE
1345  */
1346 bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware)
1347 {
1348         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1349         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1350
1351         if (MON_CONFUSED(m_ptr) || !aware)
1352         {
1353                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
1354                 return TRUE;
1355         }
1356
1357         if (random_walk(target_ptr, mm, m_ptr)) return TRUE;
1358
1359         if ((r_ptr->flags1 & RF1_NEVER_MOVE) && (m_ptr->cdis > 1))
1360         {
1361                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
1362                 return TRUE;
1363         }
1364
1365         if (decide_pet_movement_direction(target_ptr, mm, m_idx)) return TRUE;
1366
1367         if (!is_hostile(m_ptr))
1368         {
1369                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
1370                 get_enemy_dir(target_ptr, m_idx, mm);
1371                 return TRUE;
1372         }
1373
1374         if (!get_moves(target_ptr, m_idx, mm)) return FALSE;
1375
1376         return TRUE;
1377 }
1378
1379
1380 /*!
1381  * todo ↓のように書いたが、"5"とはもしかして「その場に留まる」という意味か?
1382  * @brief 不規則歩行フラグを持つモンスターの移動方向をその確率に基づいて決定する
1383  * @param target_ptr プレーヤーへの参照ポインタ
1384  * @param mm 移動方向
1385  * @param m_ptr モンスターへの参照ポインタ
1386  * @return 不規則な方向へ歩くことになったらTRUE
1387  */
1388 bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr)
1389 {
1390         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1391         if (((r_ptr->flags1 & (RF1_RAND_50 | RF1_RAND_25)) == (RF1_RAND_50 | RF1_RAND_25)) && (randint0(100) < 75))
1392         {
1393                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= (RF1_RAND_50 | RF1_RAND_25);
1394
1395                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
1396                 return TRUE;
1397         }
1398
1399         if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 50))
1400         {
1401                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_50;
1402
1403                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
1404                 return TRUE;
1405         }
1406
1407         if ((r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 25))
1408         {
1409                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_25;
1410
1411                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
1412                 return TRUE;
1413         }
1414
1415         return FALSE;
1416 }
1417
1418
1419 /*!
1420  * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
1421  * @param target_ptr プレーヤーへの参照ポインタ
1422  * @param mm 移動方向
1423  * @param m_idx モンスターID
1424  * @return モンスターがペットであればTRUE
1425  */
1426 bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx)
1427 {
1428         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1429         if (!is_pet(m_ptr)) return FALSE;
1430
1431         bool avoid = ((target_ptr->pet_follow_distance < 0) && (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
1432         bool lonely = (!avoid && (m_ptr->cdis > target_ptr->pet_follow_distance));
1433         bool distant = (m_ptr->cdis > PET_SEEK_DIST);
1434         mm[0] = mm[1] = mm[2] = mm[3] = 5;
1435         if (get_enemy_dir(target_ptr, m_idx, mm)) return TRUE;
1436         if (!avoid && !lonely && !distant) return TRUE;
1437
1438         POSITION dis = target_ptr->pet_follow_distance;
1439         if (target_ptr->pet_follow_distance > PET_SEEK_DIST)
1440         {
1441                 target_ptr->pet_follow_distance = PET_SEEK_DIST;
1442         }
1443
1444         (void)get_moves(target_ptr, m_idx, mm);
1445         target_ptr->pet_follow_distance = (s16b)dis;
1446         return TRUE;
1447 }
1448
1449
1450 /*!
1451  * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
1452  * @param target_ptr プレーヤーへの参照ポインタ
1453  * @param m_idx モンスターID
1454  * @param is_riding_mon 騎乗状態ならばTRUE
1455  * @param see_m モンスターが視界内にいたらTRUE
1456  * @return モンスターがフロアから消えたらTRUE
1457  */
1458 bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx)
1459 {
1460         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1461         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1462         bool can_runaway = is_pet(m_ptr) || is_friendly(m_ptr);
1463         can_runaway &= ((r_ptr->flags1 & RF1_UNIQUE) != 0) || ((r_ptr->flags7 & RF7_NAZGUL) != 0);
1464         can_runaway &= !target_ptr->phase_out;
1465         if (!can_runaway) return FALSE;
1466
1467         static int riding_pinch = 0;
1468
1469         if (m_ptr->hp >= m_ptr->maxhp / 3)
1470         {
1471                 /* Reset the counter */
1472                 if (turn_flags_ptr->is_riding_mon) riding_pinch = 0;
1473
1474                 return FALSE;
1475         }
1476
1477         GAME_TEXT m_name[MAX_NLEN];
1478         monster_desc(target_ptr, m_name, m_ptr, 0);
1479         if (turn_flags_ptr->is_riding_mon && riding_pinch < 2)
1480         {
1481                 msg_format(_("%sは傷の痛さの余りあなたの束縛から逃れようとしている。",
1482                         "%^s seems to be in so much pain and tries to escape from your restriction."), m_name);
1483                 riding_pinch++;
1484                 disturb(target_ptr, TRUE, TRUE);
1485                 return FALSE;
1486         }
1487
1488         escape_monster(target_ptr, turn_flags_ptr, m_ptr, m_name);
1489         check_quest_completion(target_ptr, m_ptr);
1490         delete_monster_idx(target_ptr, m_idx);
1491         return TRUE;
1492 }
1493
1494
1495 /*!
1496  * @brief HPが1/3未満になった有効的なユニークモンスターの逃走処理を行う
1497  * @param target_ptr プレーヤーへの参照ポインタ
1498  * @param is_riding_mon 騎乗状態ならばTRUE
1499  * @param m_ptr モンスターへの参照ポインタ
1500  * @param m_name モンスター名称
1501  * @param see_m モンスターが視界内にいたらTRUE
1502  * @return なし
1503  */
1504 void escape_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, GAME_TEXT *m_name)
1505 {
1506         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1507         if (turn_flags_ptr->is_riding_mon)
1508         {
1509                 msg_format(_("%sはあなたの束縛から脱出した。", "%^s succeeded to escape from your restriction!"), m_name);
1510                 if (rakuba(target_ptr, -1, FALSE))
1511                 {
1512                         msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
1513                 }
1514         }
1515
1516         if (turn_flags_ptr->see_m)
1517         {
1518                 if ((r_ptr->flags2 & RF2_CAN_SPEAK) && (m_ptr->r_idx != MON_GRIP) && (m_ptr->r_idx != MON_WOLF) && (m_ptr->r_idx != MON_FANG) &&
1519                         player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx) && projectable(target_ptr, m_ptr->fy, m_ptr->fx, target_ptr->y, target_ptr->x))
1520                 {
1521                         msg_format(_("%^s「ピンチだ!退却させてもらう!」", "%^s says 'It is the pinch! I will retreat'."), m_name);
1522                 }
1523
1524                 msg_format(_("%^sがテレポート・レベルの巻物を読んだ。", "%^s reads a scroll of teleport level."), m_name);
1525                 msg_format(_("%^sが消え去った。", "%^s disappears."), m_name);
1526         }
1527
1528         if (turn_flags_ptr->is_riding_mon && rakuba(target_ptr, -1, FALSE))
1529         {
1530                 msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
1531         }
1532 }
1533
1534
1535 /*!
1536  * @brief モンスターに魔法を試行させる
1537  * @param target_ptr プレーヤーへの参照ポインタ
1538  * @param m_idx モンスターID
1539  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1540  * @return 魔法を唱えられなければ強制的にFALSE、その後モンスターが実際に魔法を唱えればTRUE
1541  */
1542 bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware)
1543 {
1544         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1545         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1546         if ((r_ptr->freq_spell == 0) || (randint1(100) > r_ptr->freq_spell))
1547                 return FALSE;
1548
1549         bool counterattack = FALSE;
1550         if (m_ptr->target_y)
1551         {
1552                 MONSTER_IDX t_m_idx = target_ptr->current_floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
1553                 if (t_m_idx && are_enemies(target_ptr, m_ptr, &target_ptr->current_floor_ptr->m_list[t_m_idx]) &&
1554                         projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
1555                 {
1556                         counterattack = TRUE;
1557                 }
1558         }
1559
1560         if (counterattack)
1561         {
1562                 if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
1563                 if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
1564         }
1565         else
1566         {
1567                 if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
1568                 if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
1569         }
1570
1571         return FALSE;
1572 }
1573
1574
1575 /*!
1576  * todo 少し長いが、これといってブロックとしてまとまった部分もないので暫定でこのままとする
1577  * @brief モンスターの移動に関するメインルーチン
1578  * @param target_ptr プレーヤーへの参照ポインタ
1579  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1580  * @param m_idx モンスターID
1581  * @param mm モンスターの移動方向
1582  * @param oy 移動前の、モンスターのY座標
1583  * @param ox 移動前の、モンスターのX座標
1584  * @param count 移動回数 (のはず todo)
1585  * @return 移動が阻害される何か (ドア等)があったらFALSE
1586  */
1587 bool process_monster_movement(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, DIRECTION *mm, POSITION oy, POSITION ox, int *count)
1588 {
1589         for (int i = 0; mm[i]; i++)
1590         {
1591                 int d = mm[i];
1592                 if (d == 5) d = ddd[randint0(8)];
1593
1594                 POSITION ny = oy + ddy[d];
1595                 POSITION nx = ox + ddx[d];
1596                 if (!in_bounds2(target_ptr->current_floor_ptr, ny, nx)) continue;
1597
1598                 grid_type *g_ptr;
1599                 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1600                 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1601                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
1602                 bool can_cross = monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0);
1603
1604                 if (!process_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx, can_cross))
1605                 {
1606                         if (!process_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1607                                 return FALSE;
1608                 }
1609
1610                 if (!process_protection_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1611                 {
1612                         if (!process_explosive_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1613                                 return FALSE;
1614                 }
1615
1616                 exe_monster_attack_to_player(target_ptr, turn_flags_ptr, m_idx, ny, nx);
1617                 if (process_monster_attack_to_monster(target_ptr, turn_flags_ptr, m_idx, g_ptr, can_cross)) return FALSE;
1618
1619                 if (turn_flags_ptr->is_riding_mon)
1620                 {
1621                         if (!target_ptr->riding_ryoute && !MON_MONFEAR(&target_ptr->current_floor_ptr->m_list[target_ptr->riding])) turn_flags_ptr->do_move = FALSE;
1622                 }
1623
1624                 if (!process_post_dig_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx)) return FALSE;
1625
1626                 if (turn_flags_ptr->must_alter_to_move && (r_ptr->flags7 & RF7_AQUATIC))
1627                 {
1628                         if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0))
1629                                 turn_flags_ptr->do_move = FALSE;
1630                 }
1631
1632                 if (turn_flags_ptr->do_move && !can_cross && !turn_flags_ptr->did_kill_wall && !turn_flags_ptr->did_bash_door)
1633                         turn_flags_ptr->do_move = FALSE;
1634
1635                 if (turn_flags_ptr->do_move && (r_ptr->flags1 & RF1_NEVER_MOVE))
1636                 {
1637                         if (is_original_ap_and_seen(target_ptr, m_ptr))
1638                                 r_ptr->r_flags1 |= (RF1_NEVER_MOVE);
1639
1640                         turn_flags_ptr->do_move = FALSE;
1641                 }
1642
1643                 if (!turn_flags_ptr->do_move)
1644                 {
1645                         if (turn_flags_ptr->do_turn) break;
1646
1647                         continue;
1648                 }
1649
1650                 turn_flags_ptr->do_turn = TRUE;
1651                 feature_type *f_ptr;
1652                 f_ptr = &f_info[g_ptr->feat];
1653                 if (have_flag(f_ptr->flags, FF_TREE))
1654                 {
1655                         if (!(r_ptr->flags7 & RF7_CAN_FLY) && !(r_ptr->flags8 & RF8_WILD_WOOD))
1656                         {
1657                                 m_ptr->energy_need += ENERGY_NEED();
1658                         }
1659                 }
1660
1661                 if (!update_riding_monster(target_ptr, turn_flags_ptr, m_idx, oy, ox, ny, nx)) break;
1662
1663                 monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
1664                 if (m_ptr->ml &&
1665                         (disturb_move ||
1666                         (disturb_near && (m_ptr->mflag & MFLAG_VIEW) && projectable(target_ptr, target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx)) ||
1667                                 (disturb_high && ap_r_ptr->r_tkills && ap_r_ptr->level >= target_ptr->lev)))
1668                 {
1669                         if (is_hostile(m_ptr))
1670                                 disturb(target_ptr, FALSE, TRUE);
1671                 }
1672
1673                 bool is_takable_or_killable = g_ptr->o_idx > 0;
1674                 is_takable_or_killable &= (r_ptr->flags2 & (RF2_TAKE_ITEM | RF2_KILL_ITEM)) != 0;
1675
1676                 bool is_pickup_items = (target_ptr->pet_extra_flags & PF_PICKUP_ITEMS) != 0;
1677                 is_pickup_items &= (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
1678
1679                 is_takable_or_killable &= !is_pet(m_ptr) || is_pickup_items;
1680                 if (!is_takable_or_killable)
1681                 {
1682                         if (turn_flags_ptr->do_turn) break;
1683
1684                         continue;
1685                 }
1686
1687                 update_object_by_monster_movement(target_ptr, turn_flags_ptr, m_idx, ny, nx);
1688                 if (turn_flags_ptr->do_turn) break;
1689
1690                 (*count)++;
1691         }
1692
1693         return TRUE;
1694 }
1695
1696
1697 /*!
1698  * @brief モンスターによる壁の透過・破壊を行う
1699  * @param target_ptr プレーヤーへの参照ポインタ
1700  * @param m_ptr モンスターへの参照ポインタ
1701  * @param ny モンスターのY座標
1702  * @param nx モンスターのX座標
1703  * @param can_cross モンスターが地形を踏破できるならばTRUE
1704  * @return 透過も破壊もしなかった場合はFALSE、それ以外はTRUE
1705  */
1706 bool process_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx, bool can_cross)
1707 {
1708         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1709         grid_type *g_ptr;
1710         g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1711         feature_type *f_ptr;
1712         f_ptr = &f_info[g_ptr->feat];
1713         if (player_bold(target_ptr, ny, nx))
1714         {
1715                 turn_flags_ptr->do_move = TRUE;
1716                 return TRUE;
1717         }
1718
1719         if (g_ptr->m_idx > 0)
1720         {
1721                 turn_flags_ptr->do_move = TRUE;
1722                 return TRUE;
1723         }
1724
1725         if (((r_ptr->flags2 & RF2_KILL_WALL) != 0) &&
1726                 (can_cross ? !have_flag(f_ptr->flags, FF_LOS) : !turn_flags_ptr->is_riding_mon) &&
1727                 have_flag(f_ptr->flags, FF_HURT_DISI) && !have_flag(f_ptr->flags, FF_PERMANENT) &&
1728                 check_hp_for_feat_destruction(f_ptr, m_ptr))
1729         {
1730                 turn_flags_ptr->do_move = TRUE;
1731                 if (!can_cross) turn_flags_ptr->must_alter_to_move = TRUE;
1732
1733                 turn_flags_ptr->did_kill_wall = TRUE;
1734                 return TRUE;
1735         }
1736
1737         if (!can_cross) return FALSE;
1738
1739         turn_flags_ptr->do_move = TRUE;
1740         if (((r_ptr->flags2 & RF2_PASS_WALL) != 0) && (!turn_flags_ptr->is_riding_mon || target_ptr->pass_wall) &&
1741                 have_flag(f_ptr->flags, FF_CAN_PASS))
1742         {
1743                 turn_flags_ptr->did_pass_wall = TRUE;
1744         }
1745
1746         return TRUE;
1747 }
1748
1749
1750 /*!
1751  * @brief モンスターによるドアの開放・破壊を行う
1752  * @param target_ptr プレーヤーへの参照ポインタ
1753  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1754  * @param m_ptr モンスターへの参照ポインタ
1755  * @param ny モンスターのY座標
1756  * @param nx モンスターのX座標
1757  * @return モンスターが死亡した場合のみFALSE
1758  */
1759 bool process_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
1760 {
1761         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1762         grid_type *g_ptr;
1763         g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1764         if (!is_closed_door(target_ptr, g_ptr->feat)) return TRUE;
1765
1766         feature_type *f_ptr;
1767         f_ptr = &f_info[g_ptr->feat];
1768         bool may_bash = bash_normal_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx);
1769         bash_glass_door(target_ptr, turn_flags_ptr, m_ptr, f_ptr, may_bash);
1770
1771         if (!turn_flags_ptr->did_open_door && !turn_flags_ptr->did_bash_door) return TRUE;
1772
1773         if (turn_flags_ptr->did_bash_door &&
1774                 ((randint0(100) < 50) || (feat_state(target_ptr, g_ptr->feat, FF_OPEN) == g_ptr->feat) || have_flag(f_ptr->flags, FF_GLASS)))
1775         {
1776                 cave_alter_feat(target_ptr, ny, nx, FF_BASH);
1777                 if (!monster_is_valid(m_ptr))
1778                 {
1779                         target_ptr->update |= (PU_FLOW);
1780                         target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1781                         if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
1782
1783                         return FALSE;
1784                 }
1785         }
1786         else
1787         {
1788                 cave_alter_feat(target_ptr, ny, nx, FF_OPEN);
1789         }
1790
1791         f_ptr = &f_info[g_ptr->feat];
1792         turn_flags_ptr->do_view = TRUE;
1793         return TRUE;
1794 }
1795
1796
1797 /*!
1798  * @brief モンスターが普通のドアを開ける処理
1799  * @param target_ptr プレーヤーへの参照ポインタ
1800  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1801  * @param m_ptr モンスターへの参照ポインタ
1802  * @param ny モンスターのY座標
1803  * @param nx モンスターのX座標
1804  * @return ここではドアを開けず、ガラスのドアを開ける可能性があるならTRUE
1805  */
1806 bool bash_normal_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
1807 {
1808         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1809         grid_type *g_ptr;
1810         g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1811         feature_type *f_ptr;
1812         f_ptr = &f_info[g_ptr->feat];
1813         turn_flags_ptr->do_move = FALSE;
1814         if (((r_ptr->flags2 & RF2_OPEN_DOOR) == 0) || !have_flag(f_ptr->flags, FF_OPEN) ||
1815                 (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
1816                 return TRUE;
1817
1818         if (f_ptr->power == 0)
1819         {
1820                 turn_flags_ptr->did_open_door = TRUE;
1821                 turn_flags_ptr->do_turn = TRUE;
1822                 return FALSE;
1823         }
1824
1825         if (randint0(m_ptr->hp / 10) > f_ptr->power)
1826         {
1827                 cave_alter_feat(target_ptr, ny, nx, FF_DISARM);
1828                 turn_flags_ptr->do_turn = TRUE;
1829                 return FALSE;
1830         }
1831
1832         return TRUE;
1833 }
1834
1835
1836 /*!
1837  * @brief モンスターがガラスのドアを開ける処理
1838  * @param target_ptr プレーヤーへの参照ポインタ
1839  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1840  * @param m_ptr モンスターへの参照ポインタ
1841  * @param g_ptr グリッドへの参照ポインタ
1842  * @param f_ptr 地形への参照ポインタ
1843  * @return なし
1844  */
1845 void bash_glass_door(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, feature_type *f_ptr, bool may_bash)
1846 {
1847         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1848         if (!may_bash || ((r_ptr->flags2 & RF2_BASH_DOOR) == 0) || !have_flag(f_ptr->flags, FF_BASH) ||
1849                 (is_pet(m_ptr) && ((target_ptr->pet_extra_flags & PF_OPEN_DOORS) == 0)))
1850                 return;
1851
1852         if (!check_hp_for_feat_destruction(f_ptr, m_ptr) || (randint0(m_ptr->hp / 10) <= f_ptr->power))
1853                 return;
1854
1855         if (have_flag(f_ptr->flags, FF_GLASS))
1856                 msg_print(_("ガラスが砕ける音がした!", "You hear glass breaking!"));
1857         else
1858                 msg_print(_("ドアを叩き開ける音がした!", "You hear a door burst open!"));
1859
1860         if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
1861
1862         turn_flags_ptr->did_bash_door = TRUE;
1863         turn_flags_ptr->do_move = TRUE;
1864         turn_flags_ptr->must_alter_to_move = TRUE;
1865 }
1866
1867
1868 /*!
1869  * @brief モンスターが壁を掘った後続処理を実行する
1870  * @param target_ptr プレーヤーへの参照ポインタ
1871  * @turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1872  * @param m_ptr モンスターへの参照ポインタ
1873  * @param ny モンスターのY座標
1874  * @param nx モンスターのX座標
1875  * @return モンスターが死亡した場合のみFALSE
1876  */
1877 bool process_post_dig_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx)
1878 {
1879         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1880         grid_type *g_ptr;
1881         g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1882         feature_type *f_ptr;
1883         f_ptr = &f_info[g_ptr->feat];
1884         if (!turn_flags_ptr->did_kill_wall || !turn_flags_ptr->do_move) return TRUE;
1885
1886         if (one_in_(GRINDNOISE))
1887         {
1888                 if (have_flag(f_ptr->flags, FF_GLASS))
1889                         msg_print(_("何かの砕ける音が聞こえる。", "There is a crashing sound."));
1890                 else
1891                         msg_print(_("ギシギシいう音が聞こえる。", "There is a grinding sound."));
1892         }
1893
1894         cave_alter_feat(target_ptr, ny, nx, FF_HURT_DISI);
1895
1896         if (!monster_is_valid(m_ptr))
1897         {
1898                 target_ptr->update |= (PU_FLOW);
1899                 target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1900                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags2 |= (RF2_KILL_WALL);
1901
1902                 return FALSE;
1903         }
1904
1905         f_ptr = &f_info[g_ptr->feat];
1906         turn_flags_ptr->do_view = TRUE;
1907         turn_flags_ptr->do_turn = TRUE;
1908         return TRUE;
1909 }
1910
1911
1912 /*!
1913  * @brief 騎乗中のモンスター情報を更新する
1914  * @param target_ptr プレーヤーへの参照ポインタ
1915  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1916  * @param m_idx モンスターID
1917  * @param oy 移動前の、モンスターのY座標
1918  * @param ox 移動前の、モンスターのX座標
1919  * @param ny 移動後の、モンスターのY座標
1920  * @param ox 移動後の、モンスターのX座標
1921  * @return アイテム等に影響を及ぼしたらTRUE
1922  */
1923 bool update_riding_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, POSITION ny, POSITION nx)
1924 {
1925         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1926         grid_type *g_ptr;
1927         g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1928         monster_type *y_ptr;
1929         y_ptr = &target_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
1930         if (turn_flags_ptr->is_riding_mon)
1931                 return move_player_effect(target_ptr, ny, nx, MPE_DONT_PICKUP);
1932
1933         target_ptr->current_floor_ptr->grid_array[oy][ox].m_idx = g_ptr->m_idx;
1934         if (g_ptr->m_idx)
1935         {
1936                 y_ptr->fy = oy;
1937                 y_ptr->fx = ox;
1938                 update_monster(target_ptr, g_ptr->m_idx, TRUE);
1939         }
1940
1941         g_ptr->m_idx = m_idx;
1942         m_ptr->fy = ny;
1943         m_ptr->fx = nx;
1944         update_monster(target_ptr, m_idx, TRUE);
1945
1946         lite_spot(target_ptr, oy, ox);
1947         lite_spot(target_ptr, ny, nx);
1948         return TRUE;
1949 }
1950
1951
1952 /*!
1953  * @brief updateフィールドを更新する
1954  * @param target_ptr プレーヤーへの参照ポインタ
1955  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1956  * @return なし
1957  */
1958 void update_player_type(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_race *r_ptr)
1959 {
1960         if (turn_flags_ptr->do_view)
1961         {
1962                 target_ptr->update |= (PU_FLOW);
1963                 target_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1964         }
1965
1966         if (turn_flags_ptr->do_move && ((r_ptr->flags7 & (RF7_SELF_LD_MASK | RF7_HAS_DARK_1 | RF7_HAS_DARK_2))
1967                 || ((r_ptr->flags7 & (RF7_HAS_LITE_1 | RF7_HAS_LITE_2)) && !target_ptr->phase_out)))
1968         {
1969                 target_ptr->update |= (PU_MON_LITE);
1970         }
1971 }
1972
1973
1974 /*!
1975  * @brief モンスターのフラグを更新する
1976  * @param target_ptr プレーヤーへの参照ポインタ
1977  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1978  * @param m_ptr モンスターへの参照ポインタ
1979  * @return なし
1980  */
1981 void update_monster_race_flags(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr)
1982 {
1983         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1984         if (!is_original_ap_and_seen(target_ptr, m_ptr)) return;
1985
1986         if (turn_flags_ptr->did_open_door) r_ptr->r_flags2 |= (RF2_OPEN_DOOR);
1987         if (turn_flags_ptr->did_bash_door) r_ptr->r_flags2 |= (RF2_BASH_DOOR);
1988         if (turn_flags_ptr->did_take_item) r_ptr->r_flags2 |= (RF2_TAKE_ITEM);
1989         if (turn_flags_ptr->did_kill_item) r_ptr->r_flags2 |= (RF2_KILL_ITEM);
1990         if (turn_flags_ptr->did_move_body) r_ptr->r_flags2 |= (RF2_MOVE_BODY);
1991         if (turn_flags_ptr->did_pass_wall) r_ptr->r_flags2 |= (RF2_PASS_WALL);
1992         if (turn_flags_ptr->did_kill_wall) r_ptr->r_flags2 |= (RF2_KILL_WALL);
1993 }
1994
1995
1996 /*!
1997  * @brief モンスターの恐怖状態を処理する
1998  * @param target_ptr プレーヤーへの参照ポインタ
1999  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
2000  * @param m_idx モンスターID
2001  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
2002  * @return モンスターが戦いを決意したらTRUE
2003  */
2004 bool process_monster_fear(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx)
2005 {
2006         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
2007         bool is_battle_determined = !turn_flags_ptr->do_turn && !turn_flags_ptr->do_move && MON_MONFEAR(m_ptr) && turn_flags_ptr->aware;
2008         if (!is_battle_determined) return FALSE;
2009
2010         (void)set_monster_monfear(target_ptr, m_idx, 0);
2011         if (!turn_flags_ptr->see_m) return TRUE;
2012
2013         GAME_TEXT m_name[MAX_NLEN];
2014         monster_desc(target_ptr, m_name, m_ptr, 0);
2015         msg_format(_("%^sは戦いを決意した!", "%^s turns to fight!"), m_name);
2016         return TRUE;
2017 }
2018
2019
2020 /*!
2021  * @brief 全モンスターのターン管理メインルーチン /
2022  * Process all the "live" monsters, once per game turn.
2023  * @return なし
2024  * @details
2025  * During each game current game turn, we scan through the list of all the "live" monsters,\n
2026  * (backwards, so we can excise any "freshly dead" monsters), energizing each\n
2027  * monster, and allowing fully energized monsters to move, attack, pass, etc.\n
2028  *\n
2029  * Note that monsters can never move in the monster array (except when the\n
2030  * "compact_monsters()" function is called by "dungeon()" or "save_player()").\n
2031  *\n
2032  * This function is responsible for at least half of the processor time\n
2033  * on a normal system with a "normal" amount of monsters and a player doing\n
2034  * normal things.\n
2035  *\n
2036  * When the player is resting, virtually 90% of the processor time is spent\n
2037  * in this function, and its children, "process_monster()" and "make_move()".\n
2038  *\n
2039  * Most of the rest of the time is spent in "update_view()" and "lite_spot()",\n
2040  * especially when the player is running.\n
2041  *\n
2042  * Note the special "MFLAG_BORN" flag, which allows us to ignore "fresh"\n
2043  * monsters while they are still being "born".  A monster is "fresh" only\n
2044  * during the game turn in which it is created, and we use the "hack_m_idx" to\n
2045  * determine if the monster is yet to be processed during the game turn.\n
2046  *\n
2047  * Note the special "MFLAG_NICE" flag, which allows the player to get one\n
2048  * move before any "nasty" monsters get to use their spell attacks.\n
2049  *\n
2050  * Note that when the "knowledge" about the currently tracked monster\n
2051  * changes (flags, attacks, spells), we induce a redraw of the monster\n
2052  * recall window.\n
2053  */
2054 void process_monsters(player_type *target_ptr)
2055 {
2056         old_race_flags tmp_flags;
2057         old_race_flags *old_race_flags_ptr = init_old_race_flags(&tmp_flags);
2058
2059         floor_type *floor_ptr = target_ptr->current_floor_ptr;
2060         floor_ptr->monster_noise = FALSE;
2061
2062         MONRACE_IDX old_monster_race_idx = target_ptr->monster_race_idx;
2063         save_old_race_flags(target_ptr->monster_race_idx, old_race_flags_ptr);
2064         sweep_monster_process(target_ptr);
2065
2066         hack_m_idx = 0;
2067         if (!target_ptr->monster_race_idx || (target_ptr->monster_race_idx != old_monster_race_idx))
2068                 return;
2069
2070         update_player_window(target_ptr->monster_race_idx, &target_ptr->window, old_race_flags_ptr);
2071 }
2072
2073
2074 /*!
2075  * @brief フロア内のモンスターについてターン終了時の処理を繰り返す
2076  * @param target_ptr プレーヤーへの参照ポインタ
2077  */
2078 void sweep_monster_process(player_type *target_ptr)
2079 {
2080         floor_type *floor_ptr = target_ptr->current_floor_ptr;
2081         for (MONSTER_IDX i = floor_ptr->m_max - 1; i >= 1; i--)
2082         {
2083                 monster_type *m_ptr;
2084                 m_ptr = &floor_ptr->m_list[i];
2085
2086                 if (target_ptr->leaving) return;
2087                 if (!monster_is_valid(m_ptr)) continue;
2088                 if (target_ptr->wild_mode) continue;
2089
2090                 if (m_ptr->mflag & MFLAG_BORN)
2091                 {
2092                         m_ptr->mflag &= ~(MFLAG_BORN);
2093                         continue;
2094                 }
2095
2096                 if (m_ptr->cdis >= AAF_LIMIT) continue;
2097                 if (!decide_process_continue(target_ptr, m_ptr)) continue;
2098
2099                 SPEED speed = (target_ptr->riding == i) ? target_ptr->pspeed : decide_monster_speed(m_ptr);
2100                 m_ptr->energy_need -= SPEED_TO_ENERGY(speed);
2101                 if (m_ptr->energy_need > 0) continue;
2102
2103                 m_ptr->energy_need += ENERGY_NEED();
2104                 hack_m_idx = i;
2105                 process_monster(target_ptr, i);
2106                 reset_target(m_ptr);
2107
2108                 if (target_ptr->no_flowed && one_in_(3))
2109                         m_ptr->mflag2 |= MFLAG2_NOFLOW;
2110
2111                 if (!target_ptr->playing || target_ptr->is_dead) return;
2112                 if (target_ptr->leaving) return;
2113         }
2114 }
2115
2116
2117 /*!
2118  * @brief 後続のモンスター処理が必要かどうか判定する (要調査)
2119  * @param target_ptr プレーヤーへの参照ポインタ
2120  * @param m_ptr モンスターへの参照ポインタ
2121  * @return 後続処理が必要ならTRUE
2122  */
2123 bool decide_process_continue(player_type *target_ptr, monster_type *m_ptr)
2124 {
2125         monster_race *r_ptr;
2126         r_ptr = &r_info[m_ptr->r_idx];
2127         if (!target_ptr->no_flowed)
2128         {
2129                 m_ptr->mflag2 &= ~MFLAG2_NOFLOW;
2130         }
2131
2132         if (m_ptr->cdis <= (is_pet(m_ptr) ? (r_ptr->aaf > MAX_SIGHT ? MAX_SIGHT : r_ptr->aaf) : r_ptr->aaf))
2133                 return TRUE;
2134
2135         if ((m_ptr->cdis <= MAX_SIGHT || target_ptr->phase_out) &&
2136                 (player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx) || (target_ptr->cursed & TRC_AGGRAVATE)))
2137                 return TRUE;
2138
2139         if (m_ptr->target_y)
2140                 return TRUE;
2141
2142         return FALSE;
2143 }