diff --git a/VisualStudio/Hengband/Hengband.vcxproj b/VisualStudio/Hengband/Hengband.vcxproj index 449ba07672..6624aa990a 100644 --- a/VisualStudio/Hengband/Hengband.vcxproj +++ b/VisualStudio/Hengband/Hengband.vcxproj @@ -1427,6 +1427,7 @@ + @@ -1595,7 +1596,7 @@ - + diff --git a/VisualStudio/Hengband/Hengband.vcxproj.filters b/VisualStudio/Hengband/Hengband.vcxproj.filters index c4433f0e47..64c583efe3 100644 --- a/VisualStudio/Hengband/Hengband.vcxproj.filters +++ b/VisualStudio/Hengband/Hengband.vcxproj.filters @@ -2520,6 +2520,9 @@ monster + + save + @@ -3824,9 +3827,6 @@ monster-floor - - system - game-option @@ -5457,6 +5457,15 @@ floor + + save + + + system\enums + + + system\enums + @@ -5724,6 +5733,9 @@ {a5b8bf13-a675-4500-8b4c-37ea664757eb} + + {31491e27-d3e4-4605-b68a-c2c00d563479} + diff --git a/src/Makefile.am b/src/Makefile.am index e53a518b57..f9c295e724 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -929,7 +929,6 @@ hengband_SOURCES = \ system/dungeon-info.cpp system/dungeon-info.h \ system/floor-type-definition.cpp system/floor-type-definition.h \ system/grid-type-definition.cpp system/grid-type-definition.h \ - system/game-option-types.h \ system/h-basic.h system/h-config.h \ system/h-system.h system/h-type.h \ system/inner-game-data.cpp system/inner-game-data.h \ @@ -943,6 +942,9 @@ hengband_SOURCES = \ system/terrain-type-definition.cpp system/terrain-type-definition.h \ system/gamevalue.h \ \ + system/enums/game-option-page.h \ + system/enums/grid-flow.h \ + \ target/grid-selector.cpp target/grid-selector.h \ target/projection-path-calculator.cpp target/projection-path-calculator.h \ target/target-checker.cpp target/target-checker.h \ diff --git a/src/birth/auto-roller.cpp b/src/birth/auto-roller.cpp index 4cbc603953..aff7d10900 100644 --- a/src/birth/auto-roller.cpp +++ b/src/birth/auto-roller.cpp @@ -10,12 +10,14 @@ #include "player/player-personality.h" #include "player/player-sex.h" #include "player/player-status-table.h" -#include "system/game-option-types.h" +#include "system/enums/game-option-page.h" #include "system/player-type-definition.h" #include "term/screen-processor.h" #include "term/term-color-types.h" #include "term/z-form.h" #include "util/int-char-converter.h" +#include +#include /*! オートローラの能力値的要求水準 / Autoroll limit */ int16_t stat_limit[6]; @@ -36,8 +38,8 @@ static int32_t get_autoroller_prob(int *minval) /* 1 percent of the valid random space (60^6 && 72 MAXITEMS) { - cs = MAXITEMS; + if (cs > max_items) { + cs = max_items; } break; case '4': @@ -521,13 +521,13 @@ bool get_chara_limits(PlayerType *player_ptr, chara_limit_type *chara_limit_ptr) break; case '6': case 'l': - if (cs < MAXITEMS) { + if (cs < max_items) { cs++; } break; case '-': case '<': - if (cs != MAXITEMS) { + if (cs != max_items) { if (cs % 2) { if (cval[cs] > cval[cs - 1]) { cval[cs]--; @@ -544,7 +544,7 @@ bool get_chara_limits(PlayerType *player_ptr, chara_limit_type *chara_limit_ptr) break; case '+': case '>': - if (cs != MAXITEMS) { + if (cs != max_items) { if (cs % 2) { if (cval[cs] < mval[cs]) { cval[cs]++; @@ -560,7 +560,7 @@ bool get_chara_limits(PlayerType *player_ptr, chara_limit_type *chara_limit_ptr) break; case 'm': - if (cs != MAXITEMS) { + if (cs != max_items) { if (cs % 2) { if (cval[cs] < mval[cs]) { cval[cs] = mval[cs]; @@ -576,7 +576,7 @@ bool get_chara_limits(PlayerType *player_ptr, chara_limit_type *chara_limit_ptr) break; case 'n': - if (cs != MAXITEMS) { + if (cs != max_items) { if (cs % 2) { if (cval[cs] > cval[cs - 1]) { cval[cs] = cval[cs - 1]; @@ -600,7 +600,7 @@ bool get_chara_limits(PlayerType *player_ptr, chara_limit_type *chara_limit_ptr) break; case '=': screen_save(); - do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); + do_cmd_options_aux(player_ptr, GameOptionPage::BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); screen_load(); break; default: @@ -608,7 +608,7 @@ bool get_chara_limits(PlayerType *player_ptr, chara_limit_type *chara_limit_ptr) break; } - if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == MAXITEMS)) { + if (c == ESCAPE || ((c == ' ' || c == '\r' || c == '\n') && cs == max_items)) { break; } } diff --git a/src/birth/birth-util.cpp b/src/birth/birth-util.cpp index b4429e822d..70e4fa43fe 100644 --- a/src/birth/birth-util.cpp +++ b/src/birth/birth-util.cpp @@ -2,9 +2,10 @@ #include "cmd-io/cmd-gameoption.h" #include "core/show-file.h" #include "main/sound-of-music.h" -#include "system/game-option-types.h" +#include "system/enums/game-option-page.h" #include "system/player-type-definition.h" #include "term/screen-processor.h" +#include /*! * @brief プレイヤー作成を中断して変愚蛮怒を終了する @@ -19,7 +20,7 @@ void birth_quit(void) * @param player_ptr プレイヤーへの参照ポインタ * @param helpfile ファイル名 */ -void show_help(PlayerType *player_ptr, concptr helpfile) +void show_help(PlayerType *player_ptr, std::string_view helpfile) { screen_save(); FileDisplayer(player_ptr->name).display(true, helpfile, 0, 0); @@ -28,7 +29,7 @@ void show_help(PlayerType *player_ptr, concptr helpfile) void birth_help_option(PlayerType *player_ptr, char c, BirthKind bk) { - concptr help_file; + std::string help_file; switch (bk) { case BirthKind::RACE: help_file = _("jraceclas.txt#TheRaces", "raceclas.txt#TheRaces"); @@ -54,7 +55,7 @@ void birth_help_option(PlayerType *player_ptr, char c, BirthKind bk) show_help(player_ptr, help_file); } else if (c == '=') { screen_save(); - do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); + do_cmd_options_aux(player_ptr, GameOptionPage::BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); screen_load(); } else if (c != '2' && c != '4' && c != '6' && c != '8') { bell(); diff --git a/src/birth/birth-util.h b/src/birth/birth-util.h index bc3801ce96..f1ed406886 100644 --- a/src/birth/birth-util.h +++ b/src/birth/birth-util.h @@ -1,6 +1,6 @@ #pragma once -#include "system/angband.h" +#include enum class BirthKind { REALM, @@ -12,5 +12,5 @@ enum class BirthKind { class PlayerType; void birth_quit(); -void show_help(PlayerType *player_ptr, concptr helpfile); +void show_help(PlayerType *player_ptr, std::string_view helpfile); void birth_help_option(PlayerType *player_ptr, char c, BirthKind bk); diff --git a/src/birth/birth-wizard.cpp b/src/birth/birth-wizard.cpp index a9247cfcd8..4acd808ba0 100644 --- a/src/birth/birth-wizard.cpp +++ b/src/birth/birth-wizard.cpp @@ -30,7 +30,7 @@ #include "player/player-status-table.h" #include "player/player-status.h" #include "player/process-name.h" -#include "system/game-option-types.h" +#include "system/enums/game-option-page.h" #include "system/player-type-definition.h" #include "system/redrawing-flags-updater.h" #include "term/screen-processor.h" @@ -47,16 +47,6 @@ #include "world/world.h" #include -/*! - * オートローラーの内容を描画する間隔 / - * How often the autoroller will update the display and pause - * to check for user interuptions. - * Bigger values will make the autoroller faster, but slower - * system may have problems because the user can't stop the - * autoroller for this number of rolls. - */ -#define AUTOROLLER_STEP 54321L - static void display_initial_birth_message(PlayerType *player_ptr) { term_clear(); @@ -80,7 +70,7 @@ static void display_help_on_sex_select(PlayerType *player_ptr, char c) do_cmd_help(player_ptr); } else if (c == '=') { screen_save(); - do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); + do_cmd_options_aux(player_ptr, GameOptionPage::BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); screen_load(); } else if (c != '4' && c != '6') { bell(); @@ -273,7 +263,7 @@ static bool let_player_build_character(PlayerType *player_ptr) static void display_initial_options(PlayerType *player_ptr) { const auto expfact_mod = static_cast(get_expfact(player_ptr)) - 100; - int16_t adj[A_MAX]; + int16_t adj[A_MAX]{}; for (int i = 0; i < A_MAX; i++) { adj[i] = rp_ptr->r_adj[i] + cp_ptr->c_adj[i] + ap_ptr->a_adj[i]; } @@ -303,7 +293,7 @@ static void display_initial_options(PlayerType *player_ptr) clear_from(10); screen_save(); - do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); + do_cmd_options_aux(player_ptr, GameOptionPage::BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); screen_load(); } @@ -399,7 +389,13 @@ static bool decide_body_spec(PlayerType *player_ptr, chara_limit_type chara_limi static bool display_auto_roller_count(PlayerType *player_ptr, const int col) { - if ((auto_round % AUTOROLLER_STEP) != 0) { + /*! + * @details ここで指定された回数だけロールする度にその時の結果を画面に表示する + * @todo この定数を定義した時代に比べて、CPUパワーが相当に上がっている. + * 表示部で足を引っ張っているので、タイマで数えて0.1秒/表示 くらいで良いと思われる. + */ + constexpr auto roll_results_per_display = 54321; + if ((auto_round % roll_results_per_display) != 0) { return false; } diff --git a/src/birth/character-builder.cpp b/src/birth/character-builder.cpp index ad387ba6fb..ef1321f9a0 100644 --- a/src/birth/character-builder.cpp +++ b/src/birth/character-builder.cpp @@ -74,7 +74,7 @@ static void write_birth_diary(PlayerType *player_ptr) } if (player_ptr->element) { - const auto mes_element = format(_("%s元素系統に%sを選択した。", "%schose %s system."), indent, get_element_title(player_ptr->element)); + const auto mes_element = format(_("%s元素系統に%sを選択した。", "%schose %s system."), indent, get_element_title(player_ptr->element).data()); exe_write_diary(floor, DiaryKind::DESCRIPTION, 1, mes_element); } diff --git a/src/cmd-io/cmd-gameoption.cpp b/src/cmd-io/cmd-gameoption.cpp index 4ae730c1e1..1fef513f70 100644 --- a/src/cmd-io/cmd-gameoption.cpp +++ b/src/cmd-io/cmd-gameoption.cpp @@ -14,7 +14,7 @@ #include "io/input-key-acceptor.h" #include "io/write-diary.h" #include "main/sound-of-music.h" -#include "system/game-option-types.h" +#include "system/enums/game-option-page.h" #include "system/player-type-definition.h" #include "system/redrawing-flags-updater.h" #include "term/gameterm.h" @@ -27,16 +27,16 @@ #include "view/display-messages.h" #include "view/display-symbol.h" #include "world/world.h" +#include -#define OPT_NUM 15 - +namespace { struct opts { char key; - concptr name; + std::string name; int row; }; -static opts option_fields[OPT_NUM] = { +const std::vector option_fields = { { '1', _(" キー入力 オプション", "Input Options"), 3 }, { '2', _(" マップ画面 オプション", "Map Screen Options"), 4 }, { '3', _(" テキスト表示 オプション", "Text Display Options"), 5 }, @@ -55,6 +55,7 @@ static opts option_fields[OPT_NUM] = { { 'b', _(" 初期 オプション (参照のみ)", "Birth Options (Browse Only)"), 18 }, { 'c', _(" 詐欺 オプション", "Cheat Options"), 19 }, }; +} /*! * @brief セーブ頻度ターンの次の値を返す @@ -91,79 +92,65 @@ static int16_t toggle_frequency(int16_t current) * @brief 自動セーブオプションを変更するコマンドのメインルーチン * @param info 表示メッセージ */ -static void do_cmd_options_autosave(PlayerType *player_ptr, concptr info) +static void do_cmd_options_autosave(PlayerType *player_ptr, std::string_view info) { - char ch; - int i, k = 0, n = 2; + auto k = 0; + constexpr auto n = 2; term_clear(); while (true) { - prt(format(_("%s ( リターンで次へ, y/n でセット, F で頻度を入力, ESC で決定 ) ", "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) "), info), 0, 0); - for (i = 0; i < n; i++) { + prt(format(_("%s ( リターンで次へ, y/n でセット, F で頻度を入力, ESC で決定 ) ", "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) "), info.data()), 0, 0); + for (auto i = 0; i < n; i++) { byte a = TERM_WHITE; if (i == k) { a = TERM_L_BLUE; } - 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); + const auto &autosave = autosave_info[i]; + c_prt(a, format("%-48s: %s (%s)", autosave.description.data(), (*autosave.value ? _("はい ", "yes") : _("いいえ", "no ")), autosave.text.data()), i + 2, 0); } prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0); move_cursor(k + 2, 50); - ch = inkey(); + auto ch = inkey(); + auto &autosave = autosave_info[k]; switch (ch) { - case ESCAPE: { + case ESCAPE: return; - } - case '-': - case '8': { + case '8': k = (n + k - 1) % n; break; - } - case ' ': case '\n': case '\r': - case '2': { + case '2': k = (k + 1) % n; break; - } - case 'y': case 'Y': - case '6': { - - (*autosave_info[k].o_var) = true; + case '6': + *autosave.value = true; k = (k + 1) % n; break; - } - case 'n': case 'N': - case '4': { - (*autosave_info[k].o_var) = false; + case '4': + *autosave.value = false; k = (k + 1) % n; break; - } - case 'f': - case 'F': { + case 'F': autosave_freq = toggle_frequency(autosave_freq); prt(format(_("自動セーブの頻度: %d ターン毎", "Timed autosave frequency: every %d turns"), autosave_freq), 5, 0); break; - } - - case '?': { + case '?': FileDisplayer(player_ptr->name).display(true, _("joption.txt#Autosave", "option.txt#Autosave"), 0, 0); term_clear(); break; - } - - default: { + default: bell(); break; } - } } } @@ -352,8 +339,9 @@ static void do_cmd_options_cheat(const FloorType &floor, std::string_view player a = TERM_L_BLUE; } - const auto yesno = *cheat_info[i].o_var ? _("はい ", "yes") : _("いいえ", "no "); - c_prt(enum2i(a), format("%-48s: %s (%s)", cheat_info[i].o_desc, yesno, cheat_info[i].o_text), i + 2, 0); + const auto &cheat = cheat_info[i]; + const auto yesno = *cheat.value ? _("はい ", "yes") : _("いいえ", "no "); + c_prt(enum2i(a), format("%-48s: %s (%s)", cheat.description.data(), yesno, cheat.text.data()), i + 2, 0); } move_cursor(k + 2, 50); @@ -363,6 +351,7 @@ static void do_cmd_options_cheat(const FloorType &floor, std::string_view player ch = I2D(dir); } + const auto &cheat = cheat_info[k]; switch (ch) { case ESCAPE: return; @@ -385,19 +374,19 @@ static void do_cmd_options_cheat(const FloorType &floor, std::string_view player _("詐欺オプションをONにして、スコアを残せなくなった。", "gave up sending score to use cheating options.")); } - world.noscore |= cheat_info[k].o_set * 256 + cheat_info[k].o_bit; - *cheat_info[k].o_var = true; + world.noscore |= cheat.flag_position * 256 + cheat.offset; + *cheat.value = true; k = (k + 1) % n; break; } case 'n': case 'N': case '4': - *cheat_info[k].o_var = false; + *cheat.value = false; k = (k + 1) % n; break; case '?': - FileDisplayer(player_name).display(true, std::string(_("joption.txt#", "option.txt#")).append(cheat_info[k].o_text), 0, 0); + FileDisplayer(player_name).display(true, std::string(_("joption.txt#", "option.txt#")).append(cheat.text), 0, 0); term_clear(); break; default: @@ -412,15 +401,13 @@ static void do_cmd_options_cheat(const FloorType &floor, std::string_view player */ void extract_option_vars(void) { - for (int i = 0; option_info[i].o_desc; i++) { - int os = option_info[i].o_set; - int ob = option_info[i].o_bit; - if (option_info[i].o_var) { - if (g_option_flags[os] & (1UL << ob)) { - (*option_info[i].o_var) = true; - } else { - (*option_info[i].o_var) = false; - } + for (auto &option : option_info) { + int os = option.flag_position; + int ob = option.offset; + if (g_option_flags[os] & (1UL << ob)) { + *option.value = true; + } else { + *option.value = false; } } } @@ -444,7 +431,7 @@ void do_cmd_options(PlayerType *player_ptr) screen_save(); const auto &world = AngbandWorld::get_instance(); while (true) { - int n = OPT_NUM; + auto n = std::ssize(option_fields); if (!world.noscore && !allow_debug_opts) { n--; } @@ -457,7 +444,7 @@ void do_cmd_options(PlayerType *player_ptr) if (i == y) { a = TERM_L_BLUE; } - term_putstr(5, option_fields[i].row, -1, a, format("(%c) %s", toupper(option_fields[i].key), option_fields[i].name)); + term_putstr(5, option_fields[i].row, -1, a, format("(%c) %s", toupper(option_fields[i].key), option_fields[i].name.data())); } prt(_("<方向>で移動, Enterで決定, ESCでキャンセル, ?でヘルプ: ", "Move to , Select to Enter, Cancel to ESC, ? to help: "), 21, 0); @@ -510,37 +497,37 @@ void do_cmd_options(PlayerType *player_ptr) switch (k) { case '1': { - do_cmd_options_aux(player_ptr, OPT_PAGE_INPUT, _("キー入力オプション", "Input Options")); + do_cmd_options_aux(player_ptr, GameOptionPage::INPUT, _("キー入力オプション", "Input Options")); break; } case '2': { - do_cmd_options_aux(player_ptr, OPT_PAGE_MAPSCREEN, _("マップ画面オプション", "Map Screen Options")); + do_cmd_options_aux(player_ptr, GameOptionPage::MAPSCREEN, _("マップ画面オプション", "Map Screen Options")); break; } case '3': { - do_cmd_options_aux(player_ptr, OPT_PAGE_TEXT, _("テキスト表示オプション", "Text Display Options")); + do_cmd_options_aux(player_ptr, GameOptionPage::TEXT, _("テキスト表示オプション", "Text Display Options")); break; } case '4': { - do_cmd_options_aux(player_ptr, OPT_PAGE_GAMEPLAY, _("ゲームプレイ・オプション", "Game-Play Options")); + do_cmd_options_aux(player_ptr, GameOptionPage::GAMEPLAY, _("ゲームプレイ・オプション", "Game-Play Options")); break; } case '5': { - do_cmd_options_aux(player_ptr, OPT_PAGE_DISTURBANCE, _("行動中止関係のオプション", "Disturbance Options")); + do_cmd_options_aux(player_ptr, GameOptionPage::DISTURBANCE, _("行動中止関係のオプション", "Disturbance Options")); break; } case '6': { - do_cmd_options_aux(player_ptr, OPT_PAGE_AUTODESTROY, _("簡易自動破壊オプション", "Easy Auto-Destroyer Options")); + do_cmd_options_aux(player_ptr, GameOptionPage::AUTODESTROY, _("簡易自動破壊オプション", "Easy Auto-Destroyer Options")); break; } case 'R': case 'r': { - do_cmd_options_aux(player_ptr, OPT_PAGE_PLAYRECORD, _("プレイ記録オプション", "Play-record Options")); + do_cmd_options_aux(player_ptr, GameOptionPage::PLAYRECORD, _("プレイ記録オプション", "Play-record Options")); break; } case 'B': case 'b': { - do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH, + do_cmd_options_aux(player_ptr, GameOptionPage::BIRTH, (!world.wizard || !allow_debug_opts) ? _("初期オプション(参照のみ)", "Birth Options(browse only)") : _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); break; @@ -646,54 +633,57 @@ void do_cmd_options(PlayerType *player_ptr) } /*! - * @brief 標準オプションを変更するコマンドのサブルーチン / - * Interact with some options + * @brief 標準オプションを変更するコマンドのサブルーチン * @param page オプションページ番号 * @param info 表示メッセージ */ -void do_cmd_options_aux(PlayerType *player_ptr, game_option_types page, concptr info) +void do_cmd_options_aux(PlayerType *player_ptr, GameOptionPage page, std::string_view info) { char ch; - int i, k = 0, n = 0, l; + int k = 0, n = 0, l; int opt[MAIN_TERM_MIN_ROWS]{}; const auto &world = AngbandWorld::get_instance(); - const auto browse_only = (page == OPT_PAGE_BIRTH) && world.character_generated && (!world.wizard || !allow_debug_opts); - for (i = 0; i < MAIN_TERM_MIN_ROWS; i++) { + const auto browse_only = (page == GameOptionPage::BIRTH) && world.character_generated && (!world.wizard || !allow_debug_opts); + for (auto i = 0; i < MAIN_TERM_MIN_ROWS; i++) { opt[i] = 0; } - for (i = 0; option_info[i].o_desc; i++) { - if (option_info[i].o_page == page) { - opt[n++] = i; + auto option_num = 0; + for (auto &option : option_info) { + if (option.page == page) { + opt[n++] = option_num; } + + option_num++; } term_clear(); while (true) { DIRECTION dir; constexpr auto command = _("%s (リターン:次, %sESC:終了, ?:ヘルプ) ", "%s (RET:next, %s, ?:help) "); - prt(format(command, info, browse_only ? _("", "ESC:exit") : _("y/n:変更, ", "y/n:change, ESC:accept")), 0, 0); - if (page == OPT_PAGE_AUTODESTROY) { + prt(format(command, info.data(), browse_only ? _("", "ESC:exit") : _("y/n:変更, ", "y/n:change, ESC:accept")), 0, 0); + if (page == GameOptionPage::AUTODESTROY) { constexpr auto mes = _("以下のオプションは、簡易自動破壊を使用するときのみ有効", "Following options will protect items from easy auto-destroyer."); c_prt(TERM_YELLOW, mes, 6, _(6, 3)); } - for (i = 0; i < n; i++) { + for (auto i = 0; i < n; i++) { byte a = TERM_WHITE; if (i == k) { a = TERM_L_BLUE; } - const auto reply = *option_info[opt[i]].o_var ? _("はい ", "yes") : _("いいえ", "no "); - const auto label = format("%-48s: %s (%.19s)", option_info[opt[i]].o_desc, reply, option_info[opt[i]].o_text); - if ((page == OPT_PAGE_AUTODESTROY) && i > 2) { + const auto &option = option_info[opt[i]]; + const auto reply = *option.value ? _("はい ", "yes") : _("いいえ", "no "); + const auto label = format("%-48s: %s (%.19s)", option.description.data(), reply, option.text.data()); + if ((page == GameOptionPage::AUTODESTROY) && i > 2) { c_prt(a, label, i + 5, 0); } else { c_prt(a, label, i + 2, 0); } } - if ((page == OPT_PAGE_AUTODESTROY) && (k > 2)) { + if ((page == GameOptionPage::AUTODESTROY) && (k > 2)) { l = 3; } else { l = 0; @@ -706,58 +696,54 @@ void do_cmd_options_aux(PlayerType *player_ptr, game_option_types page, concptr ch = I2D(dir); } + const auto &option = option_info[opt[k]]; switch (ch) { - case ESCAPE: { + case ESCAPE: return; - } case '-': - case '8': { + case '8': k = (n + k - 1) % n; break; - } case ' ': case '\n': case '\r': - case '2': { + case '2': k = (k + 1) % n; break; - } case 'y': case 'Y': - case '6': { + case '6': if (browse_only) { break; } - (*option_info[opt[k]].o_var) = true; + + *option.value = true; k = (k + 1) % n; break; - } case 'n': case 'N': - case '4': { + case '4': if (browse_only) { break; } - (*option_info[opt[k]].o_var) = false; + + *option.value = false; k = (k + 1) % n; break; - } case 't': - case 'T': { + case 'T': if (!browse_only) { - (*option_info[opt[k]].o_var) = !(*option_info[opt[k]].o_var); + *option.value = !*option.value; } + break; - } - case '?': { - FileDisplayer(player_ptr->name).display(true, std::string(_("joption.txt#", "option.txt#")).append(option_info[opt[k]].o_text), 0, 0); + case '?': + FileDisplayer(player_ptr->name).display(true, std::string(_("joption.txt#", "option.txt#")).append(option.text), 0, 0); term_clear(); break; - } - default: { + default: bell(); break; } - } } } diff --git a/src/cmd-io/cmd-gameoption.h b/src/cmd-io/cmd-gameoption.h index 006b44a2ae..cf777779ee 100644 --- a/src/cmd-io/cmd-gameoption.h +++ b/src/cmd-io/cmd-gameoption.h @@ -1,9 +1,9 @@ #pragma once -#include "system/angband.h" -#include "system/game-option-types.h" +#include +enum class GameOptionPage : int; class PlayerType; void extract_option_vars(); -void do_cmd_options_aux(PlayerType *player_ptr, game_option_types page, concptr info); +void do_cmd_options_aux(PlayerType *player_ptr, GameOptionPage page, std::string_view info); void do_cmd_options(PlayerType *player_ptr); diff --git a/src/game-option/option-types-table.cpp b/src/game-option/option-types-table.cpp index 82919072ba..0936e70f9f 100644 --- a/src/game-option/option-types-table.cpp +++ b/src/game-option/option-types-table.cpp @@ -9,325 +9,335 @@ #include "game-option/play-record-options.h" #include "game-option/special-options.h" #include "game-option/text-display-options.h" -#include "system/game-option-types.h" +#include "locale/language-switcher.h" +#include "system/enums/game-option-page.h" +#include + +GameOption::GameOption(bool *value, bool norm, uint8_t set, uint8_t bits, std::string &&text, std::string &&description, const std::optional &page) + : value(value) + , default_value(norm) + , flag_position(set) + , offset(bits) + , text(std::move(text)) + , description(std::move(description)) + , page(page) +{ +} /*! * @brief オプションテーブル / * Available Options */ -const std::vector option_info = { +const std::vector option_info = { /*** Input Options ***/ - { &rogue_like_commands, false, OPT_PAGE_INPUT, 0, 0, "rogue_like_commands", _("ローグ風キー配置を使用する", "Rogue-like commands") }, + { &rogue_like_commands, false, 0, 0, "rogue_like_commands", _("ローグ風キー配置を使用する", "Rogue-like commands"), GameOptionPage::INPUT }, - { &always_pickup, false, OPT_PAGE_INPUT, 0, 5, "always_pickup", _("常にアイテムを拾う", "Pick things up by default") }, + { &always_pickup, false, 0, 5, "always_pickup", _("常にアイテムを拾う", "Pick things up by default"), GameOptionPage::INPUT }, - { &carry_query_flag, false, OPT_PAGE_INPUT, 0, 3, "carry_query_flag", _("アイテムを拾う前に確認する", "Prompt before picking things up") }, + { &carry_query_flag, false, 0, 3, "carry_query_flag", _("アイテムを拾う前に確認する", "Prompt before picking things up"), GameOptionPage::INPUT }, - { &quick_messages, true, OPT_PAGE_INPUT, 0, 1, "quick_messages", _("クイック・メッセージを使用する", "Activate quick messages") }, + { &quick_messages, true, 0, 1, "quick_messages", _("クイック・メッセージを使用する", "Activate quick messages"), GameOptionPage::INPUT }, - { &auto_more, false, OPT_PAGE_INPUT, 2, 6, "auto_more", _("キー待ちしないで連続でメッセージを表示する", "Automatically clear '-more-' prompts") }, + { &auto_more, false, 2, 6, "auto_more", _("キー待ちしないで連続でメッセージを表示する", "Automatically clear '-more-' prompts"), GameOptionPage::INPUT }, - { &skip_more, false, OPT_PAGE_INPUT, 2, 18, "skip_more", _("キー待ちしないで全てのメッセージを読み飛ばす", "Automatically skip all messages.") }, + { &skip_more, false, 2, 18, "skip_more", _("キー待ちしないで全てのメッセージを読み飛ばす", "Automatically skip all messages."), GameOptionPage::INPUT }, - { &command_menu, true, OPT_PAGE_INPUT, 2, 7, "command_menu", _("メニューによりコマンド選択を有効にする", "Enable command selection menu") }, + { &command_menu, true, 2, 7, "command_menu", _("メニューによりコマンド選択を有効にする", "Enable command selection menu"), GameOptionPage::INPUT }, - { &other_query_flag, false, OPT_PAGE_INPUT, 0, 2, "other_query_flag", _("床上のアイテムを使用するときに確認する", "Prompt for floor item selection") }, + { &other_query_flag, false, 0, 2, "other_query_flag", _("床上のアイテムを使用するときに確認する", "Prompt for floor item selection"), GameOptionPage::INPUT }, - { &use_old_target, false, OPT_PAGE_INPUT, 0, 4, "use_old_target", _("常に以前のターゲットを指定する", "Use old target by default") }, + { &use_old_target, false, 0, 4, "use_old_target", _("常に以前のターゲットを指定する", "Use old target by default"), GameOptionPage::INPUT }, - { &always_repeat, true, OPT_PAGE_INPUT, 0, 6, "always_repeat", _("コマンド自動繰り返し", "Repeat obvious commands") }, + { &always_repeat, true, 0, 6, "always_repeat", _("コマンド自動繰り返し", "Repeat obvious commands"), GameOptionPage::INPUT }, - { &confirm_destroy, false, OPT_PAGE_INPUT, 5, 3, "confirm_destroy", - _("「無価値」なアイテムを破壊する時確認する", "Prompt for destruction of known worthless items") }, + { &confirm_destroy, false, 5, 3, "confirm_destroy", + _("「無価値」なアイテムを破壊する時確認する", "Prompt for destruction of known worthless items"), GameOptionPage::INPUT }, - { &confirm_wear, true, OPT_PAGE_INPUT, 5, 4, "confirm_wear", _("呪われた物を装備する時確認する", "Confirm to wear/wield known cursed items") }, + { &confirm_wear, true, 5, 4, "confirm_wear", _("呪われた物を装備する時確認する", "Confirm to wear/wield known cursed items"), GameOptionPage::INPUT }, - { &confirm_quest, true, OPT_PAGE_INPUT, 1, 9, "confirm_quest", _("クエストを諦めて階段で逃げる前に確認する", "Prompt before exiting a quest level") }, + { &confirm_quest, true, 1, 9, "confirm_quest", _("クエストを諦めて階段で逃げる前に確認する", "Prompt before exiting a quest level"), GameOptionPage::INPUT }, - { &target_pet, false, OPT_PAGE_INPUT, 2, 5, "target_pet", _("ペットをターゲットにする", "Allow targeting pets") }, + { &target_pet, false, 2, 5, "target_pet", _("ペットをターゲットにする", "Allow targeting pets"), GameOptionPage::INPUT }, - { &easy_open, true, OPT_PAGE_INPUT, 5, 7, "easy_open", _("自動的にドアを開ける", "Automatically open doors") }, + { &easy_open, true, 5, 7, "easy_open", _("自動的にドアを開ける", "Automatically open doors"), GameOptionPage::INPUT }, - { &easy_disarm, true, OPT_PAGE_INPUT, 5, 8, "easy_disarm", _("自動的に罠を解除する", "Automatically disarm traps") }, + { &easy_disarm, true, 5, 8, "easy_disarm", _("自動的に罠を解除する", "Automatically disarm traps"), GameOptionPage::INPUT }, - { &easy_floor, true, OPT_PAGE_INPUT, 5, 9, "easy_floor", _("床上で重なったアイテムをリストする", "Display floor stacks in a list") }, + { &easy_floor, true, 5, 9, "easy_floor", _("床上で重なったアイテムをリストする", "Display floor stacks in a list"), GameOptionPage::INPUT }, - { &use_command, false, OPT_PAGE_INPUT, 5, 10, "use_command", _("「使う(a)」コマンドでアイテムを何でも使える", "Allow unified use command") }, + { &use_command, false, 5, 10, "use_command", _("「使う(a)」コマンドでアイテムを何でも使える", "Allow unified use command"), GameOptionPage::INPUT }, - { &over_exert, false, OPT_PAGE_INPUT, 0, 29, "over_exert", _("MPが足りなくても魔法に挑戦する", "Allow casting spells when short of mana") }, + { &over_exert, false, 0, 29, "over_exert", _("MPが足りなくても魔法に挑戦する", "Allow casting spells when short of mana"), GameOptionPage::INPUT }, - { &numpad_as_cursorkey, true, OPT_PAGE_INPUT, 2, 31, "numpad_as_cursorkey", - _("エディタ内でテンキーをカーソルキーとして使う", "Use numpad keys as cursor keys in editor mode") }, + { &numpad_as_cursorkey, true, 2, 31, "numpad_as_cursorkey", + _("エディタ内でテンキーをカーソルキーとして使う", "Use numpad keys as cursor keys in editor mode"), GameOptionPage::INPUT }, /*** Map Screen Options ***/ - { ¢er_player, false, OPT_PAGE_MAPSCREEN, 5, 11, "center_player", _("常にプレイヤーを中心に置く(*遅い*)", "Center map while walking (*slow*)") }, + { ¢er_player, false, 5, 11, "center_player", _("常にプレイヤーを中心に置く(*遅い*)", "Center map while walking (*slow*)"), GameOptionPage::MAPSCREEN }, - { ¢er_running, true, OPT_PAGE_MAPSCREEN, 5, 12, "center_running", _("走っている時でも中心に置く", "Centering even while running") }, + { ¢er_running, true, 5, 12, "center_running", _("走っている時でも中心に置く", "Centering even while running"), GameOptionPage::MAPSCREEN }, - { &view_yellow_lite, true, OPT_PAGE_MAPSCREEN, 1, 28, "view_yellow_lite", _("明かりの範囲を特別な色で表示する", "Use special colors for torch-lit grids") }, + { &view_yellow_lite, true, 1, 28, "view_yellow_lite", _("明かりの範囲を特別な色で表示する", "Use special colors for torch-lit grids"), GameOptionPage::MAPSCREEN }, - { &view_bright_lite, true, OPT_PAGE_MAPSCREEN, 1, 29, "view_bright_lite", _("視界の範囲を特別な色で表示する", "Use special colors for 'viewable' grids") }, + { &view_bright_lite, true, 1, 29, "view_bright_lite", _("視界の範囲を特別な色で表示する", "Use special colors for 'viewable' grids"), GameOptionPage::MAPSCREEN }, - { &view_granite_lite, true, OPT_PAGE_MAPSCREEN, 1, 30, "view_granite_lite", _("壁を特別な色で表示する(重い)", "Use special colors for wall grids (slow)") }, + { &view_granite_lite, true, 1, 30, "view_granite_lite", _("壁を特別な色で表示する(重い)", "Use special colors for wall grids (slow)"), GameOptionPage::MAPSCREEN }, - { &view_special_lite, true, OPT_PAGE_MAPSCREEN, 1, 31, "view_special_lite", - _("床を特別な色で表示する(重い)", "Use special colors for floor grids (slow)") }, + { &view_special_lite, true, 1, 31, "view_special_lite", + _("床を特別な色で表示する(重い)", "Use special colors for floor grids (slow)"), GameOptionPage::MAPSCREEN }, - { &view_perma_grids, true, OPT_PAGE_MAPSCREEN, 1, 6, "view_perma_grids", _("明るい場所はそのままにする", "Map remembers all perma-lit grids") }, + { &view_perma_grids, true, 1, 6, "view_perma_grids", _("明るい場所はそのままにする", "Map remembers all perma-lit grids"), GameOptionPage::MAPSCREEN }, - { &view_torch_grids, false, OPT_PAGE_MAPSCREEN, 1, 7, "view_torch_grids", _("明かりで照らした場所はそのままにする", "Map remembers all torch-lit grids") }, + { &view_torch_grids, false, 1, 7, "view_torch_grids", _("明かりで照らした場所はそのままにする", "Map remembers all torch-lit grids"), GameOptionPage::MAPSCREEN }, - { &view_unsafe_grids, true, OPT_PAGE_MAPSCREEN, 1, 8, "view_unsafe_grids", _("トラップ感知済みでない場所を表示する", "Map marked by detect traps") }, + { &view_unsafe_grids, true, 1, 8, "view_unsafe_grids", _("トラップ感知済みでない場所を表示する", "Map marked by detect traps"), GameOptionPage::MAPSCREEN }, - { &view_hidden_walls, true, OPT_PAGE_MAPSCREEN, 1, 2, "view_hidden_walls", _("壁の中に囲まれた壁を表示する", "Map walls hidden in other walls") }, + { &view_hidden_walls, true, 1, 2, "view_hidden_walls", _("壁の中に囲まれた壁を表示する", "Map walls hidden in other walls"), GameOptionPage::MAPSCREEN }, - { &view_unsafe_walls, false, OPT_PAGE_MAPSCREEN, 1, 1, "view_unsafe_walls", _("トラップ未感知の壁の中に囲まれた壁を表示する", "Map hidden walls not marked by detect traps") }, + { &view_unsafe_walls, false, 1, 1, "view_unsafe_walls", _("トラップ未感知の壁の中に囲まれた壁を表示する", "Map hidden walls not marked by detect traps"), GameOptionPage::MAPSCREEN }, - { &view_reduce_view, false, OPT_PAGE_MAPSCREEN, 1, 17, "view_reduce_view", _("街では視野を狭くする", "Reduce view-radius in town") }, + { &view_reduce_view, false, 1, 17, "view_reduce_view", _("街では視野を狭くする", "Reduce view-radius in town"), GameOptionPage::MAPSCREEN }, - { &fresh_before, true, OPT_PAGE_MAPSCREEN, 1, 23, "fresh_before", _("連続コマンド中に画面を再描画し続ける", "Flush output while in repeated command") }, + { &fresh_before, true, 1, 23, "fresh_before", _("連続コマンド中に画面を再描画し続ける", "Flush output while in repeated command"), GameOptionPage::MAPSCREEN }, - { &fresh_after, false, OPT_PAGE_MAPSCREEN, 1, 24, "fresh_after", _("コマンド後に画面を常に再描画し続ける", "Flush output after monster's move") }, + { &fresh_after, false, 1, 24, "fresh_after", _("コマンド後に画面を常に再描画し続ける", "Flush output after monster's move"), GameOptionPage::MAPSCREEN }, - { &fresh_once, false, OPT_PAGE_MAPSCREEN, 1, 10, "fresh_once", _("キー入力毎に一度だけ画面を再描画する", "Flush output once per key input") }, + { &fresh_once, false, 1, 10, "fresh_once", _("キー入力毎に一度だけ画面を再描画する", "Flush output once per key input"), GameOptionPage::MAPSCREEN }, - { &fresh_message, false, OPT_PAGE_MAPSCREEN, 1, 25, "fresh_message", _("メッセージの後に画面を再描画する", "Flush output after every message") }, + { &fresh_message, false, 1, 25, "fresh_message", _("メッセージの後に画面を再描画する", "Flush output after every message"), GameOptionPage::MAPSCREEN }, - { &hilite_player, false, OPT_PAGE_MAPSCREEN, 1, 27, "hilite_player", _("プレイヤーにカーソルを合わせる", "Highlight the player with the cursor") }, + { &hilite_player, false, 1, 27, "hilite_player", _("プレイヤーにカーソルを合わせる", "Highlight the player with the cursor"), GameOptionPage::MAPSCREEN }, - { &display_path, true, OPT_PAGE_MAPSCREEN, 2, 8, "display_path", _("魔法や矢の軌跡を表示する", "Display actual path before shooting") }, + { &display_path, true, 2, 8, "display_path", _("魔法や矢の軌跡を表示する", "Display actual path before shooting"), GameOptionPage::MAPSCREEN }, /*** Text Display Options ***/ - { &plain_descriptions, true, OPT_PAGE_TEXT, 5, 1, "plain_descriptions", _("アイテムの記述を簡略にする", "Plain object descriptions") }, + { &plain_descriptions, true, 5, 1, "plain_descriptions", _("アイテムの記述を簡略にする", "Plain object descriptions"), GameOptionPage::TEXT }, - { &plain_pickup, false, OPT_PAGE_TEXT, 6, 6, "plain_pickup", _("「拾った」メッセージを簡略化する", "Plain pickup messages(japanese only)") }, + { &plain_pickup, false, 6, 6, "plain_pickup", _("「拾った」メッセージを簡略化する", "Plain pickup messages(japanese only)"), GameOptionPage::TEXT }, - { &always_show_list, true, OPT_PAGE_TEXT, 4, 0, "always_show_list", _("選択時には常に一覧を表示する", "Always show list when choosing items") }, + { &always_show_list, true, 4, 0, "always_show_list", _("選択時には常に一覧を表示する", "Always show list when choosing items"), GameOptionPage::TEXT }, - { &depth_in_feet, false, OPT_PAGE_TEXT, 0, 7, "depth_in_feet", _("ダンジョンの深さをフィートで表示する", "Show dungeon level in feet") }, + { &depth_in_feet, false, 0, 7, "depth_in_feet", _("ダンジョンの深さをフィートで表示する", "Show dungeon level in feet"), GameOptionPage::TEXT }, - { &show_labels, true, OPT_PAGE_TEXT, 0, 10, "show_labels", _("装備一覧で装備場所を表示する", "Show labels in object listings") }, + { &show_labels, true, 0, 10, "show_labels", _("装備一覧で装備場所を表示する", "Show labels in object listings"), GameOptionPage::TEXT }, - { &show_weights, true, OPT_PAGE_TEXT, 0, 11, "show_weights", _("アイテム一覧で重量を表示する", "Show weights in object listings") }, + { &show_weights, true, 0, 11, "show_weights", _("アイテム一覧で重量を表示する", "Show weights in object listings"), GameOptionPage::TEXT }, - { &show_item_graph, true, OPT_PAGE_TEXT, 2, 0, "show_item_graph", _("アイテムのシンボルを表示する", "Show items graphics") }, + { &show_item_graph, true, 2, 0, "show_item_graph", _("アイテムのシンボルを表示する", "Show items graphics"), GameOptionPage::TEXT }, - { &equippy_chars, true, OPT_PAGE_TEXT, 1, 12, "equippy_chars", _("ステータスに文字で装備を表示する", "Display 'equippy' chars") }, + { &equippy_chars, true, 1, 12, "equippy_chars", _("ステータスに文字で装備を表示する", "Display 'equippy' chars"), GameOptionPage::TEXT }, - { &display_mutations, false, OPT_PAGE_TEXT, 5, 0, "display_mutations", _("'C'コマンドで突然変異を表示する", "Display mutations in 'C'haracter Display") }, + { &display_mutations, false, 5, 0, "display_mutations", _("'C'コマンドで突然変異を表示する", "Display mutations in 'C'haracter Display"), GameOptionPage::TEXT }, - { &compress_savefile, false, OPT_PAGE_TEXT, 1, 26, "compress_savefile", _("セーブ・ファイル中のメッセージを圧縮する", "Compress messages in savefiles") }, + { &compress_savefile, false, 1, 26, "compress_savefile", _("セーブ・ファイル中のメッセージを圧縮する", "Compress messages in savefiles"), GameOptionPage::TEXT }, - { &abbrev_extra, false, OPT_PAGE_TEXT, 2, 10, "abbrev_extra", - _("アイテムに追加耐性/能力の略称を刻む", "Describe obj's extra resistances by abbreviation") }, + { &abbrev_extra, false, 2, 10, "abbrev_extra", + _("アイテムに追加耐性/能力の略称を刻む", "Describe obj's extra resistances by abbreviation"), GameOptionPage::TEXT }, - { &abbrev_all, true, OPT_PAGE_TEXT, 2, 11, "abbrev_all", _("アイテムに全ての耐性/能力の略称を刻む", "Describe obj's all resistances by abbreviation") }, + { &abbrev_all, true, 2, 11, "abbrev_all", _("アイテムに全ての耐性/能力の略称を刻む", "Describe obj's all resistances by abbreviation"), GameOptionPage::TEXT }, - { &exp_need, false, OPT_PAGE_TEXT, 2, 12, "exp_need", _("次のレベルに必要な経験値を表示する", "Show the experience needed for next level") }, + { &exp_need, false, 2, 12, "exp_need", _("次のレベルに必要な経験値を表示する", "Show the experience needed for next level"), GameOptionPage::TEXT }, - { &ignore_unview, false, OPT_PAGE_TEXT, 2, 13, "ignore_unview", _("視界外のモンスターの行動を表示しない", "Ignore out-of-sight monster behavior") }, + { &ignore_unview, false, 2, 13, "ignore_unview", _("視界外のモンスターの行動を表示しない", "Ignore out-of-sight monster behavior"), GameOptionPage::TEXT }, - { &show_ammo_detail, true, OPT_PAGE_TEXT, 2, 14, "show_ammo_detail", _("矢弾のダメージの説明を表示する", "Show description of ammo damage") }, + { &show_ammo_detail, true, 2, 14, "show_ammo_detail", _("矢弾のダメージの説明を表示する", "Show description of ammo damage"), GameOptionPage::TEXT }, - { &show_ammo_no_crit, false, OPT_PAGE_TEXT, 2, 15, "show_ammo_no_crit", - _("会心を考慮しない場合の矢弾のダメージを表示する", "Show ammo damage with no critical") }, + { &show_ammo_no_crit, false, 2, 15, "show_ammo_no_crit", + _("会心を考慮しない場合の矢弾のダメージを表示する", "Show ammo damage with no critical"), GameOptionPage::TEXT }, - { &show_ammo_crit_ratio, false, OPT_PAGE_TEXT, 2, 16, "show_ammo_crit_ratio", _("矢弾の会心発生率を表示する", "Show critical ratio of ammo") }, + { &show_ammo_crit_ratio, false, 2, 16, "show_ammo_crit_ratio", _("矢弾の会心発生率を表示する", "Show critical ratio of ammo"), GameOptionPage::TEXT }, - { &show_actual_value, true, OPT_PAGE_TEXT, 2, 17, "show_actual_value", _("技能値等に実値を並記する", "Show actual values of skills or etc.") }, + { &show_actual_value, true, 2, 17, "show_actual_value", _("技能値等に実値を並記する", "Show actual values of skills or etc."), GameOptionPage::TEXT }, /*** Game-Play ***/ - { &stack_force_notes, true, OPT_PAGE_GAMEPLAY, 0, 8, "stack_force_notes", _("異なる銘のアイテムをまとめる", "Merge inscriptions when stacking") }, + { &stack_force_notes, true, 0, 8, "stack_force_notes", _("異なる銘のアイテムをまとめる", "Merge inscriptions when stacking"), GameOptionPage::GAMEPLAY }, - { &stack_force_costs, false, OPT_PAGE_GAMEPLAY, 0, 9, "stack_force_costs", _("異なる割引表示のアイテムをまとめる", "Merge discounts when stacking") }, + { &stack_force_costs, false, 0, 9, "stack_force_costs", _("異なる割引表示のアイテムをまとめる", "Merge discounts when stacking"), GameOptionPage::GAMEPLAY }, - { &expand_list, true, OPT_PAGE_GAMEPLAY, 1, 5, "expand_list", _("「一覧」コマンドを拡張する", "Expand the power of the list commands") }, + { &expand_list, true, 1, 5, "expand_list", _("「一覧」コマンドを拡張する", "Expand the power of the list commands"), GameOptionPage::GAMEPLAY }, - { &small_levels, true, OPT_PAGE_GAMEPLAY, 0, 30, "small_levels", _("非常に小さいフロアの生成を可能にする", "Allow unusually small dungeon levels") }, + { &small_levels, true, 0, 30, "small_levels", _("非常に小さいフロアの生成を可能にする", "Allow unusually small dungeon levels"), GameOptionPage::GAMEPLAY }, - { &always_small_levels, false, OPT_PAGE_GAMEPLAY, 2, 3, "always_small_levels", - _("常に非常に小さいフロアを生成する", "Always create unusually small dungeon levels") }, + { &always_small_levels, false, 2, 3, "always_small_levels", + _("常に非常に小さいフロアを生成する", "Always create unusually small dungeon levels"), GameOptionPage::GAMEPLAY }, - { &empty_levels, true, OPT_PAGE_GAMEPLAY, 0, 31, "empty_levels", _("空っぽの「アリーナ」レベルの生成を可能にする", "Allow empty 'arena' levels") }, + { &empty_levels, true, 0, 31, "empty_levels", _("空っぽの「アリーナ」レベルの生成を可能にする", "Allow empty 'arena' levels"), GameOptionPage::GAMEPLAY }, - { &bound_walls_perm, true, OPT_PAGE_GAMEPLAY, 2, 1, "bound_walls_perm", _("ダンジョンの外壁を永久岩にする", "Boundary walls become 'permanent wall'") }, + { &bound_walls_perm, true, 2, 1, "bound_walls_perm", _("ダンジョンの外壁を永久岩にする", "Boundary walls become 'permanent wall'"), GameOptionPage::GAMEPLAY }, - { &last_words, true, OPT_PAGE_GAMEPLAY, 0, 28, "last_words", _("キャラクターが死んだ時遺言をのこす", "Leave last words when your character dies") }, + { &last_words, true, 0, 28, "last_words", _("キャラクターが死んだ時遺言をのこす", "Leave last words when your character dies"), GameOptionPage::GAMEPLAY }, - { &auto_dump, false, OPT_PAGE_GAMEPLAY, 4, 5, "auto_dump", _("自動的にキャラクターの記録をファイルに書き出す", "Dump a character record automatically") }, + { &auto_dump, false, 4, 5, "auto_dump", _("自動的にキャラクターの記録をファイルに書き出す", "Dump a character record automatically"), GameOptionPage::GAMEPLAY }, #ifdef WORLD_SCORE - { &send_score, true, OPT_PAGE_GAMEPLAY, 4, 6, "send_score", _("スコアサーバにスコアを送る", "Send score dump to the world score server") }, + { &send_score, true, 4, 6, "send_score", _("スコアサーバにスコアを送る", "Send score dump to the world score server"), GameOptionPage::GAMEPLAY }, #else - { &send_score, false, OPT_PAGE_HIDE, 4, 6, "send_score", _("スコアサーバにスコアを送る", "Send score dump to the world score server") }, + { &send_score, false, 4, 6, "send_score", _("スコアサーバにスコアを送る", "Send score dump to the world score server"), GameOptionPage::HIDE }, #endif - { &allow_debug_opts, false, OPT_PAGE_GAMEPLAY, 6, 11, "allow_debug_opts", _("デバッグ/詐欺オプションを許可する", "Allow use of debug/cheat options") }, + { &allow_debug_opts, false, 6, 11, "allow_debug_opts", _("デバッグ/詐欺オプションを許可する", "Allow use of debug/cheat options"), GameOptionPage::GAMEPLAY }, /*** Disturbance ***/ - { &find_ignore_stairs, false, OPT_PAGE_DISTURBANCE, 0, 16, "find_ignore_stairs", _("階段は通過する", "Run past stairs") }, + { &find_ignore_stairs, false, 0, 16, "find_ignore_stairs", _("階段は通過する", "Run past stairs"), GameOptionPage::DISTURBANCE }, - { &find_ignore_doors, true, OPT_PAGE_DISTURBANCE, 0, 17, "find_ignore_doors", _("ドアは通過する", "Run through open doors") }, + { &find_ignore_doors, true, 0, 17, "find_ignore_doors", _("ドアは通過する", "Run through open doors"), GameOptionPage::DISTURBANCE }, - { &find_cut, false, OPT_PAGE_DISTURBANCE, 0, 18, "find_cut", _("曲り角を斜めに最短距離で通過する", "Run past known corners") }, + { &find_cut, false, 0, 18, "find_cut", _("曲り角を斜めに最短距離で通過する", "Run past known corners"), GameOptionPage::DISTURBANCE }, - { &check_abort, true, OPT_PAGE_DISTURBANCE, 1, 18, "check_abort", _("連続コマンドはキー入力で中断する", "Check for user abort while in repeated command") }, + { &check_abort, true, 1, 18, "check_abort", _("連続コマンドはキー入力で中断する", "Check for user abort while in repeated command"), GameOptionPage::DISTURBANCE }, - { &flush_failure, true, OPT_PAGE_DISTURBANCE, 1, 20, "flush_failure", _("様々なミス発生時に入力をクリアする", "Flush input on various failures") }, + { &flush_failure, true, 1, 20, "flush_failure", _("様々なミス発生時に入力をクリアする", "Flush input on various failures"), GameOptionPage::DISTURBANCE }, - { &flush_disturb, false, OPT_PAGE_DISTURBANCE, 1, 21, "flush_disturb", _("障害発生時に入力をクリアする", "Flush input whenever disturbed") }, + { &flush_disturb, false, 1, 21, "flush_disturb", _("障害発生時に入力をクリアする", "Flush input whenever disturbed"), GameOptionPage::DISTURBANCE }, - { &disturb_move, false, OPT_PAGE_DISTURBANCE, 0, 20, "disturb_move", _("どこのモンスターが動いても行動を中止する", "Disturb whenever any monster moves") }, + { &disturb_move, false, 0, 20, "disturb_move", _("どこのモンスターが動いても行動を中止する", "Disturb whenever any monster moves"), GameOptionPage::DISTURBANCE }, - { &disturb_high, true, OPT_PAGE_DISTURBANCE, 1, 3, "disturb_high", - _("レベルの高いモンスターが動いたら行動を中止する", "Disturb whenever high-level monster moves") }, + { &disturb_high, true, 1, 3, "disturb_high", + _("レベルの高いモンスターが動いたら行動を中止する", "Disturb whenever high-level monster moves"), GameOptionPage::DISTURBANCE }, - { &disturb_unknown, true, OPT_PAGE_DISTURBANCE, 0, 26, "disturb_unknown", - _("レベル不明のモンスターが動いたら行動を中止する", "Disturb whenever unknown-level monster moves") }, + { &disturb_unknown, true, 0, 26, "disturb_unknown", + _("レベル不明のモンスターが動いたら行動を中止する", "Disturb whenever unknown-level monster moves"), GameOptionPage::DISTURBANCE }, - { &disturb_near, true, OPT_PAGE_DISTURBANCE, 0, 21, "disturb_near", - _("視界内のモンスターが動いたら行動を中止する", "Disturb whenever viewable monster moves") }, + { &disturb_near, true, 0, 21, "disturb_near", + _("視界内のモンスターが動いたら行動を中止する", "Disturb whenever viewable monster moves"), GameOptionPage::DISTURBANCE }, - { &disturb_pets, false, OPT_PAGE_DISTURBANCE, 5, 6, "disturb_pets", _("視界内のペットが動いたら行動を中止する", "Disturb when visible pets move") }, + { &disturb_pets, false, 5, 6, "disturb_pets", _("視界内のペットが動いたら行動を中止する", "Disturb when visible pets move"), GameOptionPage::DISTURBANCE }, - { &disturb_panel, true, OPT_PAGE_DISTURBANCE, 0, 22, "disturb_panel", _("画面スクロール時に行動を中止する", "Disturb whenever map panel changes") }, + { &disturb_panel, true, 0, 22, "disturb_panel", _("画面スクロール時に行動を中止する", "Disturb whenever map panel changes"), GameOptionPage::DISTURBANCE }, - { &disturb_state, true, OPT_PAGE_DISTURBANCE, 0, 23, "disturb_state", - _("自分のステータス変化時に行動を中止する", "Disturb whenever player state changes") }, + { &disturb_state, true, 0, 23, "disturb_state", + _("自分のステータス変化時に行動を中止する", "Disturb whenever player state changes"), GameOptionPage::DISTURBANCE }, - { &disturb_minor, true, OPT_PAGE_DISTURBANCE, 0, 24, "disturb_minor", _("些細なことが起きても行動を中止する", "Disturb whenever boring things happen") }, + { &disturb_minor, true, 0, 24, "disturb_minor", _("些細なことが起きても行動を中止する", "Disturb whenever boring things happen"), GameOptionPage::DISTURBANCE }, - { &ring_bell, false, OPT_PAGE_DISTURBANCE, 0, 14, "ring_bell", _("エラー時にビープ音を鳴らす", "Audible bell (on errors, etc)") }, + { &ring_bell, false, 0, 14, "ring_bell", _("エラー時にビープ音を鳴らす", "Audible bell (on errors, etc)"), GameOptionPage::DISTURBANCE }, - { &disturb_trap_detect, true, OPT_PAGE_DISTURBANCE, 0, 27, "disturb_trap_detect", - _("トラップ感知範囲外に出る直前に行動を中止する", "Disturb when leaving trap detected area") }, + { &disturb_trap_detect, true, 0, 27, "disturb_trap_detect", + _("トラップ感知範囲外に出る直前に行動を中止する", "Disturb when leaving trap detected area"), GameOptionPage::DISTURBANCE }, - { &alert_trap_detect, true, OPT_PAGE_DISTURBANCE, 0, 25, "alert_trap_detect", - _("トラップ感知範囲外に出る直前に警告する", "Alert when leaving trap detected area") }, + { &alert_trap_detect, true, 0, 25, "alert_trap_detect", + _("トラップ感知範囲外に出る直前に警告する", "Alert when leaving trap detected area"), GameOptionPage::DISTURBANCE }, /*** Birth Options ***/ - { &smart_learn, true, OPT_PAGE_BIRTH, 1, 14, "smart_learn", _("モンスターは失敗を学習する(*)", "Monsters learn from their mistakes (*)") }, + { &smart_learn, true, 1, 14, "smart_learn", _("モンスターは失敗を学習する(*)", "Monsters learn from their mistakes (*)"), GameOptionPage::BIRTH }, - { &smart_cheat, false, OPT_PAGE_BIRTH, 1, 15, "smart_cheat", _("モンスターはプレイヤーの弱みを突く(*)", "Monsters exploit players weaknesses (*)") }, + { &smart_cheat, false, 1, 15, "smart_cheat", _("モンスターはプレイヤーの弱みを突く(*)", "Monsters exploit players weaknesses (*)"), GameOptionPage::BIRTH }, - { &vanilla_town, false, OPT_PAGE_BIRTH, 6, 0, "vanilla_town", _("元祖の街/クエストと荒野なし", "Use 'vanilla' town without quests and wilderness") }, + { &vanilla_town, false, 6, 0, "vanilla_town", _("元祖の街/クエストと荒野なし", "Use 'vanilla' town without quests and wilderness"), GameOptionPage::BIRTH }, - { &lite_town, false, OPT_PAGE_BIRTH, 6, 1, "lite_town", _("小規模な街/荒野なし", "Use 'lite' town without a wilderness") }, + { &lite_town, false, 6, 1, "lite_town", _("小規模な街/荒野なし", "Use 'lite' town without a wilderness"), GameOptionPage::BIRTH }, - { &ironman_shops, false, OPT_PAGE_BIRTH, 6, 2, "ironman_shops", _("(鉄人用)店を使用しない(*)", "Stores are permanently closed (*)") }, + { &ironman_shops, false, 6, 2, "ironman_shops", _("(鉄人用)店を使用しない(*)", "Stores are permanently closed (*)"), GameOptionPage::BIRTH }, - { &ironman_small_levels, false, OPT_PAGE_BIRTH, 6, 3, "ironman_small_levels", - _("(鉄人用)常に非常に小さいフロアを生成(*)", "Always create unusually small dungeon levels (*)") }, + { &ironman_small_levels, false, 6, 3, "ironman_small_levels", + _("(鉄人用)常に非常に小さいフロアを生成(*)", "Always create unusually small dungeon levels (*)"), GameOptionPage::BIRTH }, - { &ironman_downward, false, OPT_PAGE_BIRTH, 6, 4, "ironman_downward", _("(鉄人用)帰還と上り階段なし(*)", "Disable recall and use of up stairs (*)") }, + { &ironman_downward, false, 6, 4, "ironman_downward", _("(鉄人用)帰還と上り階段なし(*)", "Disable recall and use of up stairs (*)"), GameOptionPage::BIRTH }, - { &ironman_empty_levels, false, OPT_PAGE_BIRTH, 6, 8, "ironman_empty_levels", - _("(鉄人用)常に空っぽのアリーナレベルを生成(*)", "Always create empty 'arena' levels (*)") }, + { &ironman_empty_levels, false, 6, 8, "ironman_empty_levels", + _("(鉄人用)常に空っぽのアリーナレベルを生成(*)", "Always create empty 'arena' levels (*)"), GameOptionPage::BIRTH }, - { &ironman_rooms, false, OPT_PAGE_BIRTH, 6, 12, "ironman_rooms", _("(鉄人用)常に普通でない部屋を生成する(*)", "Always generate very unusual rooms (*)") }, + { &ironman_rooms, false, 6, 12, "ironman_rooms", _("(鉄人用)常に普通でない部屋を生成する(*)", "Always generate very unusual rooms (*)"), GameOptionPage::BIRTH }, - { &ironman_nightmare, false, OPT_PAGE_BIRTH, 6, 18, "ironman_nightmare", - _("(鉄人用)悪夢モード(これは全く不条理です!)(*)", "Nightmare mode(it isn't even remotely fair!)(*)") }, + { &ironman_nightmare, false, 6, 18, "ironman_nightmare", + _("(鉄人用)悪夢モード(これは全く不条理です!)(*)", "Nightmare mode(it isn't even remotely fair!)(*)"), GameOptionPage::BIRTH }, - { &left_hander, false, OPT_PAGE_BIRTH, 6, 13, "left_hander", _("左利きである", "Left-Hander") }, + { &left_hander, false, 6, 13, "left_hander", _("左利きである", "Left-Hander"), GameOptionPage::BIRTH }, - { &preserve_mode, true, OPT_PAGE_BIRTH, 6, 14, "preserve_mode", _("伝説のアイテムを取り逃しても再生成される(*)", "Preserve artifacts (*)") }, + { &preserve_mode, true, 6, 14, "preserve_mode", _("伝説のアイテムを取り逃しても再生成される(*)", "Preserve artifacts (*)"), GameOptionPage::BIRTH }, - { &autoroller, true, OPT_PAGE_BIRTH, 6, 15, "autoroller", _("能力値にオートローラー使用(*)", "Allow use of autoroller for stats (*)") }, + { &autoroller, true, 6, 15, "autoroller", _("能力値にオートローラー使用(*)", "Allow use of autoroller for stats (*)"), GameOptionPage::BIRTH }, - { &autochara, false, OPT_PAGE_BIRTH, 6, 16, "autochara", _("体格/地位にオートローラー使用", "Autoroll for weight, height and social status") }, + { &autochara, false, 6, 16, "autochara", _("体格/地位にオートローラー使用", "Autoroll for weight, height and social status"), GameOptionPage::BIRTH }, - { &powerup_home, true, OPT_PAGE_BIRTH, 4, 3, "powerup_home", _("我が家を拡張する(*)", "Increase capacity of your home (*)") }, + { &powerup_home, true, 4, 3, "powerup_home", _("我が家を拡張する(*)", "Increase capacity of your home (*)"), GameOptionPage::BIRTH }, - { &keep_savefile, true, OPT_PAGE_BIRTH, 4, 4, "keep_savefile", _("同一のセーブファイルでゲームを開始する", "Start game with same savefile thet is loaded") }, + { &keep_savefile, true, 4, 4, "keep_savefile", _("同一のセーブファイルでゲームを開始する", "Start game with same savefile thet is loaded"), GameOptionPage::BIRTH }, /*** Easy Object Auto-Destroyer ***/ - { &destroy_items, false, OPT_PAGE_AUTODESTROY, 7, 0, "destroy_items", _("アイテムの簡易自動破壊を使用する", "Use easy auto-destroyer") }, + { &destroy_items, false, 7, 0, "destroy_items", _("アイテムの簡易自動破壊を使用する", "Use easy auto-destroyer"), GameOptionPage::AUTODESTROY }, - { &destroy_feeling, false, OPT_PAGE_AUTODESTROY, 7, 8, "destroy_feeling", _("簡易鑑定したとき自動破壊を適用する", "Apply auto-destroy as sense feeling") }, + { &destroy_feeling, false, 7, 8, "destroy_feeling", _("簡易鑑定したとき自動破壊を適用する", "Apply auto-destroy as sense feeling"), GameOptionPage::AUTODESTROY }, - { &destroy_identify, false, OPT_PAGE_AUTODESTROY, 7, 9, "destroy_identify", _("鑑定したとき自動破壊を適用する", "Apply auto-destroy as identify an item") }, + { &destroy_identify, false, 7, 9, "destroy_identify", _("鑑定したとき自動破壊を適用する", "Apply auto-destroy as identify an item"), GameOptionPage::AUTODESTROY }, - { &leave_worth, true, OPT_PAGE_AUTODESTROY, 7, 2, "leave_worth", _("価値があるアイテムは壊さない", "Auto-destroyer leaves known worthy items") }, + { &leave_worth, true, 7, 2, "leave_worth", _("価値があるアイテムは壊さない", "Auto-destroyer leaves known worthy items"), GameOptionPage::AUTODESTROY }, - { &leave_equip, false, OPT_PAGE_AUTODESTROY, 7, 3, "leave_equip", _("武器/防具は壊さない", "Auto-destroyer leaves weapons and armour") }, + { &leave_equip, false, 7, 3, "leave_equip", _("武器/防具は壊さない", "Auto-destroyer leaves weapons and armour"), GameOptionPage::AUTODESTROY }, - { &leave_chest, true, OPT_PAGE_AUTODESTROY, 7, 7, "leave_chest", _("開封されていない箱は壊さない", "Auto-destroyer leaves closed chests") }, + { &leave_chest, true, 7, 7, "leave_chest", _("開封されていない箱は壊さない", "Auto-destroyer leaves closed chests"), GameOptionPage::AUTODESTROY }, - { &leave_wanted, true, OPT_PAGE_AUTODESTROY, 7, 4, "leave_wanted", _("賞金首の死体/骨は壊さない", "Auto-destroyer leaves wanted corpses") }, + { &leave_wanted, true, 7, 4, "leave_wanted", _("賞金首の死体/骨は壊さない", "Auto-destroyer leaves wanted corpses"), GameOptionPage::AUTODESTROY }, - { &leave_corpse, false, OPT_PAGE_AUTODESTROY, 7, 5, "leave_corpse", _("死体/骨は壊さない", "Auto-destroyer leaves corpses and skeletons") }, + { &leave_corpse, false, 7, 5, "leave_corpse", _("死体/骨は壊さない", "Auto-destroyer leaves corpses and skeletons"), GameOptionPage::AUTODESTROY }, - { &leave_junk, false, OPT_PAGE_AUTODESTROY, 7, 6, "leave_junk", _("がらくたは壊さない", "Auto-destroyer leaves junk") }, + { &leave_junk, false, 7, 6, "leave_junk", _("がらくたは壊さない", "Auto-destroyer leaves junk"), GameOptionPage::AUTODESTROY }, - { &leave_special, true, OPT_PAGE_AUTODESTROY, 7, 1, "leave_special", - _("種族/職業で特別に必要なアイテムは壊さない", "Auto-destroyer leaves items your race/class needs") }, + { &leave_special, true, 7, 1, "leave_special", + _("種族/職業で特別に必要なアイテムは壊さない", "Auto-destroyer leaves items your race/class needs"), GameOptionPage::AUTODESTROY }, /*** Play-record Options ***/ - { &record_fix_art, true, OPT_PAGE_PLAYRECORD, 4, 11, "record_fix_art", _("固定アーティファクトの入手を記録する", "Record fixed artifacts") }, + { &record_fix_art, true, 4, 11, "record_fix_art", _("固定アーティファクトの入手を記録する", "Record fixed artifacts"), GameOptionPage::PLAYRECORD }, - { &record_rand_art, true, OPT_PAGE_PLAYRECORD, 4, 12, "record_rand_art", _("ランダムアーティファクトの入手を記録する", "Record random artifacts") }, + { &record_rand_art, true, 4, 12, "record_rand_art", _("ランダムアーティファクトの入手を記録する", "Record random artifacts"), GameOptionPage::PLAYRECORD }, - { &record_destroy_uniq, true, OPT_PAGE_PLAYRECORD, 4, 13, "record_destroy_uniq", - _("ユニークモンスターを倒したときを記録する", "Record when destroy unique monster") }, + { &record_destroy_uniq, true, 4, 13, "record_destroy_uniq", + _("ユニークモンスターを倒したときを記録する", "Record when destroy unique monster"), GameOptionPage::PLAYRECORD }, - { &record_fix_quest, true, OPT_PAGE_PLAYRECORD, 4, 14, "record_fix_quest", _("固定クエストの達成を記録する", "Record fixed quests") }, + { &record_fix_quest, true, 4, 14, "record_fix_quest", _("固定クエストの達成を記録する", "Record fixed quests"), GameOptionPage::PLAYRECORD }, - { &record_rand_quest, true, OPT_PAGE_PLAYRECORD, 4, 15, "record_rand_quest", _("ランダムクエストの達成を記録する", "Record random quests") }, + { &record_rand_quest, true, 4, 15, "record_rand_quest", _("ランダムクエストの達成を記録する", "Record random quests"), GameOptionPage::PLAYRECORD }, - { &record_maxdepth, true, OPT_PAGE_PLAYRECORD, 4, 16, "record_maxdepth", _("最深階を更新したときに記録する", "Record movements to deepest level") }, + { &record_maxdepth, true, 4, 16, "record_maxdepth", _("最深階を更新したときに記録する", "Record movements to deepest level"), GameOptionPage::PLAYRECORD }, - { &record_stair, true, OPT_PAGE_PLAYRECORD, 4, 17, "record_stair", _("階の移動を記録する", "Record recall and stair movements") }, + { &record_stair, true, 4, 17, "record_stair", _("階の移動を記録する", "Record recall and stair movements"), GameOptionPage::PLAYRECORD }, - { &record_buy, true, OPT_PAGE_PLAYRECORD, 4, 18, "record_buy", _("アイテムの購入を記録する", "Record purchased items") }, + { &record_buy, true, 4, 18, "record_buy", _("アイテムの購入を記録する", "Record purchased items"), GameOptionPage::PLAYRECORD }, - { &record_sell, false, OPT_PAGE_PLAYRECORD, 4, 19, "record_sell", _("アイテムの売却を記録する", "Record sold items") }, + { &record_sell, false, 4, 19, "record_sell", _("アイテムの売却を記録する", "Record sold items"), GameOptionPage::PLAYRECORD }, - { &record_danger, true, OPT_PAGE_PLAYRECORD, 4, 20, "record_danger", _("ピンチになったときを記録する", "Record hitpoint warning") }, + { &record_danger, true, 4, 20, "record_danger", _("ピンチになったときを記録する", "Record hitpoint warning"), GameOptionPage::PLAYRECORD }, - { &record_arena, true, OPT_PAGE_PLAYRECORD, 4, 21, "record_arena", _("アリーナでの勝利を記録する", "Record arena victories") }, + { &record_arena, true, 4, 21, "record_arena", _("アリーナでの勝利を記録する", "Record arena victories"), GameOptionPage::PLAYRECORD }, - { &record_ident, true, OPT_PAGE_PLAYRECORD, 4, 22, "record_ident", _("未判明のアイテムの識別を記録する", "Record first identified items") }, + { &record_ident, true, 4, 22, "record_ident", _("未判明のアイテムの識別を記録する", "Record first identified items"), GameOptionPage::PLAYRECORD }, - { &record_named_pet, false, OPT_PAGE_PLAYRECORD, 4, 23, "record_named_pet", _("名前つきペットの情報を記録する", "Record information about named pets") }, - - /*** End of Table ***/ - { nullptr, 0, 0, 0, 0, nullptr, nullptr } + { &record_named_pet, false, 4, 23, "record_named_pet", _("名前つきペットの情報を記録する", "Record information about named pets"), GameOptionPage::PLAYRECORD }, }; /*! * チートオプションの定義テーブル / Cheating options */ -const std::vector cheat_info = { - { &cheat_peek, false, 255, 0x01, 0x00, "cheat_peek", _("アイテムの生成をのぞき見る", "Peek into object creation") }, +const std::vector cheat_info = { + { &cheat_peek, false, 0x01, 0x00, "cheat_peek", _("アイテムの生成をのぞき見る", "Peek into object creation") }, - { &cheat_hear, false, 255, 0x02, 0x00, "cheat_hear", _("モンスターの生成をのぞき見る", "Peek into monster creation") }, + { &cheat_hear, false, 0x02, 0x00, "cheat_hear", _("モンスターの生成をのぞき見る", "Peek into monster creation") }, - { &cheat_room, false, 255, 0x04, 0x00, "cheat_room", _("ダンジョンの生成をのぞき見る", "Peek into dungeon creation") }, + { &cheat_room, false, 0x04, 0x00, "cheat_room", _("ダンジョンの生成をのぞき見る", "Peek into dungeon creation") }, - { &cheat_xtra, false, 255, 0x08, 0x00, "cheat_xtra", _("その他の事をのぞき見る", "Peek into something else") }, + { &cheat_xtra, false, 0x08, 0x00, "cheat_xtra", _("その他の事をのぞき見る", "Peek into something else") }, - { &cheat_know, false, 255, 0x10, 0x00, "cheat_know", _("完全なモンスターの思い出を知る", "Know complete monster info") }, + { &cheat_know, false, 0x10, 0x00, "cheat_know", _("完全なモンスターの思い出を知る", "Know complete monster info") }, - { &cheat_live, false, 255, 0x20, 0x00, "cheat_live", _("死を回避することを可能にする", "Allow player to avoid death") }, + { &cheat_live, false, 0x20, 0x00, "cheat_live", _("死を回避することを可能にする", "Allow player to avoid death") }, - { &cheat_save, false, 255, 0x40, 0x00, "cheat_save", _("死んだ時セーブするか確認する", "Ask for saving death") }, + { &cheat_save, false, 0x40, 0x00, "cheat_save", _("死んだ時セーブするか確認する", "Ask for saving death") }, - { &cheat_diary_output, false, 255, 0x80, 0x00, "cheat_diary_output", _("ウィザードログを日記に出力する", "Output wizard log to diary.") }, + { &cheat_diary_output, false, 0x80, 0x00, "cheat_diary_output", _("ウィザードログを日記に出力する", "Output wizard log to diary.") }, - { &cheat_turn, false, 255, 0x81, 0x00, "cheat_turn", _("ゲームメッセージにターン表示を行う", "Put turn in game messages.") }, + { &cheat_turn, false, 0x81, 0x00, "cheat_turn", _("ゲームメッセージにターン表示を行う", "Put turn in game messages.") }, - { &cheat_sight, false, 255, 0x82, 0x00, "cheat_sight", _("「見る」コマンドを拡張する。", "Expand \"L\"ook command.") }, + { &cheat_sight, false, 0x82, 0x00, "cheat_sight", _("「見る」コマンドを拡張する。", "Expand \"L\"ook command.") }, - { &cheat_immortal, false, 255, 0x83, 0x00, "cheat_immortal", _("完全な不滅状態になる。", "Completely immortal.") } + { &cheat_immortal, false, 0x83, 0x00, "cheat_immortal", _("完全な不滅状態になる。", "Completely immortal.") } }; /*! * 自動セーブオプションテーブル */ -const std::vector autosave_info = { - { &autosave_l, false, 255, 0x01, 0x00, "autosave_l", _("新しい階に入る度に自動セーブする", "Autosave when entering new levels") }, +const std::vector autosave_info = { + { &autosave_l, false, 0x01, 0x00, "autosave_l", _("新しい階に入る度に自動セーブする", "Autosave when entering new levels") }, - { &autosave_t, false, 255, 0x02, 0x00, "autosave_t", _("一定ターン毎に自動セーブする", "Timed autosave") }, + { &autosave_t, false, 0x02, 0x00, "autosave_t", _("一定ターン毎に自動セーブする", "Timed autosave") }, }; diff --git a/src/game-option/option-types-table.h b/src/game-option/option-types-table.h index 8bffe1732c..670e53f61d 100644 --- a/src/game-option/option-types-table.h +++ b/src/game-option/option-types-table.h @@ -1,28 +1,23 @@ #pragma once -#include "system/angband.h" +#include +#include +#include #include -/* - * Available "options" - * - Address of actual option variable (or nullptr) - * - Normal Value (TRUE or FALSE) - * - Option Page Number (or zero) - * - Savefile Set (or zero) - * - Savefile Bit in that set - * - Textual name (or nullptr) - * - Textual description - */ -struct option_type { - bool *o_var{}; - byte o_norm{}; - byte o_page{}; - byte o_set{}; - byte o_bit{}; - concptr o_text{}; - concptr o_desc{}; +enum class GameOptionPage : int; +class GameOption { +public: + GameOption(bool *value, bool norm, uint8_t set, uint8_t bits, std::string &&text, std::string &&description, const std::optional &page = std::nullopt); + bool *value; + bool default_value; + uint8_t flag_position; + uint8_t offset; + std::string text; + std::string description; + std::optional page; }; -extern const std::vector option_info; -extern const std::vector cheat_info; -extern const std::vector autosave_info; +extern const std::vector option_info; +extern const std::vector cheat_info; +extern const std::vector autosave_info; diff --git a/src/grid/grid.cpp b/src/grid/grid.cpp index f5a86e3fcb..9c55a4bb8d 100644 --- a/src/grid/grid.cpp +++ b/src/grid/grid.cpp @@ -43,6 +43,7 @@ #include "player/player-status.h" #include "room/rooms-builder.h" #include "system/dungeon-info.h" +#include "system/enums/grid-flow.h" #include "system/floor-type-definition.h" #include "system/grid-type-definition.h" #include "system/item-entity.h" @@ -667,7 +668,7 @@ void update_flow(PlayerType *player_ptr) flow_y = player_ptr->y; flow_x = player_ptr->x; - for (auto i = 0; i < FLOW_MAX; i++) { + for (const auto gf : GRID_FLOW_RANGE) { // 幅優先探索用のキュー。 std::queue que; que.emplace(player_ptr->y, player_ptr->x); @@ -680,8 +681,8 @@ void update_flow(PlayerType *player_ptr) /* Add the "children" */ for (auto d = 0; d < 8; d++) { - byte m = grid.costs[i] + 1; - byte n = grid.dists[i] + 1; + uint8_t m = grid.costs.at(gf) + 1; + const uint8_t n = grid.dists.at(gf) + 1; const Pos2D pos_neighbor(pos.y + ddy_ddd[d], pos.x + ddx_ddd[d]); /* Ignore player's grid */ @@ -695,14 +696,16 @@ void update_flow(PlayerType *player_ptr) } /* Ignore "pre-stamped" entries */ - if ((grid_neighbor.dists[i] != 0) && (grid_neighbor.dists[i] <= n) && (grid_neighbor.costs[i] <= m)) { + auto &cost_neighbor = grid_neighbor.costs.at(gf); + auto &dist_neighbor = grid_neighbor.dists.at(gf); + if ((dist_neighbor != 0) && (dist_neighbor <= n) && (cost_neighbor <= m)) { continue; } /* Ignore "walls", "holes" and "rubble" */ auto can_move = false; - switch (i) { - case FLOW_CAN_FLY: + switch (gf) { + case GridFlow::CAN_FLY: can_move = grid_neighbor.cave_has_flag(TerrainCharacteristics::MOVE) || grid_neighbor.cave_has_flag(TerrainCharacteristics::CAN_FLY); break; default: @@ -715,11 +718,11 @@ void update_flow(PlayerType *player_ptr) } /* Save the flow cost */ - if (grid_neighbor.costs[i] == 0 || (grid_neighbor.costs[i] > m)) { - grid_neighbor.costs[i] = m; + if (cost_neighbor == 0 || (cost_neighbor > m)) { + cost_neighbor = m; } - if (grid_neighbor.dists[i] == 0 || (grid_neighbor.dists[i] > n)) { - grid_neighbor.dists[i] = n; + if (dist_neighbor == 0 || (dist_neighbor > n)) { + dist_neighbor = n; } // 敵のプレイヤーに対する移動道のりの最大値(この値以上は処理を打ち切る). diff --git a/src/io/interpret-pref-file.cpp b/src/io/interpret-pref-file.cpp index 7fd5e683c0..71af696bf8 100644 --- a/src/io/interpret-pref-file.cpp +++ b/src/io/interpret-pref-file.cpp @@ -14,7 +14,7 @@ #include "io/input-key-requester.h" #include "io/tokenizer.h" #include "system/baseitem-info.h" -#include "system/game-option-types.h" +#include "system/enums/game-option-page.h" #include "system/monster-race-info.h" #include "system/player-type-definition.h" #include "system/terrain-type-definition.h" @@ -23,8 +23,6 @@ #include "view/display-messages.h" #include "world/world.h" -#define MAX_MACRO_CHARS 16128 // 1つのマクロキー押下で実行可能なコマンド最大数 (エスケープシーケンス含む). - std::optional histpref_buf; /*! @@ -338,18 +336,14 @@ static bool interpret_v_token(char *buf) static void interpret_xy_token(PlayerType *player_ptr, char *buf) { const auto &world = AngbandWorld::get_instance(); - for (int i = 0; option_info[i].o_desc; i++) { - bool is_option = option_info[i].o_var != nullptr; - is_option &= option_info[i].o_text != nullptr; - is_option &= streq(option_info[i].o_text, buf + 2); - if (!is_option) { + for (auto &option : option_info) { + if (option.text != buf + 2) { continue; } - int os = option_info[i].o_set; - int ob = option_info[i].o_bit; - - if ((player_ptr->playing || world.character_xtra) && (OPT_PAGE_BIRTH == option_info[i].o_page) && !world.wizard) { + int os = option.flag_position; + int ob = option.offset; + if ((player_ptr->playing || world.character_xtra) && (GameOptionPage::BIRTH == option.page) && !world.wizard) { msg_format(_("初期オプションは変更できません! '%s'", "Birth options can not be changed! '%s'"), buf); msg_print(nullptr); return; @@ -357,12 +351,12 @@ static void interpret_xy_token(PlayerType *player_ptr, char *buf) if (buf[0] == 'X') { g_option_flags[os] &= ~(1UL << ob); - (*option_info[i].o_var) = false; + *option.value = false; return; } g_option_flags[os] |= (1UL << ob); - (*option_info[i].o_var) = true; + *option.value = true; return; } @@ -449,7 +443,9 @@ static bool decide_template_modifier(int tok, char **zz) */ static bool interpret_macro_keycodes(int tok, char **zz) { - char buf_aux[MAX_MACRO_CHARS]{}; + //!< @details 1つのマクロキー押下で実行可能なコマンド最大数 (エスケープシーケンス含む). + constexpr auto max_macro_chars = 16128; + char buf_aux[max_macro_chars]{}; if (max_macrotrigger >= MAX_MACRO_TRIG) { msg_print(_("マクロトリガーの設定が多すぎます!", "Too many macro triggers!")); return false; diff --git a/src/io/report.cpp b/src/io/report.cpp index bf90663d23..17a67ccc13 100644 --- a/src/io/report.cpp +++ b/src/io/report.cpp @@ -272,7 +272,7 @@ bool report_score(PlayerType *player_ptr) personality_desc.append(_(ap_ptr->no ? "の" : "", " ")); PlayerRealm pr(player_ptr); - auto realm1_name = PlayerClass(player_ptr).equals(PlayerClassType::ELEMENTALIST) ? get_element_title(player_ptr->element) : pr.realm1().get_name().data(); + const auto &realm1_name = PlayerClass(player_ptr).equals(PlayerClassType::ELEMENTALIST) ? get_element_title(player_ptr->element) : pr.realm1().get_name().string(); score_ss << format("name: %s\n", player_ptr->name) << format("version: %s\n", AngbandSystem::get_instance().build_version_expression(VersionExpression::FULL).data()) << format("score: %ld\n", calc_score(player_ptr)) @@ -287,7 +287,7 @@ bool report_score(PlayerType *player_ptr) << format("race: %s\n", rp_ptr->title.data()) << format("class: %s\n", cp_ptr->title.data()) << format("seikaku: %s\n", personality_desc.data()) - << format("realm1: %s\n", realm1_name) + << format("realm1: %s\n", realm1_name.data()) << format("realm2: %s\n", pr.realm2().get_name().data()) << format("killer: %s\n", player_ptr->died_from.data()) << "-----charcter dump-----\n"; diff --git a/src/main/game-data-initializer.cpp b/src/main/game-data-initializer.cpp index a0aeef6caa..1677fea3bb 100644 --- a/src/main/game-data-initializer.cpp +++ b/src/main/game-data-initializer.cpp @@ -57,15 +57,11 @@ void init_other(PlayerType *player_ptr) macro_patterns.assign(MACRO_MAX, {}); macro_actions.assign(MACRO_MAX, {}); macro_buffers.assign(FILE_READ_BUFF_SIZE, {}); - for (auto i = 0; option_info[i].o_desc; i++) { - int os = option_info[i].o_set; - int ob = option_info[i].o_bit; - if (option_info[i].o_var == nullptr) { - continue; - } - + for (auto &option : option_info) { + int os = option.flag_position; + int ob = option.offset; g_option_masks[os] |= (1UL << ob); - if (option_info[i].o_norm) { + if (option.default_value) { set_bits(g_option_flags[os], 1U << ob); } else { reset_bits(g_option_flags[os], 1U << ob); diff --git a/src/mind/mind-elementalist.cpp b/src/mind/mind-elementalist.cpp index 7c490e1850..4bbb798852 100644 --- a/src/mind/mind-elementalist.cpp +++ b/src/mind/mind-elementalist.cpp @@ -54,8 +54,8 @@ #include "spell-kind/spells-world.h" #include "status/bad-status-setter.h" #include "status/base-status.h" +#include "system/enums/game-option-page.h" #include "system/floor-type-definition.h" -#include "system/game-option-types.h" #include "system/grid-type-definition.h" #include "system/monster-entity.h" #include "system/monster-race-info.h" @@ -104,9 +104,9 @@ enum class ElementSpells { * @brief 元素魔法タイプ構造体 */ struct element_type { - std::string_view title; //!< 領域名 + std::string title; //!< 領域名 std::array type; //!< 属性タイプリスト - std::array name; //!< 属性名リスト + std::array name; //!< 属性名リスト std::unordered_map extra; //!< 追加属性タイプ }; @@ -120,8 +120,8 @@ struct element_power { using element_type_list = const std::unordered_map; using element_power_list = const std::unordered_map; -using element_tip_list = const std::unordered_map; -using element_text_list = const std::unordered_map; +using element_tip_list = const std::unordered_map; +using element_text_list = const std::unordered_map; // clang-format off /*! @@ -294,10 +294,10 @@ static element_text_list element_texts = { * @param realm_idx 領域番号 * @return 領域名 */ -concptr get_element_title(int realm_idx) +const std::string &get_element_title(int realm_idx) { auto realm = i2enum(realm_idx); - return element_types.at(realm).title.data(); + return element_types.at(realm).title; } /*! @@ -305,7 +305,7 @@ concptr get_element_title(int realm_idx) * @param realm_idx 領域番号 * @return 領域で使用できる属性リスト */ -static std::array get_element_types(int realm_idx) +static const std::array &get_element_types(int realm_idx) { auto realm = i2enum(realm_idx); return element_types.at(realm).type; @@ -319,7 +319,7 @@ static std::array get_element_types(int realm_idx) */ AttributeType get_element_type(int realm_idx, int n) { - return get_element_types(realm_idx)[n]; + return get_element_types(realm_idx).at(n); } /*! @@ -345,9 +345,9 @@ static AttributeType get_element_spells_type(PlayerType *player_ptr, int n) * @param realm_idx 領域番号 * @return 領域で使用できる属性の名称リスト */ -static std::array get_element_names(int realm_idx) +static const std::array &get_element_names(int realm_idx) { - auto realm = i2enum(realm_idx); + const auto realm = i2enum(realm_idx); return element_types.at(realm).name; } @@ -357,9 +357,9 @@ static std::array get_element_names(int realm_idx) * @param n 属性の何番目か * @return 属性名 */ -concptr get_element_name(int realm_idx, int n) +const std::string &get_element_name(int realm_idx, int n) { - return get_element_names(realm_idx)[n].data(); + return get_element_names(realm_idx).at(n); } /*! @@ -970,7 +970,7 @@ void display_element_spell_list(PlayerType *player_ptr, int y, int x) } const auto elem = get_elemental_elem(player_ptr, i); - const auto name = format(spell.name, get_element_name(player_ptr->element, elem)); + const auto name = format(spell.name, get_element_name(player_ptr->element, elem).data()); const auto mana_cost = decide_element_mana_cost(player_ptr, spell); const auto chance = decide_element_chance(player_ptr, spell); @@ -990,7 +990,7 @@ void display_element_spell_list(PlayerType *player_ptr, int y, int x) * @param type 魔法攻撃属性 * @return 効果があるならTRUE、なければFALSE */ -bool is_elemental_genocide_effective(MonsterRaceInfo *r_ptr, AttributeType type) +static bool is_elemental_genocide_effective(MonsterRaceInfo *r_ptr, AttributeType type) { switch (type) { case AttributeType::FIRE: @@ -1048,19 +1048,18 @@ bool is_elemental_genocide_effective(MonsterRaceInfo *r_ptr, AttributeType type) */ ProcessResult effect_monster_elemental_genocide(PlayerType *player_ptr, EffectMonster *em_ptr) { - auto type = get_element_type(player_ptr->element, 0); - auto name = get_element_name(player_ptr->element, 0); - bool b = is_elemental_genocide_effective(em_ptr->r_ptr, type); - + const auto &name = get_element_name(player_ptr->element, 0); if (em_ptr->seen_msg) { - msg_format(_("%sが%sを包み込んだ。", "The %s surrounds %s."), name, em_ptr->m_name); + msg_format(_("%sが%sを包み込んだ。", "The %s surrounds %s."), name.data(), em_ptr->m_name); } if (em_ptr->seen) { em_ptr->obvious = true; } - if (!b) { + const auto type = get_element_type(player_ptr->element, 0); + const auto is_effective = is_elemental_genocide_effective(em_ptr->r_ptr, type); + if (!is_effective) { if (em_ptr->seen_msg) { msg_format(_("%sには効果がなかった。", "%s^ is unaffected."), em_ptr->m_name); } @@ -1109,7 +1108,7 @@ bool has_element_resist(PlayerType *player_ptr, ElementRealmType realm, PLAYER_L static void display_realm_cursor(int i, int n, term_color_type color) { char sym; - concptr name; + std::string name; if (i == n) { sym = '*'; name = _("ランダム", "Random"); @@ -1118,7 +1117,7 @@ static void display_realm_cursor(int i, int n, term_color_type color) name = element_types.at(i2enum(i + 1)).title.data(); } - c_put_str(color, format("%c) %s", sym, name), 12 + (i / 5), 2 + 15 * (i % 5)); + c_put_str(color, format("%c) %s", sym, name.data()), 12 + (i / 5), 2 + 15 * (i % 5)); } /*! @@ -1218,7 +1217,7 @@ static int get_element_realm(PlayerType *player_ptr, int is, int n) if (c == '=') { screen_save(); - do_cmd_options_aux(player_ptr, OPT_PAGE_BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); + do_cmd_options_aux(player_ptr, GameOptionPage::BIRTH, _("初期オプション((*)はスコアに影響)", "Birth Options ((*)) affect score")); screen_load(); } else if (c != '2' && c != '4' && c != '6' && c != '8') { bell(); diff --git a/src/mind/mind-elementalist.h b/src/mind/mind-elementalist.h index 974e265f61..986c415ec4 100644 --- a/src/mind/mind-elementalist.h +++ b/src/mind/mind-elementalist.h @@ -2,6 +2,7 @@ #include "effect/attribute-types.h" #include "system/angband.h" +#include enum class ElementRealmType { FIRE = 1, @@ -19,9 +20,9 @@ class PlayerType; class EffectMonster; struct rc_type; -concptr get_element_title(int realm_idx); +const std::string &get_element_title(int realm_idx); AttributeType get_element_type(int realm_idx, int n); -concptr get_element_name(int realm_idx, int n); +const std::string &get_element_name(int realm_idx, int n); void do_cmd_element(PlayerType *player_ptr); void do_cmd_element_browse(PlayerType *player_ptr); void display_element_spell_list(PlayerType *player_ptr, int y = 1, int x = 1); diff --git a/src/monster-floor/monster-safety-hiding.cpp b/src/monster-floor/monster-safety-hiding.cpp index f1c36e48bf..11aeae523a 100644 --- a/src/monster-floor/monster-safety-hiding.cpp +++ b/src/monster-floor/monster-safety-hiding.cpp @@ -51,11 +51,11 @@ static coordinate_candidate sweep_safe_coordinate(PlayerType *player_ptr, MONSTE } if (m_ptr->mflag2.has_not(MonsterConstantFlagType::NOFLOW)) { - byte dist = g_ptr->get_distance(r_ptr); + const auto dist = g_ptr->get_distance(r_ptr->get_grid_flow_type()); if (dist == 0) { continue; } - if (dist > floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].get_distance(r_ptr) + 2 * d) { + if (dist > floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].get_distance(r_ptr->get_grid_flow_type()) + 2 * d) { continue; } } diff --git a/src/monster-floor/monster-sweep-grid.cpp b/src/monster-floor/monster-sweep-grid.cpp index fed8092269..cc5bd96363 100644 --- a/src/monster-floor/monster-sweep-grid.cpp +++ b/src/monster-floor/monster-sweep-grid.cpp @@ -55,7 +55,7 @@ bool MonsterSweepGrid::get_movable_grid() auto x2 = this->player_ptr->x; this->will_run = this->mon_will_run(); Pos2D pos_monster_from(monster_from.fy, monster_from.fx); - const auto no_flow = monster_from.mflag2.has(MonsterConstantFlagType::NOFLOW) && (floor.get_grid(pos_monster_from).get_cost(&monrace) > 2); + const auto no_flow = monster_from.mflag2.has(MonsterConstantFlagType::NOFLOW) && (floor.get_grid(pos_monster_from).get_cost(monrace.get_grid_flow_type()) > 2); this->can_pass_wall = monrace.feature_flags.has(MonsterFeatureType::PASS_WALL) && (!monster_from.is_riding() || has_pass_wall(this->player_ptr)); if (!this->will_run && monster_from.target_y) { Pos2D pos_target(monster_from.target_y, monster_from.target_x); @@ -141,14 +141,15 @@ void MonsterSweepGrid::check_hiding_grid(POSITION *y, POSITION *x, POSITION *y2, return; } + const auto gf = r_ptr->get_grid_flow_type(); if ((!los(this->player_ptr, m_ptr->fy, m_ptr->fx, this->player_ptr->y, this->player_ptr->x) || !projectable(this->player_ptr, m_ptr->fy, m_ptr->fx, this->player_ptr->y, this->player_ptr->x))) { - if (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].get_distance(r_ptr) >= MAX_PLAYER_SIGHT / 2) { + if (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].get_distance(gf) >= MAX_PLAYER_SIGHT / 2) { return; } } this->search_room_to_run(y, x); - if (this->done || (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].get_distance(r_ptr) >= 3)) { + if (this->done || (floor_ptr->grid_array[m_ptr->fy][m_ptr->fx].get_distance(gf) >= 3)) { return; } @@ -249,9 +250,9 @@ void MonsterSweepGrid::search_pet_runnable_grid(POSITION *y, POSITION *x, bool n */ void MonsterSweepGrid::sweep_movable_grid(POSITION *yp, POSITION *xp, bool no_flow) { - auto &floor = *this->player_ptr->current_floor_ptr; - auto &monster = floor.m_list[this->m_idx]; - auto &monrace = monster.get_monrace(); + const auto &floor = *this->player_ptr->current_floor_ptr; + const auto &monster = floor.m_list[this->m_idx]; + const auto &monrace = monster.get_monrace(); if (!this->check_movable_grid(yp, xp, no_flow)) { return; } @@ -260,14 +261,15 @@ void MonsterSweepGrid::sweep_movable_grid(POSITION *yp, POSITION *xp, bool no_fl auto x1 = monster.fx; const Pos2D pos(y1, x1); const auto &grid = floor.get_grid(pos); + const auto gf = monrace.get_grid_flow_type(); if (grid.has_los() && projectable(this->player_ptr, this->player_ptr->y, this->player_ptr->x, y1, x1)) { - if ((distance(y1, x1, this->player_ptr->y, this->player_ptr->x) == 1) || (monrace.freq_spell > 0) || (grid.get_cost(&monrace) > 5)) { + if ((distance(y1, x1, this->player_ptr->y, this->player_ptr->x) == 1) || (monrace.freq_spell > 0) || (grid.get_cost(gf) > 5)) { return; } } auto use_scent = false; - if (grid.get_cost(&monrace)) { + if (grid.get_cost(gf)) { this->best = 999; } else if (grid.when) { const auto p_pos = this->player_ptr->get_position(); @@ -316,16 +318,17 @@ bool MonsterSweepGrid::check_movable_grid(POSITION *yp, POSITION *xp, const bool */ bool MonsterSweepGrid::sweep_ranged_attack_grid(POSITION *yp, POSITION *xp) { - auto *floor_ptr = this->player_ptr->current_floor_ptr; - auto *m_ptr = &floor_ptr->m_list[this->m_idx]; - auto *r_ptr = &m_ptr->get_monrace(); - auto y1 = m_ptr->fy; - auto x1 = m_ptr->fx; + const auto *floor_ptr = this->player_ptr->current_floor_ptr; + const auto *m_ptr = &floor_ptr->m_list[this->m_idx]; + const auto *r_ptr = &m_ptr->get_monrace(); + const auto y1 = m_ptr->fy; + const auto x1 = m_ptr->fx; if (projectable(this->player_ptr, y1, x1, this->player_ptr->y, this->player_ptr->x)) { return false; } - auto now_cost = (int)floor_ptr->grid_array[y1][x1].get_cost(r_ptr); + const auto gf = r_ptr->get_grid_flow_type(); + int now_cost = floor_ptr->grid_array[y1][x1].get_cost(gf); if (now_cost == 0) { now_cost = 999; } @@ -345,7 +348,7 @@ bool MonsterSweepGrid::sweep_ranged_attack_grid(POSITION *yp, POSITION *xp) } const auto &grid = floor_ptr->get_grid(pos); - this->cost = grid.get_cost(r_ptr); + this->cost = grid.get_cost(gf); if (!this->is_best_cost(pos.y, pos.x, now_cost)) { continue; } @@ -421,7 +424,7 @@ bool MonsterSweepGrid::sweep_runnable_away_grid(POSITION *yp, POSITION *xp) } auto dis = distance(y, x, y1, x1); - auto s = 5000 / (dis + 3) - 500 / (floor_ptr->grid_array[y][x].get_distance(r_ptr) + 1); + auto s = 5000 / (dis + 3) - 500 / (floor_ptr->grid_array[y][x].get_distance(r_ptr->get_grid_flow_type()) + 1); if (s < 0) { s = 0; } @@ -464,7 +467,8 @@ void MonsterSweepGrid::determine_when_cost(POSITION *yp, POSITION *xp, POSITION this->best = when; } else { const auto &monrace = floor_ptr->m_list[this->m_idx].get_monrace(); - this->cost = monrace.behavior_flags.has_any_of({ MonsterBehaviorType::BASH_DOOR, MonsterBehaviorType::OPEN_DOOR }) ? g_ptr->get_distance(&monrace) : g_ptr->get_cost(&monrace); + const auto gf = monrace.get_grid_flow_type(); + this->cost = monrace.behavior_flags.has_any_of({ MonsterBehaviorType::BASH_DOOR, MonsterBehaviorType::OPEN_DOOR }) ? g_ptr->get_distance(gf) : g_ptr->get_cost(gf); if ((this->cost == 0) || (this->best < this->cost)) { continue; } diff --git a/src/racial/racial-draconian.cpp b/src/racial/racial-draconian.cpp index 30664bc3e7..62c0b70f7b 100644 --- a/src/racial/racial-draconian.cpp +++ b/src/racial/racial-draconian.cpp @@ -6,11 +6,14 @@ #include "system/player-type-definition.h" #include "target/target-getter.h" #include "view/display-messages.h" +#include +#include +#include -static void decide_breath_kind(PlayerType *player_ptr, AttributeType *breath_type, concptr *breath_type_description) +static std::optional> decide_breath_kind(PlayerType *player_ptr) { if (randint1(100) >= player_ptr->lev) { - return; + return std::nullopt; } switch (player_ptr->pclass) { @@ -22,14 +25,10 @@ static void decide_breath_kind(PlayerType *player_ptr, AttributeType *breath_typ case PlayerClassType::ARCHER: case PlayerClassType::SMITH: if (one_in_(3)) { - *breath_type = AttributeType::MISSILE; - *breath_type_description = _("エレメント", "the elements"); - } else { - *breath_type = AttributeType::SHARDS; - *breath_type_description = _("破片", "shards"); + return std::pair(AttributeType::MISSILE, _("エレメント", "the elements")); } - break; + return std::pair(AttributeType::SHARDS, _("破片", "shards")); case PlayerClassType::MAGE: case PlayerClassType::WARRIOR_MAGE: case PlayerClassType::HIGH_MAGE: @@ -39,100 +38,77 @@ static void decide_breath_kind(PlayerType *player_ptr, AttributeType *breath_typ case PlayerClassType::BLUE_MAGE: case PlayerClassType::MIRROR_MASTER: if (one_in_(3)) { - *breath_type = AttributeType::MANA; - *breath_type_description = _("魔力", "mana"); - } else { - *breath_type = AttributeType::DISENCHANT; - *breath_type_description = _("劣化", "disenchantment"); + return std::pair(AttributeType::MANA, _("魔力", "mana")); } - break; + return std::pair(AttributeType::DISENCHANT, _("劣化", "disenchantment")); case PlayerClassType::CHAOS_WARRIOR: - if (!one_in_(3)) { - *breath_type = AttributeType::CONFUSION; - *breath_type_description = _("混乱", "confusion"); - } else { - *breath_type = AttributeType::CHAOS; - *breath_type_description = _("カオス", "chaos"); + if (one_in_(3)) { + return std::pair(AttributeType::CHAOS, _("カオス", "chaos")); } - break; + return std::pair(AttributeType::CONFUSION, _("混乱", "confusion")); case PlayerClassType::MONK: case PlayerClassType::SAMURAI: case PlayerClassType::FORCETRAINER: - if (!one_in_(3)) { - *breath_type = AttributeType::CONFUSION; - *breath_type_description = _("混乱", "confusion"); - } else { - *breath_type = AttributeType::SOUND; - *breath_type_description = _("轟音", "sound"); + if (one_in_(3)) { + return std::pair(AttributeType::SOUND, _("轟音", "sound")); } - break; + return std::pair(AttributeType::CONFUSION, _("混乱", "confusion")); case PlayerClassType::MINDCRAFTER: - if (!one_in_(3)) { - *breath_type = AttributeType::CONFUSION; - *breath_type_description = _("混乱", "confusion"); - } else { - *breath_type = AttributeType::PSI; - *breath_type_description = _("精神エネルギー", "mental energy"); + if (one_in_(3)) { + return std::pair(AttributeType::PSI, _("精神エネルギー", "mental energy")); } - break; + return std::pair(AttributeType::CONFUSION, _("混乱", "confusion")); case PlayerClassType::PRIEST: case PlayerClassType::PALADIN: if (one_in_(3)) { - *breath_type = AttributeType::HELL_FIRE; - *breath_type_description = _("地獄の劫火", "hellfire"); - } else { - *breath_type = AttributeType::HOLY_FIRE; - *breath_type_description = _("聖なる炎", "holy fire"); + return std::pair(AttributeType::HELL_FIRE, _("地獄の劫火", "hellfire")); } - break; + return std::pair(AttributeType::HOLY_FIRE, _("聖なる炎", "holy fire")); case PlayerClassType::ROGUE: case PlayerClassType::NINJA: if (one_in_(3)) { - *breath_type = AttributeType::DARK; - *breath_type_description = _("暗黒", "darkness"); - } else { - *breath_type = AttributeType::POIS; - *breath_type_description = _("毒", "poison"); + return std::pair(AttributeType::DARK, _("暗黒", "darkness")); } - break; + return std::pair(AttributeType::POIS, _("毒", "poison")); case PlayerClassType::BARD: - if (!one_in_(3)) { - *breath_type = AttributeType::SOUND; - *breath_type_description = _("轟音", "sound"); - } else { - *breath_type = AttributeType::CONFUSION; - *breath_type_description = _("混乱", "confusion"); + if (one_in_(3)) { + return std::pair(AttributeType::CONFUSION, _("混乱", "confusion")); } - break; - case PlayerClassType::ELEMENTALIST: - *breath_type = get_element_type(player_ptr->element, 0); - *breath_type_description = get_element_name(player_ptr->element, 0); - break; + return std::pair(AttributeType::SOUND, _("轟音", "sound")); + case PlayerClassType::ELEMENTALIST: { + const auto type = get_element_type(player_ptr->element, 0); + const std::string name(get_element_name(player_ptr->element, 0)); + return std::pair(type, name); + } default: - break; + return std::nullopt; } } bool draconian_breath(PlayerType *player_ptr) { - AttributeType breath_type = (one_in_(3) ? AttributeType::COLD : AttributeType::FIRE); - concptr breath_type_description = ((breath_type == AttributeType::COLD) ? _("冷気", "cold") : _("炎", "fire")); + auto breath_type = one_in_(3) ? AttributeType::COLD : AttributeType::FIRE; + std::string breath_type_description((breath_type == AttributeType::COLD) ? _("冷気", "cold") : _("炎", "fire")); DIRECTION dir; if (!get_aim_dir(player_ptr, &dir)) { return false; } - decide_breath_kind(player_ptr, &breath_type, &breath_type_description); - stop_mouth(player_ptr); - msg_format(_("あなたは%sのブレスを吐いた。", "You breathe %s."), breath_type_description); + const auto special_breath = decide_breath_kind(player_ptr); + if (special_breath) { + breath_type = special_breath->first; + breath_type_description = special_breath->second; + } + stop_mouth(player_ptr); + msg_format(_("あなたは%sのブレスを吐いた。", "You breathe %s."), breath_type_description.data()); fire_breath(player_ptr, breath_type, dir, player_ptr->lev * 2, (player_ptr->lev / 15) + 1); return true; } diff --git a/src/save/info-writer.cpp b/src/save/info-writer.cpp index 226b58f58c..6cf7873c13 100644 --- a/src/save/info-writer.cpp +++ b/src/save/info-writer.cpp @@ -120,14 +120,10 @@ void wr_options() wr_bool(autosave_t); wr_s16b(autosave_freq); - for (int i = 0; option_info[i].o_desc; i++) { - int os = option_info[i].o_set; - int ob = option_info[i].o_bit; - if (!option_info[i].o_var) { - continue; - } - - if (*option_info[i].o_var) { + for (auto &option : option_info) { + int os = option.flag_position; + int ob = option.offset; + if (*option.value) { g_option_flags[os] |= (1UL << ob); } else { g_option_flags[os] &= ~(1UL << ob); diff --git a/src/system/enums/game-option-page.h b/src/system/enums/game-option-page.h new file mode 100644 index 0000000000..9efc8570e5 --- /dev/null +++ b/src/system/enums/game-option-page.h @@ -0,0 +1,13 @@ +#pragma once + +enum class GameOptionPage : int { + INPUT, + MAPSCREEN, + TEXT, + GAMEPLAY, + DISTURBANCE, + BIRTH, + AUTODESTROY, + PLAYRECORD, + HIDE, +}; diff --git a/src/system/enums/grid-flow.h b/src/system/enums/grid-flow.h new file mode 100644 index 0000000000..d29e9af1df --- /dev/null +++ b/src/system/enums/grid-flow.h @@ -0,0 +1,11 @@ +#pragma once + +#include "util/enum-range.h" + +enum class GridFlow : int { + NORMAL = 0, + CAN_FLY = 1, + MAX = 2, +}; + +constexpr EnumRange GRID_FLOW_RANGE(GridFlow::NORMAL, GridFlow::MAX); diff --git a/src/system/game-option-types.h b/src/system/game-option-types.h deleted file mode 100644 index f4a8c702fe..0000000000 --- a/src/system/game-option-types.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -enum game_option_types { - OPT_PAGE_INPUT, - OPT_PAGE_MAPSCREEN, - OPT_PAGE_TEXT, - OPT_PAGE_GAMEPLAY, - OPT_PAGE_DISTURBANCE, - OPT_PAGE_BIRTH, - OPT_PAGE_AUTODESTROY, - OPT_PAGE_PLAYRECORD, - OPT_PAGE_HIDE, -}; diff --git a/src/system/grid-type-definition.cpp b/src/system/grid-type-definition.cpp index 9556711159..60532272e7 100644 --- a/src/system/grid-type-definition.cpp +++ b/src/system/grid-type-definition.cpp @@ -2,10 +2,18 @@ #include "monster/monster-util.h" #include "room/door-definition.h" #include "system/angband-system.h" -#include "system/monster-race-info.h" +#include "system/enums/grid-flow.h" #include "system/terrain-type-definition.h" #include "util/bit-flags-calculator.h" +Grid::Grid() +{ + for (const auto gf : GRID_FLOW_RANGE) { + this->costs[gf] = 0; + this->dists[gf] = 0; + } +} + /*! * @brief 指定座標がFLOOR属性を持ったマスかどうかを返す * @param Y 指定Y座標 @@ -98,19 +106,14 @@ bool Grid::has_monster() const return is_monster(this->m_idx); } -byte Grid::get_cost(const MonsterRaceInfo *r_ptr) const -{ - return this->costs[get_grid_flow_type(r_ptr)]; -} - -byte Grid::get_distance(const MonsterRaceInfo *r_ptr) const +uint8_t Grid::get_cost(GridFlow gf) const { - return this->dists[get_grid_flow_type(r_ptr)]; + return this->costs.at(gf); } -flow_type Grid::get_grid_flow_type(const MonsterRaceInfo *r_ptr) const +uint8_t Grid::get_distance(GridFlow gf) const { - return r_ptr->feature_flags.has(MonsterFeatureType::CAN_FLY) ? FLOW_CAN_FLY : FLOW_NORMAL; + return this->dists.at(gf); } /* @@ -140,15 +143,15 @@ bool Grid::is_symbol(const int ch) const void Grid::reset_costs() { - for (auto &cost : this->costs) { - cost = 0; + for (const auto gf : GRID_FLOW_RANGE) { + this->costs[gf] = 0; } } void Grid::reset_dists() { - for (auto &dist : this->dists) { - dist = 0; + for (const auto gf : GRID_FLOW_RANGE) { + this->dists[gf] = 0; } } diff --git a/src/system/grid-type-definition.h b/src/system/grid-type-definition.h index dfe91f4670..e0845a7312 100644 --- a/src/system/grid-type-definition.h +++ b/src/system/grid-type-definition.h @@ -2,6 +2,7 @@ #include "object/object-index-list.h" #include "system/angband.h" +#include /* * 特殊なマス状態フラグ / Special grid flags @@ -38,17 +39,12 @@ // clang-format on -enum flow_type { - FLOW_NORMAL = 0, - FLOW_CAN_FLY = 1, - FLOW_MAX = 2, -}; - -class MonsterRaceInfo; +enum class GridFlow : int; class TerrainType; enum class TerrainCharacteristics; class Grid { public: + Grid(); BIT_FLAGS info{}; /* Hack -- grid flags */ FEAT_IDX feat{}; /* Hack -- feature type */ @@ -64,8 +60,8 @@ class Grid { FEAT_IDX mimic{}; /* Feature to mimic */ - byte costs[FLOW_MAX]{}; /* Hack -- cost of flowing */ - byte dists[FLOW_MAX]{}; /* Hack -- distance from player */ + std::map costs; //!< Cost of flowing + std::map dists; //!< Distance from player byte when{}; /* Hack -- when cost was computed */ bool is_floor() const; @@ -84,8 +80,8 @@ class Grid { bool is_rune_protection() const; bool is_rune_explosion() const; bool has_monster() const; - byte get_cost(const MonsterRaceInfo *r_ptr) const; - byte get_distance(const MonsterRaceInfo *r_ptr) const; + uint8_t get_cost(GridFlow gf) const; + uint8_t get_distance(GridFlow gf) const; FEAT_IDX get_feat_mimic() const; bool cave_has_flag(TerrainCharacteristics feature_flags) const; bool is_symbol(const int ch) const; @@ -100,7 +96,4 @@ class Grid { const TerrainType &get_terrain_mimic_raw() const; void place_closed_curtain(); void add_info(int grid_info); - -private: - flow_type get_grid_flow_type(const MonsterRaceInfo *r_ptr) const; }; diff --git a/src/system/monster-race-info.cpp b/src/system/monster-race-info.cpp index 691e3b903e..37ef91dc22 100644 --- a/src/system/monster-race-info.cpp +++ b/src/system/monster-race-info.cpp @@ -5,6 +5,7 @@ #include "monster-race/race-resistance-mask.h" #include "monster-race/race-sex.h" #include "monster/horror-descriptions.h" +#include "system/enums/grid-flow.h" #include "system/redrawing-flags-updater.h" #include "system/system-variables.h" #include "tracking/lore-tracker.h" @@ -308,6 +309,11 @@ bool MonsterRaceInfo::can_generate() const return can_generate; } +GridFlow MonsterRaceInfo::get_grid_flow_type() const +{ + return this->feature_flags.has(MonsterFeatureType::CAN_FLY) ? GridFlow::CAN_FLY : GridFlow::NORMAL; +} + void MonsterRaceInfo::init_sex(uint32_t value) { const auto sex_tmp = i2enum(value); diff --git a/src/system/monster-race-info.h b/src/system/monster-race-info.h index 4d97612a39..e77d03ed87 100644 --- a/src/system/monster-race-info.h +++ b/src/system/monster-race-info.h @@ -64,6 +64,7 @@ class MonsterBlow { * monster recall (no knowledge of spells, etc). All of the "recall" * fields have a special prefix to aid in searching for them. */ +enum class GridFlow : int; class DropArtifact; class Reinforce; class MonsterRaceInfo { @@ -154,6 +155,7 @@ class MonsterRaceInfo { const std::vector &get_drop_artifacts() const; const std::vector &get_reinforces() const; bool can_generate() const; + GridFlow get_grid_flow_type() const; void init_sex(uint32_t value); std::optional probe_lore(); diff --git a/src/target/target-describer.cpp b/src/target/target-describer.cpp index 2a44ab4184..f06d1d2c35 100644 --- a/src/target/target-describer.cpp +++ b/src/target/target-describer.cpp @@ -25,6 +25,7 @@ #include "player/player-status-table.h" #include "system/building-type-definition.h" #include "system/dungeon-info.h" +#include "system/enums/grid-flow.h" #include "system/floor-type-definition.h" #include "system/grid-type-definition.h" #include "system/item-entity.h" @@ -501,11 +502,11 @@ static std::string describe_grid_monster_all(GridExamination *ge_ptr) #ifdef JP return format("%s%s%s%s[%s] %x %s %d %d %d (%d,%d) %d", ge_ptr->s1, ge_ptr->name.data(), ge_ptr->s2, ge_ptr->s3, ge_ptr->info, - (uint)ge_ptr->g_ptr->info, f_idx_str.data(), ge_ptr->g_ptr->dists[FLOW_NORMAL], ge_ptr->g_ptr->costs[FLOW_NORMAL], ge_ptr->g_ptr->when, (int)ge_ptr->y, - (int)ge_ptr->x, travel.cost[ge_ptr->y][ge_ptr->x]); + (uint)ge_ptr->g_ptr->info, f_idx_str.data(), ge_ptr->g_ptr->dists[GridFlow::NORMAL], ge_ptr->g_ptr->costs[GridFlow::NORMAL], ge_ptr->g_ptr->when, + ge_ptr->y, ge_ptr->x, travel.cost[ge_ptr->y][ge_ptr->x]); #else return format("%s%s%s%s [%s] %x %s %d %d %d (%d,%d)", ge_ptr->s1, ge_ptr->s2, ge_ptr->s3, ge_ptr->name.data(), ge_ptr->info, ge_ptr->g_ptr->info, - f_idx_str.data(), ge_ptr->g_ptr->dists[FLOW_NORMAL], ge_ptr->g_ptr->costs[FLOW_NORMAL], ge_ptr->g_ptr->when, (int)ge_ptr->y, (int)ge_ptr->x); + f_idx_str.data(), ge_ptr->g_ptr->dists[GridFlow::NORMAL], ge_ptr->g_ptr->costs[GridFlow::NORMAL], ge_ptr->g_ptr->when, ge_ptr->y, ge_ptr->x); #endif } diff --git a/src/util/string-processor.cpp b/src/util/string-processor.cpp index c5b363257e..4dad12ccd5 100644 --- a/src/util/string-processor.cpp +++ b/src/util/string-processor.cpp @@ -104,7 +104,7 @@ static void trigger_text_to_ascii(char **bufptr, concptr *strptr) { char *s = *bufptr; concptr str = *strptr; - bool mod_status[MAX_MACRO_MOD]; + bool mod_status[MAX_MACRO_MOD]{}; int i, len = 0; int shiftstatus = 0; @@ -263,7 +263,7 @@ static bool trigger_ascii_to_text(char **bufptr, concptr *strptr) { char *s = *bufptr; concptr str = *strptr; - char key_code[100]; + char key_code[100]{}; int i; if (macro_template == nullptr) { return false; diff --git a/src/wizard/wizard-special-process.cpp b/src/wizard/wizard-special-process.cpp index de812e64a0..4b7034c8c7 100644 --- a/src/wizard/wizard-special-process.cpp +++ b/src/wizard/wizard-special-process.cpp @@ -106,6 +106,7 @@ #include "wizard/wizard-spoiler.h" #include "world/world.h" #include +#include #include #include #include @@ -715,16 +716,15 @@ void wiz_reset_realms(PlayerType *player_ptr) } /*! - * @brief 現在のオプション設定をダンプ出力する / + * @brief 現在のオプション設定をダンプ出力する * @param player_ptr プレイヤーへの参照ポインタ - * Hack -- Dump option bits usage */ -void wiz_dump_options(void) +void wiz_dump_options() { const auto path = path_build(ANGBAND_DIR_USER, "opt_info.txt"); const auto &filename = path.string(); - auto *fff = angband_fopen(path, FileOpenMode::APPEND); - if (fff == nullptr) { + std::ofstream ofs(path); + if (ofs.bad()) { msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), filename.data()); msg_print(nullptr); return; @@ -734,31 +734,29 @@ void wiz_dump_options(void) constexpr auto num_o_bit = 32; std::vector> exist(num_o_set, std::vector(num_o_bit)); - - for (int i = 0; option_info[i].o_desc; i++) { - const option_type *ot_ptr = &option_info[i]; - if (ot_ptr->o_var) { - exist[ot_ptr->o_set][ot_ptr->o_bit] = i + 1; - } + auto option_count = 0; + for (const auto &option : option_info) { + exist[option.flag_position][option.offset] = option_count + 1; + option_count++; } - fprintf(fff, "[Option bits usage on %s\n]", AngbandSystem::get_instance().build_version_expression(VersionExpression::FULL).data()); - fputs("Set - Bit (Page) Option Name\n", fff); - fputs("------------------------------------------------\n", fff); - for (int i = 0; i < num_o_set; i++) { - for (int j = 0; j < num_o_bit; j++) { + ofs << "[Option bits usage on %s\n]", AngbandSystem::get_instance().build_version_expression(VersionExpression::FULL); + ofs << "Set - Bit (Page) Option Name\n"; + ofs << "------------------------------------------------\n"; + for (auto i = 0; i < num_o_set; i++) { + for (auto j = 0; j < num_o_bit; j++) { if (exist[i][j]) { - const option_type *ot_ptr = &option_info[exist[i][j] - 1]; - fprintf(fff, " %d - %02d (%4d) %s\n", i, j, ot_ptr->o_page, ot_ptr->o_text); + const auto &option = option_info[exist[i][j] - 1]; + const auto page = option.page ? enum2i(*option.page) : 255; //!< @details かつてnulloptではなかった頃の値. + ofs << format(" %d - %02d (%4d) %s\n", i, j, page, option.text.data()); } else { - fprintf(fff, " %d - %02d\n", i, j); + ofs << format(" %d - %02d\n", i, j); } } - fputc('\n', fff); + ofs << '\n'; } - angband_fclose(fff); msg_format(_("オプションbit使用状況をファイル %s に書き出しました。", "Option bits usage dump saved to file %s."), filename.data()); }