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"
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"
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,
32 /*** Terrain feature variables ***/
41 FEAT_IDX feat_rune_protection;
42 FEAT_IDX feat_rune_explosion;
46 FEAT_IDX feat_up_stair;
47 FEAT_IDX feat_down_stair;
48 FEAT_IDX feat_entrance;
51 FEAT_IDX feat_trap_open;
52 FEAT_IDX feat_trap_armageddon;
53 FEAT_IDX feat_trap_piranha;
59 FEAT_IDX feat_magma_vein;
60 FEAT_IDX feat_quartz_vein;
63 FEAT_IDX feat_granite;
64 FEAT_IDX feat_permanent;
67 FEAT_IDX feat_glass_floor;
70 FEAT_IDX feat_glass_wall;
71 FEAT_IDX feat_permanent_glass_wall;
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;
85 FEAT_IDX feat_black_market;
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;
103 FEAT_IDX feat_flower;
106 FEAT_IDX feat_mountain;
109 /* Unknown grid (not detected) */
110 FEAT_IDX feat_undetected;
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];
118 * @brief 地形が罠持ちであるかの判定を行う。 / Return TRUE if the given feature is a trap
119 * @param feat 地形情報のID
120 * @return 罠持ちの地形ならばTRUEを返す。
122 bool is_trap(PlayerType *player_ptr, FEAT_IDX feat)
126 return TerrainList::get_instance()[feat].flags.has(TerrainCharacteristics::TRAP);
130 * @brief 地形が閉じたドアであるかの判定を行う。 / Return TRUE if the given grid is a closed door
131 * @param feat 地形情報のID
132 * @return 閉じたドアのある地形ならばTRUEを返す。
134 bool is_closed_door(PlayerType *player_ptr, FEAT_IDX feat)
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);
147 void apply_default_feat_lighting(TERM_COLOR *f_attr, char *f_char)
149 TERM_COLOR s_attr = f_attr[F_LIT_STANDARD];
150 auto s_char = f_char[F_LIT_STANDARD];
152 if (is_ascii_graphics(s_attr)) /* For ASCII */
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++) {
159 } else /* For tile graphics */
161 for (int i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++) {
164 f_char[F_LIT_LITE] = s_char + 2;
165 f_char[F_LIT_DARK] = s_char + 1;
170 * Not using graphical tiles for this feature?
172 bool is_ascii_graphics(char x)
174 return (x & 0x80) == 0;
177 FEAT_IDX feat_locked_door_random(int door_type)
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);
184 FEAT_IDX feat_jammed_door_random(int door_type)
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);
192 * Change the "feat" flag for a grid, and notice/redraw the grid
194 void cave_set_feat(PlayerType *player_ptr, POSITION y, POSITION x, FEAT_IDX feat)
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) {
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)) {
211 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
218 bool old_los = cave_has_flag_bold(floor_ptr, y, x, TerrainCharacteristics::LOS);
219 bool old_mirror = g_ptr->is_mirror();
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);
230 update_local_illumination(player_ptr, y, x);
233 if (terrain.flags.has_not(TerrainCharacteristics::REMEMBER)) {
234 g_ptr->info &= ~(CAVE_MARK);
237 if (g_ptr->has_monster()) {
238 update_monster(player_ptr, g_ptr->m_idx, false);
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,
250 RedrawingFlagsUpdater::get_instance().set_flags(flags);
253 if (terrain.flags.has_not(TerrainCharacteristics::GLOW) || dungeon.flags.has(DungeonFeatureType::DARKNESS)) {
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)) {
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);
271 note_spot(player_ptr, yy, xx);
272 lite_spot(player_ptr, yy, xx);
275 update_local_illumination(player_ptr, yy, xx);
278 if (floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) {
279 set_superstealth(player_ptr, false);
283 FEAT_IDX conv_dungeon_feat(const FloorType *floor_ptr, FEAT_IDX newfeat)
285 const auto &terrain = TerrainList::get_instance()[newfeat];
286 if (terrain.flags.has_not(TerrainCharacteristics::CONVERT)) {
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;