OSDN Git Service

[Refactor] #2628 Renamed object-type-definition.cpp/h to item-entity.cpp/h
[hengbandforosx/hengbandosx.git] / src / dungeon / quest-monster-placer.cpp
1 #include "dungeon/quest-monster-placer.h"
2 #include "dungeon/quest.h"
3 #include "floor/floor-generator-util.h"
4 #include "floor/geometry.h"
5 #include "monster-floor/monster-generator.h"
6 #include "monster-floor/place-monster-types.h"
7 #include "monster-race/monster-race.h"
8 #include "monster-race/race-flags1.h"
9 #include "monster/monster-info.h"
10 #include "system/floor-type-definition.h"
11 #include "system/grid-type-definition.h"
12 #include "system/monster-race-definition.h"
13 #include "system/player-type-definition.h"
14 #include "system/terrain-type-definition.h"
15 #include "util/bit-flags-calculator.h"
16
17 /*!
18  * @brief クエストに関わるモンスターの配置を行う / Place quest monsters
19  * @param player_ptr プレイヤーへの参照ポインタ
20  * @return 成功したならばTRUEを返す
21  */
22 bool place_quest_monsters(PlayerType *player_ptr)
23 {
24     auto *floor_ptr = player_ptr->current_floor_ptr;
25     const auto &quest_list = QuestList::get_instance();
26     for (const auto &[q_idx, q_ref] : quest_list) {
27         MonsterRaceInfo *r_ptr;
28         BIT_FLAGS mode;
29
30         auto no_quest_monsters = q_ref.status != QuestStatusType::TAKEN;
31         no_quest_monsters |= (q_ref.type != QuestKindType::KILL_LEVEL && q_ref.type != QuestKindType::RANDOM);
32         no_quest_monsters |= q_ref.level != floor_ptr->dun_level;
33         no_quest_monsters |= player_ptr->dungeon_idx != q_ref.dungeon;
34         no_quest_monsters |= any_bits(q_ref.flags, QUEST_FLAG_PRESET);
35
36         if (no_quest_monsters) {
37             continue;
38         }
39
40         r_ptr = &monraces_info[q_ref.r_idx];
41         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && (r_ptr->cur_num >= r_ptr->max_num)) {
42             continue;
43         }
44
45         mode = PM_NO_KAGE | PM_NO_PET;
46         if (!(r_ptr->flags1 & RF1_FRIENDS)) {
47             mode |= PM_ALLOW_GROUP;
48         }
49
50         for (int j = 0; j < (q_ref.max_num - q_ref.cur_num); j++) {
51             int k;
52             for (k = 0; k < SAFE_MAX_ATTEMPTS; k++) {
53                 POSITION x = 0;
54                 POSITION y = 0;
55                 int l;
56                 for (l = SAFE_MAX_ATTEMPTS; l > 0; l--) {
57                     grid_type *g_ptr;
58                     TerrainType *f_ptr;
59                     y = randint0(floor_ptr->height);
60                     x = randint0(floor_ptr->width);
61                     g_ptr = &floor_ptr->grid_array[y][x];
62                     f_ptr = &terrains_info[g_ptr->feat];
63                     if (f_ptr->flags.has_none_of({ TerrainCharacteristics::MOVE, TerrainCharacteristics::CAN_FLY })) {
64                         continue;
65                     }
66
67                     if (!monster_can_enter(player_ptr, y, x, r_ptr, 0)) {
68                         continue;
69                     }
70
71                     if (distance(y, x, player_ptr->y, player_ptr->x) < 10) {
72                         continue;
73                     }
74
75                     if (g_ptr->is_icky()) {
76                         continue;
77                     } else {
78                         break;
79                     }
80                 }
81
82                 if (l == 0) {
83                     return false;
84                 }
85
86                 if (place_monster_aux(player_ptr, 0, y, x, q_ref.r_idx, mode)) {
87                     break;
88                 } else {
89                     continue;
90                 }
91             }
92
93             if (k == SAFE_MAX_ATTEMPTS) {
94                 return false;
95             }
96         }
97     }
98
99     return true;
100 }