OSDN Git Service

[Refactor] #3230 PlayerType::window_flags への読み書きを行っているファイル群について、横に長過ぎる文を適宜分割した
[hengbandforosx/hengbandosx.git] / src / floor / floor-events.cpp
1 #include "floor/floor-events.h"
2 #include "cmd-io/cmd-dump.h"
3 #include "core/disturbance.h"
4 #include "core/player-redraw-types.h"
5 #include "core/player-update-types.h"
6 #include "core/window-redrawer.h"
7 #include "dungeon/dungeon-flag-types.h"
8 #include "dungeon/quest.h"
9 #include "floor/cave.h"
10 #include "floor/geometry.h"
11 #include "game-option/birth-options.h"
12 #include "game-option/cheat-options.h"
13 #include "game-option/disturbance-options.h"
14 #include "game-option/map-screen-options.h"
15 #include "grid/feature-flag-types.h"
16 #include "grid/grid.h"
17 #include "main/sound-of-music.h"
18 #include "mind/mind-ninja.h"
19 #include "monster-race/monster-race.h"
20 #include "monster-race/race-flags1.h"
21 #include "monster/monster-info.h"
22 #include "monster/monster-list.h"
23 #include "monster/monster-status.h"
24 #include "object-enchant/object-ego.h"
25 #include "object-enchant/special-object-flags.h"
26 #include "object/object-mark-types.h"
27 #include "object/object-value.h"
28 #include "object/tval-types.h"
29 #include "perception/object-perception.h"
30 #include "player/special-defense-types.h"
31 #include "sv-definition/sv-amulet-types.h"
32 #include "sv-definition/sv-protector-types.h"
33 #include "sv-definition/sv-ring-types.h"
34 #include "system/baseitem-info.h"
35 #include "system/dungeon-info.h"
36 #include "system/floor-type-definition.h"
37 #include "system/grid-type-definition.h"
38 #include "system/item-entity.h"
39 #include "system/monster-entity.h"
40 #include "system/monster-race-info.h"
41 #include "system/player-type-definition.h"
42 #include "system/terrain-type-definition.h"
43 #include "util/bit-flags-calculator.h"
44 #include "view/display-messages.h"
45 #include "world/world.h"
46
47 void day_break(PlayerType *player_ptr)
48 {
49     msg_print(_("夜が明けた。", "The sun has risen."));
50     auto *floor_ptr = player_ptr->current_floor_ptr;
51     if (!player_ptr->wild_mode) {
52         for (POSITION y = 0; y < floor_ptr->height; y++) {
53             for (POSITION x = 0; x < floor_ptr->width; x++) {
54                 auto *g_ptr = &floor_ptr->grid_array[y][x];
55                 g_ptr->info |= CAVE_GLOW;
56                 if (view_perma_grids) {
57                     g_ptr->info |= CAVE_MARK;
58                 }
59
60                 note_spot(player_ptr, y, x);
61             }
62         }
63     }
64
65     player_ptr->update |= PU_MONSTER_STATUSES | PU_MONSTER_LITE;
66     player_ptr->redraw |= PR_MAP;
67     player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
68     if ((floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) != 0) {
69         set_superstealth(player_ptr, false);
70     }
71 }
72
73 void night_falls(PlayerType *player_ptr)
74 {
75     msg_print(_("日が沈んだ。", "The sun has fallen."));
76     auto *floor_ptr = player_ptr->current_floor_ptr;
77     if (!player_ptr->wild_mode) {
78         for (POSITION y = 0; y < floor_ptr->height; y++) {
79             for (POSITION x = 0; x < floor_ptr->width; x++) {
80                 auto *g_ptr = &floor_ptr->grid_array[y][x];
81                 auto *f_ptr = &terrains_info[g_ptr->get_feat_mimic()];
82                 using Tc = TerrainCharacteristics;
83                 if (g_ptr->is_mirror() || f_ptr->flags.has(Tc::QUEST_ENTER) || f_ptr->flags.has(Tc::ENTRANCE)) {
84                     continue;
85                 }
86
87                 g_ptr->info &= ~(CAVE_GLOW);
88                 if (f_ptr->flags.has_not(Tc::REMEMBER)) {
89                     g_ptr->info &= ~(CAVE_MARK);
90                     note_spot(player_ptr, y, x);
91                 }
92             }
93
94             glow_deep_lava_and_bldg(player_ptr);
95         }
96     }
97
98     player_ptr->update |= PU_MONSTER_STATUSES | PU_MONSTER_LITE;
99     player_ptr->redraw |= PR_MAP;
100     player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
101
102     if ((floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) != 0) {
103         set_superstealth(player_ptr, false);
104     }
105 }
106
107 /*!
108  * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
109  */
110 static int rating_boost(int delta)
111 {
112     return delta * delta + 50 * delta;
113 }
114
115 /*!
116  * @brief ダンジョンの雰囲気を算出する。
117  * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
118  * @return 算出されたダンジョンの雰囲気ランク
119  */
120 static byte get_dungeon_feeling(PlayerType *player_ptr)
121 {
122     auto *floor_ptr = player_ptr->current_floor_ptr;
123     if (!floor_ptr->dun_level) {
124         return 0;
125     }
126
127     const int base = 10;
128     int rating = 0;
129     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
130         auto *m_ptr = &floor_ptr->m_list[i];
131         MonsterRaceInfo *r_ptr;
132         int delta = 0;
133         if (!m_ptr->is_valid() || m_ptr->is_pet()) {
134             continue;
135         }
136
137         r_ptr = &monraces_info[m_ptr->r_idx];
138         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
139             if (r_ptr->level + 10 > floor_ptr->dun_level) {
140                 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
141             }
142         } else if (r_ptr->level > floor_ptr->dun_level) {
143             delta += (r_ptr->level - floor_ptr->dun_level) * base;
144         }
145
146         if (r_ptr->flags1 & RF1_FRIENDS) {
147             if (5 <= get_monster_crowd_number(floor_ptr, i)) {
148                 delta += 1;
149             }
150         } else if (2 <= get_monster_crowd_number(floor_ptr, i)) {
151             delta += 1;
152         }
153
154         rating += rating_boost(delta);
155     }
156
157     for (MONSTER_IDX i = 1; i < floor_ptr->o_max; i++) {
158         auto *o_ptr = &floor_ptr->o_list[i];
159         int delta = 0;
160         if (!o_ptr->is_valid() || (o_ptr->is_known() && o_ptr->marked.has(OmType::TOUCHED)) || ((o_ptr->ident & IDENT_SENSE) != 0)) {
161             continue;
162         }
163
164         if (o_ptr->is_ego()) {
165             const auto &ego = o_ptr->get_ego();
166             delta += ego.rating * base;
167         }
168
169         if (o_ptr->is_fixed_or_random_artifact()) {
170             PRICE cost = object_value_real(o_ptr);
171             delta += 10 * base;
172             if (cost > 10000L) {
173                 delta += 10 * base;
174             }
175
176             if (cost > 50000L) {
177                 delta += 10 * base;
178             }
179
180             if (cost > 100000L) {
181                 delta += 10 * base;
182             }
183
184             if (!preserve_mode) {
185                 return 1;
186             }
187         }
188
189         if (o_ptr->bi_key.tval() == ItemKindType::DRAG_ARMOR) {
190             delta += 30 * base;
191         }
192
193         if (o_ptr->bi_key == BaseitemKey(ItemKindType::SHIELD, SV_DRAGON_SHIELD)) {
194             delta += 5 * base;
195         }
196
197         if (o_ptr->bi_key == BaseitemKey(ItemKindType::GLOVES, SV_SET_OF_DRAGON_GLOVES)) {
198             delta += 5 * base;
199         }
200
201         if (o_ptr->bi_key == BaseitemKey(ItemKindType::BOOTS, SV_PAIR_OF_DRAGON_GREAVE)) {
202             delta += 5 * base;
203         }
204
205         if (o_ptr->bi_key == BaseitemKey(ItemKindType::HELM, SV_DRAGON_HELM)) {
206             delta += 5 * base;
207         }
208
209         if (o_ptr->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_SPEED) && !o_ptr->is_cursed()) {
210             delta += 25 * base;
211         }
212
213         if (o_ptr->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_LORDLY) && !o_ptr->is_cursed()) {
214             delta += 15 * base;
215         }
216
217         if (o_ptr->bi_key == BaseitemKey(ItemKindType::AMULET, SV_AMULET_THE_MAGI) && !o_ptr->is_cursed()) {
218             delta += 15 * base;
219         }
220
221         const auto &baseitem = o_ptr->get_baseitem();
222         if (!o_ptr->is_cursed() && !o_ptr->is_broken() && baseitem.level > floor_ptr->dun_level) {
223             delta += (baseitem.level - floor_ptr->dun_level) * base;
224         }
225
226         rating += rating_boost(delta);
227     }
228
229     if (rating > rating_boost(1000)) {
230         return 2;
231     }
232
233     if (rating > rating_boost(800)) {
234         return 3;
235     }
236
237     if (rating > rating_boost(600)) {
238         return 4;
239     }
240
241     if (rating > rating_boost(400)) {
242         return 5;
243     }
244
245     if (rating > rating_boost(300)) {
246         return 6;
247     }
248
249     if (rating > rating_boost(200)) {
250         return 7;
251     }
252
253     if (rating > rating_boost(100)) {
254         return 8;
255     }
256
257     if (rating > rating_boost(0)) {
258         return 9;
259     }
260
261     return 10;
262 }
263
264 /*!
265  * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
266  * / Update dungeon feeling, and announce it if changed
267  */
268 void update_dungeon_feeling(PlayerType *player_ptr)
269 {
270     auto *floor_ptr = player_ptr->current_floor_ptr;
271     if (!floor_ptr->dun_level) {
272         return;
273     }
274
275     if (player_ptr->phase_out) {
276         return;
277     }
278
279     int delay = std::max(10, 150 - player_ptr->skill_fos) * (150 - floor_ptr->dun_level) * TURNS_PER_TICK / 100;
280     if (w_ptr->game_turn < player_ptr->feeling_turn + delay && !cheat_xtra) {
281         return;
282     }
283
284     auto quest_num = quest_number(player_ptr, floor_ptr->dun_level);
285     const auto &quest_list = QuestList::get_instance();
286
287     auto dungeon_quest = (quest_num == QuestId::OBERON);
288     dungeon_quest |= (quest_num == QuestId::SERPENT);
289     dungeon_quest |= !(quest_list[quest_num].flags & QUEST_FLAG_PRESET);
290
291     auto feeling_quest = inside_quest(quest_num);
292     feeling_quest &= QuestType::is_fixed(quest_num);
293     feeling_quest &= !dungeon_quest;
294     if (feeling_quest) {
295         return;
296     }
297     byte new_feeling = get_dungeon_feeling(player_ptr);
298     player_ptr->feeling_turn = w_ptr->game_turn;
299     if (player_ptr->feeling == new_feeling) {
300         return;
301     }
302
303     player_ptr->feeling = new_feeling;
304     do_cmd_feeling(player_ptr);
305     select_floor_music(player_ptr);
306     player_ptr->redraw |= PR_DEPTH;
307     if (disturb_minor) {
308         disturb(player_ptr, false, false);
309     }
310 }
311
312 /*
313  * Glow deep lava and building entrances in the floor
314  */
315 void glow_deep_lava_and_bldg(PlayerType *player_ptr)
316 {
317     if (dungeons_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::DARKNESS)) {
318         return;
319     }
320
321     auto *floor_ptr = player_ptr->current_floor_ptr;
322     for (POSITION y = 0; y < floor_ptr->height; y++) {
323         for (POSITION x = 0; x < floor_ptr->width; x++) {
324             grid_type *g_ptr;
325             g_ptr = &floor_ptr->grid_array[y][x];
326             if (terrains_info[g_ptr->get_feat_mimic()].flags.has_not(TerrainCharacteristics::GLOW)) {
327                 continue;
328             }
329
330             for (DIRECTION i = 0; i < 9; i++) {
331                 POSITION yy = y + ddy_ddd[i];
332                 POSITION xx = x + ddx_ddd[i];
333                 if (!in_bounds2(floor_ptr, yy, xx)) {
334                     continue;
335                 }
336
337                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
338             }
339         }
340     }
341
342     player_ptr->update |= PU_VIEW | PU_LITE | PU_MONSTER_LITE;
343     player_ptr->redraw |= PR_MAP;
344 }
345
346 /*
347  * Actually erase the entire "lite" array, redrawing every grid
348  */
349 void forget_lite(FloorType *floor_ptr)
350 {
351     if (!floor_ptr->lite_n) {
352         return;
353     }
354
355     for (int i = 0; i < floor_ptr->lite_n; i++) {
356         POSITION y = floor_ptr->lite_y[i];
357         POSITION x = floor_ptr->lite_x[i];
358         floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
359     }
360
361     floor_ptr->lite_n = 0;
362 }
363
364 /*
365  * Clear the viewable space
366  */
367 void forget_view(FloorType *floor_ptr)
368 {
369     if (!floor_ptr->view_n) {
370         return;
371     }
372
373     for (int i = 0; i < floor_ptr->view_n; i++) {
374         POSITION y = floor_ptr->view_y[i];
375         POSITION x = floor_ptr->view_x[i];
376         grid_type *g_ptr;
377         g_ptr = &floor_ptr->grid_array[y][x];
378         g_ptr->info &= ~(CAVE_VIEW);
379     }
380
381     floor_ptr->view_n = 0;
382 }