OSDN Git Service

[Refactor] 名称の変更 RARM/LARM/HANDS -> MAIN_HAND/SUB_HAND/ARMS
[hengband/hengband.git] / src / cmd-action / cmd-travel.c
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 "grid/feature.h"
6 #include "grid/grid.h"
7 #include "player/player-move.h"
8 #include "player/player-status-flags.h"
9 #include "system/floor-type-definition.h"
10 #include "target/grid-selector.h"
11 #include "view/display-messages.h"
12 #include "util/bit-flags-calculator.h"
13
14 #define TRAVEL_UNABLE 9999
15
16 /*!
17  * @brief トラベル処理中に地形に応じた移動コスト基準を返す
18  * @param creature_ptr  プレーヤーへの参照ポインタ
19  * @param y 該当地点のY座標
20  * @param x 該当地点のX座標
21  * @return コスト値
22  */
23 static int travel_flow_cost(player_type *creature_ptr, POSITION y, POSITION x)
24 {
25     int cost = 1;
26     feature_type *f_ptr = &f_info[creature_ptr->current_floor_ptr->grid_array[y][x].feat];
27     if (has_flag(f_ptr->flags, FF_AVOID_RUN))
28         cost += 1;
29
30     if (has_flag(f_ptr->flags, FF_WATER) && has_flag(f_ptr->flags, FF_DEEP) && !creature_ptr->levitation)
31         cost += 5;
32
33     if (has_flag(f_ptr->flags, FF_LAVA)) {
34         int lava = 2;
35         if (!has_resist_fire(creature_ptr))
36             lava *= 2;
37
38         if (!creature_ptr->levitation)
39             lava *= 2;
40
41         if (has_flag(f_ptr->flags, FF_DEEP))
42             lava *= 2;
43
44         cost += lava;
45     }
46
47     if (creature_ptr->current_floor_ptr->grid_array[y][x].info & (CAVE_MARK)) {
48         if (has_flag(f_ptr->flags, FF_DOOR))
49             cost += 1;
50
51         if (has_flag(f_ptr->flags, FF_TRAP))
52             cost += 10;
53     }
54
55     return cost;
56 }
57
58 /*!
59  * @brief トラベル処理の到達地点までの行程を得る処理のサブルーチン
60  * @param creature_ptr  プレーヤーへの参照ポインタ
61  * @param y 目標地点のY座標
62  * @param x 目標地点のX座標
63  * @param n 現在のコスト
64  * @param wall プレイヤーが壁の中にいるならばTRUE
65  * @return なし
66  */
67 static void travel_flow_aux(player_type *creature_ptr, POSITION y, POSITION x, int n, bool wall)
68 {
69     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
70     grid_type *g_ptr = &floor_ptr->grid_array[y][x];
71     feature_type *f_ptr = &f_info[g_ptr->feat];
72     if (!in_bounds(floor_ptr, y, x))
73         return;
74
75     if (floor_ptr->dun_level > 0 && !(g_ptr->info & CAVE_KNOWN))
76         return;
77
78     int add_cost = 1;
79     int from_wall = (n / TRAVEL_UNABLE);
80     if (has_flag(f_ptr->flags, FF_WALL) || has_flag(f_ptr->flags, FF_CAN_DIG) || (has_flag(f_ptr->flags, FF_DOOR) && floor_ptr->grid_array[y][x].mimic)
81         || (!has_flag(f_ptr->flags, FF_MOVE) && has_flag(f_ptr->flags, FF_CAN_FLY) && !creature_ptr->levitation)) {
82         if (!wall || !from_wall)
83             return;
84
85         add_cost += TRAVEL_UNABLE;
86     } else
87         add_cost = travel_flow_cost(creature_ptr, y, x);
88
89     int base_cost = (n % TRAVEL_UNABLE);
90     int cost = base_cost + add_cost;
91     if (travel.cost[y][x] <= cost)
92         return;
93
94     travel.cost[y][x] = cost;
95     int old_head = flow_head;
96     temp2_y[flow_head] = y;
97     temp2_x[flow_head] = x;
98     if (++flow_head == MAX_SHORT)
99         flow_head = 0;
100
101     if (flow_head == flow_tail)
102         flow_head = old_head;
103 }
104
105 /*!
106  * @brief トラベル処理の到達地点までの行程を得る処理のメインルーチン
107  * @param creature_ptr  プレーヤーへの参照ポインタ
108  * @param ty 目標地点のY座標
109  * @param tx 目標地点のX座標
110  * @return なし
111  */
112 static void travel_flow(player_type *creature_ptr, POSITION ty, POSITION tx)
113 {
114     flow_head = flow_tail = 0;
115     bool wall = FALSE;
116     feature_type *f_ptr = &f_info[creature_ptr->current_floor_ptr->grid_array[creature_ptr->y][creature_ptr->x].feat];
117     if (!has_flag(f_ptr->flags, FF_MOVE))
118         wall = TRUE;
119
120     travel_flow_aux(creature_ptr, ty, tx, 0, wall);
121     POSITION x, y;
122     while (flow_head != flow_tail) {
123         y = temp2_y[flow_tail];
124         x = temp2_x[flow_tail];
125         if (++flow_tail == MAX_SHORT)
126             flow_tail = 0;
127
128         for (DIRECTION d = 0; d < 8; d++)
129             travel_flow_aux(creature_ptr, y + ddy_ddd[d], x + ddx_ddd[d], travel.cost[y][x], wall);
130     }
131
132     flow_head = flow_tail = 0;
133 }
134
135 /*!
136  * @brief トラベル処理のメインルーチン
137  * @return なし
138  */
139 void do_cmd_travel(player_type *creature_ptr)
140 {
141     POSITION x, y;
142     if (travel.x != 0 && travel.y != 0 && get_check(_("トラベルを継続しますか?", "Do you continue to travel?"))) {
143         y = travel.y;
144         x = travel.x;
145     } else if (!tgt_pt(creature_ptr, &x, &y))
146         return;
147
148     if ((x == creature_ptr->x) && (y == creature_ptr->y)) {
149         msg_print(_("すでにそこにいます!", "You are already there!!"));
150         return;
151     }
152
153     floor_type *floor_ptr = creature_ptr->current_floor_ptr;
154     feature_type *f_ptr;
155     f_ptr = &f_info[floor_ptr->grid_array[y][x].feat];
156     if ((floor_ptr->grid_array[y][x].info & CAVE_MARK)
157         && (has_flag(f_ptr->flags, FF_WALL) || has_flag(f_ptr->flags, FF_CAN_DIG)
158             || (has_flag(f_ptr->flags, FF_DOOR) && floor_ptr->grid_array[y][x].mimic))) {
159         msg_print(_("そこには行くことができません!", "You cannot travel there!"));
160         return;
161     }
162
163     forget_travel_flow(creature_ptr->current_floor_ptr);
164     travel_flow(creature_ptr, y, x);
165     travel.x = x;
166     travel.y = y;
167     travel.run = 255;
168     travel.dir = 0;
169     POSITION dx = abs(creature_ptr->x - x);
170     POSITION dy = abs(creature_ptr->y - y);
171     POSITION sx = ((x == creature_ptr->x) || (dx < dy)) ? 0 : ((x > creature_ptr->x) ? 1 : -1);
172     POSITION sy = ((y == creature_ptr->y) || (dy < dx)) ? 0 : ((y > creature_ptr->y) ? 1 : -1);
173     for (int i = 1; i <= 9; i++)
174         if ((sx == ddx[i]) && (sy == ddy[i]))
175             travel.dir = i;
176 }