OSDN Git Service

[Refactor] #3286 Removed player-redraw-types.h
[hengbandforosx/hengbandosx.git] / src / core / object-compressor.cpp
1 #include "core/object-compressor.h"
2 #include "core/window-redrawer.h"
3 #include "floor/floor-object.h"
4 #include "floor/geometry.h"
5 #include "grid/grid.h"
6 #include "system/baseitem-info.h"
7 #include "system/floor-type-definition.h"
8 #include "system/item-entity.h"
9 #include "system/monster-entity.h"
10 #include "system/player-type-definition.h"
11 #include "system/redrawing-flags-updater.h"
12 #include "view/display-messages.h"
13 #include <algorithm>
14
15 /*!
16  * @brief グローバルオブジェクト配列の要素番号i1のオブジェクトを要素番号i2に移動する /
17  * Move an object from index i1 to index i2 in the object list
18  * @param i1 オブジェクト移動元の要素番号
19  * @param i2 オブジェクト移動先の要素番号
20  */
21 static void compact_objects_aux(FloorType *floor_ptr, OBJECT_IDX i1, OBJECT_IDX i2)
22 {
23     if (i1 == i2) {
24         return;
25     }
26
27     auto *o_ptr = &floor_ptr->o_list[i1];
28
29     // モンスター所為アイテムリストもしくは床上アイテムリストの要素番号i1をi2に書き換える
30     auto &list = get_o_idx_list_contains(floor_ptr, i1);
31     std::replace(list.begin(), list.end(), i1, i2);
32
33     // 要素番号i1のオブジェクトを要素番号i2に移動
34     floor_ptr->o_list[i2] = floor_ptr->o_list[i1];
35     o_ptr->wipe();
36 }
37
38 /*!
39  * @brief グローバルオブジェクト配列から優先度の低いものを削除し、データを圧縮する。 /
40  * Compact and Reorder the object list.
41  * @param player_ptr プレイヤーへの参照ポインタ
42  * @param size 最低でも減らしたいオブジェクト数の水準
43  * @details
44  * (危険なので使用には注意すること)
45  * This function can be very dangerous, use with caution!\n
46  *\n
47  * When actually "compacting" objects, we base the saving throw on a\n
48  * combination of object level, distance from player, and current\n
49  * "desperation".\n
50  *\n
51  * After "compacting" (if needed), we "reorder" the objects into a more\n
52  * compact order, and we reset the allocation info, and the "live" array.\n
53  */
54 void compact_objects(PlayerType *player_ptr, int size)
55 {
56     ItemEntity *o_ptr;
57     if (size) {
58         msg_print(_("アイテム情報を圧縮しています...", "Compacting objects..."));
59         auto &rfu = RedrawingFlagsUpdater::get_instance();
60         rfu.set_flag(MainWindowRedrawingFlag::MAP);
61         player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
62     }
63
64     auto *floor_ptr = player_ptr->current_floor_ptr;
65     for (int num = 0, cnt = 1; num < size; cnt++) {
66         int cur_lev = 5 * cnt;
67         int cur_dis = 5 * (20 - cnt);
68         for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) {
69             o_ptr = &floor_ptr->o_list[i];
70
71             if (!o_ptr->is_valid() || (o_ptr->get_baseitem().level > cur_lev)) {
72                 continue;
73             }
74
75             POSITION y, x;
76             if (o_ptr->is_held_by_monster()) {
77                 MonsterEntity *m_ptr;
78                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
79                 y = m_ptr->fy;
80                 x = m_ptr->fx;
81
82                 if (randint0(100) < 90) {
83                     continue;
84                 }
85             } else {
86                 y = o_ptr->iy;
87                 x = o_ptr->ix;
88             }
89
90             if ((cur_dis > 0) && (distance(player_ptr->y, player_ptr->x, y, x) < cur_dis)) {
91                 continue;
92             }
93
94             int chance = 90;
95             if (o_ptr->is_fixed_or_random_artifact() && (cnt < 1000)) {
96                 chance = 100;
97             }
98
99             if (randint0(100) < chance) {
100                 continue;
101             }
102
103             delete_object_idx(player_ptr, i);
104             num++;
105         }
106     }
107
108     for (OBJECT_IDX i = floor_ptr->o_max - 1; i >= 1; i--) {
109         o_ptr = &floor_ptr->o_list[i];
110         if (o_ptr->is_valid()) {
111             continue;
112         }
113
114         compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i);
115         floor_ptr->o_max--;
116     }
117 }