OSDN Git Service

[Refactor] #40030 Separated monster-direction.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-direction.h"
20 #include "monster/monster-object.h"
21 #include "monster/monster-move.h"
22 #include "monster/monster-safety-hiding.h"
23 #include "monster/monster-util.h"
24 #include "monster/monster-update.h"
25 #include "monster/quantum-effect.h"
26
27 #include "cmd-dump.h"
28 #include "cmd-pet.h"
29 #include "creature.h"
30 #include "melee.h"
31 #include "spells.h"
32 #include "spells-floor.h"
33 #include "spells-summon.h"
34 #include "quest.h"
35 #include "avatar.h"
36 #include "realm-hex.h"
37 #include "feature.h"
38 #include "grid.h"
39 #include "player-move.h"
40 #include "monster-status.h"
41 #include "monster-spell.h"
42 #include "monster-process.h"
43 #include "monsterrace-hook.h"
44 #include "floor.h"
45 #include "files.h"
46 #include "view-mainwindow.h"
47
48 void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon);
49 bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx);
50 bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
51 void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx);
52 void process_angar(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m);
53 bool explode_grenade(player_type *target_ptr, MONSTER_IDX m_idx);
54 bool decide_monster_multiplication(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox);
55 bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware);
56 bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr);
57 bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx);
58 bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx);
59 void escape_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, GAME_TEXT *m_name);
60 void process_special(player_type *target_ptr, MONSTER_IDX m_idx);
61 void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware);
62 bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware);
63
64 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);
65 bool process_post_dig_wall(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, POSITION ny, POSITION nx);
66 bool process_monster_fear(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx);
67
68 void sweep_monster_process(player_type *target_ptr);
69 bool decide_process_continue(player_type *target_ptr, monster_type *m_ptr);
70
71 /*!
72  * @brief モンスターがプレイヤーから逃走するかどうかを返す /
73  * Returns whether a given monster will try to run from the player.
74  * @param m_idx 逃走するモンスターの参照ID
75  * @return モンスターがプレイヤーから逃走するならばTRUEを返す。
76  * @details
77  * Monsters will attempt to avoid very powerful players.  See below.\n
78  *\n
79  * Because this function is called so often, little details are important\n
80  * for efficiency.  Like not using "mod" or "div" when possible.  And\n
81  * attempting to check the conditions in an optimal order.  Note that\n
82  * "(x << 2) == (x * 4)" if "x" has enough bits to hold the result.\n
83  *\n
84  * Note that this function is responsible for about one to five percent\n
85  * of the processor use in normal conditions...\n
86  */
87 static bool mon_will_run(player_type *target_ptr, MONSTER_IDX m_idx)
88 {
89         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
90         monster_race *r_ptr = &r_info[m_ptr->r_idx];
91
92         if (is_pet(m_ptr))
93         {
94                 return ((target_ptr->pet_follow_distance < 0) &&
95                         (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
96         }
97
98         if (m_ptr->cdis > MAX_SIGHT + 5) return FALSE;
99         if (MON_MONFEAR(m_ptr)) return TRUE;
100         if (m_ptr->cdis <= 5) return FALSE;
101
102         PLAYER_LEVEL p_lev = target_ptr->lev;
103         DEPTH m_lev = r_ptr->level + (m_idx & 0x08) + 25;
104         if (m_lev > p_lev + 4) return FALSE;
105         if (m_lev + 4 <= p_lev) return TRUE;
106
107         HIT_POINT p_chp = target_ptr->chp;
108         HIT_POINT p_mhp = target_ptr->mhp;
109         HIT_POINT m_chp = m_ptr->hp;
110         HIT_POINT m_mhp = m_ptr->maxhp;
111         u32b p_val = (p_lev * p_mhp) + (p_chp << 2);
112         u32b m_val = (m_lev * m_mhp) + (m_chp << 2);
113         if (p_val * m_mhp > m_val * p_mhp) return TRUE;
114
115         return FALSE;
116 }
117
118
119 /*!
120  * @brief モンスターがプレイヤーに向けて遠距離攻撃を行うことが可能なマスを走査する /
121  * Search spell castable grid
122  * @param target_ptr プレーヤーへの参照ポインタ
123  * @param m_idx モンスターの参照ID
124  * @param yp 適したマスのY座標を返す参照ポインタ
125  * @param xp 適したマスのX座標を返す参照ポインタ
126  * @return 有効なマスがあった場合TRUEを返す
127  */
128 static bool get_moves_aux2(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
129 {
130         floor_type *floor_ptr = target_ptr->current_floor_ptr;
131         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
132         monster_race *r_ptr = &r_info[m_ptr->r_idx];
133
134         POSITION y1 = m_ptr->fy;
135         POSITION x1 = m_ptr->fx;
136
137         if (projectable(target_ptr, y1, x1, target_ptr->y, target_ptr->x)) return FALSE;
138
139         int now_cost = floor_ptr->grid_array[y1][x1].cost;
140         if (now_cost == 0) now_cost = 999;
141
142         bool can_open_door = FALSE;
143         if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
144         {
145                 can_open_door = TRUE;
146         }
147
148         int best = 999;
149         for (int i = 7; i >= 0; i--)
150         {
151                 POSITION y = y1 + ddy_ddd[i];
152                 POSITION x = x1 + ddx_ddd[i];
153                 if (!in_bounds2(floor_ptr, y, x)) continue;
154                 if (player_bold(target_ptr, y, x)) return FALSE;
155
156                 grid_type *g_ptr;
157                 g_ptr = &floor_ptr->grid_array[y][x];
158                 int cost = g_ptr->cost;
159                 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))))
160                 {
161                         if (cost == 0) continue;
162                         if (!can_open_door && is_closed_door(target_ptr, g_ptr->feat)) continue;
163                 }
164
165                 if (cost == 0) cost = 998;
166
167                 if (now_cost < cost) continue;
168                 if (!projectable(target_ptr, y, x, target_ptr->y, target_ptr->x)) continue;
169                 if (best < cost) continue;
170
171                 best = cost;
172                 *yp = y1 + ddy_ddd[i];
173                 *xp = x1 + ddx_ddd[i];
174         }
175
176         if (best == 999) return FALSE;
177
178         return TRUE;
179 }
180
181
182 /*!
183  * @brief モンスターがプレイヤーに向けて接近することが可能なマスを走査する /
184  * Choose the "best" direction for "flowing"
185  * @param m_idx モンスターの参照ID
186  * @param yp 移動先のマスのY座標を返す参照ポインタ
187  * @param xp 移動先のマスのX座標を返す参照ポインタ
188  * @param no_flow モンスターにFLOWフラグが経っていない状態でTRUE
189  * @return 有効なマスがあった場合TRUEを返す
190  * @details
191  * Note that ghosts and rock-eaters are never allowed to "flow",\n
192  * since they should move directly towards the player.\n
193  *\n
194  * Prefer "non-diagonal" directions, but twiddle them a little\n
195  * to angle slightly towards the player's actual location.\n
196  *\n
197  * Allow very perceptive monsters to track old "spoor" left by\n
198  * previous locations occupied by the player.  This will tend\n
199  * to have monsters end up either near the player or on a grid\n
200  * recently occupied by the player (and left via "teleport").\n
201  *\n
202  * Note that if "smell" is turned on, all monsters get vicious.\n
203  *\n
204  * Also note that teleporting away from a location will cause\n
205  * the monsters who were chasing you to converge on that location\n
206  * as long as you are still near enough to "annoy" them without\n
207  * being close enough to chase directly.  I have no idea what will\n
208  * happen if you combine "smell" with low "aaf" values.\n
209  */
210 static bool get_moves_aux(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp, bool no_flow)
211 {
212         grid_type *g_ptr;
213         floor_type *floor_ptr = target_ptr->current_floor_ptr;
214         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
215         monster_race *r_ptr = &r_info[m_ptr->r_idx];
216
217         if (r_ptr->flags4 & (RF4_ATTACK_MASK) ||
218                 r_ptr->a_ability_flags1 & (RF5_ATTACK_MASK) ||
219                 r_ptr->a_ability_flags2 & (RF6_ATTACK_MASK))
220         {
221                 if (get_moves_aux2(target_ptr, m_idx, yp, xp)) return TRUE;
222         }
223
224         if (no_flow) return FALSE;
225         if ((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) return FALSE;
226         if ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)) return FALSE;
227
228         POSITION y1 = m_ptr->fy;
229         POSITION x1 = m_ptr->fx;
230         if (player_has_los_bold(target_ptr, y1, x1) && projectable(target_ptr, target_ptr->y, target_ptr->x, y1, x1)) return FALSE;
231
232         g_ptr = &floor_ptr->grid_array[y1][x1];
233
234         int best;
235         bool use_scent = FALSE;
236         if (g_ptr->cost)
237         {
238                 best = 999;
239         }
240         else if (g_ptr->when)
241         {
242                 if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].when - g_ptr->when > 127) return FALSE;
243
244                 use_scent = TRUE;
245                 best = 0;
246         }
247         else
248         {
249                 return FALSE;
250         }
251
252         for (int i = 7; i >= 0; i--)
253         {
254                 POSITION y = y1 + ddy_ddd[i];
255                 POSITION x = x1 + ddx_ddd[i];
256
257                 if (!in_bounds2(floor_ptr, y, x)) continue;
258
259                 g_ptr = &floor_ptr->grid_array[y][x];
260                 if (use_scent)
261                 {
262                         int when = g_ptr->when;
263                         if (best > when) continue;
264
265                         best = when;
266                 }
267                 else
268                 {
269                         int cost;
270                         if (r_ptr->flags2 & (RF2_BASH_DOOR | RF2_OPEN_DOOR))
271                         {
272                                 cost = g_ptr->dist;
273                         }
274                         else
275                         {
276                                 cost = g_ptr->cost;
277                         }
278
279                         if ((cost == 0) || (best < cost)) continue;
280
281                         best = cost;
282                 }
283
284                 *yp = target_ptr->y + 16 * ddy_ddd[i];
285                 *xp = target_ptr->x + 16 * ddx_ddd[i];
286         }
287
288         if (best == 999 || best == 0) return FALSE;
289
290         return TRUE;
291 }
292
293
294 /*!
295  * @brief モンスターがプレイヤーから逃走することが可能なマスを走査する /
296  * Provide a location to flee to, but give the player a wide berth.
297  * @param m_idx モンスターの参照ID
298  * @param yp 移動先のマスのY座標を返す参照ポインタ
299  * @param xp 移動先のマスのX座標を返す参照ポインタ
300  * @return 有効なマスがあった場合TRUEを返す
301  * @details
302  * A monster may wish to flee to a location that is behind the player,\n
303  * but instead of heading directly for it, the monster should "swerve"\n
304  * around the player so that he has a smaller chance of getting hit.\n
305  */
306 static bool get_fear_moves_aux(floor_type *floor_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
307 {
308         POSITION gy = 0, gx = 0;
309
310         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
311         POSITION fy = m_ptr->fy;
312         POSITION fx = m_ptr->fx;
313
314         POSITION y1 = fy - (*yp);
315         POSITION x1 = fx - (*xp);
316
317         int score = -1;
318         for (int i = 7; i >= 0; i--)
319         {
320                 POSITION y = fy + ddy_ddd[i];
321                 POSITION x = fx + ddx_ddd[i];
322                 if (!in_bounds2(floor_ptr, y, x)) continue;
323
324                 POSITION dis = distance(y, x, y1, x1);
325                 POSITION s = 5000 / (dis + 3) - 500 / (floor_ptr->grid_array[y][x].dist + 1);
326                 if (s < 0) s = 0;
327
328                 if (s < score) continue;
329
330                 score = s;
331                 gy = y;
332                 gx = x;
333         }
334
335         if (score == -1) return FALSE;
336
337         (*yp) = fy - gy;
338         (*xp) = fx - gx;
339
340         return TRUE;
341 }
342
343
344 /*!
345  * todo 分割したいが条件が多すぎて適切な関数名と詳細処理を追いきれない……
346  * @brief モンスターの移動方向を返す /
347  * Choose "logical" directions for monster movement
348  * @param target_ptr プレーヤーへの参照ポインタ
349  * @param m_idx モンスターの参照ID
350  * @param mm 移動方向を返す方向IDの参照ポインタ
351  * @return 有効方向があった場合TRUEを返す
352  */
353 static bool get_moves(player_type *target_ptr, MONSTER_IDX m_idx, DIRECTION *mm)
354 {
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         POSITION y = 0, x = 0;
359         POSITION y2 = target_ptr->y;
360         POSITION x2 = target_ptr->x;
361         bool done = FALSE;
362         bool will_run = mon_will_run(target_ptr, m_idx);
363         grid_type *g_ptr;
364         bool no_flow = ((m_ptr->mflag2 & MFLAG2_NOFLOW) != 0) && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].cost > 2);
365         bool can_pass_wall = ((r_ptr->flags2 & RF2_PASS_WALL) != 0) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall);
366
367         if (!will_run && m_ptr->target_y)
368         {
369                 int t_m_idx = floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
370                 if ((t_m_idx > 0) &&
371                         are_enemies(target_ptr, m_ptr, &floor_ptr->m_list[t_m_idx]) &&
372                         los(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x) &&
373                         projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
374                 {
375                         y = m_ptr->fy - m_ptr->target_y;
376                         x = m_ptr->fx - m_ptr->target_x;
377                         done = TRUE;
378                 }
379         }
380
381         if (!done && !will_run && is_hostile(m_ptr) &&
382                 (r_ptr->flags1 & RF1_FRIENDS) &&
383                 ((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)) ||
384                 (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < MAX_SIGHT / 2)))
385         {
386                 if ((r_ptr->flags3 & RF3_ANIMAL) && !can_pass_wall &&
387                         !(r_ptr->flags2 & RF2_KILL_WALL))
388                 {
389                         int room = 0;
390                         for (int i = 0; i < 8; i++)
391                         {
392                                 int xx = target_ptr->x + ddx_ddd[i];
393                                 int yy = target_ptr->y + ddy_ddd[i];
394
395                                 if (!in_bounds2(floor_ptr, yy, xx)) continue;
396
397                                 g_ptr = &floor_ptr->grid_array[yy][xx];
398                                 if (monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, 0))
399                                 {
400                                         room++;
401                                 }
402                         }
403
404                         if (floor_ptr->grid_array[target_ptr->y][target_ptr->x].info & CAVE_ROOM) room -= 2;
405                         if (!r_ptr->flags4 && !r_ptr->a_ability_flags1 && !r_ptr->a_ability_flags2) room -= 2;
406
407                         if (room < (8 * (target_ptr->chp + target_ptr->csp)) /
408                                 (target_ptr->mhp + target_ptr->msp))
409                         {
410                                 if (find_hiding(target_ptr, m_idx, &y, &x)) done = TRUE;
411                         }
412                 }
413
414                 if (!done && (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].dist < 3))
415                 {
416                         for (int i = 0; i < 8; i++)
417                         {
418                                 y2 = target_ptr->y + ddy_ddd[(m_idx + i) & 7];
419                                 x2 = target_ptr->x + ddx_ddd[(m_idx + i) & 7];
420                                 if ((m_ptr->fy == y2) && (m_ptr->fx == x2))
421                                 {
422                                         y2 = target_ptr->y;
423                                         x2 = target_ptr->x;
424                                         break;
425                                 }
426
427                                 if (!in_bounds2(floor_ptr, y2, x2)) continue;
428                                 if (!monster_can_enter(target_ptr, y2, x2, r_ptr, 0)) continue;
429
430                                 break;
431                         }
432
433                         y = m_ptr->fy - y2;
434                         x = m_ptr->fx - x2;
435                         done = TRUE;
436                 }
437         }
438
439         if (!done)
440         {
441                 (void)get_moves_aux(target_ptr, m_idx, &y2, &x2, no_flow);
442                 y = m_ptr->fy - y2;
443                 x = m_ptr->fx - x2;
444         }
445
446         if (is_pet(m_ptr) && will_run)
447         {
448                 y = (-y), x = (-x);
449         }
450         else
451         {
452                 if (!done && will_run)
453                 {
454                         int tmp_x = (-x);
455                         int tmp_y = (-y);
456                         if (find_safety(target_ptr, m_idx, &y, &x) && !no_flow)
457                         {
458                                 if (get_fear_moves_aux(target_ptr->current_floor_ptr, m_idx, &y, &x))
459                                         done = TRUE;
460                         }
461
462                         if (!done)
463                         {
464                                 y = tmp_y;
465                                 x = tmp_x;
466                         }
467                 }
468         }
469
470         if (!x && !y) return FALSE;
471
472         store_moves_val(mm, y, x);
473         return TRUE;
474 }
475
476
477 /*!
478  * @brief モンスター単体の1ターン行動処理メインルーチン /
479  * Process a monster
480  * @param target_ptr プレーヤーへの参照ポインタ
481  * @param m_idx 行動モンスターの参照ID
482  * @return なし
483  * @details
484  * The monster is known to be within 100 grids of the player\n
485  *\n
486  * In several cases, we directly update the monster lore\n
487  *\n
488  * Note that a monster is only allowed to "reproduce" if there\n
489  * are a limited number of "reproducing" monsters on the current\n
490  * level.  This should prevent the level from being "swamped" by\n
491  * reproducing monsters.  It also allows a large mass of mice to\n
492  * prevent a louse from multiplying, but this is a small price to\n
493  * pay for a simple multiplication method.\n
494  *\n
495  * XXX Monster fear is slightly odd, in particular, monsters will\n
496  * fixate on opening a door even if they cannot open it.  Actually,\n
497  * the same thing happens to normal monsters when they hit a door\n
498  *\n
499  * In addition, monsters which *cannot* open or bash\n
500  * down a door will still stand there trying to open it...\n
501  *\n
502  * XXX Technically, need to check for monster in the way\n
503  * combined with that monster being in a wall (or door?)\n
504  *\n
505  * A "direction" of "5" means "pick a random direction".\n
506  */
507 void process_monster(player_type *target_ptr, MONSTER_IDX m_idx)
508 {
509         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
510         monster_race *r_ptr = &r_info[m_ptr->r_idx];
511         turn_flags tmp_flags;
512         turn_flags *turn_flags_ptr = init_turn_flags(target_ptr->riding, m_idx, &tmp_flags);
513         turn_flags_ptr->see_m = is_seen(m_ptr);
514
515         decide_drop_from_monster(target_ptr, m_idx, turn_flags_ptr->is_riding_mon);
516         if ((m_ptr->mflag2 & MFLAG2_CHAMELEON) && one_in_(13) && !MON_CSLEEP(m_ptr))
517         {
518                 choose_new_monster(target_ptr, m_idx, FALSE, 0);
519                 r_ptr = &r_info[m_ptr->r_idx];
520         }
521
522         turn_flags_ptr->aware = process_stealth(target_ptr, m_idx);
523         if (vanish_summoned_children(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
524         if (process_quantum_effect(target_ptr, m_idx, turn_flags_ptr->see_m)) return;
525         if (explode_grenade(target_ptr, m_idx)) return;
526         if (runaway_monster(target_ptr, turn_flags_ptr, m_idx)) return;
527
528         awake_monster(target_ptr, m_idx);
529         if (MON_STUNNED(m_ptr))
530         {
531                 if (one_in_(2)) return;
532         }
533
534         if (turn_flags_ptr->is_riding_mon)
535         {
536                 target_ptr->update |= (PU_BONUS);
537         }
538
539         process_angar(target_ptr, m_idx, turn_flags_ptr->see_m);
540
541         POSITION oy = m_ptr->fy;
542         POSITION ox = m_ptr->fx;
543         if (decide_monster_multiplication(target_ptr, m_idx, oy, ox)) return;
544
545         process_special(target_ptr, m_idx);
546         process_speak_sound(target_ptr, m_idx, oy, ox, turn_flags_ptr->aware);
547         if (cast_spell(target_ptr, m_idx, turn_flags_ptr->aware)) return;
548
549         DIRECTION mm[8];
550         mm[0] = mm[1] = mm[2] = mm[3] = 0;
551         mm[4] = mm[5] = mm[6] = mm[7] = 0;
552
553         if (!decide_monster_movement_direction(target_ptr, mm, m_idx, turn_flags_ptr->aware)) return;
554
555         int count = 0;
556         if (!process_monster_movement(target_ptr, turn_flags_ptr, m_idx, mm, oy, ox, &count)) return;
557
558         /*
559          *  Forward movements failed, but now received LOS attack!
560          *  Try to flow by smell.
561          */
562         if (target_ptr->no_flowed && count > 2 && m_ptr->target_y)
563                 m_ptr->mflag2 &= ~MFLAG2_NOFLOW;
564
565         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)
566         {
567                 if (r_ptr->freq_spell && randint1(100) <= r_ptr->freq_spell)
568                 {
569                         if (make_attack_spell(m_idx, target_ptr)) return;
570                 }
571         }
572
573         update_player_type(target_ptr, turn_flags_ptr, r_ptr);
574         update_monster_race_flags(target_ptr, turn_flags_ptr, m_ptr);
575
576         if (!process_monster_fear(target_ptr, turn_flags_ptr, m_idx)) return;
577
578         if (m_ptr->ml) chg_virtue(target_ptr, V_COMPASSION, -1);
579 }
580
581
582 /*!
583  * @brief 超隠密処理
584  * @param target_ptr プレーヤーへの参照ポインタ
585  * @param m_idx モンスターID
586  * @return モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
587  */
588 bool process_stealth(player_type *target_ptr, MONSTER_IDX m_idx)
589 {
590         if ((target_ptr->special_defense & NINJA_S_STEALTH) == 0) return TRUE;
591
592         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
593         monster_race *r_ptr = &r_info[m_ptr->r_idx];
594         int tmp = target_ptr->lev * 6 + (target_ptr->skill_stl + 10) * 4;
595         if (target_ptr->monlite) tmp /= 3;
596         if (target_ptr->cursed & TRC_AGGRAVATE) tmp /= 2;
597         if (r_ptr->level > (target_ptr->lev * target_ptr->lev / 20 + 10)) tmp /= 3;
598         return (randint0(tmp) <= (r_ptr->level + 20));
599 }
600
601
602 /*!
603  * @brief 死亡したモンスターが乗馬中のモンスターだった場合に落馬処理を行う
604  * @param target_ptr プレーヤーへの参照ポインタ
605  * @param m_idx モンスターID
606  * @param is_riding_mon 騎乗中であればTRUE
607  * @return なし
608  */
609 void decide_drop_from_monster(player_type *target_ptr, MONSTER_IDX m_idx, bool is_riding_mon)
610 {
611         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
612         monster_race *r_ptr = &r_info[m_ptr->r_idx];
613         if (!is_riding_mon || ((r_ptr->flags7 & RF7_RIDING) != 0)) return;
614
615         if (rakuba(target_ptr, 0, TRUE))
616         {
617 #ifdef JP
618                 msg_print("地面に落とされた。");
619 #else
620                 GAME_TEXT m_name[MAX_NLEN];
621                 monster_desc(target_ptr, m_name, &target_ptr->current_floor_ptr->m_list[target_ptr->riding], 0);
622                 msg_format("You have fallen from %s.", m_name);
623 #endif
624         }
625 }
626
627
628 /*!
629  * @brief 召喚の親元が消滅した時、子供も消滅させる
630  * @param target_ptr プレーヤーへの参照ポインタ
631  * @param m_idx モンスターID
632  * @param see_m モンスターが視界内にいたらTRUE
633  * @return 召喚モンスターが消滅したらTRUE
634  */
635 bool vanish_summoned_children(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
636 {
637         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
638         if ((m_ptr->parent_m_idx == 0) || (target_ptr->current_floor_ptr->m_list[m_ptr->parent_m_idx].r_idx > 0))
639                 return FALSE;
640
641         if (see_m)
642         {
643                 GAME_TEXT m_name[MAX_NLEN];
644                 monster_desc(target_ptr, m_name, m_ptr, 0);
645                 msg_format(_("%sは消え去った!", "%^s disappears!"), m_name);
646         }
647
648         if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname)
649         {
650                 GAME_TEXT m_name[MAX_NLEN];
651                 monster_desc(target_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
652                 exe_write_diary(target_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_LOSE_PARENT, m_name);
653         }
654
655         delete_monster_idx(target_ptr, m_idx);
656         return TRUE;
657 }
658
659
660 /*!
661  * @brief 寝ているモンスターの起床を判定する
662  * @param target_ptr プレーヤーへの参照ポインタ
663  * @param m_idx モンスターID
664  * @return なし
665  */
666 void awake_monster(player_type *target_ptr, MONSTER_IDX m_idx)
667 {
668         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
669         monster_race *r_ptr = &r_info[m_ptr->r_idx];
670         if (!MON_CSLEEP(m_ptr)) return;
671         if (!(target_ptr->cursed & TRC_AGGRAVATE)) return;
672
673         (void)set_monster_csleep(target_ptr, m_idx, 0);
674         if (m_ptr->ml)
675         {
676                 GAME_TEXT m_name[MAX_NLEN];
677                 monster_desc(target_ptr, m_name, m_ptr, 0);
678                 msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
679         }
680
681         if (is_original_ap_and_seen(target_ptr, m_ptr) && (r_ptr->r_wake < MAX_UCHAR))
682         {
683                 r_ptr->r_wake++;
684         }
685 }
686
687
688 /*!
689  * @brief モンスターの怒り状態を判定する (起こっていたら敵に回す)
690  * @param target_ptr プレーヤーへの参照ポインタ
691  * @param m_idx モンスターID
692  * @param see_m モンスターが視界内にいたらTRUE
693  * @return なし
694  */
695 void process_angar(player_type *target_ptr, MONSTER_IDX m_idx, bool see_m)
696 {
697         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
698         monster_race *r_ptr = &r_info[m_ptr->r_idx];
699         bool gets_angry = FALSE;
700         if (is_friendly(m_ptr) && (target_ptr->cursed & TRC_AGGRAVATE))
701                 gets_angry = TRUE;
702
703         if (is_pet(m_ptr) && ((((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) &&
704                 monster_has_hostile_align(target_ptr, NULL, 10, -10, r_ptr)) || (r_ptr->flagsr & RFR_RES_ALL)))
705         {
706                 gets_angry = TRUE;
707         }
708
709         if (target_ptr->phase_out || !gets_angry) return;
710
711         if (is_pet(m_ptr) || see_m)
712         {
713                 GAME_TEXT m_name[MAX_NLEN];
714                 monster_desc(target_ptr, m_name, m_ptr, is_pet(m_ptr) ? MD_ASSUME_VISIBLE : 0);
715                 msg_format(_("%^sは突然敵にまわった!", "%^s suddenly becomes hostile!"), m_name);
716         }
717
718         set_hostile(target_ptr, m_ptr);
719 }
720
721
722 /*!
723  * @brief 手榴弾の爆発処理
724  * @param target_ptr プレーヤーへの参照ポインタ
725  * @param m_idx モンスターID
726  * @return 爆死したらTRUE
727  */
728 bool explode_grenade(player_type *target_ptr, MONSTER_IDX m_idx)
729 {
730         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
731         if (m_ptr->r_idx != MON_GRENADE) return FALSE;
732
733         bool fear, dead;
734         mon_take_hit_mon(target_ptr, m_idx, 1, &dead, &fear, _("は爆発して粉々になった。", " explodes into tiny shreds."), m_idx);
735         return dead;
736 }
737
738
739 /*!
740  * @brief モンスター依存の特別な行動を取らせる
741  * @param target_ptr プレーヤーへの参照ポインタ
742  * @param m_idx モンスターID
743  * @return なし
744  */
745 void process_special(player_type *target_ptr, MONSTER_IDX m_idx)
746 {
747         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
748         monster_race *r_ptr = &r_info[m_ptr->r_idx];
749         if ((r_ptr->a_ability_flags2 & RF6_SPECIAL) == 0) return;
750         if (m_ptr->r_idx != MON_OHMU) return;
751         if (target_ptr->current_floor_ptr->inside_arena || target_ptr->phase_out) return;
752         if ((r_ptr->freq_spell == 0) || !(randint1(100) <= r_ptr->freq_spell)) return;
753
754         int count = 0;
755         DEPTH rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
756         BIT_FLAGS p_mode = is_pet(m_ptr) ? PM_FORCE_PET : 0L;
757
758         for (int k = 0; k < A_MAX; k++)
759         {
760                 if (summon_specific(target_ptr, m_idx, m_ptr->fy, m_ptr->fx, rlev, SUMMON_MOLD, (PM_ALLOW_GROUP | p_mode)))
761                 {
762                         if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml) count++;
763                 }
764         }
765
766         if (count && is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags6 |= (RF6_SPECIAL);
767 }
768
769
770 /*!
771  * @brief モンスターを喋らせたり足音を立てたりする
772  * @param target_ptr プレーヤーへの参照ポインタ
773  * @param m_idx モンスターID
774  * @param oy モンスターが元々いたY座標
775  * @param ox モンスターが元々いたX座標
776  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
777  * @return なし
778  */
779 void process_speak_sound(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox, bool aware)
780 {
781         if (target_ptr->phase_out) return;
782
783         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
784         monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
785         if (m_ptr->ap_r_idx == MON_CYBER &&
786                 one_in_(CYBERNOISE) &&
787                 !m_ptr->ml && (m_ptr->cdis <= MAX_SIGHT))
788         {
789                 if (disturb_minor) disturb(target_ptr, FALSE, FALSE);
790                 msg_print(_("重厚な足音が聞こえた。", "You hear heavy steps."));
791         }
792
793         if (((ap_r_ptr->flags2 & RF2_CAN_SPEAK) == 0) || !aware ||
794                 !one_in_(SPEAK_CHANCE) ||
795                 !player_has_los_bold(target_ptr, oy, ox) ||
796                 !projectable(target_ptr, oy, ox, target_ptr->y, target_ptr->x))
797                 return;
798
799         GAME_TEXT m_name[MAX_NLEN];
800         char monmessage[1024];
801         concptr filename;
802
803         if (m_ptr->ml)
804                 monster_desc(target_ptr, m_name, m_ptr, 0);
805         else
806                 strcpy(m_name, _("それ", "It"));
807
808         if (MON_MONFEAR(m_ptr))
809                 filename = _("monfear_j.txt", "monfear.txt");
810         else if (is_pet(m_ptr))
811                 filename = _("monpet_j.txt", "monpet.txt");
812         else if (is_friendly(m_ptr))
813                 filename = _("monfrien_j.txt", "monfrien.txt");
814         else
815                 filename = _("monspeak_j.txt", "monspeak.txt");
816
817         if (get_rnd_line(filename, m_ptr->ap_r_idx, monmessage) == 0)
818         {
819                 msg_format(_("%^s%s", "%^s %s"), m_name, monmessage);
820         }
821 }
822
823
824 /*!
825  * @brief モンスターを分裂させるかどうかを決定する (分裂もさせる)
826  * @param target_ptr プレーヤーへの参照ポインタ
827  * @param m_idx モンスターID
828  * @param oy 分裂元モンスターのY座標
829  * @param ox 分裂元モンスターのX座標
830  * @return 実際に分裂したらTRUEを返す
831  */
832 bool decide_monster_multiplication(player_type *target_ptr, MONSTER_IDX m_idx, POSITION oy, POSITION ox)
833 {
834         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
835         monster_race *r_ptr = &r_info[m_ptr->r_idx];
836         if (((r_ptr->flags2 & RF2_MULTIPLY) == 0) || (target_ptr->current_floor_ptr->num_repro >= MAX_REPRO))
837                 return FALSE;
838
839         int k = 0;
840         for (POSITION y = oy - 1; y <= oy + 1; y++)
841         {
842                 for (POSITION x = ox - 1; x <= ox + 1; x++)
843                 {
844                         if (!in_bounds2(target_ptr->current_floor_ptr, y, x)) continue;
845                         if (target_ptr->current_floor_ptr->grid_array[y][x].m_idx) k++;
846                 }
847         }
848
849         if (multiply_barrier(target_ptr, m_idx)) k = 8;
850
851         if ((k < 4) && (!k || !randint0(k * MON_MULT_ADJ)))
852         {
853                 if (multiply_monster(target_ptr, m_idx, FALSE, (is_pet(m_ptr) ? PM_FORCE_PET : 0)))
854                 {
855                         if (target_ptr->current_floor_ptr->m_list[hack_m_idx_ii].ml && is_original_ap_and_seen(target_ptr, m_ptr))
856                         {
857                                 r_ptr->r_flags2 |= (RF2_MULTIPLY);
858                         }
859
860                         return TRUE;
861                 }
862         }
863
864         return FALSE;
865 }
866
867
868 /*!
869  * @brief モンスターの移動パターンを決定する
870  * @param target_ptr プレーヤーへの参照ポインタ
871  * @param mm 移動方向
872  * @param m_idx モンスターID
873  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
874  * @return 移動先が存在すればTRUE
875  */
876 bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware)
877 {
878         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
879         monster_race *r_ptr = &r_info[m_ptr->r_idx];
880
881         if (MON_CONFUSED(m_ptr) || !aware)
882         {
883                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
884                 return TRUE;
885         }
886
887         if (random_walk(target_ptr, mm, m_ptr)) return TRUE;
888
889         if ((r_ptr->flags1 & RF1_NEVER_MOVE) && (m_ptr->cdis > 1))
890         {
891                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
892                 return TRUE;
893         }
894
895         if (decide_pet_movement_direction(target_ptr, mm, m_idx)) return TRUE;
896
897         if (!is_hostile(m_ptr))
898         {
899                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
900                 get_enemy_dir(target_ptr, m_idx, mm);
901                 return TRUE;
902         }
903
904         if (!get_moves(target_ptr, m_idx, mm)) return FALSE;
905
906         return TRUE;
907 }
908
909
910 /*!
911  * todo ↓のように書いたが、"5"とはもしかして「その場に留まる」という意味か?
912  * @brief 不規則歩行フラグを持つモンスターの移動方向をその確率に基づいて決定する
913  * @param target_ptr プレーヤーへの参照ポインタ
914  * @param mm 移動方向
915  * @param m_ptr モンスターへの参照ポインタ
916  * @return 不規則な方向へ歩くことになったらTRUE
917  */
918 bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr)
919 {
920         monster_race *r_ptr = &r_info[m_ptr->r_idx];
921         if (((r_ptr->flags1 & (RF1_RAND_50 | RF1_RAND_25)) == (RF1_RAND_50 | RF1_RAND_25)) && (randint0(100) < 75))
922         {
923                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= (RF1_RAND_50 | RF1_RAND_25);
924
925                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
926                 return TRUE;
927         }
928
929         if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 50))
930         {
931                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_50;
932
933                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
934                 return TRUE;
935         }
936
937         if ((r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 25))
938         {
939                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_25;
940
941                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
942                 return TRUE;
943         }
944
945         return FALSE;
946 }
947
948
949 /*!
950  * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
951  * @param target_ptr プレーヤーへの参照ポインタ
952  * @param mm 移動方向
953  * @param m_idx モンスターID
954  * @return モンスターがペットであればTRUE
955  */
956 bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx)
957 {
958         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
959         if (!is_pet(m_ptr)) return FALSE;
960
961         bool avoid = ((target_ptr->pet_follow_distance < 0) && (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
962         bool lonely = (!avoid && (m_ptr->cdis > target_ptr->pet_follow_distance));
963         bool distant = (m_ptr->cdis > PET_SEEK_DIST);
964         mm[0] = mm[1] = mm[2] = mm[3] = 5;
965         if (get_enemy_dir(target_ptr, m_idx, mm)) return TRUE;
966         if (!avoid && !lonely && !distant) return TRUE;
967
968         POSITION dis = target_ptr->pet_follow_distance;
969         if (target_ptr->pet_follow_distance > PET_SEEK_DIST)
970         {
971                 target_ptr->pet_follow_distance = PET_SEEK_DIST;
972         }
973
974         (void)get_moves(target_ptr, m_idx, mm);
975         target_ptr->pet_follow_distance = (s16b)dis;
976         return TRUE;
977 }
978
979
980 /*!
981  * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
982  * @param target_ptr プレーヤーへの参照ポインタ
983  * @param m_idx モンスターID
984  * @param is_riding_mon 騎乗状態ならばTRUE
985  * @param see_m モンスターが視界内にいたらTRUE
986  * @return モンスターがフロアから消えたらTRUE
987  */
988 bool runaway_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx)
989 {
990         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
991         monster_race *r_ptr = &r_info[m_ptr->r_idx];
992         bool can_runaway = is_pet(m_ptr) || is_friendly(m_ptr);
993         can_runaway &= ((r_ptr->flags1 & RF1_UNIQUE) != 0) || ((r_ptr->flags7 & RF7_NAZGUL) != 0);
994         can_runaway &= !target_ptr->phase_out;
995         if (!can_runaway) return FALSE;
996
997         static int riding_pinch = 0;
998
999         if (m_ptr->hp >= m_ptr->maxhp / 3)
1000         {
1001                 /* Reset the counter */
1002                 if (turn_flags_ptr->is_riding_mon) riding_pinch = 0;
1003
1004                 return FALSE;
1005         }
1006
1007         GAME_TEXT m_name[MAX_NLEN];
1008         monster_desc(target_ptr, m_name, m_ptr, 0);
1009         if (turn_flags_ptr->is_riding_mon && riding_pinch < 2)
1010         {
1011                 msg_format(_("%sは傷の痛さの余りあなたの束縛から逃れようとしている。",
1012                         "%^s seems to be in so much pain and tries to escape from your restriction."), m_name);
1013                 riding_pinch++;
1014                 disturb(target_ptr, TRUE, TRUE);
1015                 return FALSE;
1016         }
1017
1018         escape_monster(target_ptr, turn_flags_ptr, m_ptr, m_name);
1019         check_quest_completion(target_ptr, m_ptr);
1020         delete_monster_idx(target_ptr, m_idx);
1021         return TRUE;
1022 }
1023
1024
1025 /*!
1026  * @brief HPが1/3未満になった有効的なユニークモンスターの逃走処理を行う
1027  * @param target_ptr プレーヤーへの参照ポインタ
1028  * @param is_riding_mon 騎乗状態ならばTRUE
1029  * @param m_ptr モンスターへの参照ポインタ
1030  * @param m_name モンスター名称
1031  * @param see_m モンスターが視界内にいたらTRUE
1032  * @return なし
1033  */
1034 void escape_monster(player_type *target_ptr, turn_flags *turn_flags_ptr, monster_type *m_ptr, GAME_TEXT *m_name)
1035 {
1036         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1037         if (turn_flags_ptr->is_riding_mon)
1038         {
1039                 msg_format(_("%sはあなたの束縛から脱出した。", "%^s succeeded to escape from your restriction!"), m_name);
1040                 if (rakuba(target_ptr, -1, FALSE))
1041                 {
1042                         msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
1043                 }
1044         }
1045
1046         if (turn_flags_ptr->see_m)
1047         {
1048                 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) &&
1049                         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))
1050                 {
1051                         msg_format(_("%^s「ピンチだ!退却させてもらう!」", "%^s says 'It is the pinch! I will retreat'."), m_name);
1052                 }
1053
1054                 msg_format(_("%^sがテレポート・レベルの巻物を読んだ。", "%^s reads a scroll of teleport level."), m_name);
1055                 msg_format(_("%^sが消え去った。", "%^s disappears."), m_name);
1056         }
1057
1058         if (turn_flags_ptr->is_riding_mon && rakuba(target_ptr, -1, FALSE))
1059         {
1060                 msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
1061         }
1062 }
1063
1064
1065 /*!
1066  * @brief モンスターに魔法を試行させる
1067  * @param target_ptr プレーヤーへの参照ポインタ
1068  * @param m_idx モンスターID
1069  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1070  * @return 魔法を唱えられなければ強制的にFALSE、その後モンスターが実際に魔法を唱えればTRUE
1071  */
1072 bool cast_spell(player_type *target_ptr, MONSTER_IDX m_idx, bool aware)
1073 {
1074         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1075         monster_race *r_ptr = &r_info[m_ptr->r_idx];
1076         if ((r_ptr->freq_spell == 0) || (randint1(100) > r_ptr->freq_spell))
1077                 return FALSE;
1078
1079         bool counterattack = FALSE;
1080         if (m_ptr->target_y)
1081         {
1082                 MONSTER_IDX t_m_idx = target_ptr->current_floor_ptr->grid_array[m_ptr->target_y][m_ptr->target_x].m_idx;
1083                 if (t_m_idx && are_enemies(target_ptr, m_ptr, &target_ptr->current_floor_ptr->m_list[t_m_idx]) &&
1084                         projectable(target_ptr, m_ptr->fy, m_ptr->fx, m_ptr->target_y, m_ptr->target_x))
1085                 {
1086                         counterattack = TRUE;
1087                 }
1088         }
1089
1090         if (counterattack)
1091         {
1092                 if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
1093                 if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
1094         }
1095         else
1096         {
1097                 if (aware && make_attack_spell(m_idx, target_ptr)) return TRUE;
1098                 if (monst_spell_monst(target_ptr, m_idx)) return TRUE;
1099         }
1100
1101         return FALSE;
1102 }
1103
1104
1105 /*!
1106  * todo 少し長いが、これといってブロックとしてまとまった部分もないので暫定でこのままとする
1107  * @brief モンスターの移動に関するメインルーチン
1108  * @param target_ptr プレーヤーへの参照ポインタ
1109  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1110  * @param m_idx モンスターID
1111  * @param mm モンスターの移動方向
1112  * @param oy 移動前の、モンスターのY座標
1113  * @param ox 移動前の、モンスターのX座標
1114  * @param count 移動回数 (のはず todo)
1115  * @return 移動が阻害される何か (ドア等)があったらFALSE
1116  */
1117 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)
1118 {
1119         for (int i = 0; mm[i]; i++)
1120         {
1121                 int d = mm[i];
1122                 if (d == 5) d = ddd[randint0(8)];
1123
1124                 POSITION ny = oy + ddy[d];
1125                 POSITION nx = ox + ddx[d];
1126                 if (!in_bounds2(target_ptr->current_floor_ptr, ny, nx)) continue;
1127
1128                 grid_type *g_ptr;
1129                 g_ptr = &target_ptr->current_floor_ptr->grid_array[ny][nx];
1130                 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1131                 monster_race *r_ptr = &r_info[m_ptr->r_idx];
1132                 bool can_cross = monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0);
1133
1134                 if (!process_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx, can_cross))
1135                 {
1136                         if (!process_door(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1137                                 return FALSE;
1138                 }
1139
1140                 if (!process_protection_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1141                 {
1142                         if (!process_explosive_rune(target_ptr, turn_flags_ptr, m_ptr, ny, nx))
1143                                 return FALSE;
1144                 }
1145
1146                 exe_monster_attack_to_player(target_ptr, turn_flags_ptr, m_idx, ny, nx);
1147                 if (process_monster_attack_to_monster(target_ptr, turn_flags_ptr, m_idx, g_ptr, can_cross)) return FALSE;
1148
1149                 if (turn_flags_ptr->is_riding_mon)
1150                 {
1151                         if (!target_ptr->riding_ryoute && !MON_MONFEAR(&target_ptr->current_floor_ptr->m_list[target_ptr->riding])) turn_flags_ptr->do_move = FALSE;
1152                 }
1153
1154                 if (!process_post_dig_wall(target_ptr, turn_flags_ptr, m_ptr, ny, nx)) return FALSE;
1155
1156                 if (turn_flags_ptr->must_alter_to_move && (r_ptr->flags7 & RF7_AQUATIC))
1157                 {
1158                         if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, turn_flags_ptr->is_riding_mon ? CEM_RIDING : 0))
1159                                 turn_flags_ptr->do_move = FALSE;
1160                 }
1161
1162                 if (turn_flags_ptr->do_move && !can_cross && !turn_flags_ptr->did_kill_wall && !turn_flags_ptr->did_bash_door)
1163                         turn_flags_ptr->do_move = FALSE;
1164
1165                 if (turn_flags_ptr->do_move && (r_ptr->flags1 & RF1_NEVER_MOVE))
1166                 {
1167                         if (is_original_ap_and_seen(target_ptr, m_ptr))
1168                                 r_ptr->r_flags1 |= (RF1_NEVER_MOVE);
1169
1170                         turn_flags_ptr->do_move = FALSE;
1171                 }
1172
1173                 if (!turn_flags_ptr->do_move)
1174                 {
1175                         if (turn_flags_ptr->do_turn) break;
1176
1177                         continue;
1178                 }
1179
1180                 turn_flags_ptr->do_turn = TRUE;
1181                 feature_type *f_ptr;
1182                 f_ptr = &f_info[g_ptr->feat];
1183                 if (have_flag(f_ptr->flags, FF_TREE))
1184                 {
1185                         if (!(r_ptr->flags7 & RF7_CAN_FLY) && !(r_ptr->flags8 & RF8_WILD_WOOD))
1186                         {
1187                                 m_ptr->energy_need += ENERGY_NEED();
1188                         }
1189                 }
1190
1191                 if (!update_riding_monster(target_ptr, turn_flags_ptr, m_idx, oy, ox, ny, nx)) break;
1192
1193                 monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
1194                 if (m_ptr->ml &&
1195                         (disturb_move ||
1196                         (disturb_near && (m_ptr->mflag & MFLAG_VIEW) && projectable(target_ptr, target_ptr->y, target_ptr->x, m_ptr->fy, m_ptr->fx)) ||
1197                                 (disturb_high && ap_r_ptr->r_tkills && ap_r_ptr->level >= target_ptr->lev)))
1198                 {
1199                         if (is_hostile(m_ptr))
1200                                 disturb(target_ptr, FALSE, TRUE);
1201                 }
1202
1203                 bool is_takable_or_killable = g_ptr->o_idx > 0;
1204                 is_takable_or_killable &= (r_ptr->flags2 & (RF2_TAKE_ITEM | RF2_KILL_ITEM)) != 0;
1205
1206                 bool is_pickup_items = (target_ptr->pet_extra_flags & PF_PICKUP_ITEMS) != 0;
1207                 is_pickup_items &= (r_ptr->flags2 & RF2_TAKE_ITEM) != 0;
1208
1209                 is_takable_or_killable &= !is_pet(m_ptr) || is_pickup_items;
1210                 if (!is_takable_or_killable)
1211                 {
1212                         if (turn_flags_ptr->do_turn) break;
1213
1214                         continue;
1215                 }
1216
1217                 update_object_by_monster_movement(target_ptr, turn_flags_ptr, m_idx, ny, nx);
1218                 if (turn_flags_ptr->do_turn) break;
1219
1220                 (*count)++;
1221         }
1222
1223         return TRUE;
1224 }
1225
1226
1227 /*!
1228  * @brief モンスターの恐怖状態を処理する
1229  * @param target_ptr プレーヤーへの参照ポインタ
1230  * @param turn_flags_ptr ターン経過処理フラグへの参照ポインタ
1231  * @param m_idx モンスターID
1232  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
1233  * @return モンスターが戦いを決意したらTRUE
1234  */
1235 bool process_monster_fear(player_type *target_ptr, turn_flags *turn_flags_ptr, MONSTER_IDX m_idx)
1236 {
1237         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
1238         bool is_battle_determined = !turn_flags_ptr->do_turn && !turn_flags_ptr->do_move && MON_MONFEAR(m_ptr) && turn_flags_ptr->aware;
1239         if (!is_battle_determined) return FALSE;
1240
1241         (void)set_monster_monfear(target_ptr, m_idx, 0);
1242         if (!turn_flags_ptr->see_m) return TRUE;
1243
1244         GAME_TEXT m_name[MAX_NLEN];
1245         monster_desc(target_ptr, m_name, m_ptr, 0);
1246         msg_format(_("%^sは戦いを決意した!", "%^s turns to fight!"), m_name);
1247         return TRUE;
1248 }
1249
1250
1251 /*!
1252  * @brief 全モンスターのターン管理メインルーチン /
1253  * Process all the "live" monsters, once per game turn.
1254  * @return なし
1255  * @details
1256  * During each game current game turn, we scan through the list of all the "live" monsters,\n
1257  * (backwards, so we can excise any "freshly dead" monsters), energizing each\n
1258  * monster, and allowing fully energized monsters to move, attack, pass, etc.\n
1259  *\n
1260  * Note that monsters can never move in the monster array (except when the\n
1261  * "compact_monsters()" function is called by "dungeon()" or "save_player()").\n
1262  *\n
1263  * This function is responsible for at least half of the processor time\n
1264  * on a normal system with a "normal" amount of monsters and a player doing\n
1265  * normal things.\n
1266  *\n
1267  * When the player is resting, virtually 90% of the processor time is spent\n
1268  * in this function, and its children, "process_monster()" and "make_move()".\n
1269  *\n
1270  * Most of the rest of the time is spent in "update_view()" and "lite_spot()",\n
1271  * especially when the player is running.\n
1272  *\n
1273  * Note the special "MFLAG_BORN" flag, which allows us to ignore "fresh"\n
1274  * monsters while they are still being "born".  A monster is "fresh" only\n
1275  * during the game turn in which it is created, and we use the "hack_m_idx" to\n
1276  * determine if the monster is yet to be processed during the game turn.\n
1277  *\n
1278  * Note the special "MFLAG_NICE" flag, which allows the player to get one\n
1279  * move before any "nasty" monsters get to use their spell attacks.\n
1280  *\n
1281  * Note that when the "knowledge" about the currently tracked monster\n
1282  * changes (flags, attacks, spells), we induce a redraw of the monster\n
1283  * recall window.\n
1284  */
1285 void process_monsters(player_type *target_ptr)
1286 {
1287         old_race_flags tmp_flags;
1288         old_race_flags *old_race_flags_ptr = init_old_race_flags(&tmp_flags);
1289
1290         floor_type *floor_ptr = target_ptr->current_floor_ptr;
1291         floor_ptr->monster_noise = FALSE;
1292
1293         MONRACE_IDX old_monster_race_idx = target_ptr->monster_race_idx;
1294         save_old_race_flags(target_ptr->monster_race_idx, old_race_flags_ptr);
1295         sweep_monster_process(target_ptr);
1296
1297         hack_m_idx = 0;
1298         if (!target_ptr->monster_race_idx || (target_ptr->monster_race_idx != old_monster_race_idx))
1299                 return;
1300
1301         update_player_window(target_ptr, old_race_flags_ptr);
1302 }
1303
1304
1305 /*!
1306  * @brief フロア内のモンスターについてターン終了時の処理を繰り返す
1307  * @param target_ptr プレーヤーへの参照ポインタ
1308  */
1309 void sweep_monster_process(player_type *target_ptr)
1310 {
1311         floor_type *floor_ptr = target_ptr->current_floor_ptr;
1312         for (MONSTER_IDX i = floor_ptr->m_max - 1; i >= 1; i--)
1313         {
1314                 monster_type *m_ptr;
1315                 m_ptr = &floor_ptr->m_list[i];
1316
1317                 if (target_ptr->leaving) return;
1318                 if (!monster_is_valid(m_ptr)) continue;
1319                 if (target_ptr->wild_mode) continue;
1320
1321                 if (m_ptr->mflag & MFLAG_BORN)
1322                 {
1323                         m_ptr->mflag &= ~(MFLAG_BORN);
1324                         continue;
1325                 }
1326
1327                 if (m_ptr->cdis >= AAF_LIMIT) continue;
1328                 if (!decide_process_continue(target_ptr, m_ptr)) continue;
1329
1330                 SPEED speed = (target_ptr->riding == i) ? target_ptr->pspeed : decide_monster_speed(m_ptr);
1331                 m_ptr->energy_need -= SPEED_TO_ENERGY(speed);
1332                 if (m_ptr->energy_need > 0) continue;
1333
1334                 m_ptr->energy_need += ENERGY_NEED();
1335                 hack_m_idx = i;
1336                 process_monster(target_ptr, i);
1337                 reset_target(m_ptr);
1338
1339                 if (target_ptr->no_flowed && one_in_(3))
1340                         m_ptr->mflag2 |= MFLAG2_NOFLOW;
1341
1342                 if (!target_ptr->playing || target_ptr->is_dead) return;
1343                 if (target_ptr->leaving) return;
1344         }
1345 }
1346
1347
1348 /*!
1349  * @brief 後続のモンスター処理が必要かどうか判定する (要調査)
1350  * @param target_ptr プレーヤーへの参照ポインタ
1351  * @param m_ptr モンスターへの参照ポインタ
1352  * @return 後続処理が必要ならTRUE
1353  */
1354 bool decide_process_continue(player_type *target_ptr, monster_type *m_ptr)
1355 {
1356         monster_race *r_ptr;
1357         r_ptr = &r_info[m_ptr->r_idx];
1358         if (!target_ptr->no_flowed)
1359         {
1360                 m_ptr->mflag2 &= ~MFLAG2_NOFLOW;
1361         }
1362
1363         if (m_ptr->cdis <= (is_pet(m_ptr) ? (r_ptr->aaf > MAX_SIGHT ? MAX_SIGHT : r_ptr->aaf) : r_ptr->aaf))
1364                 return TRUE;
1365
1366         if ((m_ptr->cdis <= MAX_SIGHT || target_ptr->phase_out) &&
1367                 (player_has_los_bold(target_ptr, m_ptr->fy, m_ptr->fx) || (target_ptr->cursed & TRC_AGGRAVATE)))
1368                 return TRUE;
1369
1370         if (m_ptr->target_y)
1371                 return TRUE;
1372
1373         return FALSE;
1374 }