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-info.h"
13 #include "system/player-type-definition.h"
14 #include "system/terrain-type-definition.h"
15 #include "util/bit-flags-calculator.h"
18 * @brief クエストに関わるモンスターの配置を行う / Place quest monsters
19 * @param player_ptr プレイヤーへの参照ポインタ
20 * @return 成功したならばTRUEを返す
22 bool place_quest_monsters(PlayerType *player_ptr)
24 auto *floor_ptr = player_ptr->current_floor_ptr;
25 const auto &quest_list = QuestList::get_instance();
26 for (const auto &[q_idx, quest] : quest_list) {
27 MonsterRaceInfo *r_ptr;
30 auto no_quest_monsters = quest.status != QuestStatusType::TAKEN;
31 no_quest_monsters |= (quest.type != QuestKindType::KILL_LEVEL && quest.type != QuestKindType::RANDOM);
32 no_quest_monsters |= quest.level != floor_ptr->dun_level;
33 no_quest_monsters |= floor_ptr->dungeon_idx != quest.dungeon;
34 no_quest_monsters |= any_bits(quest.flags, QUEST_FLAG_PRESET);
36 if (no_quest_monsters) {
40 r_ptr = &monraces_info[quest.r_idx];
41 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && (r_ptr->cur_num >= r_ptr->max_num)) {
45 mode = PM_NO_KAGE | PM_NO_PET;
46 if (r_ptr->misc_flags.has_not(MonsterMiscType::HAS_FRIENDS)) {
47 mode |= PM_ALLOW_GROUP;
50 for (int j = 0; j < (quest.max_num - quest.cur_num); j++) {
52 for (k = 0; k < SAFE_MAX_ATTEMPTS; k++) {
56 for (l = SAFE_MAX_ATTEMPTS; l > 0; l--) {
57 y = randint0(floor_ptr->height);
58 x = randint0(floor_ptr->width);
59 const auto &grid = floor_ptr->get_grid({ y, x });
60 const auto &terrain = grid.get_terrain();
61 if (terrain.flags.has_none_of({ TerrainCharacteristics::MOVE, TerrainCharacteristics::CAN_FLY })) {
65 if (!monster_can_enter(player_ptr, y, x, r_ptr, 0)) {
69 if (distance(y, x, player_ptr->y, player_ptr->x) < 10) {
84 if (place_specific_monster(player_ptr, 0, y, x, quest.r_idx, mode)) {
91 if (k == SAFE_MAX_ATTEMPTS) {