OSDN Git Service

[Refactor] #2712 Renamed enum FloorFeatureType to TerrainCharacteristics
[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/feature.h"
17 #include "grid/grid.h"
18 #include "main/sound-of-music.h"
19 #include "mind/mind-ninja.h"
20 #include "monster-race/monster-race.h"
21 #include "monster-race/race-flags1.h"
22 #include "monster/monster-info.h"
23 #include "monster/monster-list.h"
24 #include "monster/monster-status.h"
25 #include "object-enchant/object-ego.h"
26 #include "object-enchant/special-object-flags.h"
27 #include "object/object-mark-types.h"
28 #include "object/object-value.h"
29 #include "object/tval-types.h"
30 #include "perception/object-perception.h"
31 #include "player/special-defense-types.h"
32 #include "sv-definition/sv-amulet-types.h"
33 #include "sv-definition/sv-protector-types.h"
34 #include "sv-definition/sv-ring-types.h"
35 #include "system/baseitem-info-definition.h"
36 #include "system/dungeon-info.h"
37 #include "system/floor-type-definition.h"
38 #include "system/grid-type-definition.h"
39 #include "system/monster-race-definition.h"
40 #include "system/monster-type-definition.h"
41 #include "system/object-type-definition.h"
42 #include "system/player-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_MONSTERS | PU_MON_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                 if (g_ptr->is_mirror() || f_ptr->flags.has(TerrainCharacteristics::QUEST_ENTER) || f_ptr->flags.has(TerrainCharacteristics::ENTRANCE)) {
83                     continue;
84                 }
85
86                 g_ptr->info &= ~(CAVE_GLOW);
87                 if (f_ptr->flags.has_not(TerrainCharacteristics::REMEMBER)) {
88                     g_ptr->info &= ~(CAVE_MARK);
89                     note_spot(player_ptr, y, x);
90                 }
91             }
92
93             glow_deep_lava_and_bldg(player_ptr);
94         }
95     }
96
97     player_ptr->update |= PU_MONSTERS | PU_MON_LITE;
98     player_ptr->redraw |= PR_MAP;
99     player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
100
101     if ((floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) != 0) {
102         set_superstealth(player_ptr, false);
103     }
104 }
105
106 /*!
107  * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
108  */
109 static int rating_boost(int delta)
110 {
111     return delta * delta + 50 * delta;
112 }
113
114 /*!
115  * @brief ダンジョンの雰囲気を算出する。
116  * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
117  * @return 算出されたダンジョンの雰囲気ランク
118  */
119 static byte get_dungeon_feeling(PlayerType *player_ptr)
120 {
121     auto *floor_ptr = player_ptr->current_floor_ptr;
122     if (!floor_ptr->dun_level) {
123         return 0;
124     }
125
126     const int base = 10;
127     int rating = 0;
128     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
129         auto *m_ptr = &floor_ptr->m_list[i];
130         monster_race *r_ptr;
131         int delta = 0;
132         if (!m_ptr->is_valid() || m_ptr->is_pet()) {
133             continue;
134         }
135
136         r_ptr = &monraces_info[m_ptr->r_idx];
137         if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
138             if (r_ptr->level + 10 > floor_ptr->dun_level) {
139                 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
140             }
141         } else if (r_ptr->level > floor_ptr->dun_level) {
142             delta += (r_ptr->level - floor_ptr->dun_level) * base;
143         }
144
145         if (r_ptr->flags1 & RF1_FRIENDS) {
146             if (5 <= get_monster_crowd_number(floor_ptr, i)) {
147                 delta += 1;
148             }
149         } else if (2 <= get_monster_crowd_number(floor_ptr, i)) {
150             delta += 1;
151         }
152
153         rating += rating_boost(delta);
154     }
155
156     for (MONSTER_IDX i = 1; i < floor_ptr->o_max; i++) {
157         auto *o_ptr = &floor_ptr->o_list[i];
158         auto *k_ptr = &baseitems_info[o_ptr->k_idx];
159         int delta = 0;
160         if (!o_ptr->is_valid() || (o_ptr->is_known() && ((o_ptr->marked & OM_TOUCHED) != 0)) || ((o_ptr->ident & IDENT_SENSE) != 0)) {
161             continue;
162         }
163
164         if (o_ptr->is_ego()) {
165             auto *e_ptr = &egos_info[o_ptr->ego_idx];
166             delta += e_ptr->rating * base;
167         }
168
169         if (o_ptr->is_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->tval == ItemKindType::DRAG_ARMOR) {
190             delta += 30 * base;
191         }
192
193         if (o_ptr->tval == ItemKindType::SHIELD && o_ptr->sval == SV_DRAGON_SHIELD) {
194             delta += 5 * base;
195         }
196
197         if (o_ptr->tval == ItemKindType::GLOVES && o_ptr->sval == SV_SET_OF_DRAGON_GLOVES) {
198             delta += 5 * base;
199         }
200
201         if (o_ptr->tval == ItemKindType::BOOTS && o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE) {
202             delta += 5 * base;
203         }
204
205         if (o_ptr->tval == ItemKindType::HELM && o_ptr->sval == SV_DRAGON_HELM) {
206             delta += 5 * base;
207         }
208
209         if (o_ptr->tval == ItemKindType::RING && o_ptr->sval == SV_RING_SPEED && !o_ptr->is_cursed()) {
210             delta += 25 * base;
211         }
212
213         if (o_ptr->tval == ItemKindType::RING && o_ptr->sval == SV_RING_LORDLY && !o_ptr->is_cursed()) {
214             delta += 15 * base;
215         }
216
217         if (o_ptr->tval == ItemKindType::AMULET && o_ptr->sval == SV_AMULET_THE_MAGI && !o_ptr->is_cursed()) {
218             delta += 15 * base;
219         }
220
221         if (!o_ptr->is_cursed() && !o_ptr->is_broken() && k_ptr->level > floor_ptr->dun_level) {
222             delta += (k_ptr->level - floor_ptr->dun_level) * base;
223         }
224
225         rating += rating_boost(delta);
226     }
227
228     if (rating > rating_boost(1000)) {
229         return 2;
230     }
231
232     if (rating > rating_boost(800)) {
233         return 3;
234     }
235
236     if (rating > rating_boost(600)) {
237         return 4;
238     }
239
240     if (rating > rating_boost(400)) {
241         return 5;
242     }
243
244     if (rating > rating_boost(300)) {
245         return 6;
246     }
247
248     if (rating > rating_boost(200)) {
249         return 7;
250     }
251
252     if (rating > rating_boost(100)) {
253         return 8;
254     }
255
256     if (rating > rating_boost(0)) {
257         return 9;
258     }
259
260     return 10;
261 }
262
263 /*!
264  * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
265  * / Update dungeon feeling, and announce it if changed
266  */
267 void update_dungeon_feeling(PlayerType *player_ptr)
268 {
269     auto *floor_ptr = player_ptr->current_floor_ptr;
270     if (!floor_ptr->dun_level) {
271         return;
272     }
273
274     if (player_ptr->phase_out) {
275         return;
276     }
277
278     int delay = std::max(10, 150 - player_ptr->skill_fos) * (150 - floor_ptr->dun_level) * TURNS_PER_TICK / 100;
279     if (w_ptr->game_turn < player_ptr->feeling_turn + delay && !cheat_xtra) {
280         return;
281     }
282
283     auto quest_num = quest_number(player_ptr, floor_ptr->dun_level);
284     const auto &quest_list = QuestList::get_instance();
285
286     auto dungeon_quest = (quest_num == QuestId::OBERON);
287     dungeon_quest |= (quest_num == QuestId::SERPENT);
288     dungeon_quest |= !(quest_list[quest_num].flags & QUEST_FLAG_PRESET);
289
290     auto feeling_quest = inside_quest(quest_num);
291     feeling_quest &= quest_type::is_fixed(quest_num);
292     feeling_quest &= !dungeon_quest;
293     if (feeling_quest) {
294         return;
295     }
296     byte new_feeling = get_dungeon_feeling(player_ptr);
297     player_ptr->feeling_turn = w_ptr->game_turn;
298     if (player_ptr->feeling == new_feeling) {
299         return;
300     }
301
302     player_ptr->feeling = new_feeling;
303     do_cmd_feeling(player_ptr);
304     select_floor_music(player_ptr);
305     player_ptr->redraw |= PR_DEPTH;
306     if (disturb_minor) {
307         disturb(player_ptr, false, false);
308     }
309 }
310
311 /*
312  * Glow deep lava and building entrances in the floor
313  */
314 void glow_deep_lava_and_bldg(PlayerType *player_ptr)
315 {
316     if (dungeons_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::DARKNESS)) {
317         return;
318     }
319
320     auto *floor_ptr = player_ptr->current_floor_ptr;
321     for (POSITION y = 0; y < floor_ptr->height; y++) {
322         for (POSITION x = 0; x < floor_ptr->width; x++) {
323             grid_type *g_ptr;
324             g_ptr = &floor_ptr->grid_array[y][x];
325             if (terrains_info[g_ptr->get_feat_mimic()].flags.has_not(TerrainCharacteristics::GLOW)) {
326                 continue;
327             }
328
329             for (DIRECTION i = 0; i < 9; i++) {
330                 POSITION yy = y + ddy_ddd[i];
331                 POSITION xx = x + ddx_ddd[i];
332                 if (!in_bounds2(floor_ptr, yy, xx)) {
333                     continue;
334                 }
335
336                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
337             }
338         }
339     }
340
341     player_ptr->update |= PU_VIEW | PU_LITE | PU_MON_LITE;
342     player_ptr->redraw |= PR_MAP;
343 }
344
345 /*
346  * Actually erase the entire "lite" array, redrawing every grid
347  */
348 void forget_lite(floor_type *floor_ptr)
349 {
350     if (!floor_ptr->lite_n) {
351         return;
352     }
353
354     for (int i = 0; i < floor_ptr->lite_n; i++) {
355         POSITION y = floor_ptr->lite_y[i];
356         POSITION x = floor_ptr->lite_x[i];
357         floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
358     }
359
360     floor_ptr->lite_n = 0;
361 }
362
363 /*
364  * Clear the viewable space
365  */
366 void forget_view(floor_type *floor_ptr)
367 {
368     if (!floor_ptr->view_n) {
369         return;
370     }
371
372     for (int i = 0; i < floor_ptr->view_n; i++) {
373         POSITION y = floor_ptr->view_y[i];
374         POSITION x = floor_ptr->view_x[i];
375         grid_type *g_ptr;
376         g_ptr = &floor_ptr->grid_array[y][x];
377         g_ptr->info &= ~(CAVE_VIEW);
378     }
379
380     floor_ptr->view_n = 0;
381 }