OSDN Git Service

Merge branch 'master' of https://github.com/hengband/hengband
[hengbandforosx/hengbandosx.git] / src / system / floor-type-definition.cpp
1 #include "system/floor-type-definition.h"
2 #include "dungeon/quest.h"
3 #include "game-option/birth-options.h"
4 #include "system/angband-system.h"
5 #include "system/dungeon-info.h"
6 #include "system/grid-type-definition.h"
7 #include "system/item-entity.h"
8 #include "system/monster-entity.h"
9 #include "util/bit-flags-calculator.h"
10 #include "util/enum-range.h"
11
12 FloorType::FloorType()
13     : quest_number(QuestId::NONE)
14 {
15 }
16
17 Grid &FloorType::get_grid(const Pos2D pos)
18 {
19     return this->grid_array[pos.y][pos.x];
20 }
21
22 const Grid &FloorType::get_grid(const Pos2D pos) const
23 {
24     return this->grid_array[pos.y][pos.x];
25 }
26
27 bool FloorType::is_in_dungeon() const
28 {
29     return this->dun_level > 0;
30 }
31
32 bool FloorType::is_in_quest() const
33 {
34     return this->quest_number != QuestId::NONE;
35 }
36
37 void FloorType::set_dungeon_index(short dungeon_idx_)
38 {
39     this->dungeon_idx = dungeon_idx_;
40 }
41
42 void FloorType::reset_dungeon_index()
43 {
44     this->set_dungeon_index(0);
45 }
46
47 dungeon_type &FloorType::get_dungeon_definition() const
48 {
49     return dungeons_info[this->dungeon_idx];
50 }
51
52 /*!
53  * @brief 新しく入ったダンジョンの階層に固定されているランダムクエストを探し出しIDを返す。
54  * @param player_ptr プレイヤーへの参照ポインタ
55  * @param level 検索対象になる階
56  * @return クエストIDを返す。該当がない場合0を返す。
57  */
58 QuestId FloorType::get_random_quest_id(std::optional<int> level_opt) const
59 {
60     if (this->dungeon_idx != DUNGEON_ANGBAND) {
61         return QuestId::NONE;
62     }
63
64     const auto level = level_opt.value_or(this->dun_level);
65     const auto &quest_list = QuestList::get_instance();
66     for (auto q_idx : EnumRange(QuestId::RANDOM_QUEST1, QuestId::RANDOM_QUEST10)) {
67         const auto &quest = quest_list[q_idx];
68         auto is_random_quest = (quest.type == QuestKindType::RANDOM);
69         is_random_quest &= (quest.status == QuestStatusType::TAKEN);
70         is_random_quest &= (quest.level == level);
71         is_random_quest &= (quest.dungeon == DUNGEON_ANGBAND);
72         if (is_random_quest) {
73             return q_idx;
74         }
75     }
76
77     return QuestId::NONE;
78 }
79
80 /*!
81  * @brief 新しく入ったダンジョンの階層に固定されている一般のクエストを探し出しIDを返す.
82  * @param player_ptr プレイヤーへの参照ポインタ
83  * @param bonus 検索対象になる階へのボーナス。通常0
84  * @return クエストIDを返す。該当がない場合0を返す。
85  */
86 QuestId FloorType::get_quest_id(const int bonus) const
87 {
88     const auto &quest_list = QuestList::get_instance();
89     if (this->is_in_quest()) {
90         return this->quest_number;
91     }
92
93     const auto level = this->dun_level + bonus;
94     for (const auto &[q_idx, quest] : quest_list) {
95         if (quest.status != QuestStatusType::TAKEN) {
96             continue;
97         }
98
99         auto depth_quest = (quest.type == QuestKindType::KILL_LEVEL);
100         depth_quest &= !(quest.flags & QUEST_FLAG_PRESET);
101         depth_quest &= (quest.level == level);
102         depth_quest &= (quest.dungeon == this->dungeon_idx);
103         if (depth_quest) {
104             return q_idx;
105         }
106     }
107
108     return this->get_random_quest_id(level);
109 }
110
111 /*
112  * @brief 与えられた座標のグリッドがLOSフラグを持つかを調べる
113  * @param pos 座標
114  * @return LOSフラグを持つか否か
115  */
116 bool FloorType::has_los(const Pos2D pos) const
117 {
118     return this->get_grid(pos).has_los();
119 }
120
121 /*!
122  * @brief 特別なフロアにいるかを判定する
123  * @return 固定クエスト、アリーナ、モンスター闘技場のいずれかならばtrue
124  */
125 bool FloorType::is_special() const
126 {
127     auto is_in_fixed_quest = this->is_in_quest();
128     is_in_fixed_quest &= !inside_quest(this->get_random_quest_id());
129     return is_in_fixed_quest || this->inside_arena || AngbandSystem::get_instance().is_phase_out();
130 }
131
132 /*!
133  * @brief テレポート・レベル無効フロアの判定
134  * @param to_player プレイヤーを対象としているか否か
135  * @return テレポート・レベルが不可能ならばtrue
136  */
137 bool FloorType::can_teleport_level(bool to_player) const
138 {
139     auto is_invalid_floor = to_player;
140     is_invalid_floor &= inside_quest(this->get_quest_id()) || (this->dun_level >= this->get_dungeon_definition().maxdepth);
141     is_invalid_floor &= this->dun_level >= 1;
142     is_invalid_floor &= ironman_downward;
143     return this->is_special() || is_invalid_floor;
144 }