OSDN Git Service

1479602981465790932752560d7674d8ae9bfe2c
[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 "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         player_ptr->redraw |= PR_MAP;
60         player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
61     }
62
63     auto *floor_ptr = player_ptr->current_floor_ptr;
64     for (int num = 0, cnt = 1; num < size; cnt++) {
65         int cur_lev = 5 * cnt;
66         int cur_dis = 5 * (20 - cnt);
67         for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) {
68             o_ptr = &floor_ptr->o_list[i];
69
70             if (!o_ptr->is_valid() || (o_ptr->get_baseitem().level > cur_lev)) {
71                 continue;
72             }
73
74             POSITION y, x;
75             if (o_ptr->is_held_by_monster()) {
76                 MonsterEntity *m_ptr;
77                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
78                 y = m_ptr->fy;
79                 x = m_ptr->fx;
80
81                 if (randint0(100) < 90) {
82                     continue;
83                 }
84             } else {
85                 y = o_ptr->iy;
86                 x = o_ptr->ix;
87             }
88
89             if ((cur_dis > 0) && (distance(player_ptr->y, player_ptr->x, y, x) < cur_dis)) {
90                 continue;
91             }
92
93             int chance = 90;
94             if (o_ptr->is_fixed_or_random_artifact() && (cnt < 1000)) {
95                 chance = 100;
96             }
97
98             if (randint0(100) < chance) {
99                 continue;
100             }
101
102             delete_object_idx(player_ptr, i);
103             num++;
104         }
105     }
106
107     for (OBJECT_IDX i = floor_ptr->o_max - 1; i >= 1; i--) {
108         o_ptr = &floor_ptr->o_list[i];
109         if (o_ptr->is_valid()) {
110             continue;
111         }
112
113         compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i);
114         floor_ptr->o_max--;
115     }
116 }