OSDN Git Service

[Fix]アリーナの出口が開く条件がおかしいのを修正
[hengbandforosx/hengbandosx.git] / src / cmd-building / cmd-building.cpp
index e6b4967..617ef99 100644 (file)
@@ -55,6 +55,8 @@
 #include "spell-kind/spells-perception.h"
 #include "spell-kind/spells-world.h"
 #include "spell/spells-status.h"
+#include "system/angband-exceptions.h"
+#include "system/angband-system.h"
 #include "system/building-type-definition.h"
 #include "system/floor-type-definition.h"
 #include "system/grid-type-definition.h"
@@ -88,174 +90,179 @@ static void town_history(PlayerType *player_ptr)
 }
 
 /*!
- * @brief 施設の処理実行メインルーチン / Execute a building command
+ * @brief 施設の処理実行メインルーチン
  * @param player_ptr プレイヤーへの参照ポインタ
  * @param bldg 施設構造体の参照ポインタ
  * @param i 実行したい施設のサービステーブルの添字
+ * @return 施設から別フロアへ移動するか否か (アリーナ/モンスター闘技場のみtrue)
  */
-static void bldg_process_command(PlayerType *player_ptr, building_type *bldg, int i)
+static bool bldg_process_command(PlayerType *player_ptr, building_type *bldg, int i)
 {
     msg_flag = false;
     msg_erase();
-
-    PRICE bcost;
-    if (is_owner(player_ptr, bldg)) {
-        bcost = bldg->member_costs[i];
-    } else {
-        bcost = bldg->other_costs[i];
-    }
-
-    /* action restrictions */
     const auto can_be_owner = is_owner(player_ptr, bldg);
+    const auto building_cost = can_be_owner ? bldg->member_costs[i] : bldg->other_costs[i];
     if (((bldg->action_restr[i] == 1) && !is_member(player_ptr, bldg)) || ((bldg->action_restr[i] == 2) && !can_be_owner)) {
         msg_print(_("それを選択する権利はありません!", "You have no right to choose that!"));
-        return;
+        return false;
     }
 
-    auto bact = bldg->actions[i];
-    if ((bact != BACT_RECHARGE) && (((bldg->member_costs[i] > player_ptr->au) && can_be_owner) || ((bldg->other_costs[i] > player_ptr->au) && !can_be_owner))) {
+    const auto building_action = bldg->actions[i];
+    if ((building_action != BACT_RECHARGE) && (((bldg->member_costs[i] > player_ptr->au) && can_be_owner) || ((bldg->other_costs[i] > player_ptr->au) && !can_be_owner))) {
         msg_print(_("お金が足りません!", "You do not have the gold!"));
-        return;
+        return false;
     }
 
-    bool paid = false;
-    switch (bact) {
+    switch (building_action) {
     case BACT_NOTHING:
         /* Do nothing */
-        break;
+        return false;
     case BACT_RESEARCH_ITEM:
-        paid = identify_fully(player_ptr, false);
-        break;
+        if (identify_fully(player_ptr, false)) {
+            player_ptr->au -= building_cost;
+        }
+
+        return false;
     case BACT_TOWN_HISTORY:
         town_history(player_ptr);
-        break;
+        return false;
     case BACT_RACE_LEGENDS:
         race_legends(player_ptr);
-        break;
+        return false;
     case BACT_QUEST:
         castle_quest(player_ptr);
-        break;
+        return false;
     case BACT_KING_LEGENDS:
     case BACT_ARENA_LEGENDS:
     case BACT_LEGENDS:
         show_highclass(player_ptr);
-        break;
+        return false;
     case BACT_POSTER:
     case BACT_ARENA_RULES:
     case BACT_ARENA:
-        arena_comm(player_ptr, bact);
-        break;
+        return arena_comm(player_ptr, building_action);
     case BACT_IN_BETWEEN:
     case BACT_CRAPS:
     case BACT_SPIN_WHEEL:
     case BACT_DICE_SLOTS:
     case BACT_GAMBLE_RULES:
     case BACT_POKER:
-        gamble_comm(player_ptr, bact);
-        break;
+        gamble_comm(player_ptr, building_action);
+        return false;
     case BACT_REST:
     case BACT_RUMORS:
     case BACT_FOOD:
-        paid = inn_comm(player_ptr, bact);
-        break;
+        if (inn_comm(player_ptr, building_action)) {
+            player_ptr->au -= building_cost;
+        }
+
+        return false;
     case BACT_RESEARCH_MONSTER:
-        paid = research_mon(player_ptr);
-        break;
+        if (research_mon(player_ptr)) {
+            player_ptr->au -= building_cost;
+        }
+
+        return false;
     case BACT_COMPARE_WEAPONS:
-        paid = true;
-        bcost = compare_weapons(player_ptr, bcost);
-        break;
+        player_ptr->au -= compare_weapons(player_ptr, building_cost);
+        return false;
     case BACT_ENCHANT_WEAPON:
-        enchant_item(player_ptr, bcost, 1, 1, 0, FuncItemTester(&ItemEntity::allow_enchant_melee_weapon));
-        break;
+        enchant_item(player_ptr, building_cost, 1, 1, 0, FuncItemTester(&ItemEntity::allow_enchant_melee_weapon));
+        return false;
     case BACT_ENCHANT_ARMOR:
-        enchant_item(player_ptr, bcost, 0, 0, 1, FuncItemTester(&ItemEntity::is_protector));
-        break;
+        enchant_item(player_ptr, building_cost, 0, 0, 1, FuncItemTester(&ItemEntity::is_protector));
+        return false;
     case BACT_RECHARGE:
         building_recharge(player_ptr);
-        break;
+        return false;
     case BACT_RECHARGE_ALL:
         building_recharge_all(player_ptr);
-        break;
+        return false;
     case BACT_IDENTS:
         if (!input_check(_("持ち物を全て鑑定してよろしいですか?", "Do you pay to identify all your possession? "))) {
-            break;
+            return false;
         }
+
         identify_pack(player_ptr);
         msg_print(_(" 持ち物全てが鑑定されました。", "Your possessions have been identified."));
-        paid = true;
-        break;
+        player_ptr->au -= building_cost;
+        return false;
     case BACT_IDENT_ONE:
-        paid = ident_spell(player_ptr, false);
-        break;
+        if (ident_spell(player_ptr, false)) {
+            player_ptr->au -= building_cost;
+        }
+
+        return false;
     case BACT_LEARN:
         do_cmd_study(player_ptr);
-        break;
+        return false;
     case BACT_HEALING:
-        paid = cure_critical_wounds(player_ptr, 200);
-        break;
+        if (cure_critical_wounds(player_ptr, 200)) {
+            player_ptr->au -= building_cost;
+        }
+
+        return false;
     case BACT_RESTORE:
-        paid = restore_all_status(player_ptr);
-        break;
+        if (restore_all_status(player_ptr)) {
+            player_ptr->au -= building_cost;
+        }
+
+        return false;
     case BACT_ENCHANT_ARROWS:
-        enchant_item(player_ptr, bcost, 1, 1, 0, FuncItemTester(&ItemEntity::is_ammo));
-        break;
+        enchant_item(player_ptr, building_cost, 1, 1, 0, FuncItemTester(&ItemEntity::is_ammo));
+        return false;
     case BACT_ENCHANT_BOW:
-        enchant_item(player_ptr, bcost, 1, 1, 0, TvalItemTester(ItemKindType::BOW));
-        break;
-
+        enchant_item(player_ptr, building_cost, 1, 1, 0, TvalItemTester(ItemKindType::BOW));
+        return false;
     case BACT_RECALL:
         if (recall_player(player_ptr, 1)) {
-            paid = true;
+            player_ptr->au -= building_cost;
         }
-        break;
 
+        return false;
     case BACT_TELEPORT_LEVEL:
         screen_save();
         clear_bldg(4, 20);
-        paid = free_level_recall(player_ptr);
-        screen_load();
-        break;
+        if (free_level_recall(player_ptr)) {
+            player_ptr->au -= building_cost;
+        }
 
+        screen_load();
+        return false;
     case BACT_LOSE_MUTATION: {
         auto muta = player_ptr->muta;
         if (player_ptr->ppersonality == PERSONALITY_LUCKY) {
             // ラッキーマンの白オーラは突然変異治療の対象外
             muta.reset(PlayerMutationType::GOOD_LUCK);
         }
+
         if (muta.any()) {
             while (!lose_mutation(player_ptr, 0)) {
                 ;
             }
-            paid = true;
-            break;
+
+            player_ptr->au -= building_cost;
+            return false;
         }
 
         msg_print(_("治すべき突然変異が無い。", "You have no mutations."));
         msg_print(nullptr);
-        break;
+        return false;
     }
-
     case BACT_BATTLE:
-        monster_arena_comm(player_ptr);
-        break;
-
+        return monster_arena_comm(player_ptr);
     case BACT_TSUCHINOKO:
         tsuchinoko();
-        break;
-
+        return false;
     case BACT_BOUNTY:
         show_bounty();
-        break;
-
+        return false;
     case BACT_TARGET:
         today_target(player_ptr);
-        break;
-
+        return false;
     case BACT_KANKIN:
         exchange_cash(player_ptr);
-        break;
-
+        return false;
     case BACT_HEIKOUKA:
         msg_print(_("平衡化の儀式を行なった。", "You received an equalization ritual."));
         set_virtue(player_ptr, Virtue::COMPASSION, 0);
@@ -277,25 +284,26 @@ static void bldg_process_command(PlayerType *player_ptr, building_type *bldg, in
         set_virtue(player_ptr, Virtue::VALOUR, 0);
         set_virtue(player_ptr, Virtue::INDIVIDUALISM, 0);
         initialize_virtues(player_ptr);
-        paid = true;
-        break;
-
+        player_ptr->au -= building_cost;
+        return false;
     case BACT_TELE_TOWN:
-        paid = tele_town(player_ptr);
-        break;
+        if (!tele_town(player_ptr)) {
+            return false;
+        }
 
+        player_ptr->au -= building_cost;
+        return true;
     case BACT_EVAL_AC:
-        paid = eval_ac(player_ptr->dis_ac + player_ptr->dis_to_a);
-        break;
+        if (eval_ac(player_ptr->dis_ac + player_ptr->dis_to_a)) {
+            player_ptr->au -= building_cost;
+        }
 
+        return false;
     case BACT_BROKEN_WEAPON:
-        paid = true;
-        bcost = repair_broken_weapon(player_ptr, bcost);
-        break;
-    }
-
-    if (paid) {
-        player_ptr->au -= bcost;
+        player_ptr->au -= repair_broken_weapon(player_ptr, building_cost);
+        return false;
+    default:
+        THROW_EXCEPTION(std::logic_error, "Invalid building action is specified!");
     }
 }
 
@@ -311,15 +319,13 @@ void do_cmd_building(PlayerType *player_ptr)
 
     PlayerEnergy energy(player_ptr);
     energy.set_player_turn_energy(100);
-
-    if (!cave_has_flag_bold(player_ptr->current_floor_ptr, player_ptr->y, player_ptr->x, TerrainCharacteristics::BLDG)) {
+    const auto p_pos = player_ptr->get_position();
+    if (!cave_has_flag_bold(player_ptr->current_floor_ptr, p_pos.y, p_pos.x, TerrainCharacteristics::BLDG)) {
         msg_print(_("ここには建物はない。", "You see no building here."));
         return;
     }
 
-    TermCenteredOffsetSetter tcos(MAIN_TERM_MIN_COLS, MAIN_TERM_MIN_ROWS);
-
-    int which = terrains_info[player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].feat].subtype;
+    int which = player_ptr->current_floor_ptr->get_grid(p_pos).get_terrain().subtype;
 
     building_type *bldg;
     bldg = &buildings[which];
@@ -329,8 +335,10 @@ void do_cmd_building(PlayerType *player_ptr)
     if ((which == 2) && (player_ptr->arena_number < 0)) {
         msg_print(_("「敗者に用はない。」", "'There's no place here for a LOSER like you!'"));
         return;
-    } else if ((which == 2) && player_ptr->current_floor_ptr->inside_arena) {
-        if (!player_ptr->exit_bldg && player_ptr->current_floor_ptr->m_cnt > 0) {
+    }
+
+    if ((which == 2) && player_ptr->current_floor_ptr->inside_arena) {
+        if (!w_ptr->get_arena() && player_ptr->current_floor_ptr->m_cnt > 0) {
             prt(_("ゲートは閉まっている。モンスターがあなたを待っている!", "The gates are closed.  The monster awaits!"), 0, 0);
         } else {
             prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS | CFM_NO_RETURN);
@@ -341,18 +349,22 @@ void do_cmd_building(PlayerType *player_ptr)
         }
 
         return;
-    } else if (player_ptr->phase_out) {
+    }
+
+    TermCenteredOffsetSetter tcos(MAIN_TERM_MIN_COLS, MAIN_TERM_MIN_ROWS);
+
+    auto &system = AngbandSystem::get_instance();
+    if (system.is_phase_out()) {
         prepare_change_floor_mode(player_ptr, CFM_SAVE_FLOORS | CFM_NO_RETURN);
         player_ptr->leaving = true;
-        player_ptr->phase_out = false;
+        system.set_phase_out(false);
         command_new = SPECIAL_KEY_BUILDING;
         energy.reset_player_turn();
         return;
-    } else {
-        player_ptr->oldpy = player_ptr->y;
-        player_ptr->oldpx = player_ptr->x;
     }
 
+    player_ptr->oldpy = player_ptr->y;
+    player_ptr->oldpx = player_ptr->x;
     forget_lite(player_ptr->current_floor_ptr);
     forget_view(player_ptr->current_floor_ptr);
     w_ptr->character_icky_depth++;
@@ -362,38 +374,32 @@ void do_cmd_building(PlayerType *player_ptr)
     command_new = 0;
 
     display_buikding_service(player_ptr, bldg);
-    player_ptr->leave_bldg = false;
     play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_BUILD);
 
-    bool validcmd;
-    while (!player_ptr->leave_bldg) {
-        validcmd = false;
+    while (true) {
         prt("", 1, 0);
-
         building_prt_gold(player_ptr);
-
-        char command = inkey();
-
+        const auto command = inkey();
         if (command == ESCAPE) {
-            player_ptr->leave_bldg = true;
             player_ptr->current_floor_ptr->inside_arena = false;
-            player_ptr->phase_out = false;
+            system.set_phase_out(false);
             break;
         }
 
+        auto is_valid_command = false;
         int i;
         for (i = 0; i < 8; i++) {
             if (bldg->letters[i] && (bldg->letters[i] == command)) {
-                validcmd = true;
+                is_valid_command = true;
                 break;
             }
         }
 
-        if (validcmd) {
-            bldg_process_command(player_ptr, bldg, i);
-        }
-
+        const auto should_leave = is_valid_command ? bldg_process_command(player_ptr, bldg, i) : false;
         handle_stuff(player_ptr);
+        if (should_leave) {
+            break;
+        }
     }
 
     select_floor_music(player_ptr);