2 * @file open-close-execution.cpp
8 #include "action/open-close-execution.h"
9 #include "action/movement-execution.h"
10 #include "combat/attack-power-table.h"
11 #include "game-option/disturbance-options.h"
12 #include "game-option/input-options.h"
13 #include "grid/feature.h"
14 #include "grid/grid.h"
15 #include "grid/trap.h"
16 #include "main/sound-definitions-table.h"
17 #include "main/sound-of-music.h"
18 #include "perception/object-perception.h"
19 #include "player-base/player-class.h"
20 #include "player-status/player-energy.h"
21 #include "player/player-status-table.h"
22 #include "specific-object/chest.h"
23 #include "status/bad-status-setter.h"
24 #include "status/experience.h"
25 #include "system/floor-type-definition.h"
26 #include "system/grid-type-definition.h"
27 #include "system/item-entity.h"
28 #include "system/player-type-definition.h"
29 #include "system/terrain-type-definition.h"
30 #include "term/screen-processor.h"
31 #include "timed-effect/player-blindness.h"
32 #include "timed-effect/player-confusion.h"
33 #include "timed-effect/player-hallucination.h"
34 #include "timed-effect/timed-effects.h"
35 #include "util/bit-flags-calculator.h"
36 #include "view/display-messages.h"
39 * @brief 「開ける」動作コマンドのサブルーチン /
40 * Perform the basic "open" command on doors
41 * @param y 対象を行うマスのY座標
42 * @param x 対象を行うマスのX座標
43 * @return 連続でコマンドを実行する時のみTRUE、1回きりの時はFALSE
45 bool exe_open(PlayerType *player_ptr, POSITION y, POSITION x)
47 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
48 auto *f_ptr = &terrains_info[g_ptr->feat];
49 PlayerEnergy(player_ptr).set_player_turn_energy(100);
50 if (f_ptr->flags.has_not(TerrainCharacteristics::OPEN)) {
51 msg_format(_("%sはがっちりと閉じられているようだ。", "The %s appears to be stuck."), terrains_info[g_ptr->get_feat_mimic()].name.data());
56 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::OPEN);
57 sound(SOUND_OPENDOOR);
61 int i = player_ptr->skill_dis;
62 const auto effects = player_ptr->effects();
63 if (effects->blindness()->is_blind() || no_lite(player_ptr)) {
67 if (effects->confusion()->is_confused() || effects->hallucination()->is_hallucinated()) {
77 if (randint0(100) >= j) {
82 msg_print(_("鍵をはずせなかった。", "You failed to pick the lock."));
86 msg_print(_("鍵をはずした。", "You have picked the lock."));
87 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::OPEN);
88 sound(SOUND_OPENDOOR);
89 gain_exp(player_ptr, 1);
94 * @brief 「閉じる」動作コマンドのサブルーチン /
95 * Perform the basic "close" command
96 * @param y 対象を行うマスのY座標
97 * @param x 対象を行うマスのX座標
98 * @return 実際に処理が行われた場合TRUEを返す。
100 * Assume destination is an open/broken door
101 * Assume there is no monster blocking the destination
102 * Returns TRUE if repeated commands may continue
103 * @todo 常にFALSEを返している
105 bool exe_close(PlayerType *player_ptr, POSITION y, POSITION x)
107 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
108 FEAT_IDX old_feat = g_ptr->feat;
110 PlayerEnergy(player_ptr).set_player_turn_energy(100);
111 if (terrains_info[old_feat].flags.has_not(TerrainCharacteristics::CLOSE)) {
115 int16_t closed_feat = feat_state(player_ptr->current_floor_ptr, old_feat, TerrainCharacteristics::CLOSE);
116 if ((!g_ptr->o_idx_list.empty() || g_ptr->is_object()) && (closed_feat != old_feat) && terrains_info[closed_feat].flags.has_not(TerrainCharacteristics::DROP)) {
117 msg_print(_("何かがつっかえて閉まらない。", "Something prevents it from closing."));
121 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::CLOSE);
122 if (old_feat == g_ptr->feat) {
123 msg_print(_("ドアは壊れてしまっている。", "The door appears to be broken."));
125 sound(SOUND_SHUTDOOR);
132 * @brief 移動処理による簡易な「開く」処理 /
134 * @return 開く処理が実際に試みられた場合TRUEを返す
137 * If there is a jammed/closed/locked door at the given location,
138 * then attempt to unlock/open it. Return TRUE if an attempt was
139 * made (successful or not), otherwise return FALSE.
141 * The code here should be nearly identical to that in
142 * do_cmd_open_test() and exe_open().
145 bool easy_open_door(PlayerType *player_ptr, POSITION y, POSITION x)
148 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
149 auto *f_ptr = &terrains_info[g_ptr->feat];
150 if (!is_closed_door(player_ptr, g_ptr->feat)) {
154 if (f_ptr->flags.has_not(TerrainCharacteristics::OPEN)) {
155 msg_format(_("%sはがっちりと閉じられているようだ。", "The %s appears to be stuck."), terrains_info[g_ptr->get_feat_mimic()].name.data());
156 } else if (f_ptr->power) {
157 i = player_ptr->skill_dis;
158 const auto effects = player_ptr->effects();
159 if (effects->blindness()->is_blind() || no_lite(player_ptr)) {
163 if (effects->confusion()->is_confused() || effects->hallucination()->is_hallucinated()) {
173 if (randint0(100) < j) {
174 msg_print(_("鍵をはずした。", "You have picked the lock."));
175 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::OPEN);
176 sound(SOUND_OPENDOOR);
177 gain_exp(player_ptr, 1);
183 msg_print(_("鍵をはずせなかった。", "You failed to pick the lock."));
186 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::OPEN);
187 sound(SOUND_OPENDOOR);
194 * @brief 箱のトラップを解除する実行処理 /
195 * Perform the basic "disarm" command
196 * @param y 解除を行うマスのY座標
197 * @param x 解除を行うマスのX座標
198 * @param o_idx 箱のオブジェクトID
199 * @return ターンを消費する処理が行われた場合TRUEを返す
202 * Assume destination is a visible trap
203 * Assume there is no monster blocking the destination
204 * Returns TRUE if repeated commands may continue
207 bool exe_disarm_chest(PlayerType *player_ptr, POSITION y, POSITION x, OBJECT_IDX o_idx)
210 auto *o_ptr = &player_ptr->current_floor_ptr->o_list[o_idx];
211 PlayerEnergy(player_ptr).set_player_turn_energy(100);
212 int i = player_ptr->skill_dis;
213 const auto effects = player_ptr->effects();
214 if (effects->blindness()->is_blind() || no_lite(player_ptr)) {
218 if (effects->confusion()->is_confused() || effects->hallucination()->is_hallucinated()) {
222 int j = i - o_ptr->pval;
227 if (!o_ptr->is_known()) {
228 msg_print(_("トラップが見あたらない。", "I don't see any traps."));
229 } else if (o_ptr->pval <= 0) {
230 msg_print(_("箱にはトラップが仕掛けられていない。", "The chest is not trapped."));
231 } else if (chest_traps[o_ptr->pval].none()) {
232 msg_print(_("箱にはトラップが仕掛けられていない。", "The chest is not trapped."));
233 } else if (randint0(100) < j) {
234 msg_print(_("箱に仕掛けられていたトラップを解除した。", "You have disarmed the chest."));
235 gain_exp(player_ptr, o_ptr->pval);
236 o_ptr->pval = (0 - o_ptr->pval);
237 } else if ((i > 5) && (randint1(i) > 5)) {
243 msg_print(_("箱のトラップ解除に失敗した。", "You failed to disarm the chest."));
245 msg_print(_("トラップを作動させてしまった!", "You set off a trap!"));
247 Chest(player_ptr).chest_trap(y, x, o_idx);
254 * @brief 箱のトラップを解除するコマンドのサブルーチン /
255 * Perform the basic "disarm" command
256 * @param y 解除を行うマスのY座標
257 * @param x 解除を行うマスのX座標
258 * @param dir プレイヤーからみた方向ID
259 * @return ターンを消費する処理が行われた場合TRUEを返す
262 * Assume destination is a visible trap
263 * Assume there is no monster blocking the destination
264 * Returns TRUE if repeated commands may continue
268 bool exe_disarm(PlayerType *player_ptr, POSITION y, POSITION x, DIRECTION dir)
270 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
271 auto *f_ptr = &terrains_info[g_ptr->feat];
272 concptr name = f_ptr->name.data();
273 int power = f_ptr->power;
275 int i = player_ptr->skill_dis;
276 PlayerEnergy(player_ptr).set_player_turn_energy(100);
277 auto effects = player_ptr->effects();
278 if (effects->blindness()->is_blind() || no_lite(player_ptr)) {
282 if (effects->confusion()->is_confused() || effects->hallucination()->is_hallucinated()) {
291 if (randint0(100) < j) {
292 msg_format(_("%sを解除した。", "You have disarmed the %s."), name);
293 gain_exp(player_ptr, power);
294 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::DISARM);
295 exe_movement(player_ptr, dir, easy_disarm, false);
296 } else if ((i > 5) && (randint1(i) > 5)) {
301 msg_format(_("%sの解除に失敗した。", "You failed to disarm the %s."), name);
304 msg_format(_("%sを作動させてしまった!", "You set off the %s!"), name);
305 exe_movement(player_ptr, dir, easy_disarm, false);
312 * @brief 「打ち破る」動作コマンドのサブルーチン /
313 * Perform the basic "bash" command
314 * @param y 対象を行うマスのY座標
315 * @param x 対象を行うマスのX座標
316 * @param dir プレイヤーから見たターゲットの方角ID
317 * @return 実際に処理が行われた場合TRUEを返す。
320 * Assume destination is a closed/locked/jammed door
321 * Assume there is no monster blocking the destination
322 * Returns TRUE if repeated commands may continue
325 bool exe_bash(PlayerType *player_ptr, POSITION y, POSITION x, DIRECTION dir)
327 auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
328 auto *f_ptr = &terrains_info[g_ptr->feat];
329 int bash = adj_str_blow[player_ptr->stat_index[A_STR]];
330 int temp = f_ptr->power;
332 concptr name = terrains_info[g_ptr->get_feat_mimic()].name.data();
333 PlayerEnergy(player_ptr).set_player_turn_energy(100);
334 msg_format(_("%sに体当たりをした!", "You smash into the %s!"), name);
335 temp = (bash - (temp * 10));
336 if (PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER)) {
344 if (randint0(100) < temp) {
345 msg_format(_("%sを壊した!", "The %s crashes open!"), name);
346 sound(f_ptr->flags.has(TerrainCharacteristics::GLASS) ? SOUND_GLASS : SOUND_OPENDOOR);
347 if ((randint0(100) < 50) || (feat_state(player_ptr->current_floor_ptr, g_ptr->feat, TerrainCharacteristics::OPEN) == g_ptr->feat) || f_ptr->flags.has(TerrainCharacteristics::GLASS)) {
348 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::BASH);
350 cave_alter_feat(player_ptr, y, x, TerrainCharacteristics::OPEN);
353 exe_movement(player_ptr, dir, false, false);
354 } else if (randint0(100) < adj_dex_safe[player_ptr->stat_index[A_DEX]] + player_ptr->lev) {
355 msg_format(_("この%sは頑丈だ。", "The %s holds firm."), name);
358 msg_print(_("体のバランスをくずしてしまった。", "You are off-balance."));
359 (void)BadStatusSetter(player_ptr).mod_paralysis(2 + randint0(2));