OSDN Git Service

Merge pull request #2335 from sikabane-works/release/3.0.0Alpha54
[hengbandforosx/hengbandosx.git] / src / cmd-io / cmd-gameoption.cpp
1 #include "cmd-io/cmd-gameoption.h"
2 #include "autopick/autopick.h"
3 #include "cmd-io/cmd-autopick.h"
4 #include "cmd-io/cmd-dump.h"
5 #include "core/asking-player.h"
6 #include "core/player-redraw-types.h"
7 #include "core/show-file.h"
8 #include "core/window-redrawer.h"
9 #include "floor/geometry.h"
10 #include "game-option/game-play-options.h"
11 #include "game-option/keymap-directory-getter.h"
12 #include "game-option/option-flags.h"
13 #include "game-option/option-types-table.h"
14 #include "game-option/special-options.h"
15 #include "io/input-key-acceptor.h"
16 #include "io/write-diary.h"
17 #include "main/sound-of-music.h"
18 #include "system/game-option-types.h"
19 #include "system/player-type-definition.h"
20 #include "term/gameterm.h"
21 #include "term/screen-processor.h"
22 #include "term/term-color-types.h"
23 #include "util/bit-flags-calculator.h"
24 #include "util/int-char-converter.h"
25 #include "util/string-processor.h"
26 #include "view/display-messages.h"
27 #include "world/world.h"
28
29 #define OPT_NUM 15
30
31 struct opts {
32     char key;
33     concptr name;
34     int row;
35 };
36
37 static opts option_fields[OPT_NUM] = {
38     { '1', _("    キー入力     オプション", "Input Options"), 3 },
39     { '2', _("   マップ画面    オプション", "Map Screen Options"), 4 },
40     { '3', _("  テキスト表示   オプション", "Text Display Options"), 5 },
41     { '4', _("  ゲームプレイ   オプション", "Game-Play Options"), 6 },
42     { '5', _("  行動中止関係   オプション", "Disturbance Options"), 7 },
43     { '6', _("  簡易自動破壊   オプション", "Easy Auto-Destroyer Options"), 8 },
44     { 'r', _("   プレイ記録    オプション", "Play record Options"), 9 },
45
46     { 'p', _("自動拾いエディタ", "Auto-picker/destroyer editor"), 11 },
47     { 'd', _(" 基本ウェイト量 ", "Base Delay Factor"), 12 },
48     { 'h', _("低ヒットポイント", "Hitpoint Warning"), 13 },
49     { 'm', _("  低魔力色閾値  ", "Mana Color Threshold"), 14 },
50     { 'a', _("   自動セーブ    オプション", "Autosave Options"), 15 },
51     { 'w', _("ウインドウフラグ", "Window Flags"), 16 },
52
53     { 'b', _("      初期       オプション (参照のみ)", "Birth Options (Browse Only)"), 18 },
54     { 'c', _("      詐欺       オプション", "Cheat Options"), 19 },
55 };
56
57 /*!
58  * @brief セーブ頻度ターンの次の値を返す
59  * @param current 現在のセーブ頻度ターン値
60  * @return 次のセーブ頻度ターン値
61  */
62 static int16_t toggle_frequency(int16_t current)
63 {
64     switch (current) {
65     case 0:
66         return 50;
67     case 50:
68         return 100;
69     case 100:
70         return 250;
71     case 250:
72         return 500;
73     case 500:
74         return 1000;
75     case 1000:
76         return 2500;
77     case 2500:
78         return 5000;
79     case 5000:
80         return 10000;
81     case 10000:
82         return 25000;
83     default:
84         return 0;
85     }
86 }
87
88 /*!
89  * @brief 自動セーブオプションを変更するコマンドのメインルーチン
90  * @param info 表示メッセージ
91  */
92 static void do_cmd_options_autosave(PlayerType *player_ptr, concptr info)
93 {
94     char ch;
95     int i, k = 0, n = 2;
96     char buf[80];
97     term_clear();
98     while (true) {
99         sprintf(buf,
100             _("%s ( リターンで次へ, y/n でセット, F で頻度を入力, ESC で決定 ) ", "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) "), info);
101         prt(buf, 0, 0);
102         for (i = 0; i < n; i++) {
103             byte a = TERM_WHITE;
104             if (i == k) {
105                 a = TERM_L_BLUE;
106             }
107
108             sprintf(
109                 buf, "%-48s: %s (%s)", autosave_info[i].o_desc, (*autosave_info[i].o_var ? _("はい  ", "yes") : _("いいえ", "no ")), autosave_info[i].o_text);
110             c_prt(a, buf, i + 2, 0);
111         }
112
113         prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0);
114         move_cursor(k + 2, 50);
115         ch = inkey();
116         switch (ch) {
117         case ESCAPE: {
118             return;
119         }
120
121         case '-':
122         case '8': {
123             k = (n + k - 1) % n;
124             break;
125         }
126
127         case ' ':
128         case '\n':
129         case '\r':
130         case '2': {
131             k = (k + 1) % n;
132             break;
133         }
134
135         case 'y':
136         case 'Y':
137         case '6': {
138
139             (*autosave_info[k].o_var) = true;
140             k = (k + 1) % n;
141             break;
142         }
143
144         case 'n':
145         case 'N':
146         case '4': {
147             (*autosave_info[k].o_var) = false;
148             k = (k + 1) % n;
149             break;
150         }
151
152         case 'f':
153         case 'F': {
154             autosave_freq = toggle_frequency(autosave_freq);
155             prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0);
156             break;
157         }
158
159         case '?': {
160             (void)show_file(player_ptr, true, _("joption.txt#Autosave", "option.txt#Autosave"), nullptr, 0, 0);
161             term_clear();
162             break;
163         }
164
165         default: {
166             bell();
167             break;
168         }
169         }
170     }
171 }
172
173 /*!
174  * @brief 指定のサブウィンドウが指定のウィンドウフラグを持つか調べる
175  * @param x ウィンドウ番号
176  * @param y ウィンドウフラグ番号
177  * @return 持つならTRUE、持たないならFALSE
178  */
179 static bool has_window_flag(int x, int y)
180 {
181     auto flag = i2enum<window_redraw_type>(1UL << y);
182     return any_bits(window_flag[x], flag);
183 }
184
185 /*!
186  * @brief 指定のサブウィンドウに指定のウィンドウフラグをセットする
187  * @param x ウィンドウ番号
188  * @param y ウィンドウフラグ番号
189  * @details
190  * 未使用フラグはセットしない。
191  */
192 static void set_window_flag(int x, int y)
193 {
194     auto flag = i2enum<window_redraw_type>(1UL << y);
195     if (any_bits(PW_ALL, flag)) {
196         set_bits(window_flag[x], flag);
197     }
198 }
199
200 /*!
201  * @brief 指定のウィンドウフラグをサブウィンドウからクリアする
202  * @param y ウィンドウフラグ番号
203  */
204 static void clear_window_flag(int x, int y)
205 {
206     window_flag[x] = 0;
207
208     auto flag = i2enum<window_redraw_type>(1UL << y);
209     for (int i = 0; i < 8; i++) {
210         reset_bits(window_flag[i], flag);
211     }
212 }
213
214 /*!
215  * @brief ウィンドウオプションを変更するコマンドのメインルーチン /
216  * Modify the "window" options
217  */
218 static void do_cmd_options_win(PlayerType *player_ptr)
219 {
220     int i, j, d;
221     TERM_LEN y = 0;
222     TERM_LEN x = 0;
223     char ch;
224     bool go = true;
225     uint32_t old_flag[8];
226
227     for (j = 0; j < 8; j++) {
228         old_flag[j] = window_flag[j];
229     }
230
231     term_clear();
232     while (go) {
233         prt(_("ウィンドウ・フラグ (<方向>で移動, 't'でON/OFF,'s'でON(他窓OFF), ESC)", "Window Flags (<dir>, <t>oggle, <s>et, ESC) "), 0, 0);
234         for (j = 0; j < 8; j++) {
235             byte a = TERM_WHITE;
236             concptr s = angband_term_name[j];
237             if (j == x) {
238                 a = TERM_L_BLUE;
239             }
240
241             term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s);
242         }
243
244         for (i = 0; i < 16; i++) {
245             byte a = TERM_WHITE;
246             concptr str = window_flag_desc[i];
247             if (i == y) {
248                 a = TERM_L_BLUE;
249             }
250
251             if (!str) {
252                 str = _("(未使用)", "(Unused option)");
253             }
254
255             term_putstr(0, i + 5, -1, a, str);
256             for (j = 0; j < 8; j++) {
257                 char c = '.';
258                 a = TERM_WHITE;
259                 if ((i == y) && (j == x)) {
260                     a = TERM_L_BLUE;
261                 }
262
263                 if (window_flag[j] & (1UL << i)) {
264                     c = 'X';
265                 }
266
267                 term_putch(35 + j * 5, i + 5, a, c);
268             }
269         }
270
271         bool has_flag = false;
272         term_gotoxy(35 + x * 5, y + 5);
273         ch = inkey();
274         switch (ch) {
275         case ESCAPE:
276             go = false;
277             break;
278         case ' ':
279         case 't':
280         case 'T':
281             has_flag = has_window_flag(x, y);
282             window_flag[x] = 0;
283             if (x > 0 && !has_flag) {
284                 set_window_flag(x, y);
285             }
286             break;
287         case 's':
288         case 'S':
289             if (x == 0) {
290                 break;
291             }
292             window_flag[x] = 0;
293             clear_window_flag(x, y);
294             set_window_flag(x, y);
295             break;
296         case '?':
297             (void)show_file(player_ptr, true, _("joption.txt#Window", "option.txt#Window"), nullptr, 0, 0);
298             term_clear();
299             break;
300         default:
301             d = get_keymap_dir(ch);
302             x = (x + ddx[d] + 8) % 8;
303             y = (y + ddy[d] + 16) % 16;
304             if (!d) {
305                 bell();
306             }
307             break;
308         }
309     }
310
311     for (j = 0; j < 8; j++) {
312         term_type *old = game_term;
313         if (!angband_term[j]) {
314             continue;
315         }
316
317         if (window_flag[j] == old_flag[j]) {
318             continue;
319         }
320
321         term_activate(angband_term[j]);
322         term_clear();
323         term_fresh();
324         term_activate(old);
325     }
326 }
327
328 /*!
329  * @brief チートオプションを変更するコマンドのメインルーチン
330  * Interact with some options for cheating
331  * @param info 表示メッセージ
332  */
333 static void do_cmd_options_cheat(PlayerType *player_ptr, concptr info)
334 {
335     term_clear();
336     auto k = 0U;
337     const auto n = cheat_info.size();
338     while (true) {
339         char buf[80];
340         sprintf(buf, _("%s ( リターンで次へ, y/n でセット, ESC で決定 )", "%s (RET to advance, y/n to set, ESC to accept) "), info);
341         prt(buf, 0, 0);
342
343 #ifdef JP
344         /* 詐欺オプションをうっかりいじってしまう人がいるようなので注意 */
345         prt("                                 <<  注意  >>", 11, 0);
346         prt("      詐欺オプションを一度でも設定すると、スコア記録が残らなくなります!", 12, 0);
347         prt("      後に解除してもダメですので、勝利者を目指す方はここのオプションはい", 13, 0);
348         prt("      じらないようにして下さい。", 14, 0);
349 #endif
350         for (auto i = 0U; i < n; i++) {
351             auto a = TERM_WHITE;
352             if (i == k) {
353                 a = TERM_L_BLUE;
354             }
355
356             sprintf(buf, "%-48s: %s (%s)", cheat_info[i].o_desc, (*cheat_info[i].o_var ? _("はい  ", "yes") : _("いいえ", "no ")), cheat_info[i].o_text);
357             c_prt(enum2i(a), buf, i + 2, 0);
358         }
359
360         move_cursor(k + 2, 50);
361         auto ch = inkey();
362         auto dir = get_keymap_dir(ch);
363         if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) {
364             ch = I2D(dir);
365         }
366
367         switch (ch) {
368         case ESCAPE:
369             return;
370         case '-':
371         case '8':
372             k = (n + k - 1) % n;
373             break;
374         case ' ':
375         case '\n':
376         case '\r':
377         case '2':
378             k = (k + 1) % n;
379             break;
380         case 'y':
381         case 'Y':
382         case '6':
383             if (!w_ptr->noscore) {
384                 exe_write_diary(player_ptr, DIARY_DESCRIPTION, 0,
385                     _("詐欺オプションをONにして、スコアを残せなくなった。", "gave up sending score to use cheating options."));
386             }
387
388             w_ptr->noscore |= cheat_info[k].o_set * 256 + cheat_info[k].o_bit;
389             *cheat_info[k].o_var = true;
390             k = (k + 1) % n;
391             break;
392         case 'n':
393         case 'N':
394         case '4':
395             *cheat_info[k].o_var = false;
396             k = (k + 1) % n;
397             break;
398         case '?':
399             strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), cheat_info[k].o_text);
400             (void)show_file(player_ptr, true, buf, nullptr, 0, 0);
401             term_clear();
402             break;
403         default:
404             bell();
405             break;
406         }
407     }
408 }
409
410 /*!
411  * @brief ビットセットからゲームオプションを展開する / Extract option variables from bit sets
412  */
413 void extract_option_vars(void)
414 {
415     for (int i = 0; option_info[i].o_desc; i++) {
416         int os = option_info[i].o_set;
417         int ob = option_info[i].o_bit;
418         if (option_info[i].o_var) {
419             if (option_flag[os] & (1UL << ob)) {
420                 (*option_info[i].o_var) = true;
421             } else {
422                 (*option_info[i].o_var) = false;
423             }
424         }
425     }
426 }
427
428 /*!
429  * @brief 標準オプションを変更するコマンドのメインルーチン /
430  * Set or unset various options.
431  * @details
432  * <pre>
433  * The user must use the "Ctrl-R" command to "adapt" to changes
434  * in any options which control "visual" aspects of the game.
435  * </pre>
436  */
437 void do_cmd_options(PlayerType *player_ptr)
438 {
439     char k;
440     int d, skey;
441     TERM_LEN i, y = 0;
442     screen_save();
443     while (true) {
444         int n = OPT_NUM;
445         if (!w_ptr->noscore && !allow_debug_opts) {
446             n--;
447         }
448
449         term_clear();
450         prt(_("[ オプションの設定 ]", "Game options"), 1, 0);
451         while (true) {
452             for (i = 0; i < n; i++) {
453                 byte a = TERM_WHITE;
454                 if (i == y) {
455                     a = TERM_L_BLUE;
456                 }
457                 term_putstr(5, option_fields[i].row, -1, a, format("(%c) %s", toupper(option_fields[i].key), option_fields[i].name));
458             }
459
460             prt(_("<方向>で移動, Enterで決定, ESCでキャンセル, ?でヘルプ: ", "Move to <dir>, Select to Enter, Cancel to ESC, ? to help: "), 21, 0);
461             skey = inkey_special(true);
462             if (!(skey & SKEY_MASK)) {
463                 k = (char)skey;
464             } else {
465                 k = 0;
466             }
467
468             if (k == ESCAPE) {
469                 break;
470             }
471
472             if (angband_strchr("\n\r ", k)) {
473                 k = option_fields[y].key;
474                 break;
475             }
476
477             for (i = 0; i < n; i++) {
478                 if (tolower(k) == option_fields[i].key) {
479                     break;
480                 }
481             }
482
483             if (i < n) {
484                 break;
485             }
486
487             if (k == '?') {
488                 break;
489             }
490
491             d = 0;
492             if (skey == SKEY_UP) {
493                 d = 8;
494             }
495             if (skey == SKEY_DOWN) {
496                 d = 2;
497             }
498             y = (y + ddy[d] + n) % n;
499             if (!d) {
500                 bell();
501             }
502         }
503
504         if (k == ESCAPE) {
505             break;
506         }
507
508         switch (k) {
509         case '1': {
510             do_cmd_options_aux(player_ptr, OPT_PAGE_INPUT, _("キー入力オプション", "Input Options"));
511             break;
512         }
513         case '2': {
514             do_cmd_options_aux(player_ptr, OPT_PAGE_MAPSCREEN, _("マップ画面オプション", "Map Screen Options"));
515             break;
516         }
517         case '3': {
518             do_cmd_options_aux(player_ptr, OPT_PAGE_TEXT, _("テキスト表示オプション", "Text Display Options"));
519             break;
520         }
521         case '4': {
522             do_cmd_options_aux(player_ptr, OPT_PAGE_GAMEPLAY, _("ゲームプレイ・オプション", "Game-Play Options"));
523             break;
524         }
525         case '5': {
526             do_cmd_options_aux(player_ptr, OPT_PAGE_DISTURBANCE, _("行動中止関係のオプション", "Disturbance Options"));
527             break;
528         }
529         case '6': {
530             do_cmd_options_aux(player_ptr, OPT_PAGE_AUTODESTROY, _("簡易自動破壊オプション", "Easy Auto-Destroyer Options"));
531             break;
532         }
533         case 'R':
534         case 'r': {
535             do_cmd_options_aux(player_ptr, OPT_PAGE_PLAYRECORD, _("プレイ記録オプション", "Play-record Options"));
536             break;
537         }
538         case 'B':
539         case 'b': {
540             do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH,
541                 (!w_ptr->wizard || !allow_debug_opts) ? _("初期オプション(参照のみ)", "Birth Options(browse only)")
542                                                       : _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score"));
543             break;
544         }
545         case 'C':
546         case 'c': {
547             if (!w_ptr->noscore && !allow_debug_opts) {
548                 bell();
549                 break;
550             }
551
552             do_cmd_options_cheat(player_ptr, _("詐欺師は決して勝利できない!", "Cheaters never win"));
553             break;
554         }
555         case 'a':
556         case 'A': {
557             do_cmd_options_autosave(player_ptr, _("自動セーブ", "Autosave"));
558             break;
559         }
560         case 'W':
561         case 'w': {
562             do_cmd_options_win(player_ptr);
563             player_ptr->window_flags = PW_ALL;
564             break;
565         }
566         case 'P':
567         case 'p': {
568             do_cmd_edit_autopick(player_ptr);
569             break;
570         }
571         case 'D':
572         case 'd': {
573             clear_from(18);
574             prt(format(_("現在ウェイト量(msec): %d", "Current Delay Factor(msec): %d"), delay_factor), 19, 0);
575             (void)get_value(_("コマンド: ウェイト量(msec)", "Command: Delay Factor(msec)"), 0, 1000, &delay_factor);
576             clear_from(18);
577             break;
578         }
579         case 'H':
580         case 'h': {
581             clear_from(18);
582             prt(_("コマンド: 低ヒットポイント警告", "Command: Hitpoint Warning"), 19, 0);
583             while (true) {
584                 prt(format(_("現在の低ヒットポイント警告: %d0%%", "Current hitpoint warning: %d0%%"), hitpoint_warn), 22, 0);
585                 prt(_("低ヒットポイント警告 (0-9) ESCで決定: ", "Hitpoint Warning (0-9 or ESC to accept): "), 20, 0);
586                 k = inkey();
587                 if (k == ESCAPE) {
588                     break;
589                 } else if (k == '?') {
590                     (void)show_file(player_ptr, true, _("joption.txt#Hitpoint", "option.txt#Hitpoint"), nullptr, 0, 0);
591                     term_clear();
592                 } else if (isdigit(k)) {
593                     hitpoint_warn = D2I(k);
594                 } else {
595                     bell();
596                 }
597             }
598
599             break;
600         }
601         case 'M':
602         case 'm': {
603             clear_from(18);
604             prt(_("コマンド: 低魔力色閾値", "Command: Mana Color Threshold"), 19, 0);
605             while (true) {
606                 prt(format(_("現在の低魔力色閾値: %d0%%", "Current mana color threshold: %d0%%"), mana_warn), 22, 0);
607                 prt(_("低魔力閾値 (0-9) ESCで決定: ", "Mana color Threshold (0-9 or ESC to accept): "), 20, 0);
608                 k = inkey();
609                 if (k == ESCAPE) {
610                     break;
611                 } else if (k == '?') {
612                     (void)show_file(player_ptr, true, _("joption.txt#Manapoint", "option.txt#Manapoint"), nullptr, 0, 0);
613                     term_clear();
614                 } else if (isdigit(k)) {
615                     mana_warn = D2I(k);
616                 } else {
617                     bell();
618                 }
619             }
620
621             break;
622         }
623         case '?':
624             (void)show_file(player_ptr, true, _("joption.txt", "option.txt"), nullptr, 0, 0);
625             term_clear();
626             break;
627         default: {
628             bell();
629             break;
630         }
631         }
632
633         msg_erase();
634     }
635
636     screen_load();
637     player_ptr->redraw |= (PR_EQUIPPY);
638 }
639
640 /*!
641  * @brief 標準オプションを変更するコマンドのサブルーチン /
642  * Interact with some options
643  * @param page オプションページ番号
644  * @param info 表示メッセージ
645  */
646 void do_cmd_options_aux(PlayerType *player_ptr, game_option_types page, concptr info)
647 {
648     char ch;
649     int i, k = 0, n = 0, l;
650     int opt[24];
651     char buf[80];
652     bool browse_only = (page == OPT_PAGE_BIRTH) && w_ptr->character_generated && (!w_ptr->wizard || !allow_debug_opts);
653
654     for (i = 0; i < 24; i++) {
655         opt[i] = 0;
656     }
657
658     for (i = 0; option_info[i].o_desc; i++) {
659         if (option_info[i].o_page == page) {
660             opt[n++] = i;
661         }
662     }
663
664     term_clear();
665     while (true) {
666         DIRECTION dir;
667         sprintf(buf, _("%s (リターン:次, %sESC:終了, ?:ヘルプ) ", "%s (RET:next, %s, ?:help) "), info,
668             browse_only ? _("", "ESC:exit") : _("y/n:変更, ", "y/n:change, ESC:accept"));
669         prt(buf, 0, 0);
670         if (page == OPT_PAGE_AUTODESTROY) {
671             c_prt(TERM_YELLOW, _("以下のオプションは、簡易自動破壊を使用するときのみ有効", "Following options will protect items from easy auto-destroyer."), 6,
672                 _(6, 3));
673         }
674
675         for (i = 0; i < n; i++) {
676             byte a = TERM_WHITE;
677             if (i == k) {
678                 a = TERM_L_BLUE;
679             }
680
681             sprintf(buf, "%-48s: %s (%.19s)", option_info[opt[i]].o_desc, (*option_info[opt[i]].o_var ? _("はい  ", "yes") : _("いいえ", "no ")),
682                 option_info[opt[i]].o_text);
683             if ((page == OPT_PAGE_AUTODESTROY) && i > 2) {
684                 c_prt(a, buf, i + 5, 0);
685             } else {
686                 c_prt(a, buf, i + 2, 0);
687             }
688         }
689
690         if ((page == OPT_PAGE_AUTODESTROY) && (k > 2)) {
691             l = 3;
692         } else {
693             l = 0;
694         }
695
696         move_cursor(k + 2 + l, 50);
697         ch = inkey();
698         dir = get_keymap_dir(ch);
699         if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) {
700             ch = I2D(dir);
701         }
702
703         switch (ch) {
704         case ESCAPE: {
705             return;
706         }
707         case '-':
708         case '8': {
709             k = (n + k - 1) % n;
710             break;
711         }
712         case ' ':
713         case '\n':
714         case '\r':
715         case '2': {
716             k = (k + 1) % n;
717             break;
718         }
719         case 'y':
720         case 'Y':
721         case '6': {
722             if (browse_only) {
723                 break;
724             }
725             (*option_info[opt[k]].o_var) = true;
726             k = (k + 1) % n;
727             break;
728         }
729         case 'n':
730         case 'N':
731         case '4': {
732             if (browse_only) {
733                 break;
734             }
735             (*option_info[opt[k]].o_var) = false;
736             k = (k + 1) % n;
737             break;
738         }
739         case 't':
740         case 'T': {
741             if (!browse_only) {
742                 (*option_info[opt[k]].o_var) = !(*option_info[opt[k]].o_var);
743             }
744             break;
745         }
746         case '?': {
747             strnfmt(buf, sizeof(buf), _("joption.txt#%s", "option.txt#%s"), option_info[opt[k]].o_text);
748             (void)show_file(player_ptr, true, buf, nullptr, 0, 0);
749             term_clear();
750             break;
751         }
752         default: {
753             bell();
754             break;
755         }
756         }
757     }
758 }