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/show-file.h"
7 #include "core/window-redrawer.h"
8 #include "floor/geometry.h"
9 #include "game-option/game-play-options.h"
10 #include "game-option/keymap-directory-getter.h"
11 #include "game-option/option-flags.h"
12 #include "game-option/option-types-table.h"
13 #include "game-option/special-options.h"
14 #include "io/input-key-acceptor.h"
15 #include "io/write-diary.h"
16 #include "main/sound-of-music.h"
17 #include "system/game-option-types.h"
18 #include "system/player-type-definition.h"
19 #include "system/redrawing-flags-updater.h"
20 #include "term/gameterm.h"
21 #include "term/screen-processor.h"
22 #include "term/term-color-types.h"
23 #include "term/z-form.h"
24 #include "util/bit-flags-calculator.h"
25 #include "util/int-char-converter.h"
26 #include "util/string-processor.h"
27 #include "view/display-messages.h"
28 #include "view/display-symbol.h"
29 #include "world/world.h"
39 static opts option_fields[OPT_NUM] = {
40 { '1', _(" キー入力 オプション", "Input Options"), 3 },
41 { '2', _(" マップ画面 オプション", "Map Screen Options"), 4 },
42 { '3', _(" テキスト表示 オプション", "Text Display Options"), 5 },
43 { '4', _(" ゲームプレイ オプション", "Game-Play Options"), 6 },
44 { '5', _(" 行動中止関係 オプション", "Disturbance Options"), 7 },
45 { '6', _(" 簡易自動破壊 オプション", "Easy Auto-Destroyer Options"), 8 },
46 { 'r', _(" プレイ記録 オプション", "Play record Options"), 9 },
48 { 'p', _("自動拾いエディタ", "Auto-picker/destroyer editor"), 11 },
49 { 'd', _(" 基本ウェイト量 ", "Base Delay Factor"), 12 },
50 { 'h', _("低ヒットポイント", "Hitpoint Warning"), 13 },
51 { 'm', _(" 低魔力色閾値 ", "Mana Color Threshold"), 14 },
52 { 'a', _(" 自動セーブ オプション", "Autosave Options"), 15 },
53 { 'w', _("ウインドウフラグ", "Window Flags"), 16 },
55 { 'b', _(" 初期 オプション (参照のみ)", "Birth Options (Browse Only)"), 18 },
56 { 'c', _(" 詐欺 オプション", "Cheat Options"), 19 },
60 * @brief セーブ頻度ターンの次の値を返す
61 * @param current 現在のセーブ頻度ターン値
64 static int16_t toggle_frequency(int16_t current)
91 * @brief 自動セーブオプションを変更するコマンドのメインルーチン
94 static void do_cmd_options_autosave(PlayerType *player_ptr, concptr info)
100 prt(format(_("%s ( リターンで次へ, y/n でセット, F で頻度を入力, ESC で決定 ) ", "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) "), info), 0, 0);
101 for (i = 0; i < n; i++) {
107 c_prt(a, format("%-48s: %s (%s)", autosave_info[i].o_desc, (*autosave_info[i].o_var ? _("はい ", "yes") : _("いいえ", "no ")), autosave_info[i].o_text), i + 2, 0);
110 prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0);
111 move_cursor(k + 2, 50);
136 (*autosave_info[k].o_var) = true;
144 (*autosave_info[k].o_var) = false;
151 autosave_freq = toggle_frequency(autosave_freq);
152 prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0);
157 FileDisplayer(player_ptr->name).display(true, _("joption.txt#Autosave", "option.txt#Autosave"), 0, 0);
171 * @brief 指定のサブウィンドウが指定のウィンドウフラグを持つか調べる
173 * @param y ウィンドウフラグ番号
174 * @return 持つならTRUE、持たないかメインウィンドウならFALSE
176 static bool has_window_flag(int x, int y)
182 auto flag = i2enum<SubWindowRedrawingFlag>(y);
183 return g_window_flags[x].has(flag);
187 * @brief 指定のサブウィンドウに指定のウィンドウフラグをセットする
189 * @param y ウィンドウフラグ番号
193 static void set_window_flag(int x, int y)
199 auto flag = i2enum<SubWindowRedrawingFlag>(y);
200 g_window_flags[x].set(flag);
204 * @brief 指定のウィンドウフラグをサブウィンドウからクリアする
205 * @param y ウィンドウフラグ番号
207 static void clear_window_flag(int x, int y)
209 g_window_flags[x].clear();
214 auto flag = i2enum<SubWindowRedrawingFlag>(y);
215 for (auto &window_flag : g_window_flags) {
216 window_flag.reset(flag);
221 * @brief ウィンドウオプションを変更するコマンドのメインルーチン /
222 * Modify the "window" options
224 static void do_cmd_options_win(PlayerType *player_ptr)
231 const auto old_flags = g_window_flags;
234 prt(_("ウィンドウ・フラグ (<方向>で移動, 't'でON/OFF,'s'でON(他窓OFF), ESC)", "Window Flags (<dir>, <t>oggle, <s>et, ESC) "), 0, 0);
235 for (j = 0; j < 8; j++) {
237 auto s = angband_term_name[j];
242 term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s);
245 for (i = 0; i < 16; i++) {
247 concptr str = window_flag_desc[i];
253 str = _("(未使用)", "(Unused option)");
256 term_putstr(0, i + 5, -1, a, str);
257 for (j = 0; j < 8; j++) {
260 if ((i == y) && (j == x)) {
264 if (g_window_flags[j].has(i2enum<SubWindowRedrawingFlag>(i))) {
268 term_putch(35 + j * 5, i + 5, { a, c });
272 bool has_flag = false;
273 term_gotoxy(35 + x * 5, y + 5);
282 has_flag = has_window_flag(x, y);
283 g_window_flags[x].clear();
284 if (x > 0 && !has_flag) {
285 set_window_flag(x, y);
293 g_window_flags[x].clear();
294 clear_window_flag(x, y);
295 set_window_flag(x, y);
298 FileDisplayer(player_ptr->name).display(true, _("joption.txt#Window", "option.txt#Window"), 0, 0);
302 d = get_keymap_dir(ch);
303 x = (x + ddx[d] + 8) % 8;
304 y = (y + ddy[d] + 16) % 16;
312 for (auto term_index = 0U; term_index < angband_terms.size(); ++term_index) {
313 term_type *old = game_term;
314 if (!angband_terms[term_index]) {
318 if (g_window_flags[term_index] == old_flags[term_index]) {
322 term_activate(angband_terms[term_index]);
330 * @brief チートオプションを変更するコマンドのメインルーチン
331 * Interact with some options for cheating
332 * @param info 表示メッセージ
334 static void do_cmd_options_cheat(const FloorType &floor, std::string_view player_name, std::string_view info)
338 const auto n = cheat_info.size();
340 prt(format(_("%s ( リターンで次へ, y/n でセット, ESC で決定 )", "%s (RET to advance, y/n to set, ESC to accept) "), info.data()), 0, 0);
343 /* 詐欺オプションをうっかりいじってしまう人がいるようなので注意 */
344 prt(" << 注意 >>", 11, 0);
345 prt(" 詐欺オプションを一度でも設定すると、スコア記録が残らなくなります!", 12, 0);
346 prt(" 後に解除してもダメですので、勝利者を目指す方はここのオプションはい", 13, 0);
347 prt(" じらないようにして下さい。", 14, 0);
349 for (auto i = 0U; i < n; i++) {
355 const auto yesno = *cheat_info[i].o_var ? _("はい ", "yes") : _("いいえ", "no ");
356 c_prt(enum2i(a), format("%-48s: %s (%s)", cheat_info[i].o_desc, yesno, cheat_info[i].o_text), i + 2, 0);
359 move_cursor(k + 2, 50);
361 auto dir = get_keymap_dir(ch);
362 if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) {
382 if (!w_ptr->noscore) {
383 exe_write_diary(floor, DiaryKind::DESCRIPTION, 0,
384 _("詐欺オプションをONにして、スコアを残せなくなった。", "gave up sending score to use cheating options."));
387 w_ptr->noscore |= cheat_info[k].o_set * 256 + cheat_info[k].o_bit;
388 *cheat_info[k].o_var = true;
394 *cheat_info[k].o_var = false;
398 FileDisplayer(player_name).display(true, std::string(_("joption.txt#", "option.txt#")).append(cheat_info[k].o_text), 0, 0);
409 * @brief ビットセットからゲームオプションを展開する / Extract option variables from bit sets
411 void extract_option_vars(void)
413 for (int i = 0; option_info[i].o_desc; i++) {
414 int os = option_info[i].o_set;
415 int ob = option_info[i].o_bit;
416 if (option_info[i].o_var) {
417 if (g_option_flags[os] & (1UL << ob)) {
418 (*option_info[i].o_var) = true;
420 (*option_info[i].o_var) = false;
427 * @brief 標準オプションを変更するコマンドのメインルーチン /
428 * Set or unset various options.
431 * The user must use the "Ctrl-R" command to "adapt" to changes
432 * in any options which control "visual" aspects of the game.
435 void do_cmd_options(PlayerType *player_ptr)
437 TermCenteredOffsetSetter tcos(MAIN_TERM_MIN_COLS, MAIN_TERM_MIN_ROWS);
445 if (!w_ptr->noscore && !allow_debug_opts) {
450 prt(_("[ オプションの設定 ]", "Game options"), 1, 0);
452 for (i = 0; i < n; i++) {
457 term_putstr(5, option_fields[i].row, -1, a, format("(%c) %s", toupper(option_fields[i].key), option_fields[i].name));
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)) {
472 if (angband_strchr("\n\r ", k)) {
473 k = option_fields[y].key;
477 for (i = 0; i < n; i++) {
478 if (tolower(k) == option_fields[i].key) {
492 if (skey == SKEY_UP) {
495 if (skey == SKEY_DOWN) {
498 y = (y + ddy[d] + n) % n;
510 do_cmd_options_aux(player_ptr, OPT_PAGE_INPUT, _("キー入力オプション", "Input Options"));
514 do_cmd_options_aux(player_ptr, OPT_PAGE_MAPSCREEN, _("マップ画面オプション", "Map Screen Options"));
518 do_cmd_options_aux(player_ptr, OPT_PAGE_TEXT, _("テキスト表示オプション", "Text Display Options"));
522 do_cmd_options_aux(player_ptr, OPT_PAGE_GAMEPLAY, _("ゲームプレイ・オプション", "Game-Play Options"));
526 do_cmd_options_aux(player_ptr, OPT_PAGE_DISTURBANCE, _("行動中止関係のオプション", "Disturbance Options"));
530 do_cmd_options_aux(player_ptr, OPT_PAGE_AUTODESTROY, _("簡易自動破壊オプション", "Easy Auto-Destroyer Options"));
535 do_cmd_options_aux(player_ptr, OPT_PAGE_PLAYRECORD, _("プレイ記録オプション", "Play-record Options"));
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"));
547 if (!w_ptr->noscore && !allow_debug_opts) {
552 do_cmd_options_cheat(*player_ptr->current_floor_ptr, player_ptr->name, _("詐欺師は決して勝利できない!", "Cheaters never win"));
557 do_cmd_options_autosave(player_ptr, _("自動セーブ", "Autosave"));
562 do_cmd_options_win(player_ptr);
563 RedrawingFlagsUpdater::get_instance().fill_up_sub_flags();
568 do_cmd_edit_autopick(player_ptr);
574 prt(format(_("現在ウェイト量(msec): %d", "Current Delay Factor(msec): %d"), delay_factor), 19, 0);
575 constexpr auto prompt = _("コマンド: ウェイト量(msec)", "Command: Delay Factor(msec)");
576 const auto new_delay_factor = input_integer(prompt, 0, 1000, delay_factor);
577 if (new_delay_factor) {
578 delay_factor = *new_delay_factor;
587 prt(_("コマンド: 低ヒットポイント警告", "Command: Hitpoint Warning"), 19, 0);
589 prt(format(_("現在の低ヒットポイント警告: %d0%%", "Current hitpoint warning: %d0%%"), hitpoint_warn), 22, 0);
590 prt(_("低ヒットポイント警告 (0-9) ESCで決定: ", "Hitpoint Warning (0-9 or ESC to accept): "), 20, 0);
594 } else if (k == '?') {
595 FileDisplayer(player_ptr->name).display(true, _("joption.txt#Hitpoint", "option.txt#Hitpoint"), 0, 0);
597 } else if (isdigit(k)) {
598 hitpoint_warn = D2I(k);
609 prt(_("コマンド: 低魔力色閾値", "Command: Mana Color Threshold"), 19, 0);
611 prt(format(_("現在の低魔力色閾値: %d0%%", "Current mana color threshold: %d0%%"), mana_warn), 22, 0);
612 prt(_("低魔力閾値 (0-9) ESCで決定: ", "Mana color Threshold (0-9 or ESC to accept): "), 20, 0);
616 } else if (k == '?') {
617 FileDisplayer(player_ptr->name).display(true, _("joption.txt#Manapoint", "option.txt#Manapoint"), 0, 0);
619 } else if (isdigit(k)) {
629 FileDisplayer(player_ptr->name).display(true, _("joption.txt", "option.txt"), 0, 0);
642 RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::EQUIPPY);
646 * @brief 標準オプションを変更するコマンドのサブルーチン /
647 * Interact with some options
648 * @param page オプションページ番号
649 * @param info 表示メッセージ
651 void do_cmd_options_aux(PlayerType *player_ptr, game_option_types page, concptr info)
654 int i, k = 0, n = 0, l;
655 int opt[MAIN_TERM_MIN_ROWS]{};
656 bool browse_only = (page == OPT_PAGE_BIRTH) && w_ptr->character_generated && (!w_ptr->wizard || !allow_debug_opts);
658 for (i = 0; i < MAIN_TERM_MIN_ROWS; i++) {
662 for (i = 0; option_info[i].o_desc; i++) {
663 if (option_info[i].o_page == page) {
671 constexpr auto command = _("%s (リターン:次, %sESC:終了, ?:ヘルプ) ", "%s (RET:next, %s, ?:help) ");
672 prt(format(command, info, browse_only ? _("", "ESC:exit") : _("y/n:変更, ", "y/n:change, ESC:accept")), 0, 0);
673 if (page == OPT_PAGE_AUTODESTROY) {
674 constexpr auto mes = _("以下のオプションは、簡易自動破壊を使用するときのみ有効", "Following options will protect items from easy auto-destroyer.");
675 c_prt(TERM_YELLOW, mes, 6, _(6, 3));
678 for (i = 0; i < n; i++) {
684 const auto reply = *option_info[opt[i]].o_var ? _("はい ", "yes") : _("いいえ", "no ");
685 const auto label = format("%-48s: %s (%.19s)", option_info[opt[i]].o_desc, reply, option_info[opt[i]].o_text);
686 if ((page == OPT_PAGE_AUTODESTROY) && i > 2) {
687 c_prt(a, label, i + 5, 0);
689 c_prt(a, label, i + 2, 0);
693 if ((page == OPT_PAGE_AUTODESTROY) && (k > 2)) {
699 move_cursor(k + 2 + l, 50);
701 dir = get_keymap_dir(ch);
702 if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) {
728 (*option_info[opt[k]].o_var) = true;
738 (*option_info[opt[k]].o_var) = false;
745 (*option_info[opt[k]].o_var) = !(*option_info[opt[k]].o_var);
750 FileDisplayer(player_ptr->name).display(true, std::string(_("joption.txt#", "option.txt#")).append(option_info[opt[k]].o_text), 0, 0);