OSDN Git Service

[Refactor] enum classの型名変更 DF -> DungeonFeatureType
[hengbandforosx/hengbandosx.git] / src / io / input-key-processor.cpp
1 /*!
2  * @brief キー入力に応じてゲーム内コマンドを実行する
3  * @date 2020/05/10
4  * @author Hourier
5  * @todo Ctrl+C がShift+Q に認識されている。仕様の可能性も高いが要確認
6  */
7
8 #include "io/input-key-processor.h"
9 #include "autopick/autopick-pref-processor.h"
10 #include "cmd-action/cmd-hissatsu.h"
11 #include "cmd-action/cmd-mane.h"
12 #include "cmd-action/cmd-mind.h"
13 #include "cmd-action/cmd-move.h"
14 #include "cmd-action/cmd-open-close.h"
15 #include "cmd-action/cmd-others.h"
16 #include "cmd-action/cmd-pet.h"
17 #include "cmd-action/cmd-racial.h"
18 #include "cmd-action/cmd-shoot.h"
19 #include "cmd-action/cmd-spell.h"
20 #include "cmd-action/cmd-travel.h"
21 #include "cmd-action/cmd-tunnel.h"
22 #include "cmd-building/cmd-building.h"
23 #include "cmd-io/cmd-autopick.h"
24 #include "cmd-io/cmd-diary.h"
25 #include "cmd-io/cmd-dump.h"
26 #include "cmd-io/cmd-floor.h"
27 #include "cmd-io/cmd-gameoption.h"
28 #include "cmd-io/cmd-help.h"
29 #include "cmd-io/cmd-knowledge.h"
30 #include "cmd-io/cmd-lore.h"
31 #include "cmd-io/cmd-macro.h"
32 #include "cmd-io/cmd-process-screen.h"
33 #include "cmd-io/cmd-save.h"
34 #include "cmd-item/cmd-destroy.h"
35 #include "cmd-item/cmd-eat.h"
36 #include "cmd-item/cmd-equipment.h"
37 #include "cmd-item/cmd-item.h"
38 #include "cmd-item/cmd-magiceat.h"
39 #include "cmd-item/cmd-quaff.h"
40 #include "cmd-item/cmd-read.h"
41 #include "cmd-item/cmd-refill.h"
42 #include "cmd-item/cmd-throw.h"
43 #include "cmd-item/cmd-usestaff.h"
44 #include "cmd-item/cmd-zaprod.h"
45 #include "cmd-item/cmd-zapwand.h"
46 #include "cmd-visual/cmd-draw.h"
47 #include "cmd-visual/cmd-map.h"
48 #include "cmd-visual/cmd-visuals.h"
49 #include "core/asking-player.h"
50 #include "core/player-redraw-types.h"
51 #include "core/player-update-types.h"
52 #include "core/special-internal-keys.h"
53 #include "dungeon/dungeon-flag-types.h"
54 #include "dungeon/dungeon.h"
55 #include "dungeon/quest.h" //!< @do_cmd_quest() がある。後で移設する.
56 #include "floor/wild.h"
57 #include "game-option/birth-options.h"
58 #include "game-option/disturbance-options.h"
59 #include "game-option/game-play-options.h"
60 #include "game-option/input-options.h"
61 #include "io-dump/random-art-info-dumper.h"
62 #include "io/command-repeater.h"
63 #include "io/files-util.h"
64 #include "io/input-key-requester.h" //!< @todo 相互依存している、後で何とかする.
65 #include "io/record-play-movie.h"
66 #include "io/write-diary.h"
67 #include "knowledge/knowledge-autopick.h"
68 #include "knowledge/knowledge-quests.h"
69 #include "main/sound-definitions-table.h"
70 #include "main/sound-of-music.h"
71 #include "mind/mind-blue-mage.h"
72 #include "mind/mind-elementalist.h"
73 #include "mind/mind-magic-eater.h"
74 #include "mind/mind-sniper.h"
75 #include "mind/mind-weaponsmith.h"
76 #include "mind/snipe-types.h"
77 #include "player-base/player-class.h"
78 #include "player-info/class-info.h"
79 #include "player-info/samurai-data-type.h"
80 #include "player-info/sniper-data-type.h"
81 #include "player-status/player-energy.h"
82 #include "player/attack-defense-types.h"
83 #include "player/digestion-processor.h"
84 #include "player/player-status.h"
85 #include "player/special-defense-types.h"
86 #include "status/action-setter.h"
87 #include "store/cmd-store.h"
88 #include "store/home.h"
89 #include "store/store-util.h"
90 #include "system/floor-type-definition.h"
91 #include "system/player-type-definition.h"
92 #include "term/screen-processor.h"
93 #include "util/int-char-converter.h"
94 #include "view/display-messages.h"
95 #include "window/display-sub-windows.h"
96 #include "wizard/cmd-wizard.h"
97 #include "world/world.h"
98
99 /*!
100  * @brief デバッグコマンドへの導入処理
101  * / Verify use of "debug" commands
102  * @param player_ptr プレイヤーへの参照ポインタ
103  * @return 実際にデバッグコマンドへ移行したらTRUEを返す。
104  */
105 static bool enter_debug_mode(player_type *player_ptr)
106 {
107     if (!w_ptr->noscore) {
108         if (!allow_debug_options) {
109             msg_print(_("デバッグコマンドは許可されていません。 ", "Use of debug command is not permitted."));
110             return false;
111         }
112
113         msg_print(_("デバッグ・コマンドはデバッグと実験のためのコマンドです。 ", "The debug commands are for debugging and experimenting."));
114         msg_print(_("デバッグ・コマンドを使うとスコアは記録されません。", "The game will not be scored if you use debug commands."));
115         msg_print(nullptr);
116         if (!get_check(_("本当にデバッグ・コマンドを使いますか? ", "Are you sure you want to use debug commands? "))) {
117             return false;
118         }
119
120         exe_write_diary(
121             player_ptr, DIARY_DESCRIPTION, 0, _("デバッグモードに突入してスコアを残せなくなった。", "gave up sending score to use debug commands."));
122         w_ptr->noscore |= 0x0008;
123     }
124
125     return true;
126 }
127
128 /*!
129  * @brief プレイヤーから受けた入力コマンドの分岐処理。
130  * / Parse and execute the current command Give "Warning" on illegal commands.
131  * @todo Make some "blocks"
132  */
133 void process_command(player_type *player_ptr)
134 {
135     COMMAND_CODE old_now_message = now_message;
136     repeat_check();
137     now_message = 0;
138     auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
139     if (sniper_data && sniper_data->concent > 0) {
140         sniper_data->reset_concent = true;
141     }
142
143     floor_type *floor_ptr = player_ptr->current_floor_ptr;
144     switch (command_cmd) {
145     case ESCAPE:
146     case ' ':
147     case '\r':
148     case '\n': {
149         /* Ignore */
150         break;
151     }
152     case KTRL('A'): {
153         if (enter_debug_mode(player_ptr)) {
154             do_cmd_debug(player_ptr);
155         }
156
157         break;
158     }
159     case 'w': {
160         if (!player_ptr->wild_mode)
161             do_cmd_wield(player_ptr);
162
163         break;
164     }
165     case 't': {
166         if (!player_ptr->wild_mode)
167             do_cmd_takeoff(player_ptr);
168
169         break;
170     }
171     case 'd': {
172         if (!player_ptr->wild_mode)
173             do_cmd_drop(player_ptr);
174
175         break;
176     }
177     case 'k': {
178         do_cmd_destroy(player_ptr);
179         break;
180     }
181     case 'e': {
182         do_cmd_equip(player_ptr);
183         break;
184     }
185     case 'i': {
186         do_cmd_inven(player_ptr);
187         break;
188     }
189     case 'I': {
190         do_cmd_observe(player_ptr);
191         break;
192     }
193
194     case KTRL('I'): {
195         toggle_inventory_equipment(player_ptr);
196         break;
197     }
198     case '+': {
199         if (!player_ptr->wild_mode)
200             do_cmd_alter(player_ptr);
201
202         break;
203     }
204     case 'T': {
205         if (!player_ptr->wild_mode)
206             do_cmd_tunnel(player_ptr);
207
208         break;
209     }
210     case ';': {
211         do_cmd_walk(player_ptr, false);
212         break;
213     }
214     case '-': {
215         do_cmd_walk(player_ptr, true);
216         break;
217     }
218     case '.': {
219         if (!player_ptr->wild_mode)
220             do_cmd_run(player_ptr);
221
222         break;
223     }
224     case ',': {
225         do_cmd_stay(player_ptr, always_pickup);
226         break;
227     }
228     case 'g': {
229         do_cmd_stay(player_ptr, !always_pickup);
230         break;
231     }
232     case 'R': {
233         do_cmd_rest(player_ptr);
234         break;
235     }
236     case 's': {
237         do_cmd_search(player_ptr);
238         break;
239     }
240     case 'S': {
241         if (player_ptr->action == ACTION_SEARCH)
242             set_action(player_ptr, ACTION_NONE);
243         else
244             set_action(player_ptr, ACTION_SEARCH);
245
246         break;
247     }
248     case SPECIAL_KEY_STORE: {
249         do_cmd_store(player_ptr);
250         break;
251     }
252     case SPECIAL_KEY_BUILDING: {
253         do_cmd_building(player_ptr);
254         break;
255     }
256     case SPECIAL_KEY_QUEST: {
257         do_cmd_quest(player_ptr);
258         break;
259     }
260     case '<': {
261         if (!player_ptr->wild_mode && !floor_ptr->dun_level && !floor_ptr->inside_arena && !floor_ptr->inside_quest) {
262             if (vanilla_town)
263                 break;
264
265             if (player_ptr->ambush_flag) {
266                 msg_print(_("襲撃から逃げるにはマップの端まで移動しなければならない。", "To flee the ambush you have to reach the edge of the map."));
267                 break;
268             }
269
270             if (player_ptr->food < PY_FOOD_WEAK) {
271                 msg_print(_("その前に食事をとらないと。", "You must eat something here."));
272                 break;
273             }
274
275             change_wild_mode(player_ptr, false);
276         } else
277             do_cmd_go_up(player_ptr);
278
279         break;
280     }
281     case '>': {
282         if (player_ptr->wild_mode)
283             change_wild_mode(player_ptr, false);
284         else
285             do_cmd_go_down(player_ptr);
286
287         break;
288     }
289     case 'o': {
290         do_cmd_open(player_ptr);
291         break;
292     }
293     case 'c': {
294         do_cmd_close(player_ptr);
295         break;
296     }
297     case 'j': {
298         do_cmd_spike(player_ptr);
299         break;
300     }
301     case 'B': {
302         do_cmd_bash(player_ptr);
303         break;
304     }
305     case 'D': {
306         do_cmd_disarm(player_ptr);
307         break;
308     }
309     case 'G': {
310         if (player_ptr->pclass == PlayerClassType::SORCERER || player_ptr->pclass == PlayerClassType::RED_MAGE || player_ptr->pclass == PlayerClassType::ELEMENTALIST)
311             msg_print(_("呪文を学習する必要はない!", "You don't have to learn spells!"));
312         else if (player_ptr->pclass == PlayerClassType::SAMURAI)
313             do_cmd_gain_hissatsu(player_ptr);
314         else if (player_ptr->pclass == PlayerClassType::MAGIC_EATER)
315             import_magic_device(player_ptr);
316         else
317             do_cmd_study(player_ptr);
318
319         break;
320     }
321     case 'b': {
322         if ((player_ptr->pclass == PlayerClassType::MINDCRAFTER) || (player_ptr->pclass == PlayerClassType::BERSERKER) || (player_ptr->pclass == PlayerClassType::NINJA)
323             || (player_ptr->pclass == PlayerClassType::MIRROR_MASTER))
324             do_cmd_mind_browse(player_ptr);
325         else if (player_ptr->pclass == PlayerClassType::ELEMENTALIST)
326             do_cmd_element_browse(player_ptr);
327         else if (player_ptr->pclass == PlayerClassType::SMITH)
328             do_cmd_kaji(player_ptr, true);
329         else if (player_ptr->pclass == PlayerClassType::MAGIC_EATER)
330             do_cmd_magic_eater(player_ptr, true, false);
331         else if (player_ptr->pclass == PlayerClassType::SNIPER)
332             do_cmd_snipe_browse(player_ptr);
333         else
334             do_cmd_browse(player_ptr);
335
336         break;
337     }
338     case 'm': {
339         if (player_ptr->wild_mode) {
340             break;
341         }
342
343         if ((player_ptr->pclass == PlayerClassType::WARRIOR) || (player_ptr->pclass == PlayerClassType::ARCHER) || (player_ptr->pclass == PlayerClassType::CAVALRY)) {
344             msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));
345             break;
346         }
347
348         if (floor_ptr->dun_level && d_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::NO_MAGIC) && (player_ptr->pclass != PlayerClassType::BERSERKER)
349             && (player_ptr->pclass != PlayerClassType::SMITH)) {
350             msg_print(_("ダンジョンが魔法を吸収した!", "The dungeon absorbs all attempted magic!"));
351             msg_print(nullptr);
352             break;
353         }
354
355         if (player_ptr->anti_magic && (player_ptr->pclass != PlayerClassType::BERSERKER) && (player_ptr->pclass != PlayerClassType::SMITH)) {
356             concptr which_power = _("魔法", "magic");
357             switch (player_ptr->pclass) {
358             case PlayerClassType::MINDCRAFTER:
359                 which_power = _("超能力", "psionic powers");
360                 break;
361             case PlayerClassType::IMITATOR:
362                 which_power = _("ものまね", "imitation");
363                 break;
364             case PlayerClassType::SAMURAI:
365                 which_power = _("必殺剣", "hissatsu");
366                 break;
367             case PlayerClassType::MIRROR_MASTER:
368                 which_power = _("鏡魔法", "mirror magic");
369                 break;
370             case PlayerClassType::NINJA:
371                 which_power = _("忍術", "ninjutsu");
372                 break;
373             case PlayerClassType::ELEMENTALIST:
374                 which_power = _("元素魔法", "magic");
375                 break;
376             default:
377                 if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK)
378                     which_power = _("祈り", "prayer");
379                 break;
380             }
381
382             msg_format(_("反魔法バリアが%sを邪魔した!", "An anti-magic shell disrupts your %s!"), which_power);
383             PlayerEnergy(player_ptr).reset_player_turn();
384             break;
385         }
386
387         if (is_shero(player_ptr) && (player_ptr->pclass != PlayerClassType::BERSERKER)) {
388             msg_format(_("狂戦士化していて頭が回らない!", "You cannot think directly!"));
389             PlayerEnergy(player_ptr).reset_player_turn();
390             break;
391         }
392
393         if ((player_ptr->pclass == PlayerClassType::MINDCRAFTER) || (player_ptr->pclass == PlayerClassType::BERSERKER) || (player_ptr->pclass == PlayerClassType::NINJA)
394             || (player_ptr->pclass == PlayerClassType::MIRROR_MASTER))
395             do_cmd_mind(player_ptr);
396         else if (player_ptr->pclass == PlayerClassType::ELEMENTALIST)
397             do_cmd_element(player_ptr);
398         else if (player_ptr->pclass == PlayerClassType::IMITATOR)
399             do_cmd_mane(player_ptr, false);
400         else if (player_ptr->pclass == PlayerClassType::MAGIC_EATER)
401             do_cmd_magic_eater(player_ptr, false, false);
402         else if (player_ptr->pclass == PlayerClassType::SAMURAI)
403             do_cmd_hissatsu(player_ptr);
404         else if (player_ptr->pclass == PlayerClassType::BLUE_MAGE)
405             do_cmd_cast_learned(player_ptr);
406         else if (player_ptr->pclass == PlayerClassType::SMITH)
407             do_cmd_kaji(player_ptr, false);
408         else if (player_ptr->pclass == PlayerClassType::SNIPER)
409             do_cmd_snipe(player_ptr);
410         else
411             (void)do_cmd_cast(player_ptr);
412
413         break;
414     }
415     case 'p': {
416         do_cmd_pet(player_ptr);
417         break;
418     }
419     case '{': {
420         do_cmd_inscribe(player_ptr);
421         break;
422     }
423     case '}': {
424         do_cmd_uninscribe(player_ptr);
425         break;
426     }
427     case 'A': {
428         do_cmd_activate(player_ptr);
429         break;
430     }
431     case 'E': {
432         do_cmd_eat_food(player_ptr);
433         break;
434     }
435     case 'F': {
436         do_cmd_refill(player_ptr);
437         break;
438     }
439     case 'f': {
440         do_cmd_fire(player_ptr, SP_NONE);
441         break;
442     }
443     case 'v': {
444         (void)ThrowCommand(player_ptr).do_cmd_throw(1, false, -1);
445         break;
446     }
447     case 'a': {
448         do_cmd_aim_wand(player_ptr);
449         break;
450     }
451     case 'z': {
452         if (use_command && rogue_like_commands) {
453             do_cmd_use(player_ptr);
454         } else {
455             do_cmd_zap_rod(player_ptr);
456         }
457
458         break;
459     }
460     case 'q': {
461         do_cmd_quaff_potion(player_ptr);
462         break;
463     }
464     case 'r': {
465         do_cmd_read_scroll(player_ptr);
466         break;
467     }
468     case 'u': {
469         if (use_command && !rogue_like_commands)
470             do_cmd_use(player_ptr);
471         else
472             do_cmd_use_staff(player_ptr);
473
474         break;
475     }
476     case 'U': {
477         do_cmd_racial_power(player_ptr);
478         break;
479     }
480     case 'M': {
481         do_cmd_view_map(player_ptr);
482         break;
483     }
484     case 'L': {
485         do_cmd_locate(player_ptr);
486         break;
487     }
488     case 'l': {
489         do_cmd_look(player_ptr);
490         break;
491     }
492     case '*': {
493         do_cmd_target(player_ptr);
494         break;
495     }
496     case '?': {
497         do_cmd_help(player_ptr);
498         break;
499     }
500     case '/': {
501         do_cmd_query_symbol(player_ptr);
502         break;
503     }
504     case 'C': {
505         do_cmd_player_status(player_ptr);
506         break;
507     }
508     case '!': {
509         (void)term_user(0);
510         break;
511     }
512     case '"': {
513         do_cmd_pref(player_ptr);
514         break;
515     }
516     case '$': {
517         do_cmd_reload_autopick(player_ptr);
518         break;
519     }
520     case '_': {
521         do_cmd_edit_autopick(player_ptr);
522         break;
523     }
524     case '@': {
525         do_cmd_macros(player_ptr);
526         break;
527     }
528     case '%': {
529         do_cmd_visuals(player_ptr);
530         do_cmd_redraw(player_ptr);
531         break;
532     }
533     case '&': {
534         do_cmd_colors(player_ptr);
535         do_cmd_redraw(player_ptr);
536         break;
537     }
538     case '=': {
539         do_cmd_options(player_ptr);
540         (void)combine_and_reorder_home(player_ptr, StoreSaleType::HOME);
541         do_cmd_redraw(player_ptr);
542         break;
543     }
544     case ':': {
545         do_cmd_note();
546         break;
547     }
548     case 'V': {
549         do_cmd_version();
550         break;
551     }
552     case KTRL('F'): {
553         do_cmd_feeling(player_ptr);
554         break;
555     }
556     case KTRL('O'): {
557         do_cmd_message_one();
558         break;
559     }
560     case KTRL('P'): {
561         do_cmd_messages(old_now_message);
562         break;
563     }
564     case KTRL('Q'): {
565         do_cmd_checkquest(player_ptr);
566         break;
567     }
568     case KTRL('R'): {
569         now_message = old_now_message;
570         do_cmd_redraw(player_ptr);
571         break;
572     }
573     case KTRL('S'): {
574         do_cmd_save_game(player_ptr, false);
575         break;
576     }
577     case KTRL('T'): {
578         do_cmd_time(player_ptr);
579         break;
580     }
581     case KTRL('X'):
582     case SPECIAL_KEY_QUIT: {
583         do_cmd_save_and_exit(player_ptr);
584         break;
585     }
586     case 'Q': {
587         do_cmd_suicide(player_ptr);
588         break;
589     }
590     case '|': {
591         do_cmd_diary(player_ptr);
592         break;
593     }
594     case '~': {
595         do_cmd_knowledge(player_ptr);
596         break;
597     }
598     case '(': {
599         do_cmd_load_screen();
600         break;
601     }
602     case ')': {
603         do_cmd_save_screen(player_ptr);
604         break;
605     }
606     case ']': {
607         prepare_movie_hooks(player_ptr);
608         break;
609     }
610     case KTRL('V'): {
611         spoil_random_artifact(player_ptr, "randifact.txt");
612         break;
613     }
614     case '`': {
615         if (!player_ptr->wild_mode)
616             do_cmd_travel(player_ptr);
617         PlayerClass(player_ptr).break_samurai_stance({ SamuraiStance::MUSOU });
618
619         break;
620     }
621     default: {
622         if (flush_failure)
623             flush();
624         if (one_in_(2)) {
625             char error_m[1024];
626             sound(SOUND_ILLEGAL);
627             if (!get_rnd_line(_("error_j.txt", "error.txt"), 0, error_m))
628                 msg_print(error_m);
629         } else {
630             prt(_(" '?' でヘルプが表示されます。", "Type '?' for help."), 0, 0);
631         }
632
633         break;
634     }
635     }
636
637     if (!player_ptr->energy_use && !now_message)
638         now_message = old_now_message;
639 }