OSDN Git Service

[Refactor] #1172 Changed '(TRUE, ', '(FALSE, ', ', TRUE)', ', FALSE)' ', TRUE,' and...
[hengbandforosx/hengbandosx.git] / src / cmd-action / cmd-open-close.cpp
1 #include "cmd-action/cmd-open-close.h"
2 #include "action/open-close-execution.h"
3 #include "action/open-util.h"
4 #include "cmd-action/cmd-attack.h"
5 #include "core/disturbance.h"
6 #include "core/player-redraw-types.h"
7 #include "floor/geometry.h"
8 #include "game-option/disturbance-options.h"
9 #include "game-option/input-options.h"
10 #include "grid/feature.h"
11 #include "grid/grid.h"
12 #include "inventory/inventory-object.h"
13 #include "inventory/inventory-slot-types.h"
14 #include "io/input-key-requester.h"
15 #include "player-status/player-energy.h"
16 #include "player/attack-defense-types.h"
17 #include "player/special-defense-types.h"
18 #include "specific-object/chest.h"
19 #include "status/action-setter.h"
20 #include "status/experience.h"
21 #include "system/floor-type-definition.h"
22 #include "system/object-type-definition.h"
23 #include "system/player-type-definition.h"
24 #include "target/target-getter.h"
25 #include "term/screen-processor.h"
26 #include "util/bit-flags-calculator.h"
27 #include "view/display-messages.h"
28
29 /*!
30  * @brief 箱を開ける実行処理 /
31  * Attempt to open the given chest at the given location
32  * @param y 箱の存在するマスのY座標
33  * @param x 箱の存在するマスのX座標
34  * @param o_idx 箱のオブジェクトID
35  * @return 箱が開かなかった場合TRUE / Returns TRUE if repeated commands may continue
36  * @details
37  * Assume there is no monster blocking the destination
38  */
39 static bool exe_open_chest(player_type *creature_ptr, POSITION y, POSITION x, OBJECT_IDX o_idx)
40 {
41     bool flag = true;
42     bool more = false;
43     object_type *o_ptr = &creature_ptr->current_floor_ptr->o_list[o_idx];
44     PlayerEnergy(creature_ptr).set_player_turn_energy(100);
45     if (o_ptr->pval > 0) {
46         flag = false;
47         int i = creature_ptr->skill_dis;
48         if (creature_ptr->blind || no_lite(creature_ptr))
49             i = i / 10;
50
51         if (creature_ptr->confused || creature_ptr->image)
52             i = i / 10;
53
54         int j = i - o_ptr->pval;
55         if (j < 2)
56             j = 2;
57
58         if (randint0(100) < j) {
59             msg_print(_("鍵をはずした。", "You have picked the lock."));
60             gain_exp(creature_ptr, 1);
61             flag = true;
62         } else {
63             more = true;
64             if (flush_failure)
65                 flush();
66
67             msg_print(_("鍵をはずせなかった。", "You failed to pick the lock."));
68         }
69     }
70
71     if (flag) {
72         chest_trap(creature_ptr, y, x, o_idx);
73         chest_death(creature_ptr, false, y, x, o_idx);
74     }
75
76     return more;
77 }
78
79 /*!
80  * @brief 「開ける」コマンドのメインルーチン /
81  * Open a closed/locked/jammed door or a closed/locked chest.
82  * @details
83  * Unlocking a locked door/chest is worth one experience point.
84  */
85 void do_cmd_open(player_type *creature_ptr)
86 {
87     POSITION y, x;
88     DIRECTION dir;
89     OBJECT_IDX o_idx;
90     bool more = false;
91     if (creature_ptr->wild_mode)
92         return;
93
94     if (creature_ptr->special_defense & KATA_MUSOU)
95         set_action(creature_ptr, ACTION_NONE);
96
97     if (easy_open) {
98         int num_doors = count_dt(creature_ptr, &y, &x, is_closed_door, false);
99         int num_chests = count_chests(creature_ptr, &y, &x, false);
100         if (num_doors || num_chests) {
101             bool too_many = (num_doors && num_chests) || (num_doors > 1) || (num_chests > 1);
102             if (!too_many)
103                 command_dir = coords_to_dir(creature_ptr, y, x);
104         }
105     }
106
107     if (command_arg) {
108         command_rep = command_arg - 1;
109         creature_ptr->redraw |= PR_STATE;
110         command_arg = 0;
111     }
112
113     if (get_rep_dir(creature_ptr, &dir, true)) {
114         FEAT_IDX feat;
115         grid_type *g_ptr;
116         y = creature_ptr->y + ddy[dir];
117         x = creature_ptr->x + ddx[dir];
118         g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
119         feat = get_feat_mimic(g_ptr);
120         o_idx = chest_check(creature_ptr->current_floor_ptr, y, x, false);
121         if (!has_flag(f_info[feat].flags, FF_OPEN) && !o_idx) {
122             msg_print(_("そこには開けるものが見当たらない。", "You see nothing there to open."));
123         } else if (g_ptr->m_idx && creature_ptr->riding != g_ptr->m_idx) {
124             PlayerEnergy(creature_ptr).set_player_turn_energy(100);
125             msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
126             do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
127         } else if (o_idx) {
128             more = exe_open_chest(creature_ptr, y, x, o_idx);
129         } else {
130             more = exe_open(creature_ptr, y, x);
131         }
132     }
133
134     if (!more)
135         disturb(creature_ptr, false, false);
136 }
137
138 /*!
139  * @brief 「閉じる」コマンドのメインルーチン /
140  * Close an open door.
141  * @details
142  * Unlocking a locked door/chest is worth one experience point.
143  */
144 void do_cmd_close(player_type *creature_ptr)
145 {
146     POSITION y, x;
147     DIRECTION dir;
148     bool more = false;
149     if (creature_ptr->wild_mode)
150         return;
151
152     if (creature_ptr->special_defense & KATA_MUSOU)
153         set_action(creature_ptr, ACTION_NONE);
154
155     if (easy_open && (count_dt(creature_ptr, &y, &x, is_open, false) == 1))
156         command_dir = coords_to_dir(creature_ptr, y, x);
157
158     if (command_arg) {
159         command_rep = command_arg - 1;
160         creature_ptr->redraw |= (PR_STATE);
161         command_arg = 0;
162     }
163
164     if (get_rep_dir(creature_ptr, &dir, false)) {
165         grid_type *g_ptr;
166         FEAT_IDX feat;
167         y = creature_ptr->y + ddy[dir];
168         x = creature_ptr->x + ddx[dir];
169         g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
170         feat = get_feat_mimic(g_ptr);
171         if (!has_flag(f_info[feat].flags, FF_CLOSE)) {
172             msg_print(_("そこには閉じるものが見当たらない。", "You see nothing there to close."));
173         } else if (g_ptr->m_idx) {
174             PlayerEnergy(creature_ptr).set_player_turn_energy(100);
175             msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
176             do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
177         } else {
178             more = exe_close(creature_ptr, y, x);
179         }
180     }
181
182     if (!more)
183         disturb(creature_ptr, false, false);
184 }
185
186 /*!
187  * @brief 箱、床のトラップ解除処理双方の統合メインルーチン /
188  * Disarms a trap, or chest
189  */
190 void do_cmd_disarm(player_type *creature_ptr)
191 {
192     POSITION y, x;
193     DIRECTION dir;
194     OBJECT_IDX o_idx;
195     bool more = false;
196     if (creature_ptr->wild_mode)
197         return;
198
199     if (creature_ptr->special_defense & KATA_MUSOU)
200         set_action(creature_ptr, ACTION_NONE);
201
202     if (easy_disarm) {
203         int num_traps = count_dt(creature_ptr, &y, &x, is_trap, true);
204         int num_chests = count_chests(creature_ptr, &y, &x, true);
205         if (num_traps || num_chests) {
206             bool too_many = (num_traps && num_chests) || (num_traps > 1) || (num_chests > 1);
207             if (!too_many)
208                 command_dir = coords_to_dir(creature_ptr, y, x);
209         }
210     }
211
212     if (command_arg) {
213         command_rep = command_arg - 1;
214         creature_ptr->redraw |= (PR_STATE);
215         command_arg = 0;
216     }
217
218     if (get_rep_dir(creature_ptr, &dir, true)) {
219         grid_type *g_ptr;
220         FEAT_IDX feat;
221         y = creature_ptr->y + ddy[dir];
222         x = creature_ptr->x + ddx[dir];
223         g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
224         feat = get_feat_mimic(g_ptr);
225         o_idx = chest_check(creature_ptr->current_floor_ptr, y, x, true);
226         if (!is_trap(creature_ptr, feat) && !o_idx) {
227             msg_print(_("そこには解除するものが見当たらない。", "You see nothing there to disarm."));
228         } else if (g_ptr->m_idx && creature_ptr->riding != g_ptr->m_idx) {
229             msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
230             do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
231         } else if (o_idx) {
232             more = exe_disarm_chest(creature_ptr, y, x, o_idx);
233         } else {
234             more = exe_disarm(creature_ptr, y, x, dir);
235         }
236     }
237
238     if (!more)
239         disturb(creature_ptr, false, false);
240 }
241
242 /*!
243  * @brief 「打ち破る」動作コマンドのメインルーチン /
244  * Bash open a door, success based on character strength
245  * @details
246  * <pre>
247  * For a closed door, pval is positive if locked; negative if stuck.
248  *
249  * For an open door, pval is positive for a broken door.
250  *
251  * A closed door can be opened - harder if locked. Any door might be
252  * bashed open (and thereby broken). Bashing a door is (potentially)
253  * faster! You move into the door way. To open a stuck door, it must
254  * be bashed. A closed door can be jammed (see do_cmd_spike()).
255  *
256  * Creatures can also open or bash doors, see elsewhere.
257  * </pre>
258  */
259 void do_cmd_bash(player_type *creature_ptr)
260 {
261     POSITION y, x;
262     DIRECTION dir;
263     grid_type *g_ptr;
264     bool more = false;
265     if (creature_ptr->wild_mode)
266         return;
267
268     if (creature_ptr->special_defense & KATA_MUSOU)
269         set_action(creature_ptr, ACTION_NONE);
270
271     if (command_arg) {
272         command_rep = command_arg - 1;
273         creature_ptr->redraw |= (PR_STATE);
274         command_arg = 0;
275     }
276
277     if (get_rep_dir(creature_ptr, &dir, false)) {
278         FEAT_IDX feat;
279         y = creature_ptr->y + ddy[dir];
280         x = creature_ptr->x + ddx[dir];
281         g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
282         feat = get_feat_mimic(g_ptr);
283         if (!has_flag(f_info[feat].flags, FF_BASH)) {
284             msg_print(_("そこには体当たりするものが見当たらない。", "You see nothing there to bash."));
285         } else if (g_ptr->m_idx) {
286             PlayerEnergy(creature_ptr).set_player_turn_energy(100);
287             msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
288             do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
289         } else {
290             more = exe_bash(creature_ptr, y, x, dir);
291         }
292     }
293
294     if (!more)
295         disturb(creature_ptr, false, false);
296 }
297
298
299 /*!
300  * @brief 「くさびを打つ」ために必要なオブジェクトを所持しているかどうかの判定を返す /
301  * Find the index of some "spikes", if possible.
302  * @param ip くさびとして打てるオブジェクトのID
303  * @return オブジェクトがある場合TRUEを返す
304  * @details
305  * <pre>
306  * Let user choose a pile of spikes, perhaps?
307  * </pre>
308  */
309 static bool get_spike(player_type *creature_ptr, INVENTORY_IDX *ip)
310 {
311     for (INVENTORY_IDX i = 0; i < INVEN_PACK; i++) {
312         object_type *o_ptr = &creature_ptr->inventory_list[i];
313         if (!o_ptr->k_idx)
314             continue;
315
316         if (o_ptr->tval == TV_SPIKE) {
317             *ip = i;
318             return true;
319         }
320     }
321
322     return false;
323 }
324
325 /*!
326  * @brief 「くさびを打つ」動作コマンドのメインルーチン /
327  * Jam a closed door with a spike
328  * @param creature_ptr プレーヤーへの参照ポインタ
329  * @details
330  * <pre>
331  * This command may NOT be repeated
332  * </pre>
333  */
334 void do_cmd_spike(player_type *creature_ptr)
335 {
336     DIRECTION dir;
337     if (creature_ptr->wild_mode)
338         return;
339
340     if (creature_ptr->special_defense & KATA_MUSOU)
341         set_action(creature_ptr, ACTION_NONE);
342
343     if (!get_rep_dir(creature_ptr, &dir, false))
344         return;
345
346     POSITION y = creature_ptr->y + ddy[dir];
347     POSITION x = creature_ptr->x + ddx[dir];
348     grid_type *g_ptr;
349     g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
350     FEAT_IDX feat = get_feat_mimic(g_ptr);
351     INVENTORY_IDX item;
352     if (!has_flag(f_info[feat].flags, FF_SPIKE)) {
353         msg_print(_("そこにはくさびを打てるものが見当たらない。", "You see nothing there to spike."));
354     } else if (!get_spike(creature_ptr, &item)) {
355         msg_print(_("くさびを持っていない!", "You have no spikes!"));
356     } else if (g_ptr->m_idx) {
357         PlayerEnergy(creature_ptr).set_player_turn_energy(100);
358         msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
359         do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
360     } else {
361         PlayerEnergy(creature_ptr).set_player_turn_energy(100);
362         msg_format(_("%sにくさびを打ち込んだ。", "You jam the %s with a spike."), f_info[feat].name.c_str());
363         cave_alter_feat(creature_ptr, y, x, FF_SPIKE);
364         vary_item(creature_ptr, item, -1);
365     }
366 }