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/attack-defense-types.h"
16 #include "player/player-status.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"
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
37 * Assume there is no monster blocking the destination
39 static bool exe_open_chest(player_type *creature_ptr, POSITION y, POSITION x, OBJECT_IDX o_idx)
43 object_type *o_ptr = &creature_ptr->current_floor_ptr->o_list[o_idx];
44 take_turn(creature_ptr, 100);
45 if (o_ptr->pval > 0) {
47 int i = creature_ptr->skill_dis;
48 if (creature_ptr->blind || no_lite(creature_ptr))
51 if (creature_ptr->confused || creature_ptr->image)
54 int j = i - o_ptr->pval;
58 if (randint0(100) < j) {
59 msg_print(_("鍵をはずした。", "You have picked the lock."));
60 gain_exp(creature_ptr, 1);
67 msg_print(_("鍵をはずせなかった。", "You failed to pick the lock."));
72 chest_trap(creature_ptr, y, x, o_idx);
73 chest_death(creature_ptr, FALSE, y, x, o_idx);
80 * @brief 「開ける」コマンドのメインルーチン /
81 * Open a closed/locked/jammed door or a closed/locked chest.
84 * Unlocking a locked door/chest is worth one experience point.
86 void do_cmd_open(player_type *creature_ptr)
92 if (creature_ptr->wild_mode)
95 if (creature_ptr->special_defense & KATA_MUSOU)
96 set_action(creature_ptr, ACTION_NONE);
99 int num_doors = count_dt(creature_ptr, &y, &x, is_closed_door, FALSE);
100 int num_chests = count_chests(creature_ptr, &y, &x, FALSE);
101 if (num_doors || num_chests) {
102 bool too_many = (num_doors && num_chests) || (num_doors > 1) || (num_chests > 1);
104 command_dir = coords_to_dir(creature_ptr, y, x);
109 command_rep = command_arg - 1;
110 creature_ptr->redraw |= PR_STATE;
114 if (get_rep_dir(creature_ptr, &dir, TRUE)) {
117 y = creature_ptr->y + ddy[dir];
118 x = creature_ptr->x + ddx[dir];
119 g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
120 feat = get_feat_mimic(g_ptr);
121 o_idx = chest_check(creature_ptr->current_floor_ptr, y, x, FALSE);
122 if (!has_flag(f_info[feat].flags, FF_OPEN) && !o_idx) {
123 msg_print(_("そこには開けるものが見当たらない。", "You see nothing there to open."));
124 } else if (g_ptr->m_idx && creature_ptr->riding != g_ptr->m_idx) {
125 take_turn(creature_ptr, 100);
126 msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
127 do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
129 more = exe_open_chest(creature_ptr, y, x, o_idx);
131 more = exe_open(creature_ptr, y, x);
136 disturb(creature_ptr, FALSE, FALSE);
140 * @brief 「閉じる」コマンドのメインルーチン /
141 * Close an open door.
144 * Unlocking a locked door/chest is worth one experience point.
146 void do_cmd_close(player_type *creature_ptr)
151 if (creature_ptr->wild_mode)
154 if (creature_ptr->special_defense & KATA_MUSOU)
155 set_action(creature_ptr, ACTION_NONE);
157 if (easy_open && (count_dt(creature_ptr, &y, &x, is_open, FALSE) == 1))
158 command_dir = coords_to_dir(creature_ptr, y, x);
161 command_rep = command_arg - 1;
162 creature_ptr->redraw |= (PR_STATE);
166 if (get_rep_dir(creature_ptr, &dir, FALSE)) {
169 y = creature_ptr->y + ddy[dir];
170 x = creature_ptr->x + ddx[dir];
171 g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
172 feat = get_feat_mimic(g_ptr);
173 if (!has_flag(f_info[feat].flags, FF_CLOSE)) {
174 msg_print(_("そこには閉じるものが見当たらない。", "You see nothing there to close."));
175 } else if (g_ptr->m_idx) {
176 take_turn(creature_ptr, 100);
177 msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
178 do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
180 more = exe_close(creature_ptr, y, x);
185 disturb(creature_ptr, FALSE, FALSE);
189 * @brief 箱、床のトラップ解除処理双方の統合メインルーチン /
190 * Disarms a trap, or chest
193 void do_cmd_disarm(player_type *creature_ptr)
199 if (creature_ptr->wild_mode)
202 if (creature_ptr->special_defense & KATA_MUSOU)
203 set_action(creature_ptr, ACTION_NONE);
206 int num_traps = count_dt(creature_ptr, &y, &x, is_trap, TRUE);
207 int num_chests = count_chests(creature_ptr, &y, &x, TRUE);
208 if (num_traps || num_chests) {
209 bool too_many = (num_traps && num_chests) || (num_traps > 1) || (num_chests > 1);
211 command_dir = coords_to_dir(creature_ptr, y, x);
216 command_rep = command_arg - 1;
217 creature_ptr->redraw |= (PR_STATE);
221 if (get_rep_dir(creature_ptr, &dir, TRUE)) {
224 y = creature_ptr->y + ddy[dir];
225 x = creature_ptr->x + ddx[dir];
226 g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
227 feat = get_feat_mimic(g_ptr);
228 o_idx = chest_check(creature_ptr->current_floor_ptr, y, x, TRUE);
229 if (!is_trap(creature_ptr, feat) && !o_idx) {
230 msg_print(_("そこには解除するものが見当たらない。", "You see nothing there to disarm."));
231 } else if (g_ptr->m_idx && creature_ptr->riding != g_ptr->m_idx) {
232 msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
233 do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
235 more = exe_disarm_chest(creature_ptr, y, x, o_idx);
237 more = exe_disarm(creature_ptr, y, x, dir);
242 disturb(creature_ptr, FALSE, FALSE);
246 * @brief 「打ち破る」動作コマンドのメインルーチン /
247 * Bash open a door, success based on character strength
251 * For a closed door, pval is positive if locked; negative if stuck.
253 * For an open door, pval is positive for a broken door.
255 * A closed door can be opened - harder if locked. Any door might be
256 * bashed open (and thereby broken). Bashing a door is (potentially)
257 * faster! You move into the door way. To open a stuck door, it must
258 * be bashed. A closed door can be jammed (see do_cmd_spike()).
260 * Creatures can also open or bash doors, see elsewhere.
263 void do_cmd_bash(player_type *creature_ptr)
269 if (creature_ptr->wild_mode)
272 if (creature_ptr->special_defense & KATA_MUSOU)
273 set_action(creature_ptr, ACTION_NONE);
276 command_rep = command_arg - 1;
277 creature_ptr->redraw |= (PR_STATE);
281 if (get_rep_dir(creature_ptr, &dir, FALSE)) {
283 y = creature_ptr->y + ddy[dir];
284 x = creature_ptr->x + ddx[dir];
285 g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
286 feat = get_feat_mimic(g_ptr);
287 if (!has_flag(f_info[feat].flags, FF_BASH)) {
288 msg_print(_("そこには体当たりするものが見当たらない。", "You see nothing there to bash."));
289 } else if (g_ptr->m_idx) {
290 take_turn(creature_ptr, 100);
291 msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
292 do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
294 more = exe_bash(creature_ptr, y, x, dir);
299 disturb(creature_ptr, FALSE, FALSE);
304 * @brief 「くさびを打つ」ために必要なオブジェクトを所持しているかどうかの判定を返す /
305 * Find the index of some "spikes", if possible.
306 * @param ip くさびとして打てるオブジェクトのID
307 * @return オブジェクトがある場合TRUEを返す
310 * Let user choose a pile of spikes, perhaps?
313 static bool get_spike(player_type *creature_ptr, INVENTORY_IDX *ip)
315 for (INVENTORY_IDX i = 0; i < INVEN_PACK; i++) {
316 object_type *o_ptr = &creature_ptr->inventory_list[i];
320 if (o_ptr->tval == TV_SPIKE) {
330 * @brief 「くさびを打つ」動作コマンドのメインルーチン /
331 * Jam a closed door with a spike
332 * @param creature_ptr プレーヤーへの参照ポインタ
336 * This command may NOT be repeated
339 void do_cmd_spike(player_type *creature_ptr)
342 if (creature_ptr->wild_mode)
345 if (creature_ptr->special_defense & KATA_MUSOU)
346 set_action(creature_ptr, ACTION_NONE);
348 if (!get_rep_dir(creature_ptr, &dir, FALSE))
351 POSITION y = creature_ptr->y + ddy[dir];
352 POSITION x = creature_ptr->x + ddx[dir];
354 g_ptr = &creature_ptr->current_floor_ptr->grid_array[y][x];
355 FEAT_IDX feat = get_feat_mimic(g_ptr);
357 if (!has_flag(f_info[feat].flags, FF_SPIKE)) {
358 msg_print(_("そこにはくさびを打てるものが見当たらない。", "You see nothing there to spike."));
359 } else if (!get_spike(creature_ptr, &item)) {
360 msg_print(_("くさびを持っていない!", "You have no spikes!"));
361 } else if (g_ptr->m_idx) {
362 take_turn(creature_ptr, 100);
363 msg_print(_("モンスターが立ちふさがっている!", "There is a monster in the way!"));
364 do_cmd_attack(creature_ptr, y, x, HISSATSU_NONE);
366 take_turn(creature_ptr, 100);
367 msg_format(_("%sにくさびを打ち込んだ。", "You jam the %s with a spike."), f_info[feat].name.c_str());
368 cave_alter_feat(creature_ptr, y, x, FF_SPIKE);
369 vary_item(creature_ptr, item, -1);