OSDN Git Service

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