OSDN Git Service

[Refactor] #1710 Definitions QUEST_STATUS_* to enum class QuestStatusType
[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/dungeon.h"
9 #include "dungeon/quest.h"
10 #include "floor/cave.h"
11 #include "floor/geometry.h"
12 #include "game-option/birth-options.h"
13 #include "game-option/cheat-options.h"
14 #include "game-option/disturbance-options.h"
15 #include "game-option/map-screen-options.h"
16 #include "grid/feature-flag-types.h"
17 #include "grid/feature.h"
18 #include "grid/grid.h"
19 #include "main/sound-of-music.h"
20 #include "mind/mind-ninja.h"
21 #include "monster-race/monster-race.h"
22 #include "monster-race/race-flags1.h"
23 #include "monster/monster-info.h"
24 #include "monster/monster-list.h"
25 #include "monster/monster-status.h"
26 #include "object-enchant/object-ego.h"
27 #include "object-enchant/special-object-flags.h"
28 #include "object/object-kind.h"
29 #include "object/object-mark-types.h"
30 #include "object/object-value.h"
31 #include "perception/object-perception.h"
32 #include "player/special-defense-types.h"
33 #include "sv-definition/sv-amulet-types.h"
34 #include "sv-definition/sv-protector-types.h"
35 #include "sv-definition/sv-ring-types.h"
36 #include "system/floor-type-definition.h"
37 #include "system/grid-type-definition.h"
38 #include "system/monster-race-definition.h"
39 #include "system/monster-type-definition.h"
40 #include "system/object-type-definition.h"
41 #include "system/player-type-definition.h"
42 #include "util/bit-flags-calculator.h"
43 #include "view/display-messages.h"
44 #include "world/world.h"
45
46 void day_break(player_type *player_ptr)
47 {
48     msg_print(_("夜が明けた。", "The sun has risen."));
49     floor_type *floor_ptr = player_ptr->current_floor_ptr;
50     if (!player_ptr->wild_mode) {
51         for (POSITION y = 0; y < floor_ptr->height; y++) {
52             for (POSITION x = 0; x < floor_ptr->width; x++) {
53                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
54                 g_ptr->info |= CAVE_GLOW;
55                 if (view_perma_grids)
56                     g_ptr->info |= CAVE_MARK;
57
58                 note_spot(player_ptr, y, x);
59             }
60         }
61     }
62
63     player_ptr->update |= PU_MONSTERS | PU_MON_LITE;
64     player_ptr->redraw |= PR_MAP;
65     player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
66     if (((player_ptr->special_defense & NINJA_S_STEALTH) != 0) && ((floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) != 0))
67         set_superstealth(player_ptr, false);
68 }
69
70 void night_falls(player_type *player_ptr)
71 {
72     msg_print(_("日が沈んだ。", "The sun has fallen."));
73     floor_type *floor_ptr = player_ptr->current_floor_ptr;
74     if (!player_ptr->wild_mode) {
75         for (POSITION y = 0; y < floor_ptr->height; y++) {
76             for (POSITION x = 0; x < floor_ptr->width; x++) {
77                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
78                 feature_type *f_ptr = &f_info[g_ptr->get_feat_mimic()];
79                 if (g_ptr->is_mirror() || f_ptr->flags.has(FF::QUEST_ENTER) || f_ptr->flags.has(FF::ENTRANCE))
80                     continue;
81
82                 g_ptr->info &= ~(CAVE_GLOW);
83                 if (f_ptr->flags.has_not(FF::REMEMBER)) {
84                     g_ptr->info &= ~(CAVE_MARK);
85                     note_spot(player_ptr, y, x);
86                 }
87             }
88
89             glow_deep_lava_and_bldg(player_ptr);
90         }
91     }
92
93     player_ptr->update |= PU_MONSTERS | PU_MON_LITE;
94     player_ptr->redraw |= PR_MAP;
95     player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
96
97     if (((player_ptr->special_defense & NINJA_S_STEALTH) != 0) && ((floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) != 0))
98         set_superstealth(player_ptr, false);
99 }
100
101 /*!
102  * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
103  */
104 static int rating_boost(int delta) { return delta * delta + 50 * delta; }
105
106 /*!
107  * @brief ダンジョンの雰囲気を算出する。
108  * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
109  * @return 算出されたダンジョンの雰囲気ランク
110  */
111 static byte get_dungeon_feeling(player_type *player_ptr)
112 {
113     floor_type *floor_ptr = player_ptr->current_floor_ptr;
114     if (!floor_ptr->dun_level)
115         return 0;
116
117     const int base = 10;
118     int rating = 0;
119     for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
120         monster_type *m_ptr = &floor_ptr->m_list[i];
121         monster_race *r_ptr;
122         int delta = 0;
123         if (!monster_is_valid(m_ptr) || is_pet(m_ptr))
124             continue;
125
126         r_ptr = &r_info[m_ptr->r_idx];
127         if (r_ptr->flags1 & RF1_UNIQUE) {
128             if (r_ptr->level + 10 > floor_ptr->dun_level)
129                 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
130         } else if (r_ptr->level > floor_ptr->dun_level)
131             delta += (r_ptr->level - floor_ptr->dun_level) * base;
132
133         if (r_ptr->flags1 & RF1_FRIENDS) {
134             if (5 <= get_monster_crowd_number(floor_ptr, i))
135                 delta += 1;
136         } else if (2 <= get_monster_crowd_number(floor_ptr, i))
137             delta += 1;
138
139         rating += rating_boost(delta);
140     }
141
142     for (MONSTER_IDX i = 1; i < floor_ptr->o_max; i++) {
143         object_type *o_ptr = &floor_ptr->o_list[i];
144         object_kind *k_ptr = &k_info[o_ptr->k_idx];
145         int delta = 0;
146         if (!o_ptr->is_valid() || (o_ptr->is_known() && ((o_ptr->marked & OM_TOUCHED) != 0)) || ((o_ptr->ident & IDENT_SENSE) != 0))
147             continue;
148
149         if (o_ptr->is_ego()) {
150             ego_item_type *e_ptr = &e_info[o_ptr->name2];
151             delta += e_ptr->rating * base;
152         }
153
154         if (o_ptr->is_artifact()) {
155             PRICE cost = object_value_real(o_ptr);
156             delta += 10 * base;
157             if (cost > 10000L)
158                 delta += 10 * base;
159
160             if (cost > 50000L)
161                 delta += 10 * base;
162
163             if (cost > 100000L)
164                 delta += 10 * base;
165
166             if (!preserve_mode)
167                 return 1;
168         }
169
170         if (o_ptr->tval == TV_DRAG_ARMOR)
171             delta += 30 * base;
172
173         if (o_ptr->tval == TV_SHIELD && o_ptr->sval == SV_DRAGON_SHIELD)
174             delta += 5 * base;
175
176         if (o_ptr->tval == TV_GLOVES && o_ptr->sval == SV_SET_OF_DRAGON_GLOVES)
177             delta += 5 * base;
178
179         if (o_ptr->tval == TV_BOOTS && o_ptr->sval == SV_PAIR_OF_DRAGON_GREAVE)
180             delta += 5 * base;
181
182         if (o_ptr->tval == TV_HELM && o_ptr->sval == SV_DRAGON_HELM)
183             delta += 5 * base;
184
185         if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_SPEED && !o_ptr->is_cursed())
186             delta += 25 * base;
187
188         if (o_ptr->tval == TV_RING && o_ptr->sval == SV_RING_LORDLY && !o_ptr->is_cursed())
189             delta += 15 * base;
190
191         if (o_ptr->tval == TV_AMULET && o_ptr->sval == SV_AMULET_THE_MAGI && !o_ptr->is_cursed())
192             delta += 15 * base;
193
194         if (!o_ptr->is_cursed() && !o_ptr->is_broken() && k_ptr->level > floor_ptr->dun_level)
195             delta += (k_ptr->level - floor_ptr->dun_level) * base;
196
197         rating += rating_boost(delta);
198     }
199
200     if (rating > rating_boost(1000))
201         return 2;
202
203     if (rating > rating_boost(800))
204         return 3;
205
206     if (rating > rating_boost(600))
207         return 4;
208
209     if (rating > rating_boost(400))
210         return 5;
211
212     if (rating > rating_boost(300))
213         return 6;
214
215     if (rating > rating_boost(200))
216         return 7;
217
218     if (rating > rating_boost(100))
219         return 8;
220
221     if (rating > rating_boost(0))
222         return 9;
223
224     return 10;
225 }
226
227 /*!
228  * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
229  * / Update dungeon feeling, and announce it if changed
230  */
231 void update_dungeon_feeling(player_type *player_ptr)
232 {
233     floor_type *floor_ptr = player_ptr->current_floor_ptr;
234     if (!floor_ptr->dun_level)
235         return;
236
237     if (player_ptr->phase_out)
238         return;
239
240     int delay = MAX(10, 150 - player_ptr->skill_fos) * (150 - floor_ptr->dun_level) * TURNS_PER_TICK / 100;
241     if (w_ptr->game_turn < player_ptr->feeling_turn + delay && !cheat_xtra)
242         return;
243
244     auto quest_num = quest_number(player_ptr, floor_ptr->dun_level);
245     if ((quest_num > 0)
246         && (quest_type::is_fixed(quest_num) && !((quest_num == QUEST_OBERON) || (quest_num == QUEST_SERPENT) || !(quest[quest_num].flags & QUEST_FLAG_PRESET))))
247         return;
248
249     byte new_feeling = get_dungeon_feeling(player_ptr);
250     player_ptr->feeling_turn = w_ptr->game_turn;
251     if (player_ptr->feeling == new_feeling)
252         return;
253
254     player_ptr->feeling = new_feeling;
255     do_cmd_feeling(player_ptr);
256     select_floor_music(player_ptr);
257     player_ptr->redraw |= PR_DEPTH;
258     if (disturb_minor)
259         disturb(player_ptr, false, false);
260 }
261
262 /*
263  * Glow deep lava and building entrances in the floor
264  */
265 void glow_deep_lava_and_bldg(player_type *player_ptr)
266 {
267     if (d_info[player_ptr->dungeon_idx].flags.has(DF::DARKNESS))
268         return;
269
270     floor_type *floor_ptr = player_ptr->current_floor_ptr;
271     for (POSITION y = 0; y < floor_ptr->height; y++) {
272         for (POSITION x = 0; x < floor_ptr->width; x++) {
273             grid_type *g_ptr;
274             g_ptr = &floor_ptr->grid_array[y][x];
275             if (f_info[g_ptr->get_feat_mimic()].flags.has_not(FF::GLOW))
276                 continue;
277
278             for (DIRECTION i = 0; i < 9; i++) {
279                 POSITION yy = y + ddy_ddd[i];
280                 POSITION xx = x + ddx_ddd[i];
281                 if (!in_bounds2(floor_ptr, yy, xx))
282                     continue;
283
284                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
285             }
286         }
287     }
288
289     player_ptr->update |= PU_VIEW | PU_LITE | PU_MON_LITE;
290     player_ptr->redraw |= PR_MAP;
291 }
292
293 /*
294  * Actually erase the entire "lite" array, redrawing every grid
295  */
296 void forget_lite(floor_type *floor_ptr)
297 {
298     if (!floor_ptr->lite_n)
299         return;
300
301     for (int i = 0; i < floor_ptr->lite_n; i++) {
302         POSITION y = floor_ptr->lite_y[i];
303         POSITION x = floor_ptr->lite_x[i];
304         floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
305     }
306
307     floor_ptr->lite_n = 0;
308 }
309
310 /*
311  * Clear the viewable space
312  */
313 void forget_view(floor_type *floor_ptr)
314 {
315     if (!floor_ptr->view_n)
316         return;
317
318     for (int i = 0; i < floor_ptr->view_n; i++) {
319         POSITION y = floor_ptr->view_y[i];
320         POSITION x = floor_ptr->view_x[i];
321         grid_type *g_ptr;
322         g_ptr = &floor_ptr->grid_array[y][x];
323         g_ptr->info &= ~(CAVE_VIEW);
324     }
325
326     floor_ptr->view_n = 0;
327 }