1 #include "floor/floor-events.h"
2 #include "cmd-io/cmd-dump.h"
3 #include "core/disturbance.h"
4 #include "core/window-redrawer.h"
5 #include "dungeon/dungeon-flag-types.h"
6 #include "dungeon/quest.h"
7 #include "floor/cave.h"
8 #include "floor/geometry.h"
9 #include "game-option/birth-options.h"
10 #include "game-option/cheat-options.h"
11 #include "game-option/disturbance-options.h"
12 #include "game-option/map-screen-options.h"
13 #include "grid/feature-flag-types.h"
14 #include "grid/grid.h"
15 #include "main/sound-of-music.h"
16 #include "mind/mind-ninja.h"
17 #include "monster-race/monster-race.h"
18 #include "monster-race/race-flags1.h"
19 #include "monster/monster-info.h"
20 #include "monster/monster-list.h"
21 #include "monster/monster-status.h"
22 #include "object-enchant/object-ego.h"
23 #include "object-enchant/special-object-flags.h"
24 #include "object/object-mark-types.h"
25 #include "object/object-value.h"
26 #include "object/tval-types.h"
27 #include "perception/object-perception.h"
28 #include "player/special-defense-types.h"
29 #include "sv-definition/sv-amulet-types.h"
30 #include "sv-definition/sv-protector-types.h"
31 #include "sv-definition/sv-ring-types.h"
32 #include "system/baseitem-info.h"
33 #include "system/dungeon-info.h"
34 #include "system/floor-type-definition.h"
35 #include "system/grid-type-definition.h"
36 #include "system/item-entity.h"
37 #include "system/monster-entity.h"
38 #include "system/monster-race-info.h"
39 #include "system/player-type-definition.h"
40 #include "system/redrawing-flags-updater.h"
41 #include "system/terrain-type-definition.h"
42 #include "util/bit-flags-calculator.h"
43 #include "view/display-messages.h"
44 #include "world/world.h"
46 static void update_sun_light(PlayerType *player_ptr)
48 auto &rfu = RedrawingFlagsUpdater::get_instance();
49 static constexpr auto flags_srf = {
50 StatusRecalculatingFlag::MONSTER_STATUSES,
51 StatusRecalculatingFlag::MONSTER_LITE,
53 rfu.set_flags(flags_srf);
54 rfu.set_flag(MainWindowRedrawingFlag::MAP);
55 static constexpr auto flags = {
56 SubWindowRedrawingFlag::OVERHEAD,
57 SubWindowRedrawingFlag::DUNGEON,
60 if ((player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) != 0) {
61 set_superstealth(player_ptr, false);
65 void day_break(PlayerType *player_ptr)
67 msg_print(_("夜が明けた。", "The sun has risen."));
68 auto *floor_ptr = player_ptr->current_floor_ptr;
69 if (player_ptr->wild_mode) {
70 update_sun_light(player_ptr);
74 for (auto y = 0; y < floor_ptr->height; y++) {
75 for (auto x = 0; x < floor_ptr->width; x++) {
76 auto *g_ptr = &floor_ptr->grid_array[y][x];
77 g_ptr->info |= CAVE_GLOW;
78 if (view_perma_grids) {
79 g_ptr->info |= CAVE_MARK;
82 note_spot(player_ptr, y, x);
86 update_sun_light(player_ptr);
89 void night_falls(PlayerType *player_ptr)
91 msg_print(_("日が沈んだ。", "The sun has fallen."));
92 auto *floor_ptr = player_ptr->current_floor_ptr;
93 if (player_ptr->wild_mode) {
94 update_sun_light(player_ptr);
98 for (auto y = 0; y < floor_ptr->height; y++) {
99 for (auto x = 0; x < floor_ptr->width; x++) {
100 auto *g_ptr = &floor_ptr->grid_array[y][x];
101 auto *f_ptr = &terrains_info[g_ptr->get_feat_mimic()];
102 using Tc = TerrainCharacteristics;
103 if (g_ptr->is_mirror() || f_ptr->flags.has(Tc::QUEST_ENTER) || f_ptr->flags.has(Tc::ENTRANCE)) {
107 g_ptr->info &= ~(CAVE_GLOW);
108 if (f_ptr->flags.has_not(Tc::REMEMBER)) {
109 g_ptr->info &= ~(CAVE_MARK);
110 note_spot(player_ptr, y, x);
114 glow_deep_lava_and_bldg(player_ptr);
117 update_sun_light(player_ptr);
121 * ダンジョンの雰囲気を計算するための非線形基準値 / Dungeon rating is no longer linear
123 static int rating_boost(int delta)
125 return delta * delta + 50 * delta;
129 * @brief ダンジョンの雰囲気を算出する。
130 * / Examine all monsters and unidentified objects, and get the feeling of current dungeon floor
131 * @return 算出されたダンジョンの雰囲気ランク
133 static byte get_dungeon_feeling(PlayerType *player_ptr)
135 auto *floor_ptr = player_ptr->current_floor_ptr;
136 if (!floor_ptr->dun_level) {
142 for (MONSTER_IDX i = 1; i < floor_ptr->m_max; i++) {
143 auto *m_ptr = &floor_ptr->m_list[i];
144 MonsterRaceInfo *r_ptr;
146 if (!m_ptr->is_valid() || m_ptr->is_pet()) {
150 r_ptr = &m_ptr->get_monrace();
151 if (r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
152 if (r_ptr->level + 10 > floor_ptr->dun_level) {
153 delta += (r_ptr->level + 10 - floor_ptr->dun_level) * 2 * base;
155 } else if (r_ptr->level > floor_ptr->dun_level) {
156 delta += (r_ptr->level - floor_ptr->dun_level) * base;
159 if (r_ptr->flags1 & RF1_FRIENDS) {
160 if (5 <= get_monster_crowd_number(floor_ptr, i)) {
163 } else if (2 <= get_monster_crowd_number(floor_ptr, i)) {
167 rating += rating_boost(delta);
170 for (MONSTER_IDX i = 1; i < floor_ptr->o_max; i++) {
171 auto *o_ptr = &floor_ptr->o_list[i];
173 if (!o_ptr->is_valid() || (o_ptr->is_known() && o_ptr->marked.has(OmType::TOUCHED)) || ((o_ptr->ident & IDENT_SENSE) != 0)) {
177 if (o_ptr->is_ego()) {
178 const auto &ego = o_ptr->get_ego();
179 delta += ego.rating * base;
182 if (o_ptr->is_fixed_or_random_artifact()) {
183 PRICE cost = object_value_real(o_ptr);
193 if (cost > 100000L) {
197 if (!preserve_mode) {
202 if (o_ptr->bi_key.tval() == ItemKindType::DRAG_ARMOR) {
206 if (o_ptr->bi_key == BaseitemKey(ItemKindType::SHIELD, SV_DRAGON_SHIELD)) {
210 if (o_ptr->bi_key == BaseitemKey(ItemKindType::GLOVES, SV_SET_OF_DRAGON_GLOVES)) {
214 if (o_ptr->bi_key == BaseitemKey(ItemKindType::BOOTS, SV_PAIR_OF_DRAGON_GREAVE)) {
218 if (o_ptr->bi_key == BaseitemKey(ItemKindType::HELM, SV_DRAGON_HELM)) {
222 if (o_ptr->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_SPEED) && !o_ptr->is_cursed()) {
226 if (o_ptr->bi_key == BaseitemKey(ItemKindType::RING, SV_RING_LORDLY) && !o_ptr->is_cursed()) {
230 if (o_ptr->bi_key == BaseitemKey(ItemKindType::AMULET, SV_AMULET_THE_MAGI) && !o_ptr->is_cursed()) {
234 const auto &baseitem = o_ptr->get_baseitem();
235 if (!o_ptr->is_cursed() && !o_ptr->is_broken() && baseitem.level > floor_ptr->dun_level) {
236 delta += (baseitem.level - floor_ptr->dun_level) * base;
239 rating += rating_boost(delta);
242 if (rating > rating_boost(1000)) {
246 if (rating > rating_boost(800)) {
250 if (rating > rating_boost(600)) {
254 if (rating > rating_boost(400)) {
258 if (rating > rating_boost(300)) {
262 if (rating > rating_boost(200)) {
266 if (rating > rating_boost(100)) {
270 if (rating > rating_boost(0)) {
278 * @brief ダンジョンの雰囲気を更新し、変化があった場合メッセージを表示する
279 * / Update dungeon feeling, and announce it if changed
281 void update_dungeon_feeling(PlayerType *player_ptr)
283 const auto &floor = *player_ptr->current_floor_ptr;
284 if (!floor.dun_level) {
288 if (player_ptr->phase_out) {
292 int delay = std::max(10, 150 - player_ptr->skill_fos) * (150 - floor.dun_level) * TURNS_PER_TICK / 100;
293 if (w_ptr->game_turn < player_ptr->feeling_turn + delay && !cheat_xtra) {
297 auto quest_num = floor.get_quest_id();
298 const auto &quest_list = QuestList::get_instance();
300 auto dungeon_quest = (quest_num == QuestId::OBERON);
301 dungeon_quest |= (quest_num == QuestId::SERPENT);
302 dungeon_quest |= !(quest_list[quest_num].flags & QUEST_FLAG_PRESET);
304 auto feeling_quest = inside_quest(quest_num);
305 feeling_quest &= QuestType::is_fixed(quest_num);
306 feeling_quest &= !dungeon_quest;
310 byte new_feeling = get_dungeon_feeling(player_ptr);
311 player_ptr->feeling_turn = w_ptr->game_turn;
312 if (player_ptr->feeling == new_feeling) {
316 player_ptr->feeling = new_feeling;
317 do_cmd_feeling(player_ptr);
318 select_floor_music(player_ptr);
319 RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::DEPTH);
321 disturb(player_ptr, false, false);
326 * Glow deep lava and building entrances in the floor
328 void glow_deep_lava_and_bldg(PlayerType *player_ptr)
330 auto *floor_ptr = player_ptr->current_floor_ptr;
331 if (floor_ptr->get_dungeon_definition().flags.has(DungeonFeatureType::DARKNESS)) {
335 for (POSITION y = 0; y < floor_ptr->height; y++) {
336 for (POSITION x = 0; x < floor_ptr->width; x++) {
338 g_ptr = &floor_ptr->grid_array[y][x];
339 if (terrains_info[g_ptr->get_feat_mimic()].flags.has_not(TerrainCharacteristics::GLOW)) {
343 for (DIRECTION i = 0; i < 9; i++) {
344 POSITION yy = y + ddy_ddd[i];
345 POSITION xx = x + ddx_ddd[i];
346 if (!in_bounds2(floor_ptr, yy, xx)) {
350 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
355 auto &rfu = RedrawingFlagsUpdater::get_instance();
356 static constexpr auto flags_srf = {
357 StatusRecalculatingFlag::VIEW,
358 StatusRecalculatingFlag::LITE,
359 StatusRecalculatingFlag::MONSTER_LITE,
361 rfu.set_flags(flags_srf);
362 rfu.set_flag(MainWindowRedrawingFlag::MAP);
366 * Actually erase the entire "lite" array, redrawing every grid
368 void forget_lite(FloorType *floor_ptr)
370 if (!floor_ptr->lite_n) {
374 for (int i = 0; i < floor_ptr->lite_n; i++) {
375 POSITION y = floor_ptr->lite_y[i];
376 POSITION x = floor_ptr->lite_x[i];
377 floor_ptr->grid_array[y][x].info &= ~(CAVE_LITE);
380 floor_ptr->lite_n = 0;
384 * Clear the viewable space
386 void forget_view(FloorType *floor_ptr)
388 if (!floor_ptr->view_n) {
392 for (int i = 0; i < floor_ptr->view_n; i++) {
393 POSITION y = floor_ptr->view_y[i];
394 POSITION x = floor_ptr->view_x[i];
396 g_ptr = &floor_ptr->grid_array[y][x];
397 g_ptr->info &= ~(CAVE_VIEW);
400 floor_ptr->view_n = 0;