OSDN Git Service

[Refactor] Grid::has_monster()の定義
[hengbandforosx/hengbandosx.git] / src / grid / feature.cpp
1 #include "grid/feature.h"
2 #include "dungeon/dungeon-flag-types.h"
3 #include "floor/cave.h"
4 #include "floor/geometry.h"
5 #include "game-option/map-screen-options.h"
6 #include "grid/grid.h"
7 #include "grid/lighting-colors-table.h"
8 #include "mind/mind-ninja.h"
9 #include "monster/monster-update.h"
10 #include "player/special-defense-types.h"
11 #include "room/door-definition.h"
12 #include "system/dungeon-info.h"
13 #include "system/floor-type-definition.h"
14 #include "system/grid-type-definition.h" // @todo 相互依存している. 後で何とかする.
15 #include "system/player-type-definition.h"
16 #include "system/redrawing-flags-updater.h"
17 #include "system/terrain-type-definition.h"
18 #include "util/bit-flags-calculator.h"
19 #include "world/world.h"
20 #include <span>
21
22 enum conversion_type {
23     CONVERT_TYPE_FLOOR = 0,
24     CONVERT_TYPE_WALL = 1,
25     CONVERT_TYPE_INNER = 2,
26     CONVERT_TYPE_OUTER = 3,
27     CONVERT_TYPE_SOLID = 4,
28     CONVERT_TYPE_STREAM1 = 5,
29     CONVERT_TYPE_STREAM2 = 6,
30 };
31
32 /*** Terrain feature variables ***/
33
34 /* Nothing */
35 FEAT_IDX feat_none;
36
37 /* Floor */
38 FEAT_IDX feat_floor;
39
40 /* Objects */
41 FEAT_IDX feat_rune_protection;
42 FEAT_IDX feat_rune_explosion;
43 FEAT_IDX feat_mirror;
44
45 /* Stairs */
46 FEAT_IDX feat_up_stair;
47 FEAT_IDX feat_down_stair;
48 FEAT_IDX feat_entrance;
49
50 /* Special traps */
51 FEAT_IDX feat_trap_open;
52 FEAT_IDX feat_trap_armageddon;
53 FEAT_IDX feat_trap_piranha;
54
55 /* Rubble */
56 FEAT_IDX feat_rubble;
57
58 /* Seams */
59 FEAT_IDX feat_magma_vein;
60 FEAT_IDX feat_quartz_vein;
61
62 /* Walls */
63 FEAT_IDX feat_granite;
64 FEAT_IDX feat_permanent;
65
66 /* Glass floor */
67 FEAT_IDX feat_glass_floor;
68
69 /* Glass walls */
70 FEAT_IDX feat_glass_wall;
71 FEAT_IDX feat_permanent_glass_wall;
72
73 /* Pattern */
74 FEAT_IDX feat_pattern_start;
75 FEAT_IDX feat_pattern_1;
76 FEAT_IDX feat_pattern_2;
77 FEAT_IDX feat_pattern_3;
78 FEAT_IDX feat_pattern_4;
79 FEAT_IDX feat_pattern_end;
80 FEAT_IDX feat_pattern_old;
81 FEAT_IDX feat_pattern_exit;
82 FEAT_IDX feat_pattern_corrupted;
83
84 /* Various */
85 FEAT_IDX feat_black_market;
86 FEAT_IDX feat_town;
87
88 /* Terrains */
89 FEAT_IDX feat_deep_water;
90 FEAT_IDX feat_shallow_water;
91 FEAT_IDX feat_deep_lava;
92 FEAT_IDX feat_shallow_lava;
93 FEAT_IDX feat_heavy_cold_zone;
94 FEAT_IDX feat_cold_zone;
95 FEAT_IDX feat_heavy_electrical_zone;
96 FEAT_IDX feat_electrical_zone;
97 FEAT_IDX feat_deep_acid_puddle;
98 FEAT_IDX feat_shallow_acid_puddle;
99 FEAT_IDX feat_deep_poisonous_puddle;
100 FEAT_IDX feat_shallow_poisonous_puddle;
101 FEAT_IDX feat_dirt;
102 FEAT_IDX feat_grass;
103 FEAT_IDX feat_flower;
104 FEAT_IDX feat_brake;
105 FEAT_IDX feat_tree;
106 FEAT_IDX feat_mountain;
107 FEAT_IDX feat_swamp;
108
109 /* Unknown grid (not detected) */
110 FEAT_IDX feat_undetected;
111
112 FEAT_IDX feat_wall_outer;
113 FEAT_IDX feat_wall_inner;
114 FEAT_IDX feat_wall_solid;
115 FEAT_IDX feat_ground_type[100], feat_wall_type[100];
116
117 /*!
118  * @brief 地形が罠持ちであるかの判定を行う。 / Return TRUE if the given feature is a trap
119  * @param feat 地形情報のID
120  * @return 罠持ちの地形ならばTRUEを返す。
121  */
122 bool is_trap(PlayerType *player_ptr, FEAT_IDX feat)
123 {
124     /* 関数ポインタの都合 */
125     (void)player_ptr;
126     return TerrainList::get_instance()[feat].flags.has(TerrainCharacteristics::TRAP);
127 }
128
129 /*!
130  * @brief 地形が閉じたドアであるかの判定を行う。 / Return TRUE if the given grid is a closed door
131  * @param feat 地形情報のID
132  * @return 閉じたドアのある地形ならばTRUEを返す。
133  */
134 bool is_closed_door(PlayerType *player_ptr, FEAT_IDX feat)
135 {
136     /* 関数ポインタの都合 */
137     (void)player_ptr;
138     const auto &terrain = TerrainList::get_instance()[feat];
139     return (terrain.flags.has(TerrainCharacteristics::OPEN) || terrain.flags.has(TerrainCharacteristics::BASH)) &&
140            terrain.flags.has_not(TerrainCharacteristics::MOVE);
141 }
142
143 /*!
144  * @brief 調査中
145  * @todo コメントを付加すること
146  */
147 void apply_default_feat_lighting(TERM_COLOR *f_attr, char *f_char)
148 {
149     TERM_COLOR s_attr = f_attr[F_LIT_STANDARD];
150     auto s_char = f_char[F_LIT_STANDARD];
151
152     if (is_ascii_graphics(s_attr)) /* For ASCII */
153     {
154         f_attr[F_LIT_LITE] = lighting_colours[s_attr & 0x0f][0];
155         f_attr[F_LIT_DARK] = lighting_colours[s_attr & 0x0f][1];
156         for (int i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) {
157             f_char[i] = s_char;
158         }
159     } else /* For tile graphics */
160     {
161         for (int i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) {
162             f_attr[i] = s_attr;
163         }
164         f_char[F_LIT_LITE] = s_char + 2;
165         f_char[F_LIT_DARK] = s_char + 1;
166     }
167 }
168
169 /*
170  * Not using graphical tiles for this feature?
171  */
172 bool is_ascii_graphics(char x)
173 {
174     return (x & 0x80) == 0;
175 }
176
177 FEAT_IDX feat_locked_door_random(int door_type)
178 {
179     const auto &door = feat_door[door_type];
180     std::span<const FEAT_IDX> candidates(std::begin(door.locked), door.num_locked);
181     return candidates.empty() ? feat_none : rand_choice(candidates);
182 }
183
184 FEAT_IDX feat_jammed_door_random(int door_type)
185 {
186     const auto &door = feat_door[door_type];
187     std::span<const FEAT_IDX> candidates(std::begin(door.jammed), door.num_jammed);
188     return candidates.empty() ? feat_none : rand_choice(candidates);
189 }
190
191 /*
192  * Change the "feat" flag for a grid, and notice/redraw the grid
193  */
194 void cave_set_feat(PlayerType *player_ptr, POSITION y, POSITION x, FEAT_IDX feat)
195 {
196     auto *floor_ptr = player_ptr->current_floor_ptr;
197     auto *g_ptr = &floor_ptr->grid_array[y][x];
198     const auto &terrain = TerrainList::get_instance()[feat];
199     const auto &dungeon = floor_ptr->get_dungeon_definition();
200     if (!w_ptr->character_dungeon) {
201         g_ptr->mimic = 0;
202         g_ptr->feat = feat;
203         if (terrain.flags.has(TerrainCharacteristics::GLOW) && dungeon.flags.has_not(DungeonFeatureType::DARKNESS)) {
204             for (DIRECTION i = 0; i < 9; i++) {
205                 POSITION yy = y + ddy_ddd[i];
206                 POSITION xx = x + ddx_ddd[i];
207                 if (!in_bounds2(floor_ptr, yy, xx)) {
208                     continue;
209                 }
210
211                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
212             }
213         }
214
215         return;
216     }
217
218     bool old_los = cave_has_flag_bold(floor_ptr, y, x, TerrainCharacteristics::LOS);
219     bool old_mirror = g_ptr->is_mirror();
220
221     g_ptr->mimic = 0;
222     g_ptr->feat = feat;
223     g_ptr->info &= ~(CAVE_OBJECT);
224     if (old_mirror && dungeon.flags.has(DungeonFeatureType::DARKNESS)) {
225         g_ptr->info &= ~(CAVE_GLOW);
226         if (!view_torch_grids) {
227             g_ptr->info &= ~(CAVE_MARK);
228         }
229
230         update_local_illumination(player_ptr, y, x);
231     }
232
233     if (terrain.flags.has_not(TerrainCharacteristics::REMEMBER)) {
234         g_ptr->info &= ~(CAVE_MARK);
235     }
236
237     if (g_ptr->has_monster()) {
238         update_monster(player_ptr, g_ptr->m_idx, false);
239     }
240
241     note_spot(player_ptr, y, x);
242     lite_spot(player_ptr, y, x);
243     if (old_los ^ terrain.flags.has(TerrainCharacteristics::LOS)) {
244         static constexpr auto flags = {
245             StatusRecalculatingFlag::VIEW,
246             StatusRecalculatingFlag::LITE,
247             StatusRecalculatingFlag::MONSTER_LITE,
248             StatusRecalculatingFlag::MONSTER_STATUSES,
249         };
250         RedrawingFlagsUpdater::get_instance().set_flags(flags);
251     }
252
253     if (terrain.flags.has_not(TerrainCharacteristics::GLOW) || dungeon.flags.has(DungeonFeatureType::DARKNESS)) {
254         return;
255     }
256
257     for (auto i = 0; i < 9; i++) {
258         POSITION yy = y + ddy_ddd[i];
259         POSITION xx = x + ddx_ddd[i];
260         if (!in_bounds2(floor_ptr, yy, xx)) {
261             continue;
262         }
263
264         auto *cc_ptr = &floor_ptr->grid_array[yy][xx];
265         cc_ptr->info |= CAVE_GLOW;
266         if (cc_ptr->is_view()) {
267             if (cc_ptr->has_monster()) {
268                 update_monster(player_ptr, cc_ptr->m_idx, false);
269             }
270
271             note_spot(player_ptr, yy, xx);
272             lite_spot(player_ptr, yy, xx);
273         }
274
275         update_local_illumination(player_ptr, yy, xx);
276     }
277
278     if (floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) {
279         set_superstealth(player_ptr, false);
280     }
281 }
282
283 FEAT_IDX conv_dungeon_feat(const FloorType *floor_ptr, FEAT_IDX newfeat)
284 {
285     const auto &terrain = TerrainList::get_instance()[newfeat];
286     if (terrain.flags.has_not(TerrainCharacteristics::CONVERT)) {
287         return newfeat;
288     }
289
290     const auto &dungeon = floor_ptr->get_dungeon_definition();
291     switch (terrain.subtype) {
292     case CONVERT_TYPE_FLOOR:
293         return rand_choice(feat_ground_type);
294     case CONVERT_TYPE_WALL:
295         return rand_choice(feat_wall_type);
296     case CONVERT_TYPE_INNER:
297         return feat_wall_inner;
298     case CONVERT_TYPE_OUTER:
299         return feat_wall_outer;
300     case CONVERT_TYPE_SOLID:
301         return feat_wall_solid;
302     case CONVERT_TYPE_STREAM1:
303         return dungeon.stream1;
304     case CONVERT_TYPE_STREAM2:
305         return dungeon.stream2;
306     default:
307         return newfeat;
308     }
309 }