OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / floor / floor-object.cpp
index e035c85..5b57e57 100644 (file)
 #include "perception/object-perception.h"
 #include "system/alloc-entries.h"
 #include "system/artifact-type-definition.h"
-#include "system/baseitem-info-definition.h"
+#include "system/baseitem-info.h"
 #include "system/floor-type-definition.h"
 #include "system/grid-type-definition.h"
-#include "system/monster-type-definition.h"
-#include "system/object-type-definition.h"
+#include "system/item-entity.h"
+#include "system/monster-entity.h"
 #include "system/player-type-definition.h"
+#include "system/redrawing-flags-updater.h"
 #include "system/system-variables.h"
 #include "target/projection-path-calculator.h"
 #include "util/bit-flags-calculator.h"
  * @brief オブジェクト生成テーブルに生成制約を加える /
  * Apply a "object restriction function" to the "object allocation table"
  * @return 常に0を返す。
- * @details 生成の制約はグローバルのget_obj_num_hook関数ポインタで加える
+ * @details 生成の制約はグローバルのget_obj_index_hook関数ポインタで加える
  */
-static errr get_obj_num_prep(void)
+static errr get_obj_index_prep(void)
 {
     for (auto &entry : alloc_kind_table) {
-        if (!get_obj_num_hook || (*get_obj_num_hook)(entry.index)) {
+        if (!get_obj_index_hook || (*get_obj_index_hook)(entry.index)) {
             entry.prob2 = entry.prob1;
         } else {
             entry.prob2 = 0;
@@ -70,15 +71,14 @@ static errr get_obj_num_prep(void)
  * @param player_ptr プレイヤーへの参照ポインタ
  * @param o_ptr デバッグ出力するオブジェクトの構造体参照ポインタ
  */
-static void object_mention(PlayerType *player_ptr, ObjectType *o_ptr)
+static void object_mention(PlayerType *player_ptr, ItemEntity *o_ptr)
 {
     object_aware(player_ptr, o_ptr);
     object_known(o_ptr);
 
     o_ptr->ident |= (IDENT_FULL_KNOWN);
-    GAME_TEXT o_name[MAX_NLEN];
-    describe_flavor(player_ptr, o_name, o_ptr, 0);
-    msg_format_wizard(player_ptr, CHEAT_OBJECT, _("%sを生成しました。", "%s was generated."), o_name);
+    const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
+    msg_format_wizard(player_ptr, CHEAT_OBJECT, _("%sを生成しました。", "%s was generated."), item_name.data());
 }
 
 static int get_base_floor(FloorType *floor_ptr, BIT_FLAGS mode, std::optional<int> rq_mon_level)
@@ -98,12 +98,10 @@ static int get_base_floor(FloorType *floor_ptr, BIT_FLAGS mode, std::optional<in
     return floor_ptr->object_level;
 }
 
-static void set_ammo_quantity(ObjectType *j_ptr)
+static void set_ammo_quantity(ItemEntity *j_ptr)
 {
-    auto is_ammo = j_ptr->tval == ItemKindType::SPIKE;
-    is_ammo |= j_ptr->tval == ItemKindType::SHOT;
-    is_ammo |= j_ptr->tval == ItemKindType::ARROW;
-    is_ammo |= j_ptr->tval == ItemKindType::BOLT;
+    auto is_ammo = j_ptr->is_ammo();
+    is_ammo |= j_ptr->bi_key.tval() == ItemKindType::SPIKE;
     if (is_ammo && !j_ptr->is_fixed_artifact()) {
         j_ptr->number = damroll(6, 7);
     }
@@ -118,31 +116,31 @@ static void set_ammo_quantity(ObjectType *j_ptr)
  * @param rq_mon_level ランダムクエスト討伐対象のレベル。ランダムクエスト以外の生成であれば無効値
  * @return アイテムの生成成功可否
  */
-bool make_object(PlayerType *player_ptr, ObjectType *j_ptr, BIT_FLAGS mode, std::optional<int> rq_mon_level)
+bool make_object(PlayerType *player_ptr, ItemEntity *j_ptr, BIT_FLAGS mode, std::optional<int> rq_mon_level)
 {
     auto *floor_ptr = player_ptr->current_floor_ptr;
     auto prob = any_bits(mode, AM_GOOD) ? 10 : 1000;
     auto base = get_base_floor(floor_ptr, mode, rq_mon_level);
     if (!one_in_(prob) || !make_artifact_special(player_ptr, j_ptr)) {
-        if (any_bits(mode, AM_GOOD) && !get_obj_num_hook) {
-            get_obj_num_hook = kind_is_good;
+        if (any_bits(mode, AM_GOOD) && !get_obj_index_hook) {
+            get_obj_index_hook = kind_is_good;
         }
 
-        if (get_obj_num_hook) {
-            get_obj_num_prep();
+        if (get_obj_index_hook) {
+            get_obj_index_prep();
         }
 
-        auto k_idx = get_obj_num(player_ptr, base, mode);
-        if (get_obj_num_hook) {
-            get_obj_num_hook = nullptr;
-            get_obj_num_prep();
+        auto bi_id = get_obj_index(floor_ptr, base, mode);
+        if (get_obj_index_hook) {
+            get_obj_index_hook = nullptr;
+            get_obj_index_prep();
         }
 
-        if (k_idx == 0) {
+        if (bi_id == 0) {
             return false;
         }
 
-        j_ptr->prep(k_idx);
+        j_ptr->prep(bi_id);
     }
 
     ItemMagicApplier(player_ptr, j_ptr, floor_ptr->object_level, mode).execute();
@@ -163,7 +161,7 @@ bool make_object(PlayerType *player_ptr, ObjectType *j_ptr, BIT_FLAGS mode, std:
  * @details
  * The location must be a legal, clean, floor grid.
  */
-bool make_gold(PlayerType *player_ptr, ObjectType *j_ptr)
+bool make_gold(PlayerType *player_ptr, ItemEntity *j_ptr)
 {
     auto *floor_ptr = player_ptr->current_floor_ptr;
     int i = ((randint1(floor_ptr->object_level + 2) + 2) / 2) - 1;
@@ -202,7 +200,7 @@ void delete_all_items_from_floor(PlayerType *player_ptr, POSITION y, POSITION x)
 
     g_ptr = &floor_ptr->grid_array[y][x];
     for (const auto this_o_idx : g_ptr->o_idx_list) {
-        ObjectType *o_ptr;
+        ItemEntity *o_ptr;
         o_ptr = &floor_ptr->o_list[this_o_idx];
         o_ptr->wipe();
         floor_ptr->o_cnt--;
@@ -233,8 +231,11 @@ void floor_item_increase(PlayerType *player_ptr, INVENTORY_IDX item, ITEM_NUMBER
 
     num -= o_ptr->number;
     o_ptr->number += num;
-
-    set_bits(player_ptr->window_flags, PW_FLOOR_ITEM_LIST);
+    static constexpr auto flags = {
+        SubWindowRedrawingFlag::FLOOR_ITEMS,
+        SubWindowRedrawingFlag::FOUND_ITEMS,
+    };
+    RedrawingFlagsUpdater::get_instance().set_flags(flags);
 }
 
 /*!
@@ -246,7 +247,7 @@ void floor_item_increase(PlayerType *player_ptr, INVENTORY_IDX item, ITEM_NUMBER
 void floor_item_optimize(PlayerType *player_ptr, INVENTORY_IDX item)
 {
     auto *o_ptr = &player_ptr->current_floor_ptr->o_list[item];
-    if (!o_ptr->k_idx) {
+    if (!o_ptr->is_valid()) {
         return;
     }
     if (o_ptr->number) {
@@ -254,8 +255,11 @@ void floor_item_optimize(PlayerType *player_ptr, INVENTORY_IDX item)
     }
 
     delete_object_idx(player_ptr, item);
-
-    set_bits(player_ptr->window_flags, PW_FLOOR_ITEM_LIST);
+    static constexpr auto flags = {
+        SubWindowRedrawingFlag::FLOOR_ITEMS,
+        SubWindowRedrawingFlag::FOUND_ITEMS,
+    };
+    RedrawingFlagsUpdater::get_instance().set_flags(flags);
 }
 
 /*!
@@ -268,7 +272,7 @@ void floor_item_optimize(PlayerType *player_ptr, INVENTORY_IDX item)
  */
 void delete_object_idx(PlayerType *player_ptr, OBJECT_IDX o_idx)
 {
-    ObjectType *j_ptr;
+    ItemEntity *j_ptr;
     auto *floor_ptr = player_ptr->current_floor_ptr;
     excise_object_idx(floor_ptr, o_idx);
     j_ptr = &floor_ptr->o_list[o_idx];
@@ -281,8 +285,11 @@ void delete_object_idx(PlayerType *player_ptr, OBJECT_IDX o_idx)
 
     j_ptr->wipe();
     floor_ptr->o_cnt--;
-
-    set_bits(player_ptr->window_flags, PW_FLOOR_ITEM_LIST);
+    static constexpr auto flags = {
+        SubWindowRedrawingFlag::FLOOR_ITEMS,
+        SubWindowRedrawingFlag::FOUND_ITEMS,
+    };
+    RedrawingFlagsUpdater::get_instance().set_flags(flags);
 }
 
 /*!
@@ -336,26 +343,25 @@ ObjectIndexList &get_o_idx_list_contains(FloorType *floor_ptr, OBJECT_IDX o_idx)
  * the object can combine, stack, or be placed.  Artifacts will try very\n
  * hard to be placed, including "teleporting" to a useful grid if needed.\n
  */
-OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chance, POSITION y, POSITION x)
+OBJECT_IDX drop_near(PlayerType *player_ptr, ItemEntity *j_ptr, PERCENTAGE chance, POSITION y, POSITION x)
 {
     int i, k, d, s;
     POSITION dy, dx;
     POSITION ty, tx = 0;
     OBJECT_IDX o_idx = 0;
     grid_type *g_ptr;
-    GAME_TEXT o_name[MAX_NLEN];
     bool flag = false;
     bool done = false;
 #ifdef JP
 #else
     bool plural = (j_ptr->number != 1);
 #endif
-    describe_flavor(player_ptr, o_name, j_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
-    if (!j_ptr->is_artifact() && (randint0(100) < chance)) {
+    const auto item_name = describe_flavor(player_ptr, j_ptr, (OD_OMIT_PREFIX | OD_NAME_ONLY));
+    if (!j_ptr->is_fixed_or_random_artifact() && (randint0(100) < chance)) {
 #ifdef JP
-        msg_format("%sは消えた。", o_name);
+        msg_format("%sは消えた。", item_name.data());
 #else
-        msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
+        msg_format("The %s disappear%s.", item_name.data(), (plural ? "" : "s"));
 #endif
         if (w_ptr->wizard) {
             msg_print(_("(破損)", "(breakage)"));
@@ -394,7 +400,7 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
 
             k = 0;
             for (const auto this_o_idx : g_ptr->o_idx_list) {
-                ObjectType *o_ptr;
+                ItemEntity *o_ptr;
                 o_ptr = &floor_ptr->o_list[this_o_idx];
                 if (object_similar(o_ptr, j_ptr)) {
                     comb = true;
@@ -431,11 +437,11 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
         }
     }
 
-    if (!flag && !j_ptr->is_artifact()) {
+    if (!flag && !j_ptr->is_fixed_or_random_artifact()) {
 #ifdef JP
-        msg_format("%sは消えた。", o_name);
+        msg_format("%sは消えた。", item_name.data());
 #else
-        msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
+        msg_format("The %s disappear%s.", item_name.data(), (plural ? "" : "s"));
 #endif
         if (w_ptr->wizard) {
             msg_print(_("(床スペースがない)", "(no floor space)"));
@@ -462,6 +468,7 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
         flag = true;
     }
 
+    auto &artifact = j_ptr->get_fixed_artifact();
     if (!flag) {
         int candidates = 0, pick;
         for (ty = 1; ty < floor_ptr->height - 1; ty++) {
@@ -474,9 +481,9 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
 
         if (!candidates) {
 #ifdef JP
-            msg_format("%sは消えた。", o_name);
+            msg_format("%sは消えた。", item_name.data());
 #else
-            msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
+            msg_format("The %s disappear%s.", item_name.data(), (plural ? "" : "s"));
 #endif
 
             if (w_ptr->wizard) {
@@ -485,7 +492,7 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
 
             if (preserve_mode) {
                 if (j_ptr->is_fixed_artifact() && !j_ptr->is_known()) {
-                    artifacts_info.at(j_ptr->fixed_artifact_idx).is_generated = false;
+                    artifact.is_generated = false;
                 }
             }
 
@@ -514,7 +521,7 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
 
     g_ptr = &floor_ptr->grid_array[by][bx];
     for (const auto this_o_idx : g_ptr->o_idx_list) {
-        ObjectType *o_ptr;
+        ItemEntity *o_ptr;
         o_ptr = &floor_ptr->o_list[this_o_idx];
         if (object_similar(o_ptr, j_ptr)) {
             object_absorb(o_ptr, j_ptr);
@@ -529,16 +536,16 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
 
     if (!done && !o_idx) {
 #ifdef JP
-        msg_format("%sは消えた。", o_name);
+        msg_format("%sは消えた。", item_name.data());
 #else
-        msg_format("The %s disappear%s.", o_name, (plural ? "" : "s"));
+        msg_format("The %s disappear%s.", item_name.data(), (plural ? "" : "s"));
 #endif
         if (w_ptr->wizard) {
             msg_print(_("(アイテムが多過ぎる)", "(too many objects)"));
         }
 
         if (j_ptr->is_fixed_artifact()) {
-            artifacts_info.at(j_ptr->fixed_artifact_idx).is_generated = false;
+            artifact.is_generated = false;
         }
 
         return 0;
@@ -554,12 +561,20 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
         done = true;
     }
 
+    if (j_ptr->is_fixed_artifact() && w_ptr->character_dungeon) {
+        artifact.floor_id = player_ptr->floor_id;
+    }
+
     note_spot(player_ptr, by, bx);
     lite_spot(player_ptr, by, bx);
     sound(SOUND_DROP);
 
     if (player_bold(player_ptr, by, bx)) {
-        set_bits(player_ptr->window_flags, PW_FLOOR_ITEM_LIST);
+        static constexpr auto flags = {
+            SubWindowRedrawingFlag::FLOOR_ITEMS,
+            SubWindowRedrawingFlag::FOUND_ITEMS,
+        };
+        RedrawingFlagsUpdater::get_instance().set_flags(flags);
     }
 
     if (chance && player_bold(player_ptr, by, bx)) {
@@ -575,27 +590,24 @@ OBJECT_IDX drop_near(PlayerType *player_ptr, ObjectType *j_ptr, PERCENTAGE chanc
  * @param floo_ptr 現在フロアへの参照ポインタ
  * @param item メッセージの対象にしたいアイテム所持スロット
  */
-void floor_item_charges(FloorType *floor_ptr, INVENTORY_IDX item)
+void floor_item_charges(FloorType *floor_ptr, INVENTORY_IDX inventory)
 {
-    auto *o_ptr = &floor_ptr->o_list[item];
-    if ((o_ptr->tval != ItemKindType::STAFF) && (o_ptr->tval != ItemKindType::WAND)) {
-        return;
-    }
-    if (!o_ptr->is_known()) {
+    const auto &item = floor_ptr->o_list[inventory];
+    if (!item.is_wand_staff() || !item.is_known()) {
         return;
     }
 
 #ifdef JP
-    if (o_ptr->pval <= 0) {
+    if (item.pval <= 0) {
         msg_print("この床上のアイテムは、もう魔力が残っていない。");
     } else {
-        msg_format("この床上のアイテムは、あと %d 回分の魔力が残っている。", o_ptr->pval);
+        msg_format("この床上のアイテムは、あと %d 回分の魔力が残っている。", item.pval);
     }
 #else
-    if (o_ptr->pval != 1) {
-        msg_format("There are %d charges remaining.", o_ptr->pval);
+    if (item.pval != 1) {
+        msg_format("There are %d charges remaining.", item.pval);
     } else {
-        msg_format("There is %d charge remaining.", o_ptr->pval);
+        msg_format("There is %d charge remaining.", item.pval);
     }
 #endif
 }
@@ -609,23 +621,22 @@ void floor_item_charges(FloorType *floor_ptr, INVENTORY_IDX item)
 void floor_item_describe(PlayerType *player_ptr, INVENTORY_IDX item)
 {
     auto *o_ptr = &player_ptr->current_floor_ptr->o_list[item];
-    GAME_TEXT o_name[MAX_NLEN];
-    describe_flavor(player_ptr, o_name, o_ptr, 0);
+    const auto item_name = describe_flavor(player_ptr, o_ptr, 0);
 #ifdef JP
     if (o_ptr->number <= 0) {
-        msg_format("床上には、もう%sはない。", o_name);
+        msg_format("床上には、もう%sはない。", item_name.data());
     } else {
-        msg_format("床上には、まだ %sがある。", o_name);
+        msg_format("床上には、まだ %sがある。", item_name.data());
     }
 #else
-    msg_format("You see %s.", o_name);
+    msg_format("You see %s.", item_name.data());
 #endif
 }
 
 /*
  * Choose an item and get auto-picker entry from it.
  */
-ObjectType *choose_object(PlayerType *player_ptr, OBJECT_IDX *idx, concptr q, concptr s, BIT_FLAGS option, const ItemTester &item_tester)
+ItemEntity *choose_object(PlayerType *player_ptr, OBJECT_IDX *idx, concptr q, concptr s, BIT_FLAGS option, const ItemTester &item_tester)
 {
     OBJECT_IDX item;