OSDN Git Service

0f5692e4c79c83315f040cf017c85dcd21e9f605
[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 "grid/feature.h"
6 #include "monster-floor/monster-generator.h"
7 #include "monster-floor/place-monster-types.h"
8 #include "monster-race/monster-race.h"
9 #include "monster-race/race-flags1.h"
10 #include "monster/monster-info.h"
11 #include "system/floor-type-definition.h"
12 #include "system/grid-type-definition.h"
13 #include "system/monster-race-definition.h"
14 #include "system/player-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     for (int i = 0; i < max_q_idx; i++) {
26         monster_race *r_ptr;
27         BIT_FLAGS mode;
28         if (quest[i].status != QuestStatusType::TAKEN || (quest[i].type != QuestKindType::KILL_LEVEL && quest[i].type != QuestKindType::RANDOM)
29             || quest[i].level != floor_ptr->dun_level || player_ptr->dungeon_idx != quest[i].dungeon || (quest[i].flags & QUEST_FLAG_PRESET)) {
30             continue;
31         }
32
33         r_ptr = &r_info[quest[i].r_idx];
34         if ((r_ptr->flags1 & RF1_UNIQUE) && (r_ptr->cur_num >= r_ptr->max_num))
35             continue;
36
37         mode = PM_NO_KAGE | PM_NO_PET;
38         if (!(r_ptr->flags1 & RF1_FRIENDS))
39             mode |= PM_ALLOW_GROUP;
40
41         for (int j = 0; j < (quest[i].max_num - quest[i].cur_num); j++) {
42             int k;
43             for (k = 0; k < SAFE_MAX_ATTEMPTS; k++) {
44                 POSITION x = 0;
45                 POSITION y = 0;
46                 int l;
47                 for (l = SAFE_MAX_ATTEMPTS; l > 0; l--) {
48                     grid_type *g_ptr;
49                     feature_type *f_ptr;
50                     y = randint0(floor_ptr->height);
51                     x = randint0(floor_ptr->width);
52                     g_ptr = &floor_ptr->grid_array[y][x];
53                     f_ptr = &f_info[g_ptr->feat];
54                     if (f_ptr->flags.has_none_of({FloorFeatureType::MOVE, FloorFeatureType::CAN_FLY}))
55                         continue;
56
57                     if (!monster_can_enter(player_ptr, y, x, r_ptr, 0))
58                         continue;
59
60                     if (distance(y, x, player_ptr->y, player_ptr->x) < 10)
61                         continue;
62
63                     if (g_ptr->is_icky())
64                         continue;
65                     else
66                         break;
67                 }
68
69                 if (l == 0)
70                     return false;
71
72                 if (place_monster_aux(player_ptr, 0, y, x, quest[i].r_idx, mode))
73                     break;
74                 else
75                     continue;
76             }
77
78             if (k == SAFE_MAX_ATTEMPTS)
79                 return false;
80         }
81     }
82
83     return true;
84 }