OSDN Git Service

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