OSDN Git Service

[Refactor] #40030 Changed function names in monster-process.c
[hengband/hengband.git] / src / monster / monster-direction.c
1 /*!
2  * @brief モンスターの移動方向を決定する処理
3  * @date 2020/03/08
4  * @author Hourier
5  */
6
7 #include "monster/monster-direction.h"
8 #include "monster/monster-util.h"
9 #include "monster-status.h"
10 #include "cmd/cmd-pet.h"
11
12 /*!
13  * @brief ペットが敵に接近するための方向を決定する
14  * @param target_ptr プレーヤーへの参照ポインタ
15  * @param m_ptr 移動を試みているモンスターへの参照ポインタ
16  * @param t_ptr 移動先モンスターへの参照ポインタ
17  * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
18  * @return ペットがモンスターに近づくならばTRUE
19  */
20 static bool decide_pet_approch_direction(player_type *target_ptr, monster_type *m_ptr, monster_type *t_ptr)
21 {
22         monster_race *r_ptr = &r_info[m_ptr->r_idx];
23         if (!is_pet(m_ptr)) return FALSE;
24
25         if (target_ptr->pet_follow_distance < 0)
26         {
27                 if (t_ptr->cdis <= (0 - target_ptr->pet_follow_distance))
28                 {
29                         return TRUE;
30                 }
31         }
32         else if ((m_ptr->cdis < t_ptr->cdis) && (t_ptr->cdis > target_ptr->pet_follow_distance))
33         {
34                 return TRUE;
35         }
36
37         return (r_ptr->aaf < t_ptr->cdis);
38 }
39
40
41 /*!
42  * @brief モンスターが敵に接近するための方向を決定する
43  * @param target_ptr プレーヤーへの参照ポインタ
44  * @param m_idx モンスターID
45  * @param start モンスターIDの開始
46  * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
47  * @param y モンスターの移動方向Y
48  * @param x モンスターの移動方向X
49  * @return なし
50  */
51 static void decide_enemy_approch_direction(player_type *target_ptr, MONSTER_IDX m_idx, int start, int plus, POSITION *y, POSITION *x)
52 {
53         floor_type *floor_ptr = target_ptr->current_floor_ptr;
54         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
55         monster_race *r_ptr = &r_info[m_ptr->r_idx];
56         for (int i = start; ((i < start + floor_ptr->m_max) && (i > start - floor_ptr->m_max)); i += plus)
57         {
58                 MONSTER_IDX dummy = (i % floor_ptr->m_max);
59                 if (dummy == 0) continue;
60
61                 MONSTER_IDX t_idx = dummy;
62                 monster_type *t_ptr;
63                 t_ptr = &floor_ptr->m_list[t_idx];
64                 if (t_ptr == m_ptr) continue;
65                 if (!monster_is_valid(t_ptr)) continue;
66                 if (decide_pet_approch_direction(target_ptr, m_ptr, t_ptr)) continue;
67                 if (!are_enemies(target_ptr, m_ptr, t_ptr)) continue;
68
69                 if (((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || target_ptr->pass_wall)) ||
70                         ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding)))
71                 {
72                         if (!in_disintegration_range(floor_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
73                 }
74                 else
75                 {
76                         if (!projectable(target_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx)) continue;
77                 }
78
79                 *y = t_ptr->fy;
80                 *x = t_ptr->fx;
81                 return;
82         }
83 }
84
85
86 /*!
87  * @brief モンスターが敵に接近するための方向を計算するメインルーチン
88  * Calculate the direction to the next enemy
89  * @param target_ptr プレーヤーへの参照ポインタ
90  * @param m_idx モンスターの参照ID
91  * @param mm 移動するべき方角IDを返す参照ポインタ
92  * @return 方向が確定した場合TRUE、接近する敵がそもそもいない場合FALSEを返す
93  */
94 bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm)
95 {
96         floor_type *floor_ptr = target_ptr->current_floor_ptr;
97         monster_type *m_ptr = &floor_ptr->m_list[m_idx];
98
99         POSITION x = 0, y = 0;
100         if (target_ptr->riding_t_m_idx && player_bold(target_ptr, m_ptr->fy, m_ptr->fx))
101         {
102                 y = floor_ptr->m_list[target_ptr->riding_t_m_idx].fy;
103                 x = floor_ptr->m_list[target_ptr->riding_t_m_idx].fx;
104         }
105         else if (is_pet(m_ptr) && target_ptr->pet_t_m_idx)
106         {
107                 y = floor_ptr->m_list[target_ptr->pet_t_m_idx].fy;
108                 x = floor_ptr->m_list[target_ptr->pet_t_m_idx].fx;
109         }
110         else
111         {
112                 int start;
113                 int plus = 1;
114                 if (target_ptr->phase_out)
115                 {
116                         start = randint1(floor_ptr->m_max - 1) + floor_ptr->m_max;
117                         if (randint0(2)) plus = -1;
118                 }
119                 else
120                 {
121                         start = floor_ptr->m_max + 1;
122                 }
123
124                 decide_enemy_approch_direction(target_ptr, m_idx, start, plus, &y, &x);
125
126                 if ((x == 0) && (y == 0)) return FALSE;
127         }
128
129         x -= m_ptr->fx;
130         y -= m_ptr->fy;
131
132         store_enemy_approch_direction(mm, y, x);
133         return TRUE;
134 }
135
136
137 /*!
138  * todo ↓のように書いたが、"5"とはもしかして「その場に留まる」という意味か?
139  * @brief 不規則歩行フラグを持つモンスターの移動方向をその確率に基づいて決定する
140  * @param target_ptr プレーヤーへの参照ポインタ
141  * @param mm 移動方向
142  * @param m_ptr モンスターへの参照ポインタ
143  * @return 不規則な方向へ歩くことになったらTRUE
144  */
145 static bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr)
146 {
147         monster_race *r_ptr = &r_info[m_ptr->r_idx];
148         if (((r_ptr->flags1 & (RF1_RAND_50 | RF1_RAND_25)) == (RF1_RAND_50 | RF1_RAND_25)) && (randint0(100) < 75))
149         {
150                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= (RF1_RAND_50 | RF1_RAND_25);
151
152                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
153                 return TRUE;
154         }
155
156         if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 50))
157         {
158                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_50;
159
160                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
161                 return TRUE;
162         }
163
164         if ((r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 25))
165         {
166                 if (is_original_ap_and_seen(target_ptr, m_ptr)) r_ptr->r_flags1 |= RF1_RAND_25;
167
168                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
169                 return TRUE;
170         }
171
172         return FALSE;
173 }
174
175
176 /*!
177  * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
178  * @param target_ptr プレーヤーへの参照ポインタ
179  * @param mm 移動方向
180  * @param m_idx モンスターID
181  * @return モンスターがペットであればTRUE
182  */
183 static bool decide_pet_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, get_moves_pf get_movable_grid)
184 {
185         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
186         if (!is_pet(m_ptr)) return FALSE;
187
188         bool avoid = ((target_ptr->pet_follow_distance < 0) && (m_ptr->cdis <= (0 - target_ptr->pet_follow_distance)));
189         bool lonely = (!avoid && (m_ptr->cdis > target_ptr->pet_follow_distance));
190         bool distant = (m_ptr->cdis > PET_SEEK_DIST);
191         mm[0] = mm[1] = mm[2] = mm[3] = 5;
192         if (get_enemy_dir(target_ptr, m_idx, mm)) return TRUE;
193         if (!avoid && !lonely && !distant) return TRUE;
194
195         POSITION dis = target_ptr->pet_follow_distance;
196         if (target_ptr->pet_follow_distance > PET_SEEK_DIST)
197         {
198                 target_ptr->pet_follow_distance = PET_SEEK_DIST;
199         }
200
201         (void)get_movable_grid(target_ptr, m_idx, mm);
202         target_ptr->pet_follow_distance = (s16b)dis;
203         return TRUE;
204 }
205
206
207 /*!
208  * @brief モンスターの移動パターンを決定する
209  * @param target_ptr プレーヤーへの参照ポインタ
210  * @param mm 移動方向
211  * @param m_idx モンスターID
212  * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
213  * @return 移動先が存在すればTRUE
214  */
215 bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware, get_moves_pf get_movable_grid)
216 {
217         monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
218         monster_race *r_ptr = &r_info[m_ptr->r_idx];
219
220         if (MON_CONFUSED(m_ptr) || !aware)
221         {
222                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
223                 return TRUE;
224         }
225
226         if (random_walk(target_ptr, mm, m_ptr)) return TRUE;
227
228         if ((r_ptr->flags1 & RF1_NEVER_MOVE) && (m_ptr->cdis > 1))
229         {
230                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
231                 return TRUE;
232         }
233
234         if (decide_pet_movement_direction(target_ptr, mm, m_idx, get_movable_grid)) return TRUE;
235
236         if (!is_hostile(m_ptr))
237         {
238                 mm[0] = mm[1] = mm[2] = mm[3] = 5;
239                 get_enemy_dir(target_ptr, m_idx, mm);
240                 return TRUE;
241         }
242
243         if (!get_movable_grid(target_ptr, m_idx, mm)) return FALSE;
244
245         return TRUE;
246 }