2 * @brief モンスターの逃走・隠匿に関する処理
7 #include "monster-floor/monster-safety-hiding.h"
8 #include "floor/cave.h"
9 #include "floor/geometry.h"
10 #include "grid/grid.h"
11 #include "monster-floor/monster-dist-offsets.h"
12 #include "monster-race/monster-race.h"
13 #include "monster/monster-flag-types.h"
14 #include "monster/monster-info.h"
15 #include "monster/monster-processor-util.h"
16 #include "mspell/mspell-checker.h"
17 #include "system/floor-type-definition.h"
18 #include "system/monster-race-definition.h"
19 #include "system/monster-type-definition.h"
20 #include "system/player-type-definition.h"
21 #include "target/projection-path-calculator.h"
24 * @brief モンスターが逃げ込める地点を走査する
25 * @param target_ptr プレーヤーへの参照ポインタ
26 * @param m_idx モンスターID
29 * @param d モンスターがいる地点からの距離
32 static coordinate_candidate sweep_safe_coordinate(player_type *target_ptr, MONSTER_IDX m_idx, const POSITION *y_offsets, const POSITION *x_offsets, int d)
34 coordinate_candidate candidate = init_coordinate_candidate();
35 floor_type *floor_ptr = target_ptr->current_floor_ptr;
36 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
37 for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0]; dx != 0 || dy != 0; i++, dx = x_offsets[i], dy = y_offsets[i]) {
38 POSITION y = m_ptr->fy + dy;
39 POSITION x = m_ptr->fx + dx;
40 if (!in_bounds(floor_ptr, y, x))
43 monster_race *r_ptr = &r_info[m_ptr->r_idx];
45 g_ptr = &floor_ptr->grid_array[y][x];
47 BIT_FLAGS16 riding_mode = (m_idx == target_ptr->riding) ? CEM_RIDING : 0;
48 if (!monster_can_cross_terrain(target_ptr, g_ptr->feat, r_ptr, riding_mode))
51 if (m_ptr->mflag2.has_not(MFLAG2::NOFLOW)) {
52 byte dist = grid_dist(g_ptr, r_ptr);
55 if (dist > grid_dist(&floor_ptr->grid_array[m_ptr->fy][m_ptr->fx], r_ptr) + 2 * d)
59 if (projectable(target_ptr, target_ptr->y, target_ptr->x, y, x))
62 POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
63 if (dis <= candidate.gdis)
75 * @brief モンスターが逃げ込める安全な地点を返す /
76 * Choose a "safe" location near a monster for it to run toward.
77 * @param target_ptr プレーヤーへの参照ポインタ
78 * @param m_idx モンスターの参照ID
79 * @param yp 移動先のマスのY座標を返す参照ポインタ
80 * @param xp 移動先のマスのX座標を返す参照ポインタ
81 * @return 有効なマスがあった場合TRUEを返す
83 * A location is "safe" if it can be reached quickly and the player\n
84 * is not able to fire into it (it isn't a "clean shot"). So, this will\n
85 * cause monsters to "duck" behind walls. Hopefully, monsters will also\n
86 * try to run towards corridor openings if they are in a room.\n
88 * This function may take lots of CPU time if lots of monsters are\n
91 * Return TRUE if a safe location is available.\n
93 bool find_safety(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
95 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
96 for (POSITION d = 1; d < 10; d++) {
97 const POSITION *y_offsets;
98 y_offsets = dist_offsets_y[d];
100 const POSITION *x_offsets;
101 x_offsets = dist_offsets_x[d];
103 coordinate_candidate candidate = sweep_safe_coordinate(target_ptr, m_idx, y_offsets, x_offsets, d);
105 if (candidate.gdis <= 0)
108 *yp = m_ptr->fy - candidate.gy;
109 *xp = m_ptr->fx - candidate.gx;
118 * @brief モンスターが隠れられる地点を走査する
119 * @param target_ptr プレーヤーへの参照ポインタ
120 * @param m_idx モンスターID
123 * @param candidate 隠れられる地点の候補地
125 static void sweep_hiding_candidate(
126 player_type *target_ptr, monster_type *m_ptr, const POSITION *y_offsets, const POSITION *x_offsets, coordinate_candidate *candidate)
128 monster_race *r_ptr = &r_info[m_ptr->r_idx];
129 for (POSITION i = 0, dx = x_offsets[0], dy = y_offsets[0]; dx != 0 || dy != 0; i++, dx = x_offsets[i], dy = y_offsets[i]) {
130 POSITION y = m_ptr->fy + dy;
131 POSITION x = m_ptr->fx + dx;
132 if (!in_bounds(target_ptr->current_floor_ptr, y, x))
134 if (!monster_can_enter(target_ptr, y, x, r_ptr, 0))
136 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))
139 POSITION dis = distance(y, x, target_ptr->y, target_ptr->x);
140 if (dis < candidate->gdis && dis >= 2) {
143 candidate->gdis = dis;
149 * @brief モンスターが隠れ潜める地点を返す /
150 * Choose a good hiding place near a monster for it to run toward.
151 * @param target_ptr プレーヤーへの参照ポインタ
152 * @param m_idx モンスターの参照ID
153 * @param yp 移動先のマスのY座標を返す参照ポインタ
154 * @param xp 移動先のマスのX座標を返す参照ポインタ
155 * @return 有効なマスがあった場合TRUEを返す
157 * Pack monsters will use this to "ambush" the player and lure him out\n
158 * of corridors into open space so they can swarm him.\n
160 * Return TRUE if a good location is available.\n
162 bool find_hiding(player_type *target_ptr, MONSTER_IDX m_idx, POSITION *yp, POSITION *xp)
164 monster_type *m_ptr = &target_ptr->current_floor_ptr->m_list[m_idx];
165 coordinate_candidate candidate = init_coordinate_candidate();
166 candidate.gdis = 999;
168 for (POSITION d = 1; d < 10; d++) {
169 const POSITION *y_offsets;
170 y_offsets = dist_offsets_y[d];
172 const POSITION *x_offsets;
173 x_offsets = dist_offsets_x[d];
175 sweep_hiding_candidate(target_ptr, m_ptr, y_offsets, x_offsets, &candidate);
176 if (candidate.gdis >= 999)
179 *yp = m_ptr->fy - candidate.gy;
180 *xp = m_ptr->fx - candidate.gx;