1 #include "cmd-action/cmd-travel.h"
2 #include "action/travel-execution.h"
3 #include "core/asking-player.h"
4 #include "floor/cave.h"
5 #include "floor/geometry.h"
6 #include "grid/feature.h"
8 #include "player/player-move.h"
9 #include "player/player-status-flags.h"
10 #include "system/floor-type-definition.h"
11 #include "system/grid-type-definition.h"
12 #include "system/player-type-definition.h"
13 #include "target/grid-selector.h"
14 #include "util/bit-flags-calculator.h"
15 #include "view/display-messages.h"
17 #define TRAVEL_UNABLE 9999
20 * @brief トラベル処理中に地形に応じた移動コスト基準を返す
21 * @param player_ptr プレイヤーへの参照ポインタ
26 static int travel_flow_cost(PlayerType *player_ptr, POSITION y, POSITION x)
29 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
30 feature_type *f_ptr = &f_info[g_ptr->feat];
31 if (f_ptr->flags.has(FloorFeatureType::AVOID_RUN))
34 if (f_ptr->flags.has_all_of({FloorFeatureType::WATER, FloorFeatureType::DEEP}) && !player_ptr->levitation)
37 if (f_ptr->flags.has(FloorFeatureType::LAVA)) {
39 if (!has_resist_fire(player_ptr))
42 if (!player_ptr->levitation)
45 if (f_ptr->flags.has(FloorFeatureType::DEEP))
51 if (g_ptr->is_mark()) {
52 if (f_ptr->flags.has(FloorFeatureType::DOOR))
55 if (f_ptr->flags.has(FloorFeatureType::TRAP))
63 * @brief トラベル処理の到達地点までの行程を得る処理のサブルーチン
64 * @param player_ptr プレイヤーへの参照ポインタ
68 * @param wall プレイヤーが壁の中にいるならばTRUE
70 static void travel_flow_aux(PlayerType *player_ptr, POSITION y, POSITION x, int n, bool wall)
72 floor_type *floor_ptr = player_ptr->current_floor_ptr;
73 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
74 feature_type *f_ptr = &f_info[g_ptr->feat];
75 if (!in_bounds(floor_ptr, y, x))
78 if (floor_ptr->dun_level > 0 && !(g_ptr->info & CAVE_KNOWN))
82 int from_wall = (n / TRAVEL_UNABLE);
83 if (f_ptr->flags.has(FloorFeatureType::WALL) || f_ptr->flags.has(FloorFeatureType::CAN_DIG) || (f_ptr->flags.has(FloorFeatureType::DOOR) && floor_ptr->grid_array[y][x].mimic)
84 || (f_ptr->flags.has_not(FloorFeatureType::MOVE) && f_ptr->flags.has(FloorFeatureType::CAN_FLY) && !player_ptr->levitation)) {
85 if (!wall || !from_wall)
88 add_cost += TRAVEL_UNABLE;
90 add_cost = travel_flow_cost(player_ptr, y, x);
92 int base_cost = (n % TRAVEL_UNABLE);
93 int cost = base_cost + add_cost;
94 if (travel.cost[y][x] <= cost)
97 travel.cost[y][x] = cost;
98 int old_head = flow_head;
99 temp2_y[flow_head] = y;
100 temp2_x[flow_head] = x;
101 if (++flow_head == MAX_SHORT)
104 if (flow_head == flow_tail)
105 flow_head = old_head;
109 * @brief トラベル処理の到達地点までの行程を得る処理のメインルーチン
110 * @param player_ptr プレイヤーへの参照ポインタ
114 static void travel_flow(PlayerType *player_ptr, POSITION ty, POSITION tx)
116 flow_head = flow_tail = 0;
118 feature_type *f_ptr = &f_info[player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].feat];
119 if (f_ptr->flags.has_not(FloorFeatureType::MOVE))
122 travel_flow_aux(player_ptr, ty, tx, 0, wall);
124 while (flow_head != flow_tail) {
125 y = temp2_y[flow_tail];
126 x = temp2_x[flow_tail];
127 if (++flow_tail == MAX_SHORT)
130 for (DIRECTION d = 0; d < 8; d++)
131 travel_flow_aux(player_ptr, y + ddy_ddd[d], x + ddx_ddd[d], travel.cost[y][x], wall);
134 flow_head = flow_tail = 0;
138 * @brief トラベル処理のメインルーチン
140 void do_cmd_travel(PlayerType *player_ptr)
143 if ((travel.x != 0) && (travel.y != 0) && (travel.x != player_ptr->x) && (travel.y != player_ptr->y)
144 && get_check(_("トラベルを継続しますか?", "Do you continue to travel? "))) {
147 } else if (!tgt_pt(player_ptr, &x, &y))
150 if ((x == player_ptr->x) && (y == player_ptr->y)) {
151 msg_print(_("すでにそこにいます!", "You are already there!!"));
155 floor_type *floor_ptr = player_ptr->current_floor_ptr;
157 f_ptr = &f_info[floor_ptr->grid_array[y][x].feat];
158 if ((floor_ptr->grid_array[y][x].info & CAVE_MARK)
159 && (f_ptr->flags.has(FloorFeatureType::WALL) || f_ptr->flags.has(FloorFeatureType::CAN_DIG) || (f_ptr->flags.has(FloorFeatureType::DOOR) && floor_ptr->grid_array[y][x].mimic))) {
160 msg_print(_("そこには行くことができません!", "You cannot travel there!"));
164 forget_travel_flow(player_ptr->current_floor_ptr);
165 travel_flow(player_ptr, y, x);
170 POSITION dx = abs(player_ptr->x - x);
171 POSITION dy = abs(player_ptr->y - y);
172 POSITION sx = ((x == player_ptr->x) || (dx < dy)) ? 0 : ((x > player_ptr->x) ? 1 : -1);
173 POSITION sy = ((y == player_ptr->y) || (dy < dx)) ? 0 : ((y > player_ptr->y) ? 1 : -1);
174 for (int i = 1; i <= 9; i++)
175 if ((sx == ddx[i]) && (sy == ddy[i]))