OSDN Git Service

[Refactor] monster_idxと0との比較を関数化する
[hengbandforosx/hengbandosx.git] / src / cmd-action / cmd-others.cpp
1 /*!
2  * @brief その他の小さなコマンド処理群 (探索、汎用グリッド処理、自殺/引退/切腹)
3  * @date 2014/01/02
4  * @author
5  * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
6  *
7  * This software may be copied and distributed for educational, research,
8  * and not for profit purposes provided that this copyright and statement
9  * are included in all such copies.  Other copyrights may also apply.
10  */
11
12 #include "cmd-action/cmd-others.h"
13 #include "action/open-close-execution.h"
14 #include "action/tunnel-execution.h"
15 #include "cmd-action/cmd-attack.h"
16 #include "core/asking-player.h"
17 #include "core/disturbance.h"
18 #include "floor/geometry.h"
19 #include "game-option/game-play-options.h"
20 #include "grid/grid.h"
21 #include "io/input-key-acceptor.h"
22 #include "io/input-key-requester.h"
23 #include "io/write-diary.h"
24 #include "main/music-definitions-table.h"
25 #include "main/sound-of-music.h"
26 #include "monster/monster-util.h"
27 #include "player-base/player-class.h"
28 #include "player-info/samurai-data-type.h"
29 #include "player-status/player-energy.h"
30 #include "player/attack-defense-types.h"
31 #include "player/player-move.h"
32 #include "player/special-defense-types.h"
33 #include "status/action-setter.h"
34 #include "system/floor-type-definition.h"
35 #include "system/grid-type-definition.h"
36 #include "system/player-type-definition.h"
37 #include "system/redrawing-flags-updater.h"
38 #include "system/terrain-type-definition.h"
39 #include "target/target-getter.h"
40 #include "term/screen-processor.h"
41 #include "util/bit-flags-calculator.h"
42 #include "view/display-messages.h"
43 #include "world/world.h"
44
45 /*!
46  * @brief 探索コマンドのメインルーチン / Simple command to "search" for one turn
47  */
48 void do_cmd_search(PlayerType *player_ptr)
49 {
50     if (command_arg) {
51         command_rep = command_arg - 1;
52         RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::ACTION);
53         command_arg = 0;
54     }
55
56     PlayerEnergy(player_ptr).set_player_turn_energy(100);
57     search(player_ptr);
58
59     if (player_ptr->action == ACTION_SEARCH) {
60         search(player_ptr);
61     }
62 }
63
64 static bool exe_alter(PlayerType *player_ptr)
65 {
66     DIRECTION dir;
67     if (!get_rep_dir(player_ptr, &dir, true)) {
68         return false;
69     }
70
71     const Pos2D pos(player_ptr->y + ddy[dir], player_ptr->x + ddx[dir]);
72     const auto &grid = player_ptr->current_floor_ptr->get_grid(pos);
73     const auto &terrain = grid.get_terrain_mimic();
74     PlayerEnergy(player_ptr).set_player_turn_energy(100);
75     if (is_monster(grid.m_idx)) {
76         do_cmd_attack(player_ptr, pos.y, pos.x, HISSATSU_NONE);
77         return false;
78     }
79
80     if (terrain.flags.has(TerrainCharacteristics::OPEN)) {
81         return exe_open(player_ptr, pos.y, pos.x);
82     }
83
84     if (terrain.flags.has(TerrainCharacteristics::BASH)) {
85         return exe_bash(player_ptr, pos.y, pos.x, dir);
86     }
87
88     if (terrain.flags.has(TerrainCharacteristics::TUNNEL)) {
89         return exe_tunnel(player_ptr, pos.y, pos.x);
90     }
91
92     if (terrain.flags.has(TerrainCharacteristics::CLOSE)) {
93         return exe_close(player_ptr, pos.y, pos.x);
94     }
95
96     if (terrain.flags.has(TerrainCharacteristics::DISARM)) {
97         return exe_disarm(player_ptr, pos.y, pos.x, dir);
98     }
99
100     msg_print(_("何もない空中を攻撃した。", "You attack the empty air."));
101     return false;
102 }
103
104 /*!
105  * @brief 特定のマスに影響を及ぼすための汎用的コマンド / Manipulate an adjacent grid in some way
106  * @details
107  */
108 void do_cmd_alter(PlayerType *player_ptr)
109 {
110     PlayerClass(player_ptr).break_samurai_stance({ SamuraiStanceType::MUSOU });
111
112     if (command_arg) {
113         command_rep = command_arg - 1;
114         RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::ACTION);
115         command_arg = 0;
116     }
117
118     if (!exe_alter(player_ptr)) {
119         disturb(player_ptr, false, false);
120     }
121 }
122
123 /*!
124  * @brief 自殺/引退/切腹の確認
125  * @param なし
126  * @return 自殺/引退/切腹を実施するならTRUE、キャンセルならFALSE
127  */
128 static bool decide_suicide(void)
129 {
130     if (w_ptr->noscore) {
131         return true;
132     }
133
134     prt(_("確認のため '@' を押して下さい。", "Please verify SUICIDE by typing the '@' sign: "), 0, 0);
135     flush();
136     int i = inkey();
137     prt("", 0, 0);
138     return i == '@';
139 }
140
141 static void accept_winner_message(PlayerType *player_ptr)
142 {
143     if (!w_ptr->total_winner || !last_words) {
144         return;
145     }
146
147     play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_WINNER);
148     std::optional<std::string> buf;
149     while (true) {
150         buf = input_string(_("*勝利*メッセージ: ", "*Winning* message: "), 1024);
151         if (!buf) {
152             continue;
153         }
154
155         if (input_check_strict(player_ptr, _("よろしいですか?", "Are you sure? "), UserCheck::NO_HISTORY)) {
156             break;
157         }
158     }
159
160     if (!buf->empty()) {
161         player_ptr->last_message = *buf;
162         msg_print(player_ptr->last_message);
163     }
164 }
165
166 /*!
167  * @brief 自殺するコマンドのメインルーチン
168  * commit suicide
169  * @details
170  */
171 void do_cmd_suicide(PlayerType *player_ptr)
172 {
173     flush();
174     if (w_ptr->total_winner) {
175         if (!input_check_strict(player_ptr, _("引退しますか? ", "Do you want to retire? "), UserCheck::NO_HISTORY)) {
176             return;
177         }
178     } else {
179         if (!input_check(_("本当に自殺しますか?", "Do you really want to commit suicide? "))) {
180             return;
181         }
182     }
183
184     if (!decide_suicide()) {
185         return;
186     }
187
188     player_ptr->last_message = "";
189     player_ptr->playing = false;
190     player_ptr->is_dead = true;
191     player_ptr->leaving = true;
192     if (w_ptr->total_winner) {
193         accept_winner_message(player_ptr);
194         w_ptr->add_retired_class(player_ptr->pclass);
195     } else {
196         play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_GAMEOVER);
197         exe_write_diary(player_ptr, DiaryKind::DESCRIPTION, 0, _("ダンジョンの探索に絶望して自殺した。", "gave up all hope to commit suicide."));
198         exe_write_diary(player_ptr, DiaryKind::GAMESTART, 1, _("-------- ゲームオーバー --------", "--------   Game  Over   --------"));
199         exe_write_diary(player_ptr, DiaryKind::DESCRIPTION, 1, "\n\n\n\n");
200     }
201
202     player_ptr->died_from = _("途中終了", "Quitting");
203 }