-/*!
+/*!
* @brief ウィザードモードの処理(特別処理中心) / Wizard commands
* @date 2014/09/07
* @author
#include "spell/spells-summon.h"
#include "status/bad-status-setter.h"
#include "status/experience.h"
+#include "system/angband-system.h"
#include "system/angband-version.h"
#include "system/artifact-type-definition.h"
#include "system/baseitem-info.h"
#include "term/z-form.h"
#include "util/angband-files.h"
#include "util/bit-flags-calculator.h"
+#include "util/candidate-selector.h"
#include "util/enum-converter.h"
+#include "util/finalizer.h"
#include "util/int-char-converter.h"
#include "view/display-messages.h"
#include "wizard/spoiler-table.h"
#include "world/world.h"
#include <algorithm>
#include <optional>
+#include <span>
#include <sstream>
#include <tuple>
#include <vector>
static std::optional<short> wiz_select_tval()
{
short list;
- char ch;
for (list = 0; (list < 80) && (tvals[list].tval > ItemKindType::NONE); list++) {
auto row = 2 + (list % 20);
auto col = _(32, 24) * (list / 20);
- ch = listsym[list];
- prt(format("[%c] %s", ch, tvals[list].desc), row, col);
+ prt(format("[%c] %s", listsym[list], tvals[list].desc), row, col);
}
- auto max_num = list;
- if (!get_com(_("アイテム種別を選んで下さい", "Get what type of object? "), &ch, false)) {
+ const auto item_type_opt = input_command(_("アイテム種別を選んで下さい", "Get what type of object? "));
+ if (!item_type_opt) {
return std::nullopt;
}
+ const auto item_type = item_type_opt.value();
short selection;
+ auto max_num = list;
for (selection = 0; selection < max_num; selection++) {
- if (listsym[selection] == ch) {
+ if (listsym[selection] == item_type) {
break;
}
}
return selection;
}
-static short wiz_select_sval(const ItemKindType tval, concptr tval_description)
+static short wiz_select_sval(const ItemKindType tval, std::string_view tval_description)
{
auto num = 0;
short choice[80]{};
- char ch;
for (const auto &baseitem : baseitems_info) {
if (num >= 80) {
break;
auto row = 2 + (num % 20);
auto col = _(30, 32) * (num / 20);
- ch = listsym[num];
const auto buf = strip_name(baseitem.idx);
- prt(format("[%c] %s", ch, buf.data()), row, col);
+ prt(format("[%c] %s", listsym[num], buf.data()), row, col);
choice[num++] = baseitem.idx;
}
auto max_num = num;
- if (!get_com(format(_("%s群の具体的なアイテムを選んで下さい", "What Kind of %s? "), tval_description), &ch, false)) {
+ const auto prompt = format(_("%s群の具体的なアイテムを選んで下さい", "What Kind of %s? "), tval_description.data());
+ const auto command = input_command(prompt);
+ if (!command) {
return 0;
}
+ const auto ch = command.value();
short selection;
for (selection = 0; selection < max_num; selection++) {
if (listsym[selection] == ch) {
{
term_clear();
auto selection = wiz_select_tval();
- if (!selection.has_value()) {
+ if (!selection) {
return 0;
}
ItemEntity item;
item.prep(lookup_baseitem_id(artifact.bi_key));
item.fixed_artifact_idx = a_idx;
- object_known(&item);
+ item.mark_as_known();
return describe_flavor(player_ptr, &item, OD_NAME_ONLY);
}
*/
static std::optional<FixedArtifactId> wiz_select_named_artifact(PlayerType *player_ptr, const std::vector<FixedArtifactId> &a_idx_list)
{
- constexpr auto MAX_PER_PAGE = 20UL;
- const auto page_max = (a_idx_list.size() - 1) / MAX_PER_PAGE + 1;
- auto current_page = 0UL;
-
- screen_save();
-
- std::optional<FixedArtifactId> selected_a_idx;
-
- while (!selected_a_idx.has_value()) {
- const auto page_base_idx = current_page * MAX_PER_PAGE;
- for (auto i = 0U; i < MAX_PER_PAGE + 1; ++i) {
- term_erase(14, i + 1, 255);
- }
- const auto page_item_count = std::min(MAX_PER_PAGE, a_idx_list.size() - page_base_idx);
- for (auto i = 0U; i < page_item_count; ++i) {
- std::stringstream ss;
- ss << I2A(i) << ") " << wiz_make_named_artifact_desc(player_ptr, a_idx_list[page_base_idx + i]);
- put_str(ss.str(), i + 1, 15);
- }
- if (page_max > 1) {
- put_str(format("-- more (%lu/%lu) --", current_page + 1, page_max), page_item_count + 1, 15);
- }
-
- char cmd = ESCAPE;
- get_com("Which artifact: ", &cmd, false);
- switch (cmd) {
- case ESCAPE:
- screen_load();
- return selected_a_idx;
- case ' ':
- current_page++;
- if (current_page >= page_max) {
- current_page = 0;
- }
- break;
- default:
- const auto select_idx = A2I(cmd) + page_base_idx;
- if (select_idx < a_idx_list.size()) {
- selected_a_idx = a_idx_list[select_idx];
- }
- break;
- }
- }
+ CandidateSelector cs("Which artifact: ", 15);
- screen_load();
-
- return selected_a_idx;
+ auto describe_artifact = [player_ptr](FixedArtifactId a_idx) { return wiz_make_named_artifact_desc(player_ptr, a_idx); };
+ const auto it = cs.select(a_idx_list, describe_artifact);
+ return (it != a_idx_list.end()) ? std::make_optional(*it) : std::nullopt;
}
/**
const auto &[tval_lit, name] = group_artifact_list[i];
std::stringstream ss;
ss << I2A(i) << ") " << name;
- term_erase(14, i + 1, 255);
+ term_erase(14, i + 1);
put_str(ss.str(), i + 1, 15);
}
std::optional<FixedArtifactId> create_a_idx;
- while (!create_a_idx.has_value()) {
- char cmd = ESCAPE;
- get_com("Kind of artifact: ", &cmd, false);
- switch (cmd) {
- case ESCAPE:
+ while (!create_a_idx) {
+ const auto command = input_command("Kind of artifact: ");
+ if (!command) {
screen_load();
return;
- default:
- if (auto idx = A2I(cmd); idx < group_artifact_list.size()) {
- const auto &a_idx_list = wiz_collect_group_a_idx(group_artifact_list[idx]);
- create_a_idx = wiz_select_named_artifact(player_ptr, a_idx_list);
- }
+ }
- break;
+ const auto idx = A2I(*command);
+ if (idx >= group_artifact_list.size()) {
+ continue;
}
+
+ const auto a_idx_list = wiz_collect_group_a_idx(group_artifact_list[idx]);
+ create_a_idx = wiz_select_named_artifact(player_ptr, a_idx_list);
}
screen_load();
msg_print("Allocated.");
}
+static void wiz_change_status_max(PlayerType *player_ptr)
+{
+ for (auto i = 0; i < A_MAX; ++i) {
+ player_ptr->stat_cur[i] = player_ptr->stat_max_max[i];
+ player_ptr->stat_max[i] = player_ptr->stat_max_max[i];
+ }
+
+ for (auto tval : TV_WEAPON_RANGE) {
+ for (auto &exp : player_ptr->weapon_exp[tval]) {
+ exp = PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER);
+ }
+ }
+ PlayerSkill(player_ptr).limit_weapon_skills_by_max_value();
+
+ for (auto &[type, exp] : player_ptr->skill_exp) {
+ exp = class_skills_info[enum2i(player_ptr->pclass)].s_max[type];
+ }
+
+ const std::span spells_exp_span(player_ptr->spell_exp);
+ for (auto &exp : spells_exp_span.first(32)) {
+ exp = PlayerSkill::spell_exp_at(PlayerSkillRank::MASTER);
+ }
+ for (auto &exp : spells_exp_span.last(32)) {
+ exp = PlayerSkill::spell_exp_at(PlayerSkillRank::EXPERT);
+ }
+
+ player_ptr->au = 999999999;
+
+ if (PlayerRace(player_ptr).equals(PlayerRaceType::ANDROID)) {
+ return;
+ }
+
+ player_ptr->max_exp = 99999999;
+ player_ptr->exp = 99999999;
+ player_ptr->exp_frac = 0;
+}
+
/*!
* @brief プレイヤーの現能力値を調整する / Change various "permanent" player variables.
* @param player_ptr プレイヤーへの参照ポインタ
*/
void wiz_change_status(PlayerType *player_ptr)
{
+ const auto finalizer = util::make_finalizer([player_ptr]() {
+ check_experience(player_ptr);
+ do_cmd_redraw(player_ptr);
+ });
+
+ constexpr auto msg = _("全てのステータスを最大にしますか?", "Maximize all statuses? ");
+ if (input_check_strict(player_ptr, msg, { UserCheck::NO_ESCAPE, UserCheck::NO_HISTORY })) {
+ wiz_change_status_max(player_ptr);
+ return;
+ }
+
for (int i = 0; i < A_MAX; i++) {
const auto max_max_ability_score = player_ptr->stat_max_max[i];
const auto max_ability_score = player_ptr->stat_max[i];
- const auto new_ability_score = input_value(stat_names[i], 3, max_max_ability_score, max_ability_score);
- if (!new_ability_score.has_value()) {
+ const auto new_ability_score = input_numerics(stat_names[i], 3, max_max_ability_score, max_ability_score);
+ if (!new_ability_score) {
return;
}
const auto unskilled = PlayerSkill::weapon_exp_at(PlayerSkillRank::UNSKILLED);
const auto master = PlayerSkill::weapon_exp_at(PlayerSkillRank::MASTER);
- const auto proficiency_opt = input_value(_("熟練度", "Proficiency"), unskilled, master, static_cast<short>(master));
- if (!proficiency_opt.has_value()) {
+ const auto proficiency_opt = input_numerics(_("熟練度", "Proficiency"), unskilled, master, static_cast<short>(master));
+ if (!proficiency_opt) {
return;
}
player_ptr->spell_exp[k] = std::min(PlayerSkill::spell_exp_at(PlayerSkillRank::EXPERT), proficiency);
}
- const auto gold = input_value("Gold: ", 0, MAX_INT, player_ptr->au);
- if (!gold.has_value()) {
+ const auto gold = input_numerics("Gold: ", 0, MAX_INT, player_ptr->au);
+ if (!gold) {
return;
}
player_ptr->au = gold.value();
if (PlayerRace(player_ptr).equals(PlayerRaceType::ANDROID)) {
- do_cmd_redraw(player_ptr);
return;
}
- const auto experience_opt = input_value("Experience: ", 0, MAX_INT, player_ptr->max_exp);
- if (!experience_opt.has_value()) {
+ const auto experience_opt = input_numerics("Experience: ", 0, MAX_INT, player_ptr->max_exp);
+ if (!experience_opt) {
return;
}
player_ptr->max_exp = experience;
player_ptr->exp = experience;
player_ptr->exp_frac = 0;
- check_experience(player_ptr);
- do_cmd_redraw(player_ptr);
}
/*!
return;
}
- auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
- const int max = terrains_info.size() - 1;
- const auto f_val1 = input_value(_("実地形ID", "FeatureID"), 0, max, g_ptr->feat);
- if (!f_val1.has_value()) {
+ const Pos2D pos(y, x);
+ auto &grid = player_ptr->current_floor_ptr->get_grid(pos);
+ const int max = TerrainList::get_instance().size() - 1;
+ const auto f_val1 = input_numerics(_("実地形ID", "FeatureID"), 0, max, grid.feat);
+ if (!f_val1) {
return;
}
- const auto f_val2 = input_value(_("偽装地形ID", "FeatureID"), 0, max, f_val1.value());
- if (!f_val2.has_value()) {
+ const auto f_val2 = input_numerics(_("偽装地形ID", "FeatureID"), 0, max, f_val1.value());
+ if (!f_val2) {
return;
}
cave_set_feat(player_ptr, y, x, f_val1.value());
- g_ptr->mimic = f_val2.value();
- auto *f_ptr = &terrains_info[g_ptr->get_feat_mimic()];
- if (f_ptr->flags.has(TerrainCharacteristics::RUNE_PROTECTION) || f_ptr->flags.has(TerrainCharacteristics::RUNE_EXPLOSION)) {
- g_ptr->info |= CAVE_OBJECT;
- } else if (f_ptr->flags.has(TerrainCharacteristics::MIRROR)) {
- g_ptr->info |= CAVE_GLOW | CAVE_OBJECT;
+ grid.mimic = f_val2.value();
+ const auto &terrain = grid.get_terrain_mimic();
+ if (terrain.flags.has(TerrainCharacteristics::RUNE_PROTECTION) || terrain.flags.has(TerrainCharacteristics::RUNE_EXPLOSION)) {
+ grid.info |= CAVE_OBJECT;
+ } else if (terrain.flags.has(TerrainCharacteristics::MIRROR)) {
+ grid.info |= CAVE_GLOW | CAVE_OBJECT;
}
note_spot(player_ptr, y, x);
}
while (true) {
- const auto dungeon_id = input_value("Jump which dungeon", DUNGEON_ANGBAND, DUNGEON_DARKNESS, initial_dungeon_id);
- if (!dungeon_id.has_value()) {
+ const auto dungeon_id = input_numerics("Jump which dungeon", DUNGEON_ANGBAND, DUNGEON_DARKNESS, initial_dungeon_id);
+ if (!dungeon_id) {
return std::nullopt;
}
}
/*
- * @brief é\81¸æ\8a\9eã\81\97ã\81\9fã\83\80ã\83³ã\82¸ã\83§ã\83³ã\81®ä»»æ\84\8fã\83\95ã\83ã\82¢を選択する
+ * @brief é\81¸æ\8a\9eã\81\97ã\81\9fã\83\80ã\83³ã\82¸ã\83§ã\83³ã\81®ä»»æ\84\8fã\83¬ã\83\99ã\83«を選択する
* @param player_ptr プレイヤーへの参照ポインタ
* @param dungeon_id ダンジョン番号
- * @return フロアを選択したらtrue、キャンセルならfalse
- * @details 0を指定すると地上に飛ぶが、元いた場所にしか飛ばない
- * @todo 可能ならダンジョンの入口 (例:ルルイエなら大洋の真ん中)へ飛べるようにしたい
+ * @return レベルを選択したらその値、キャンセルならnullopt
*/
static std::optional<int> select_debugging_floor(const FloorType &floor, int dungeon_id)
{
const auto &dungeon = dungeons_info[dungeon_id];
const auto max_depth = dungeon.maxdepth;
const auto min_depth = dungeon.mindepth;
+ const auto is_current_dungeon = floor.dungeon_idx == dungeon_id;
auto initial_depth = floor.dun_level;
- if (floor.dungeon_idx != dungeon_id) {
+ if (!is_current_dungeon) {
initial_depth = min_depth;
}
- return input_value("Jump to level", min_depth, max_depth, initial_depth);
+ return input_numerics("Jump to level", min_depth, max_depth, initial_depth);
}
/*!
void wiz_jump_to_dungeon(PlayerType *player_ptr)
{
const auto &floor = *player_ptr->current_floor_ptr;
- const auto dungeon_id_opt = select_debugging_dungeon(floor.dungeon_idx);
- if (!dungeon_id_opt.has_value()) {
+ const auto is_in_dungeon = floor.is_in_dungeon();
+ const auto dungeon_idx = is_in_dungeon ? floor.dungeon_idx : static_cast<short>(DUNGEON_ANGBAND);
+ const auto dungeon_id_opt = select_debugging_dungeon(dungeon_idx);
+ if (!dungeon_id_opt) {
+ if (!is_in_dungeon) {
+ return;
+ }
+
+ if (input_check(("Jump to the ground?"))) {
+ wiz_jump_floor(player_ptr, 0, 0);
+ }
+
return;
}
const auto dungeon_id = dungeon_id_opt.value();
- const auto level = select_debugging_floor(floor, dungeon_id);
- if (!level.has_value()) {
+ const auto level_opt = select_debugging_floor(floor, dungeon_id);
+ if (!level_opt) {
return;
}
- const auto &dungeon = dungeons_info[dungeon_id];
- command_arg = static_cast<short>(std::clamp(level.value(), dungeon.mindepth, dungeon.maxdepth));
- msg_format("You jump to dungeon level %d.", command_arg);
+ const auto level = level_opt.value();
+ msg_format("You jump to dungeon level %d.", level);
if (autosave_l) {
do_cmd_save_game(player_ptr, true);
}
- wiz_jump_floor(player_ptr, dungeon_id, command_arg);
+ wiz_jump_floor(player_ptr, dungeon_id, level);
}
/*!
*/
void wiz_reset_race(PlayerType *player_ptr)
{
- const auto new_race = input_value("RaceID", 0, MAX_RACES - 1, player_ptr->prace);
- if (!new_race.has_value()) {
+ const auto new_race = input_numerics("RaceID", 0, MAX_RACES - 1, player_ptr->prace);
+ if (!new_race) {
return;
}
*/
void wiz_reset_class(PlayerType *player_ptr)
{
- const auto new_class_opt = input_value("ClassID", 0, PLAYER_CLASS_TYPE_MAX - 1, player_ptr->pclass);
- if (!new_class_opt.has_value()) {
+ const auto new_class_opt = input_numerics("ClassID", 0, PLAYER_CLASS_TYPE_MAX - 1, player_ptr->pclass);
+ if (!new_class_opt) {
return;
}
*/
void wiz_reset_realms(PlayerType *player_ptr)
{
- const auto new_realm1 = input_value("1st Realm (None=0)", 0, MAX_REALM - 1, player_ptr->realm1);
- if (!new_realm1.has_value()) {
+ const auto new_realm1 = input_numerics("1st Realm (None=0)", 0, MAX_REALM - 1, player_ptr->realm1);
+ if (!new_realm1) {
return;
}
- const auto new_realm2 = input_value("2nd Realm (None=0)", 0, MAX_REALM - 1, player_ptr->realm2);
- if (!new_realm2.has_value()) {
+ const auto new_realm2 = input_numerics("2nd Realm (None=0)", 0, MAX_REALM - 1, player_ptr->realm2);
+ if (!new_realm2) {
return;
}
*/
void set_gametime(void)
{
- const auto game_time = input_value_int("Dungeon Turn", 0, w_ptr->dungeon_turn_limit - 1);
- if (!game_time.has_value()) {
+ const auto game_time = input_integer("Dungeon Turn", 0, w_ptr->dungeon_turn_limit - 1);
+ if (!game_time) {
return;
}
auto *floor_ptr = player_ptr->current_floor_ptr;
floor_ptr->dun_level = 0;
floor_ptr->inside_arena = false;
- player_ptr->phase_out = false;
+ AngbandSystem::get_instance().set_phase_out(false);
leaving_quest = QuestId::NONE;
floor_ptr->quest_number = QuestId::NONE;
if (floor_ptr->dungeon_idx) {