1 #include "monster/monster-compaction.h"
2 #include "core/stuff-handler.h"
3 #include "game-option/play-record-options.h"
4 #include "io/write-diary.h"
5 #include "monster-floor/monster-remover.h"
6 #include "monster-race/monster-race.h"
7 #include "monster-race/race-flags1.h"
8 #include "monster/monster-describer.h"
9 #include "monster/monster-description-types.h"
10 #include "monster/monster-info.h"
11 #include "monster/monster-status.h"
12 #include "system/floor-type-definition.h"
13 #include "system/grid-type-definition.h"
14 #include "system/monster-race-definition.h"
15 #include "system/monster-type-definition.h"
16 #include "system/object-type-definition.h"
17 #include "system/player-type-definition.h"
18 #include "target/target-checker.h"
19 #include "view/display-messages.h"
22 * @brief モンスター情報を配列内移動する / Move an object from index i1 to index i2 in the object list
23 * @param player_ptr プレイヤーへの参照ポインタ
27 static void compact_monsters_aux(PlayerType *player_ptr, MONSTER_IDX i1, MONSTER_IDX i2)
32 auto *floor_ptr = player_ptr->current_floor_ptr;
34 m_ptr = &floor_ptr->m_list[i1];
36 POSITION y = m_ptr->fy;
37 POSITION x = m_ptr->fx;
39 g_ptr = &floor_ptr->grid_array[y][x];
42 for (const auto this_o_idx : m_ptr->hold_o_idx_list) {
44 o_ptr = &floor_ptr->o_list[this_o_idx];
45 o_ptr->held_m_idx = i2;
51 if (player_ptr->pet_t_m_idx == i1)
52 player_ptr->pet_t_m_idx = i2;
53 if (player_ptr->riding_t_m_idx == i1)
54 player_ptr->riding_t_m_idx = i2;
56 if (player_ptr->riding == i1)
57 player_ptr->riding = i2;
59 if (player_ptr->health_who == i1)
60 health_track(player_ptr, i2);
63 for (int i = 1; i < floor_ptr->m_max; i++) {
64 monster_type *m2_ptr = &floor_ptr->m_list[i];
66 if (m2_ptr->parent_m_idx == i1)
67 m2_ptr->parent_m_idx = i2;
71 floor_ptr->m_list[i2] = floor_ptr->m_list[i1];
72 floor_ptr->m_list[i1] = {};
74 for (int i = 0; i < MAX_MTIMED; i++) {
75 int mproc_idx = get_mproc_idx(floor_ptr, i1, i);
77 floor_ptr->mproc_list[i][mproc_idx] = i2;
82 * @brief モンスター情報配列を圧縮する / Compact and Reorder the monster list
83 * @param player_ptr プレイヤーへの参照ポインタ
84 * @param size 圧縮後のモンスター件数目標
86 * This function can be very dangerous, use with caution!
88 * When actually "compacting" monsters, we base the saving throw
89 * on a combination of monster level, distance from player, and
90 * current "desperation".
92 * After "compacting" (if needed), we "reorder" the monsters into a more
93 * compact order, and we reset the allocation info, and the "live" array.
95 void compact_monsters(PlayerType *player_ptr, int size)
98 msg_print(_("モンスター情報を圧縮しています...", "Compacting monsters..."));
100 /* Compact at least 'size' objects */
101 auto *floor_ptr = player_ptr->current_floor_ptr;
102 for (int num = 0, cnt = 1; num < size; cnt++) {
103 int cur_lev = 5 * cnt;
104 int cur_dis = 5 * (20 - cnt);
105 for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
106 auto *m_ptr = &floor_ptr->m_list[i];
107 auto *r_ptr = &r_info[m_ptr->r_idx];
108 if (!monster_is_valid(m_ptr))
110 if (r_ptr->level > cur_lev)
112 if (i == player_ptr->riding)
114 if ((cur_dis > 0) && (m_ptr->cdis < cur_dis))
118 if ((r_ptr->flags1 & (RF1_QUESTOR)) && (cnt < 1000))
121 if (r_ptr->flags1 & (RF1_UNIQUE))
124 if (randint0(100) < chance)
127 if (record_named_pet && is_pet(m_ptr) && m_ptr->nickname) {
128 GAME_TEXT m_name[MAX_NLEN];
129 monster_desc(player_ptr, m_name, m_ptr, MD_INDEF_VISIBLE);
130 exe_write_diary(player_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_COMPACT, m_name);
133 delete_monster_idx(player_ptr, i);
138 /* Excise dead monsters (backwards!) */
139 for (MONSTER_IDX i = floor_ptr->m_max - 1; i >= 1; i--) {
140 auto *m_ptr = &floor_ptr->m_list[i];
143 compact_monsters_aux(player_ptr, floor_ptr->m_max - 1, i);