OSDN Git Service

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