OSDN Git Service

Merge branch 'master' of git.osdn.net:/gitroot/hengband/hengband
[hengband/hengband.git] / src / core / object-compressor.c
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 "grid/grid.h"
6 #include "object-hook/hook-checker.h"
7 #include "object-hook/hook-enchant.h"
8 #include "object/object-generator.h"
9 #include "object/object-kind.h"
10 #include "system/floor-type-definition.h"
11 #include "system/monster-type-definition.h"
12 #include "system/object-type-definition.h"
13 #include "view/display-messages.h"
14
15 /*!
16  * @brief \83O\83\8d\81[\83o\83\8b\83I\83u\83W\83F\83N\83g\94z\97ñ\82É\91Î\82µ\8ew\92è\94Í\88Í\82Ì\83I\83u\83W\83F\83N\83g\82ð\90®\97\9d\82µ\82ÄID\82Ì\8eá\82¢\8f\87\82É\8añ\82¹\82é /
17  * Move an object from index i1 to index i2 in the object list
18  * @param i1 \90®\97\9d\82µ\82½\82¢\94z\97ñ\82Ì\8en\93_
19  * @param i2 \90®\97\9d\82µ\82½\82¢\94z\97ñ\82Ì\8fI\93_
20  * @return \82È\82µ
21  */
22 static void compact_objects_aux(floor_type *floor_ptr, OBJECT_IDX i1, OBJECT_IDX i2)
23 {
24     if (i1 == i2)
25         return;
26
27     object_type *o_ptr;
28     for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) {
29         o_ptr = &floor_ptr->o_list[i];
30         if (!o_ptr->k_idx)
31             continue;
32
33         if (o_ptr->next_o_idx == i1)
34             o_ptr->next_o_idx = i2;
35     }
36
37     o_ptr = &floor_ptr->o_list[i1];
38
39     if (object_is_held_monster(o_ptr)) {
40         monster_type *m_ptr;
41         m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
42         if (m_ptr->hold_o_idx == i1)
43             m_ptr->hold_o_idx = i2;
44     } else {
45         POSITION y = o_ptr->iy;
46         POSITION x = o_ptr->ix;
47         grid_type *g_ptr;
48         g_ptr = &floor_ptr->grid_array[y][x];
49         if (g_ptr->o_idx == i1)
50             g_ptr->o_idx = i2;
51     }
52
53     floor_ptr->o_list[i2] = floor_ptr->o_list[i1];
54     object_wipe(o_ptr);
55 }
56
57 /*!
58  * @brief \83O\83\8d\81[\83o\83\8b\83I\83u\83W\83F\83N\83g\94z\97ñ\82©\82ç\97D\90æ\93x\82Ì\92á\82¢\82à\82Ì\82ð\8dí\8f\9c\82µ\81A\83f\81[\83^\82ð\88³\8fk\82·\82é\81B /
59  * Compact and Reorder the object list.
60  * @param player_ptr \83v\83\8c\81[\83\84\81[\82Ö\82Ì\8eQ\8fÆ\83|\83C\83\93\83^
61  * @param size \8dÅ\92á\82Å\82à\8c¸\82ç\82µ\82½\82¢\83I\83u\83W\83F\83N\83g\90\94\82Ì\90\85\8f\80
62  * @return \82È\82µ
63  * @details
64  * \81i\8aë\8c¯\82È\82Ì\82Å\8eg\97p\82É\82Í\92\8d\88Ó\82·\82é\82±\82Æ\81j
65  * This function can be very dangerous, use with caution!\n
66  *\n
67  * When actually "compacting" objects, we base the saving throw on a\n
68  * combination of object level, distance from player, and current\n
69  * "desperation".\n
70  *\n
71  * After "compacting" (if needed), we "reorder" the objects into a more\n
72  * compact order, and we reset the allocation info, and the "live" array.\n
73  */
74 void compact_objects(player_type *player_ptr, int size)
75 {
76     object_type *o_ptr;
77     if (size) {
78         msg_print(_("\83A\83C\83e\83\80\8fî\95ñ\82ð\88³\8fk\82µ\82Ä\82¢\82Ü\82·...", "Compacting objects..."));
79         player_ptr->redraw |= PR_MAP;
80         player_ptr->window |= PW_OVERHEAD | PW_DUNGEON;
81     }
82
83     floor_type *floor_ptr = player_ptr->current_floor_ptr;
84     for (int num = 0, cnt = 1; num < size; cnt++) {
85         int cur_lev = 5 * cnt;
86         int cur_dis = 5 * (20 - cnt);
87         for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) {
88             o_ptr = &floor_ptr->o_list[i];
89
90             if (!object_is_valid(o_ptr) || (k_info[o_ptr->k_idx].level > cur_lev))
91                 continue;
92
93             POSITION y, x;
94             if (object_is_held_monster(o_ptr)) {
95                 monster_type *m_ptr;
96                 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
97                 y = m_ptr->fy;
98                 x = m_ptr->fx;
99
100                 if (randint0(100) < 90)
101                     continue;
102             } else {
103                 y = o_ptr->iy;
104                 x = o_ptr->ix;
105             }
106
107             if ((cur_dis > 0) && (distance(player_ptr->y, player_ptr->x, y, x) < cur_dis))
108                 continue;
109
110             int chance = 90;
111             if ((object_is_fixed_artifact(o_ptr) || o_ptr->art_name) && (cnt < 1000))
112                 chance = 100;
113
114             if (randint0(100) < chance)
115                 continue;
116
117             delete_object_idx(player_ptr, i);
118             num++;
119         }
120     }
121
122     for (OBJECT_IDX i = floor_ptr->o_max - 1; i >= 1; i--) {
123         o_ptr = &floor_ptr->o_list[i];
124         if (o_ptr->k_idx)
125             continue;
126
127         compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i);
128         floor_ptr->o_max--;
129     }
130 }