OSDN Git Service

[Refactor] struct player_type を class PlayerType に置換。
[hengbandforosx/hengbandosx.git] / src / io / input-key-requester.cpp
1 #include "io/input-key-requester.h"
2 #include "cmd-io/cmd-menu-content-table.h"
3 #include "cmd-io/macro-util.h"
4 #include "core/asking-player.h" //!< @todo 相互依存している、後で何とかする.
5 #include "core/player-processor.h"
6 #include "core/stuff-handler.h"
7 #include "core/window-redrawer.h"
8 #include "game-option/game-play-options.h"
9 #include "game-option/input-options.h"
10 #include "game-option/map-screen-options.h"
11 #include "inventory/inventory-slot-types.h"
12 #include "io/cursor.h"
13 #include "io/input-key-acceptor.h"
14 #include "main/sound-of-music.h"
15 #include "save/save.h"
16 #include "system/floor-type-definition.h" //!< @todo 違和感、後で調査する.
17 #include "system/object-type-definition.h"
18 #include "system/player-type-definition.h"
19 #include "term/screen-processor.h" //!< @todo 相互依存している、後で何とかする.
20 #include "util/int-char-converter.h"
21 #include "util/quarks.h"
22 #include "util/string-processor.h"
23 #include "view/display-messages.h"
24 #include "window/display-sub-windows.h"
25 #include "window/main-window-util.h"
26 #include "world/world.h"
27
28 /*
29  * Keymaps for each "mode" associated with each keypress.
30  */
31 concptr keymap_act[KEYMAP_MODES][256];
32
33 bool use_menu;
34
35 int16_t command_cmd; /* Current "Angband Command" */
36 COMMAND_ARG command_arg; /*!< 各種コマンドの汎用的な引数として扱う / Gives argument of current command */
37 COMMAND_NUM command_rep; /*!< 各種コマンドの汎用的なリピート数として扱う / Gives repetition of current command */
38 DIRECTION command_dir; /*!< 各種コマンドの汎用的な方向値処理として扱う/ Gives direction of current command */
39 int16_t command_see; /* アイテム使用時等にリストを表示させるかどうか (ゲームオプションの他、様々なタイミングでONになったりOFFになったりする模様……) */
40 int16_t command_wrk; /* アイテムの使用許可状況 (ex. 装備品のみ、床上もOK等) */
41 TERM_LEN command_gap = 999; /* アイテムの表示に使う (詳細未調査) */
42 int16_t command_new; /* Command chaining from inven/equip view */
43
44 /*
45  * Hack -- special buffer to hold the action of the current keymap
46  */
47 static char request_command_buffer[256];
48
49 static char inkey_from_menu(PlayerType *player_ptr)
50 {
51     char cmd;
52     int basey, basex;
53     int num = 0, max_num, old_num = 0;
54     int menu = 0;
55     bool kisuu;
56
57     if (player_ptr->y - panel_row_min > 10)
58         basey = 2;
59     else
60         basey = 13;
61     basex = 15;
62
63     prt("", 0, 0);
64     screen_save();
65
66     floor_type *floor_ptr = player_ptr->current_floor_ptr;
67     while (true) {
68         int i;
69         char sub_cmd;
70         concptr menu_name;
71         if (!menu)
72             old_num = num;
73         put_str("+----------------------------------------------------+", basey, basex);
74         put_str("|                                                    |", basey + 1, basex);
75         put_str("|                                                    |", basey + 2, basex);
76         put_str("|                                                    |", basey + 3, basex);
77         put_str("|                                                    |", basey + 4, basex);
78         put_str("|                                                    |", basey + 5, basex);
79         put_str("+----------------------------------------------------+", basey + 6, basex);
80
81         for (i = 0; i < 10; i++) {
82             int hoge;
83             if (!menu_info[menu][i].cmd)
84                 break;
85             menu_name = menu_info[menu][i].name;
86             for (hoge = 0;; hoge++) {
87                 if (!special_menu_info[hoge].name[0])
88                     break;
89                 if ((menu != special_menu_info[hoge].window) || (i != special_menu_info[hoge].number))
90                     continue;
91                 switch (special_menu_info[hoge].jouken) {
92                 case MENU_CLASS:
93                     if (player_ptr->pclass == special_menu_info[hoge].jouken_naiyou)
94                         menu_name = special_menu_info[hoge].name;
95                     break;
96                 case MENU_WILD:
97                     if (!floor_ptr->dun_level && !floor_ptr->inside_arena && !floor_ptr->inside_quest) {
98                         auto can_do_in_wilderness = enum2i(special_menu_info[hoge].jouken_naiyou) > 0;
99                         if (player_ptr->wild_mode == can_do_in_wilderness) {
100                             menu_name = special_menu_info[hoge].name;
101                         }
102                     }
103                     break;
104                 default:
105                     break;
106                 }
107             }
108
109             put_str(menu_name, basey + 1 + i / 2, basex + 4 + (i % 2) * 24);
110         }
111
112         max_num = i;
113         kisuu = (max_num % 2) == 1;
114         put_str(_("》", "> "), basey + 1 + num / 2, basex + 2 + (num % 2) * 24);
115
116         move_cursor_relative(player_ptr->y, player_ptr->x);
117         sub_cmd = inkey();
118         if ((sub_cmd == ' ') || (sub_cmd == 'x') || (sub_cmd == 'X') || (sub_cmd == '\r') || (sub_cmd == '\n')) {
119             if (menu_info[menu][num].fin) {
120                 cmd = menu_info[menu][num].cmd;
121                 use_menu = true;
122                 break;
123             } else {
124                 menu = menu_info[menu][num].cmd;
125                 num = 0;
126                 basey += 2;
127                 basex += 8;
128             }
129         } else if ((sub_cmd == ESCAPE) || (sub_cmd == 'z') || (sub_cmd == 'Z') || (sub_cmd == '0')) {
130             if (!menu) {
131                 cmd = ESCAPE;
132                 break;
133             } else {
134                 menu = 0;
135                 num = old_num;
136                 basey -= 2;
137                 basex -= 8;
138                 screen_load();
139                 screen_save();
140             }
141         } else if ((sub_cmd == '2') || (sub_cmd == 'j') || (sub_cmd == 'J')) {
142             if (kisuu) {
143                 if (num % 2)
144                     num = (num + 2) % (max_num - 1);
145                 else
146                     num = (num + 2) % (max_num + 1);
147             } else
148                 num = (num + 2) % max_num;
149         } else if ((sub_cmd == '8') || (sub_cmd == 'k') || (sub_cmd == 'K')) {
150             if (kisuu) {
151                 if (num % 2)
152                     num = (num + max_num - 3) % (max_num - 1);
153                 else
154                     num = (num + max_num - 1) % (max_num + 1);
155             } else
156                 num = (num + max_num - 2) % max_num;
157         } else if ((sub_cmd == '4') || (sub_cmd == '6') || (sub_cmd == 'h') || (sub_cmd == 'H') || (sub_cmd == 'l') || (sub_cmd == 'L')) {
158             if ((num % 2) || (num == max_num - 1)) {
159                 num--;
160             } else if (num < max_num - 1) {
161                 num++;
162             }
163         }
164     }
165
166     screen_load();
167     if (!inkey_next)
168         inkey_next = "";
169
170     return (cmd);
171 }
172
173 /*
174  * Request a command from the user.
175  *
176  * Sets player_ptr->command_cmd, player_ptr->command_dir, player_ptr->command_rep,
177  * player_ptr->command_arg.  May modify player_ptr->command_new.
178  *
179  * Note that "caret" ("^") is treated specially, and is used to
180  * allow manual input of control characters.  This can be used
181  * on many machines to request repeated tunneling (Ctrl-H) and
182  * on the Macintosh to request "Control-Caret".
183  *
184  * Note that "backslash" is treated specially, and is used to bypass any
185  * keymap entry for the following character.  This is useful for macros.
186  *
187  * Note that this command is used both in the dungeon and in
188  * stores, and must be careful to work in both situations.
189  *
190  * Note that "player_ptr->command_new" may not work any more.
191  */
192 void request_command(PlayerType *player_ptr, int shopping)
193 {
194     int16_t cmd;
195     int mode;
196
197     concptr act;
198
199 #ifdef JP
200     int caretcmd = 0;
201 #endif
202     if (rogue_like_commands) {
203         mode = KEYMAP_MODE_ROGUE;
204     } else {
205         mode = KEYMAP_MODE_ORIG;
206     }
207
208     command_cmd = 0;
209     command_arg = 0;
210     command_dir = 0;
211     use_menu = false;
212
213     while (true) {
214         if (!macro_running() && !command_new && auto_debug_save && (!inkey_next || *inkey_next == '\0')) {
215             save_player(player_ptr, SAVE_TYPE_DEBUG);
216         }
217         if (fresh_once && macro_running()) {
218             stop_term_fresh();
219         }
220
221         if (command_new) {
222             msg_erase();
223             cmd = command_new;
224             command_new = 0;
225         } else {
226             msg_flag = false;
227             num_more = 0;
228             inkey_flag = true;
229             term_fresh();
230             cmd = inkey(true);
231             if (!shopping && command_menu && ((cmd == '\r') || (cmd == '\n') || (cmd == 'x') || (cmd == 'X')) && !keymap_act[mode][(byte)(cmd)])
232                 cmd = inkey_from_menu(player_ptr);
233         }
234
235         prt("", 0, 0);
236         if (cmd == '0') {
237             COMMAND_ARG old_arg = command_arg;
238             command_arg = 0;
239             prt(_("回数: ", "Count: "), 0, 0);
240             while (true) {
241                 cmd = inkey();
242                 if ((cmd == 0x7F) || (cmd == KTRL('H'))) {
243                     command_arg = command_arg / 10;
244                     prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
245                 } else if (cmd >= '0' && cmd <= '9') {
246                     if (command_arg >= 1000) {
247                         bell();
248                         command_arg = 9999;
249                     } else {
250                         command_arg = command_arg * 10 + D2I(cmd);
251                     }
252
253                     prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
254                 } else {
255                     break;
256                 }
257             }
258
259             if (command_arg == 0) {
260                 command_arg = 99;
261                 prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
262             }
263
264             if (old_arg != 0) {
265                 command_arg = old_arg;
266                 prt(format(_("回数: %d", "Count: %d"), command_arg), 0, 0);
267             }
268
269             if ((cmd == ' ') || (cmd == '\n') || (cmd == '\r')) {
270                 if (!get_com(_("コマンド: ", "Command: "), (char *)&cmd, false)) {
271                     command_arg = 0;
272                     continue;
273                 }
274             }
275         }
276
277         if (cmd == '\\') {
278             (void)get_com(_("コマンド: ", "Command: "), (char *)&cmd, false);
279             if (!inkey_next)
280                 inkey_next = "";
281         }
282
283         if (cmd == '^') {
284             if (get_com(_("CTRL: ", "Control: "), (char *)&cmd, false))
285                 cmd = KTRL(cmd);
286         }
287
288         act = keymap_act[mode][(byte)(cmd)];
289         if (act && !inkey_next) {
290             (void)strnfmt(request_command_buffer, 256, "%s", act);
291             inkey_next = request_command_buffer;
292             continue;
293         }
294
295         if (!cmd)
296             continue;
297
298         command_cmd = (byte)cmd;
299         break;
300     }
301
302     if (always_repeat && (command_arg <= 0)) {
303         if (angband_strchr("TBDoc+", (char)command_cmd)) {
304             command_arg = 99;
305         }
306     }
307
308     if (shopping == 1) {
309         switch (command_cmd) {
310         case 'p':
311             command_cmd = 'g';
312             break;
313
314         case 'm':
315             command_cmd = 'g';
316             break;
317
318         case 's':
319             command_cmd = 'd';
320             break;
321         }
322     }
323
324 #ifdef JP
325     for (int i = 0; i < 256; i++) {
326         concptr s;
327         if ((s = keymap_act[mode][i]) != nullptr) {
328             if (*s == command_cmd && *(s + 1) == 0) {
329                 caretcmd = i;
330                 break;
331             }
332         }
333     }
334
335     if (!caretcmd)
336         caretcmd = command_cmd;
337 #endif
338
339     for (int i = INVEN_MAIN_HAND; i < INVEN_TOTAL; i++) {
340         object_type *o_ptr = &player_ptr->inventory_list[i];
341         if (!o_ptr->k_idx)
342             continue;
343
344         if (!o_ptr->inscription)
345             continue;
346
347         concptr s = quark_str(o_ptr->inscription);
348         s = angband_strchr(s, '^');
349         while (s) {
350 #ifdef JP
351             if ((s[1] == caretcmd) || (s[1] == '*'))
352 #else
353             if ((s[1] == command_cmd) || (s[1] == '*'))
354 #endif
355             {
356                 if (!get_check(_("本当ですか? ", "Are you sure? "))) {
357                     command_cmd = ' ';
358                 }
359             }
360
361             s = angband_strchr(s + 1, '^');
362         }
363     }
364
365     prt("", 0, 0);
366 }