OSDN Git Service

[Refactor] #2200 input-key-processor.cpp にあった、不要になったtodoを削除し日付更新
[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 *cap_mon_ptr = g_cap_mon_ptr.get();
173     auto *floor_ptr = player_ptr->current_floor_ptr;
174     switch (command_cmd) {
175     case ESCAPE:
176     case ' ':
177     case '\r':
178     case '\n': {
179         /* Ignore */
180         break;
181     }
182     case KTRL('W'): {
183         if (w_ptr->wizard) {
184             w_ptr->wizard = false;
185             msg_print(_("ウィザードモード解除。", "Wizard mode off."));
186         } else if (enter_wizard_mode(player_ptr)) {
187             w_ptr->wizard = true;
188             msg_print(_("ウィザードモード突入。", "Wizard mode on."));
189         }
190
191         player_ptr->update |= (PU_MONSTERS);
192         player_ptr->redraw |= (PR_TITLE);
193         break;
194     }
195     case KTRL('A'): {
196         if (enter_debug_mode(player_ptr)) {
197             do_cmd_debug(player_ptr);
198         }
199
200         break;
201     }
202     case 'w': {
203         if (!player_ptr->wild_mode)
204             do_cmd_wield(player_ptr);
205
206         break;
207     }
208     case 't': {
209         if (!player_ptr->wild_mode)
210             do_cmd_takeoff(player_ptr);
211
212         break;
213     }
214     case 'd': {
215         if (!player_ptr->wild_mode)
216             do_cmd_drop(player_ptr);
217
218         break;
219     }
220     case 'k': {
221         do_cmd_destroy(player_ptr);
222         break;
223     }
224     case 'e': {
225         do_cmd_equip(player_ptr);
226         break;
227     }
228     case 'i': {
229         do_cmd_inven(player_ptr);
230         break;
231     }
232     case 'I': {
233         do_cmd_observe(player_ptr);
234         break;
235     }
236
237     case KTRL('I'): {
238         toggle_inventory_equipment(player_ptr);
239         break;
240     }
241     case '+': {
242         if (!player_ptr->wild_mode)
243             do_cmd_alter(player_ptr);
244
245         break;
246     }
247     case 'T': {
248         if (!player_ptr->wild_mode)
249             do_cmd_tunnel(player_ptr);
250
251         break;
252     }
253     case ';': {
254         do_cmd_walk(player_ptr, false);
255         break;
256     }
257     case '-': {
258         do_cmd_walk(player_ptr, true);
259         break;
260     }
261     case '.': {
262         if (!player_ptr->wild_mode)
263             do_cmd_run(player_ptr);
264
265         break;
266     }
267     case ',': {
268         do_cmd_stay(player_ptr, always_pickup);
269         break;
270     }
271     case 'g': {
272         do_cmd_stay(player_ptr, !always_pickup);
273         break;
274     }
275     case 'R': {
276         do_cmd_rest(player_ptr);
277         break;
278     }
279     case 's': {
280         do_cmd_search(player_ptr);
281         break;
282     }
283     case 'S': {
284         if (player_ptr->action == ACTION_SEARCH)
285             set_action(player_ptr, ACTION_NONE);
286         else
287             set_action(player_ptr, ACTION_SEARCH);
288
289         break;
290     }
291     case SPECIAL_KEY_STORE: {
292         do_cmd_store(player_ptr, cap_mon_ptr);
293         break;
294     }
295     case SPECIAL_KEY_BUILDING: {
296         do_cmd_building(player_ptr);
297         break;
298     }
299     case SPECIAL_KEY_QUEST: {
300         do_cmd_quest(player_ptr);
301         break;
302     }
303     case '<': {
304         if (!player_ptr->wild_mode && !floor_ptr->dun_level && !floor_ptr->inside_arena && !inside_quest(floor_ptr->quest_number)) {
305             if (vanilla_town)
306                 break;
307
308             if (player_ptr->ambush_flag) {
309                 msg_print(_("襲撃から逃げるにはマップの端まで移動しなければならない。", "To flee the ambush you have to reach the edge of the map."));
310                 break;
311             }
312
313             if (player_ptr->food < PY_FOOD_WEAK) {
314                 msg_print(_("その前に食事をとらないと。", "You must eat something here."));
315                 break;
316             }
317
318             change_wild_mode(player_ptr, false);
319         } else
320             do_cmd_go_up(player_ptr);
321
322         break;
323     }
324     case '>': {
325         if (player_ptr->wild_mode)
326             change_wild_mode(player_ptr, false);
327         else
328             do_cmd_go_down(player_ptr);
329
330         break;
331     }
332     case 'o': {
333         do_cmd_open(player_ptr);
334         break;
335     }
336     case 'c': {
337         do_cmd_close(player_ptr);
338         break;
339     }
340     case 'j': {
341         do_cmd_spike(player_ptr);
342         break;
343     }
344     case 'B': {
345         do_cmd_bash(player_ptr);
346         break;
347     }
348     case 'D': {
349         do_cmd_disarm(player_ptr);
350         break;
351     }
352     case 'G': {
353         PlayerClass pc(player_ptr);
354         if (pc.is_every_magic() || pc.equals(PlayerClassType::ELEMENTALIST))
355             msg_print(_("呪文を学習する必要はない!", "You don't have to learn spells!"));
356         else if (pc.equals(PlayerClassType::SAMURAI))
357             do_cmd_gain_hissatsu(player_ptr);
358         else if (pc.equals(PlayerClassType::MAGIC_EATER))
359             import_magic_device(player_ptr);
360         else
361             do_cmd_study(player_ptr);
362
363         break;
364     }
365     case 'b': {
366         PlayerClass pc(player_ptr);
367         if (pc.can_browse())
368             do_cmd_mind_browse(player_ptr);
369         else if (pc.equals(PlayerClassType::ELEMENTALIST))
370             do_cmd_element_browse(player_ptr);
371         else if (pc.equals(PlayerClassType::SMITH))
372             do_cmd_kaji(player_ptr, true);
373         else if (pc.equals(PlayerClassType::MAGIC_EATER))
374             do_cmd_magic_eater(player_ptr, true, false);
375         else if (pc.equals(PlayerClassType::SNIPER))
376             do_cmd_snipe_browse(player_ptr);
377         else
378             do_cmd_browse(player_ptr, cap_mon_ptr);
379
380         break;
381     }
382     case 'm': {
383         if (player_ptr->wild_mode) {
384             break;
385         }
386
387         PlayerClass pc(player_ptr);
388         if (pc.equals(PlayerClassType::WARRIOR) || pc.equals(PlayerClassType::ARCHER) || pc.equals(PlayerClassType::CAVALRY)) {
389             msg_print(_("呪文を唱えられない!", "You cannot cast spells!"));
390             break;
391         }
392
393         if (floor_ptr->dun_level && d_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::NO_MAGIC) && !pc.equals(PlayerClassType::BERSERKER) && !pc.equals(PlayerClassType::SMITH)) {
394             msg_print(_("ダンジョンが魔法を吸収した!", "The dungeon absorbs all attempted magic!"));
395             msg_print(nullptr);
396             break;
397         }
398
399         if (player_ptr->anti_magic && !pc.equals(PlayerClassType::BERSERKER) && !pc.equals(PlayerClassType::SMITH)) {
400             concptr which_power = _("魔法", "magic");
401             switch (player_ptr->pclass) {
402             case PlayerClassType::MINDCRAFTER:
403                 which_power = _("超能力", "psionic powers");
404                 break;
405             case PlayerClassType::IMITATOR:
406                 which_power = _("ものまね", "imitation");
407                 break;
408             case PlayerClassType::SAMURAI:
409                 which_power = _("必殺剣", "hissatsu");
410                 break;
411             case PlayerClassType::MIRROR_MASTER:
412                 which_power = _("鏡魔法", "mirror magic");
413                 break;
414             case PlayerClassType::NINJA:
415                 which_power = _("忍術", "ninjutsu");
416                 break;
417             case PlayerClassType::ELEMENTALIST:
418                 which_power = _("元素魔法", "magic");
419                 break;
420             default:
421                 if (mp_ptr->spell_book == ItemKindType::LIFE_BOOK)
422                     which_power = _("祈り", "prayer");
423                 break;
424             }
425
426             msg_format(_("反魔法バリアが%sを邪魔した!", "An anti-magic shell disrupts your %s!"), which_power);
427             PlayerEnergy(player_ptr).reset_player_turn();
428             break;
429         }
430
431         if (is_shero(player_ptr) && !pc.equals(PlayerClassType::BERSERKER)) {
432             msg_format(_("狂戦士化していて頭が回らない!", "You cannot think directly!"));
433             PlayerEnergy(player_ptr).reset_player_turn();
434             break;
435         }
436
437         if (pc.can_browse())
438             do_cmd_mind(player_ptr, cap_mon_ptr);
439         else if (pc.equals(PlayerClassType::ELEMENTALIST))
440             do_cmd_element(player_ptr);
441         else if (pc.equals(PlayerClassType::IMITATOR))
442             do_cmd_mane(player_ptr, false);
443         else if (pc.equals(PlayerClassType::MAGIC_EATER))
444             do_cmd_magic_eater(player_ptr, false, false);
445         else if (pc.equals(PlayerClassType::SAMURAI))
446             do_cmd_hissatsu(player_ptr);
447         else if (pc.equals(PlayerClassType::BLUE_MAGE))
448             do_cmd_cast_learned(player_ptr);
449         else if (pc.equals(PlayerClassType::SMITH))
450             do_cmd_kaji(player_ptr, false);
451         else if (pc.equals(PlayerClassType::SNIPER))
452             do_cmd_snipe(player_ptr);
453         else
454             (void)do_cmd_cast(player_ptr, cap_mon_ptr);
455
456         break;
457     }
458     case 'p': {
459         do_cmd_pet(player_ptr);
460         break;
461     }
462     case '{': {
463         do_cmd_inscribe(player_ptr);
464         break;
465     }
466     case '}': {
467         do_cmd_uninscribe(player_ptr);
468         break;
469     }
470     case 'A': {
471         do_cmd_activate(player_ptr, cap_mon_ptr);
472         break;
473     }
474     case 'E': {
475         do_cmd_eat_food(player_ptr);
476         break;
477     }
478     case 'F': {
479         do_cmd_refill(player_ptr);
480         break;
481     }
482     case 'f': {
483         do_cmd_fire(player_ptr, SP_NONE);
484         break;
485     }
486     case 'v': {
487         (void)ThrowCommand(player_ptr).do_cmd_throw(1, false, -1);
488         break;
489     }
490     case 'a': {
491         do_cmd_aim_wand(player_ptr);
492         break;
493     }
494     case 'z': {
495         if (use_command && rogue_like_commands) {
496             do_cmd_use(player_ptr, cap_mon_ptr);
497         } else {
498             do_cmd_zap_rod(player_ptr);
499         }
500
501         break;
502     }
503     case 'q': {
504         do_cmd_quaff_potion(player_ptr);
505         break;
506     }
507     case 'r': {
508         do_cmd_read_scroll(player_ptr);
509         break;
510     }
511     case 'u': {
512         if (use_command && !rogue_like_commands)
513             do_cmd_use(player_ptr, cap_mon_ptr);
514         else
515             do_cmd_use_staff(player_ptr);
516
517         break;
518     }
519     case 'U': {
520         do_cmd_racial_power(player_ptr, cap_mon_ptr);
521         break;
522     }
523     case 'M': {
524         do_cmd_view_map(player_ptr);
525         break;
526     }
527     case 'L': {
528         do_cmd_locate(player_ptr);
529         break;
530     }
531     case 'l': {
532         do_cmd_look(player_ptr);
533         break;
534     }
535     case '*': {
536         do_cmd_target(player_ptr);
537         break;
538     }
539     case '?': {
540         do_cmd_help(player_ptr);
541         break;
542     }
543     case '/': {
544         do_cmd_query_symbol(player_ptr);
545         break;
546     }
547     case 'C': {
548         do_cmd_player_status(player_ptr);
549         break;
550     }
551     case '!': {
552         (void)term_user(0);
553         break;
554     }
555     case '"': {
556         do_cmd_pref(player_ptr);
557         break;
558     }
559     case '$': {
560         do_cmd_reload_autopick(player_ptr);
561         break;
562     }
563     case '_': {
564         do_cmd_edit_autopick(player_ptr);
565         break;
566     }
567     case '@': {
568         do_cmd_macros(player_ptr);
569         break;
570     }
571     case '%': {
572         do_cmd_visuals(player_ptr);
573         do_cmd_redraw(player_ptr);
574         break;
575     }
576     case '&': {
577         do_cmd_colors(player_ptr);
578         do_cmd_redraw(player_ptr);
579         break;
580     }
581     case '=': {
582         do_cmd_options(player_ptr);
583         (void)combine_and_reorder_home(player_ptr, StoreSaleType::HOME);
584         do_cmd_redraw(player_ptr);
585         break;
586     }
587     case ':': {
588         do_cmd_note();
589         break;
590     }
591     case 'V': {
592         do_cmd_version();
593         break;
594     }
595     case KTRL('F'): {
596         do_cmd_feeling(player_ptr);
597         break;
598     }
599     case KTRL('O'): {
600         do_cmd_message_one();
601         break;
602     }
603     case KTRL('P'): {
604         do_cmd_messages(old_now_message);
605         break;
606     }
607     case KTRL('Q'): {
608         do_cmd_checkquest(player_ptr);
609         break;
610     }
611     case KTRL('R'): {
612         now_message = old_now_message;
613         do_cmd_redraw(player_ptr);
614         break;
615     }
616     case KTRL('S'): {
617         do_cmd_save_game(player_ptr, false);
618         break;
619     }
620     case KTRL('T'): {
621         do_cmd_time(player_ptr);
622         break;
623     }
624     case KTRL('X'):
625     case SPECIAL_KEY_QUIT: {
626         do_cmd_save_and_exit(player_ptr);
627         break;
628     }
629     case 'Q': {
630         do_cmd_suicide(player_ptr);
631         break;
632     }
633     case '|': {
634         do_cmd_diary(player_ptr);
635         break;
636     }
637     case '~': {
638         do_cmd_knowledge(player_ptr);
639         break;
640     }
641     case '(': {
642         do_cmd_load_screen();
643         break;
644     }
645     case ')': {
646         do_cmd_save_screen(player_ptr);
647         break;
648     }
649     case ']': {
650         prepare_movie_hooks(player_ptr);
651         break;
652     }
653     case KTRL('V'): {
654         spoil_random_artifact(player_ptr, "randifact.txt");
655         break;
656     }
657     case '`': {
658         if (!player_ptr->wild_mode)
659             do_cmd_travel(player_ptr);
660         PlayerClass(player_ptr).break_samurai_stance({ SamuraiStanceType::MUSOU });
661
662         break;
663     }
664     default: {
665         if (flush_failure)
666             flush();
667         if (one_in_(2)) {
668             char error_m[1024];
669             sound(SOUND_ILLEGAL);
670             if (!get_rnd_line(_("error_j.txt", "error.txt"), 0, error_m))
671                 msg_print(error_m);
672         } else {
673             prt(_(" '?' でヘルプが表示されます。", "Type '?' for help."), 0, 0);
674         }
675
676         break;
677     }
678     }
679
680     if (!player_ptr->energy_use && !now_message)
681         now_message = old_now_message;
682 }