OSDN Git Service

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