OSDN Git Service

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