2 * @brief モンスターの移動方向を決定する処理
7 #include "monster-floor/monster-direction.h"
8 #include "floor/cave.h"
9 #include "monster-floor/monster-sweep-grid.h"
10 #include "monster-race/monster-race.h"
11 #include "monster-race/race-flags1.h"
12 #include "monster-race/race-flags2.h"
13 #include "monster/monster-info.h"
14 #include "monster/monster-processor-util.h"
15 #include "monster/monster-status.h"
16 #include "pet/pet-util.h"
17 #include "player/player-status-flags.h"
18 #include "spell/range-calc.h"
19 #include "system/floor-type-definition.h"
20 #include "system/monster-race-definition.h"
21 #include "system/monster-type-definition.h"
22 #include "system/player-type-definition.h"
23 #include "target/projection-path-calculator.h"
26 * @brief ペットが敵に接近するための方向を決定する
27 * @param target_ptr プレーヤーへの参照ポインタ
28 * @param m_ptr 移動を試みているモンスターへの参照ポインタ
29 * @param t_ptr 移動先モンスターへの参照ポインタ
30 * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
31 * @return ペットがモンスターに近づくならばTRUE
33 static bool decide_pet_approch_direction(player_type *target_ptr, monster_type *m_ptr, monster_type *t_ptr)
35 monster_race *r_ptr = &r_info[m_ptr->r_idx];
39 if (target_ptr->pet_follow_distance < 0) {
40 if (t_ptr->cdis <= (0 - target_ptr->pet_follow_distance)) {
43 } else if ((m_ptr->cdis < t_ptr->cdis) && (t_ptr->cdis > target_ptr->pet_follow_distance)) {
47 return (r_ptr->aaf < t_ptr->cdis);
51 * @brief モンスターが敵に接近するための方向を決定する
52 * @param target_ptr プレーヤーへの参照ポインタ
53 * @param m_idx モンスターID
54 * @param start モンスターIDの開始
55 * @param plus モンスターIDの増減 (1/2 の確率で+1、1/2の確率で-1)
56 * @param y モンスターの移動方向Y
57 * @param x モンスターの移動方向X
59 static void decide_enemy_approch_direction(player_type *target_ptr, MONSTER_IDX m_idx, int start, int plus, POSITION *y, POSITION *x)
61 floor_type *floor_ptr = target_ptr->current_floor_ptr;
62 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
63 monster_race *r_ptr = &r_info[m_ptr->r_idx];
64 for (int i = start; ((i < start + floor_ptr->m_max) && (i > start - floor_ptr->m_max)); i += plus) {
65 MONSTER_IDX dummy = (i % floor_ptr->m_max);
69 MONSTER_IDX t_idx = dummy;
71 t_ptr = &floor_ptr->m_list[t_idx];
74 if (!monster_is_valid(t_ptr))
76 if (decide_pet_approch_direction(target_ptr, m_ptr, t_ptr))
78 if (!are_enemies(target_ptr, m_ptr, t_ptr))
81 if (((r_ptr->flags2 & RF2_PASS_WALL) && ((m_idx != target_ptr->riding) || has_pass_wall(target_ptr)))
82 || ((r_ptr->flags2 & RF2_KILL_WALL) && (m_idx != target_ptr->riding))) {
83 if (!in_disintegration_range(floor_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx))
86 if (!projectable(target_ptr, m_ptr->fy, m_ptr->fx, t_ptr->fy, t_ptr->fx))
97 * @brief モンスターが敵に接近するための方向を計算するメインルーチン
98 * Calculate the direction to the next enemy
99 * @param target_ptr プレーヤーへの参照ポインタ
100 * @param m_idx モンスターの参照ID
101 * @param mm 移動するべき方角IDを返す参照ポインタ
102 * @return 方向が確定した場合TRUE、接近する敵がそもそもいない場合FALSEを返す
104 bool get_enemy_dir(player_type *target_ptr, MONSTER_IDX m_idx, int *mm)
106 floor_type *floor_ptr = target_ptr->current_floor_ptr;
107 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
109 POSITION x = 0, y = 0;
110 if (target_ptr->riding_t_m_idx && player_bold(target_ptr, m_ptr->fy, m_ptr->fx)) {
111 y = floor_ptr->m_list[target_ptr->riding_t_m_idx].fy;
112 x = floor_ptr->m_list[target_ptr->riding_t_m_idx].fx;
113 } else if (is_pet(m_ptr) && target_ptr->pet_t_m_idx) {
114 y = floor_ptr->m_list[target_ptr->pet_t_m_idx].fy;
115 x = floor_ptr->m_list[target_ptr->pet_t_m_idx].fx;
119 if (target_ptr->phase_out) {
120 start = randint1(floor_ptr->m_max - 1) + floor_ptr->m_max;
124 start = floor_ptr->m_max + 1;
127 decide_enemy_approch_direction(target_ptr, m_idx, start, plus, &y, &x);
129 if ((x == 0) && (y == 0))
136 store_enemy_approch_direction(mm, y, x);
141 * @brief 不規則歩行フラグを持つモンスターの移動方向をその確率に基づいて決定する
142 * @param target_ptr プレーヤーへの参照ポインタ
144 * @param m_ptr モンスターへの参照ポインタ
145 * @return 不規則な方向へ歩くことになったらTRUE
146 * @todo "5"とはもしかして「その場に留まる」という意味か?
148 static bool random_walk(player_type *target_ptr, DIRECTION *mm, monster_type *m_ptr)
150 monster_race *r_ptr = &r_info[m_ptr->r_idx];
151 if (((r_ptr->flags1 & (RF1_RAND_50 | RF1_RAND_25)) == (RF1_RAND_50 | RF1_RAND_25)) && (randint0(100) < 75)) {
152 if (is_original_ap_and_seen(target_ptr, m_ptr))
153 r_ptr->r_flags1 |= (RF1_RAND_50 | RF1_RAND_25);
155 mm[0] = mm[1] = mm[2] = mm[3] = 5;
159 if ((r_ptr->flags1 & RF1_RAND_50) && (randint0(100) < 50)) {
160 if (is_original_ap_and_seen(target_ptr, m_ptr))
161 r_ptr->r_flags1 |= RF1_RAND_50;
163 mm[0] = mm[1] = mm[2] = mm[3] = 5;
167 if ((r_ptr->flags1 & RF1_RAND_25) && (randint0(100) < 25)) {
168 if (is_original_ap_and_seen(target_ptr, m_ptr))
169 r_ptr->r_flags1 |= RF1_RAND_25;
171 mm[0] = mm[1] = mm[2] = mm[3] = 5;
179 * @brief ペットや友好的なモンスターがフロアから逃げる処理を行う
180 * @param target_ptr プレーヤーへの参照ポインタ
182 * @param m_idx モンスターID
183 * @return モンスターがペットであればTRUE
185 static bool decide_pet_movement_direction(MonsterSweepGrid *msd)
187 monster_type *m_ptr = &msd->target_ptr->current_floor_ptr->m_list[msd->m_idx];
188 if (!is_pet(m_ptr)) {
192 bool avoid = ((msd->target_ptr->pet_follow_distance < 0) && (m_ptr->cdis <= (0 - msd->target_ptr->pet_follow_distance)));
193 bool lonely = (!avoid && (m_ptr->cdis > msd->target_ptr->pet_follow_distance));
194 bool distant = (m_ptr->cdis > PET_SEEK_DIST);
195 msd->mm[0] = msd->mm[1] = msd->mm[2] = msd->mm[3] = 5;
196 if (get_enemy_dir(msd->target_ptr, msd->m_idx, msd->mm)) {
200 if (!avoid && !lonely && !distant) {
204 POSITION dis = msd->target_ptr->pet_follow_distance;
205 if (msd->target_ptr->pet_follow_distance > PET_SEEK_DIST) {
206 msd->target_ptr->pet_follow_distance = PET_SEEK_DIST;
209 (void)msd->get_movable_grid();
210 msd->target_ptr->pet_follow_distance = (s16b)dis;
215 * @brief モンスターの移動パターンを決定する
216 * @param target_ptr プレーヤーへの参照ポインタ
218 * @param m_idx モンスターID
219 * @param aware モンスターがプレーヤーに気付いているならばTRUE、超隠密状態ならばFALSE
220 * @return 移動先が存在すればTRUE
222 bool decide_monster_movement_direction(player_type *target_ptr, DIRECTION *mm, MONSTER_IDX m_idx, bool aware)
224 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
225 monster_race *r_ptr = &r_info[m_ptr->r_idx];
227 if (monster_confused_remaining(m_ptr) || !aware) {
228 mm[0] = mm[1] = mm[2] = mm[3] = 5;
232 if (random_walk(target_ptr, mm, m_ptr)) {
236 if ((r_ptr->flags1 & RF1_NEVER_MOVE) && (m_ptr->cdis > 1)) {
237 mm[0] = mm[1] = mm[2] = mm[3] = 5;
241 MonsterSweepGrid msd(target_ptr, m_idx, mm);
242 if (decide_pet_movement_direction(&msd)) {
246 if (!is_hostile(m_ptr)) {
247 mm[0] = mm[1] = mm[2] = mm[3] = 5;
248 get_enemy_dir(target_ptr, m_idx, mm);
252 return msd.get_movable_grid();