1 #include "action/run-execution.h"
2 #include "action/movement-execution.h"
3 #include "core/disturbance.h"
4 #include "floor/cave.h"
5 #include "floor/floor-util.h"
6 #include "game-option/disturbance-options.h"
7 #include "grid/feature.h"
9 #include "main/sound-definitions-table.h"
10 #include "main/sound-of-music.h"
11 #include "object/object-mark-types.h"
12 #include "player/player-status-flags.h"
13 #include "system/floor-type-definition.h"
14 #include "system/object-type-definition.h"
15 #include "util/bit-flags-calculator.h"
16 #include "view/display-messages.h"
18 bool ignore_avoid_run;
20 /* Allow quick "cycling" through the legal directions */
21 byte cycle[MAX_RUN_CYCLES] = { 1, 2, 3, 6, 9, 8, 7, 4, 1, 2, 3, 6, 9, 8, 7, 4, 1 };
23 /* Map each direction into the "middle" of the "cycle[]" array */
24 byte chome[MAX_RUN_CHOME] = { 0, 8, 9, 10, 7, 0, 11, 6, 5, 4 };
26 /* The direction we are running */
27 static DIRECTION find_current;
29 /* The direction we came from */
30 static DIRECTION find_prevdir;
32 static bool find_openarea;
34 /* We are looking for a break */
35 static bool find_breakright;
36 static bool find_breakleft;
39 * @brief ダッシュ移動処理中、移動先のマスが既知の壁かどうかを判定する /
40 * Hack -- Check for a "known wall" (see below)
41 * @param creature_ptr プレーヤーへの参照ポインタ
42 * @param dir 想定する移動方向ID
45 * @return 移動先が既知の壁ならばTRUE
47 static bool see_wall(player_type *creature_ptr, DIRECTION dir, POSITION y, POSITION x)
51 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
52 if (!in_bounds2(floor_ptr, y, x))
56 g_ptr = &floor_ptr->grid_array[y][x];
57 if (!(g_ptr->info & CAVE_MARK))
60 s16b feat = get_feat_mimic(g_ptr);
61 feature_type *f_ptr = &f_info[feat];
62 if (!player_can_enter(creature_ptr, feat, 0))
63 return !has_flag(f_ptr->flags, FF_DOOR);
65 if (has_flag(f_ptr->flags, FF_AVOID_RUN) && !ignore_avoid_run)
68 if (!has_flag(f_ptr->flags, FF_MOVE) && !has_flag(f_ptr->flags, FF_CAN_FLY))
69 return !has_flag(f_ptr->flags, FF_DOOR);
76 * Initialize the running algorithm for a new direction.
77 * @param creature_ptr プレーヤーへの参照ポインタ
80 * Diagonal Corridor -- allow diaginal entry into corridors.\n
82 * Blunt Corridor -- If there is a wall two spaces ahead and\n
83 * we seem to be in a corridor, then force a turn into the side\n
84 * corridor, must be moving straight into a corridor here. ???\n
86 * Diagonal Corridor Blunt Corridor (?)\n
91 static void run_init(player_type *creature_ptr, DIRECTION dir)
96 find_breakright = find_breakleft = FALSE;
97 bool deepleft = FALSE;
98 bool deepright = FALSE;
99 bool shortright = FALSE;
100 bool shortleft = FALSE;
101 creature_ptr->run_py = creature_ptr->y;
102 creature_ptr->run_px = creature_ptr->x;
103 int row = creature_ptr->y + ddy[dir];
104 int col = creature_ptr->x + ddx[dir];
105 ignore_avoid_run = cave_has_flag_bold(creature_ptr->current_floor_ptr, row, col, FF_AVOID_RUN);
107 if (see_wall(creature_ptr, cycle[i + 1], creature_ptr->y, creature_ptr->x)) {
108 find_breakleft = TRUE;
110 } else if (see_wall(creature_ptr, cycle[i + 1], row, col)) {
111 find_breakleft = TRUE;
115 if (see_wall(creature_ptr, cycle[i - 1], creature_ptr->y, creature_ptr->x)) {
116 find_breakright = TRUE;
118 } else if (see_wall(creature_ptr, cycle[i - 1], row, col)) {
119 find_breakright = TRUE;
123 if (!find_breakleft || !find_breakright)
126 find_openarea = FALSE;
128 if (deepleft && !deepright) {
129 find_prevdir = cycle[i - 1];
130 } else if (deepright && !deepleft) {
131 find_prevdir = cycle[i + 1];
137 if (!see_wall(creature_ptr, cycle[i], row, col))
140 if (shortleft && !shortright) {
141 find_prevdir = cycle[i - 2];
142 } else if (shortright && !shortleft) {
143 find_prevdir = cycle[i + 2];
148 * @brief ダッシュ移動処理中、移動先のマスか未知の地形かどうかを判定する /
149 * Hack -- Check for an "unknown corner" (see below)
150 * @param creature_ptr プレーヤーへの参照ポインタ
151 * @param dir 想定する移動方向ID
154 * @return 移動先が未知の地形ならばTRUE
156 static bool see_nothing(player_type *creature_ptr, DIRECTION dir, POSITION y, POSITION x)
161 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
162 if (!in_bounds2(floor_ptr, y, x))
165 if (floor_ptr->grid_array[y][x].info & (CAVE_MARK))
168 if (player_can_see_bold(creature_ptr, y, x))
175 * @brief ダッシュ移動が継続できるかどうかの判定 /
176 * Update the current "run" path
177 * @param creature_ptr プレーヤーへの参照ポインタ
178 * @return 立ち止まるべき条件が満たされたらTRUE
179 * ダッシュ移動が継続できるならばTRUEを返す。
180 * Return TRUE if the running should be stopped
182 static bool run_test(player_type *creature_ptr)
184 DIRECTION prev_dir = find_prevdir;
185 int max = (prev_dir & 0x01) + 1;
186 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
187 if ((disturb_trap_detect || alert_trap_detect) && creature_ptr->dtrap && !(floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & CAVE_IN_DETECT)) {
188 creature_ptr->dtrap = FALSE;
189 if (!(floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].info & CAVE_UNSAFE)) {
190 if (alert_trap_detect) {
191 msg_print(_("* 注意:この先はトラップの感知範囲外です! *", "*Leaving trap detect region!*"));
194 if (disturb_trap_detect) {
201 DIRECTION check_dir = 0;
202 int option = 0, option2 = 0;
203 for (int i = -max; i <= max; i++) {
204 OBJECT_IDX this_o_idx, next_o_idx = 0;
205 DIRECTION new_dir = cycle[chome[prev_dir] + i];
206 int row = creature_ptr->y + ddy[new_dir];
207 int col = creature_ptr->x + ddx[new_dir];
209 g_ptr = &floor_ptr->grid_array[row][col];
210 FEAT_IDX feat = get_feat_mimic(g_ptr);
212 f_ptr = &f_info[feat];
214 monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
219 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) {
221 o_ptr = &floor_ptr->o_list[this_o_idx];
222 next_o_idx = o_ptr->next_o_idx;
223 if (o_ptr->marked & OM_FOUND)
228 if (g_ptr->info & (CAVE_MARK)) {
229 bool notice = has_flag(f_ptr->flags, FF_NOTICE);
230 if (notice && has_flag(f_ptr->flags, FF_MOVE)) {
231 if (find_ignore_doors && has_flag(f_ptr->flags, FF_DOOR) && has_flag(f_ptr->flags, FF_CLOSE)) {
233 } else if (find_ignore_stairs && has_flag(f_ptr->flags, FF_STAIRS)) {
235 } else if (has_flag(f_ptr->flags, FF_LAVA) && (has_immune_fire(creature_ptr) || is_invuln(creature_ptr))) {
237 } else if (has_flag(f_ptr->flags, FF_WATER) && has_flag(f_ptr->flags, FF_DEEP)
238 && (creature_ptr->levitation || creature_ptr->can_swim || (calc_inventory_weight(creature_ptr) <= calc_weight_limit(creature_ptr)))) {
249 if (!inv && see_wall(creature_ptr, 0, row, col)) {
252 find_breakright = TRUE;
254 find_breakleft = TRUE;
272 if (option != cycle[chome[prev_dir] + i - 1])
275 if (new_dir & 0x01) {
276 check_dir = cycle[chome[prev_dir] + i - 2];
281 check_dir = cycle[chome[prev_dir] + i + 1];
287 for (int i = -max; i < 0; i++) {
288 if (!see_wall(creature_ptr, cycle[chome[prev_dir] + i], creature_ptr->y, creature_ptr->x)) {
297 for (int i = max; i > 0; i--) {
298 if (!see_wall(creature_ptr, cycle[chome[prev_dir] + i], creature_ptr->y, creature_ptr->x)) {
307 return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x);
314 find_current = option;
315 find_prevdir = option;
316 return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x);
317 } else if (!find_cut) {
318 find_current = option;
319 find_prevdir = option2;
320 return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x);
323 int row = creature_ptr->y + ddy[option];
324 int col = creature_ptr->x + ddx[option];
325 if (!see_wall(creature_ptr, option, row, col) || !see_wall(creature_ptr, check_dir, row, col)) {
326 if (see_nothing(creature_ptr, option, row, col) && see_nothing(creature_ptr, option2, row, col)) {
327 find_current = option;
328 find_prevdir = option2;
329 return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x);
336 find_current = option2;
337 find_prevdir = option2;
338 return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x);
341 find_current = option;
342 find_prevdir = option2;
343 return see_wall(creature_ptr, find_current, creature_ptr->y, creature_ptr->x);
347 * @brief 継続的なダッシュ処理 /
348 * Take one step along the current "run" path
349 * @param creature_ptr プレーヤーへの参照ポインタ
350 * @param dir 移動を試みる方向ID
353 void run_step(player_type *creature_ptr, DIRECTION dir)
356 ignore_avoid_run = TRUE;
357 if (see_wall(creature_ptr, dir, creature_ptr->y, creature_ptr->x)) {
358 sound(SOUND_HITWALL);
359 msg_print(_("その方向には走れません。", "You cannot run in that direction."));
360 disturb(creature_ptr, FALSE, FALSE);
364 run_init(creature_ptr, dir);
366 if (run_test(creature_ptr)) {
367 disturb(creature_ptr, FALSE, FALSE);
372 if (--creature_ptr->running <= 0)
375 take_turn(creature_ptr, 100);
376 exe_movement(creature_ptr, find_current, FALSE, FALSE);
377 if (player_bold(creature_ptr, creature_ptr->run_py, creature_ptr->run_px)) {
378 creature_ptr->run_py = 0;
379 creature_ptr->run_px = 0;
380 disturb(creature_ptr, FALSE, FALSE);