OSDN Git Service

Merge remote-tracking branch 'remotes/origin/feature/Fix-saved-floor-exceed' into...
[hengband/hengband.git] / src / grid / feature.c
1 #include "grid/feature.h"
2 #include "core/player-update-types.h"
3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "floor/cave.h"
6 #include "game-option/map-screen-options.h"
7 #include "grid/grid.h"
8 #include "grid/lighting-colors-table.h"
9 #include "mind/mind-ninja.h"
10 #include "monster/monster-update.h"
11 #include "player/special-defense-types.h"
12 #include "room/door-definition.h"
13 #include "system/floor-type-definition.h"
14 #include "util/bit-flags-calculator.h"
15 #include "world/world.h"
16
17 /*** Terrain feature variables ***/
18
19 /* The terrain feature arrays */
20 feature_type *f_info;
21 char *f_name;
22 char *f_tag;
23
24 /* Nothing */
25 FEAT_IDX feat_none;
26
27 /* Floor */
28 FEAT_IDX feat_floor;
29
30 /* Objects */
31 FEAT_IDX feat_glyph;
32 FEAT_IDX feat_explosive_rune;
33 FEAT_IDX feat_mirror;
34
35 /* Stairs */
36 FEAT_IDX feat_up_stair;
37 FEAT_IDX feat_down_stair;
38 FEAT_IDX feat_entrance;
39
40 /* Special traps */
41 FEAT_IDX feat_trap_open;
42 FEAT_IDX feat_trap_armageddon;
43 FEAT_IDX feat_trap_piranha;
44
45 /* Rubble */
46 FEAT_IDX feat_rubble;
47
48 /* Seams */
49 FEAT_IDX feat_magma_vein;
50 FEAT_IDX feat_quartz_vein;
51
52 /* Walls */
53 FEAT_IDX feat_granite;
54 FEAT_IDX feat_permanent;
55
56 /* Glass floor */
57 FEAT_IDX feat_glass_floor;
58
59 /* Glass walls */
60 FEAT_IDX feat_glass_wall;
61 FEAT_IDX feat_permanent_glass_wall;
62
63 /* Pattern */
64 FEAT_IDX feat_pattern_start;
65 FEAT_IDX feat_pattern_1;
66 FEAT_IDX feat_pattern_2;
67 FEAT_IDX feat_pattern_3;
68 FEAT_IDX feat_pattern_4;
69 FEAT_IDX feat_pattern_end;
70 FEAT_IDX feat_pattern_old;
71 FEAT_IDX feat_pattern_exit;
72 FEAT_IDX feat_pattern_corrupted;
73
74 /* Various */
75 FEAT_IDX feat_black_market;
76 FEAT_IDX feat_town;
77
78 /* Terrains */
79 FEAT_IDX feat_deep_water;
80 FEAT_IDX feat_shallow_water;
81 FEAT_IDX feat_deep_lava;
82 FEAT_IDX feat_shallow_lava;
83 FEAT_IDX feat_heavy_cold_zone;
84 FEAT_IDX feat_cold_zone;
85 FEAT_IDX feat_heavy_electrical_zone;
86 FEAT_IDX feat_electrical_zone;
87 FEAT_IDX feat_deep_acid_puddle;
88 FEAT_IDX feat_shallow_acid_puddle;
89 FEAT_IDX feat_deep_poisonous_puddle;
90 FEAT_IDX feat_shallow_poisonous_puddle;
91 FEAT_IDX feat_dirt;
92 FEAT_IDX feat_grass;
93 FEAT_IDX feat_flower;
94 FEAT_IDX feat_brake;
95 FEAT_IDX feat_tree;
96 FEAT_IDX feat_mountain;
97 FEAT_IDX feat_swamp;
98
99 /* Unknown grid (not detected) */
100 FEAT_IDX feat_undetected;
101
102 FEAT_IDX feat_wall_outer;
103 FEAT_IDX feat_wall_inner;
104 FEAT_IDX feat_wall_solid;
105 FEAT_IDX feat_ground_type[100], feat_wall_type[100];
106
107 /*
108  * Maximum number of terrain features in f_info.txt
109  */
110 FEAT_IDX max_f_idx;
111
112 /*!
113  * @brief 地形が罠持ちであるかの判定を行う。 / Return TRUE if the given feature is a trap
114  * @param feat 地形情報のID
115  * @return 罠持ちの地形ならばTRUEを返す。
116  */
117 bool is_trap(player_type *player_ptr, FEAT_IDX feat)
118 {
119         /* 関数ポインタの都合 */
120         (void)player_ptr;
121         return has_flag(f_info[feat].flags, FF_TRAP);
122 }
123
124 /*!
125  * @brief 地形が閉じたドアであるかの判定を行う。 / Return TRUE if the given grid is a closed door
126  * @param feat 地形情報のID
127  * @return 閉じたドアのある地形ならばTRUEを返す。
128  */
129 bool is_closed_door(player_type *player_ptr, FEAT_IDX feat)
130 {
131         /* 関数ポインタの都合 */
132         (void)player_ptr;
133         feature_type *f_ptr = &f_info[feat];
134
135         return (has_flag(f_ptr->flags, FF_OPEN) || has_flag(f_ptr->flags, FF_BASH)) &&
136                 !has_flag(f_ptr->flags, FF_MOVE);
137 }
138
139 /*!
140  * @brief 調査中
141  * @todo コメントを付加すること
142  */
143 void apply_default_feat_lighting(TERM_COLOR *f_attr, SYMBOL_CODE *f_char)
144 {
145     TERM_COLOR s_attr = f_attr[F_LIT_STANDARD];
146     SYMBOL_CODE s_char = f_char[F_LIT_STANDARD];
147
148     if (is_ascii_graphics(s_attr)) /* For ASCII */
149     {
150         f_attr[F_LIT_LITE] = lighting_colours[s_attr & 0x0f][0];
151         f_attr[F_LIT_DARK] = lighting_colours[s_attr & 0x0f][1];
152         for (int i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
153             f_char[i] = s_char;
154     } else /* For tile graphics */
155     {
156         for (int i = F_LIT_NS_BEGIN; i < F_LIT_MAX; i++)
157             f_attr[i] = s_attr;
158         f_char[F_LIT_LITE] = s_char + 2;
159         f_char[F_LIT_DARK] = s_char + 1;
160     }
161 }
162
163 /*
164  * Not using graphical tiles for this feature?
165  */
166 bool is_ascii_graphics(char x) { return (x & 0x80) == 0; }
167
168 /*
169  * Determine if a "feature" is "permanent wall"
170  */
171 bool permanent_wall(feature_type *f_ptr) { return has_flag(f_ptr->flags, FF_WALL) && has_flag(f_ptr->flags, FF_PERMANENT); }
172
173 FEAT_IDX feat_locked_door_random(int door_type)
174 {
175     return feat_door[door_type].num_locked ? feat_door[door_type].locked[randint0(feat_door[door_type].num_locked)] : feat_none;
176 }
177
178 FEAT_IDX feat_jammed_door_random(int door_type)
179 {
180     return feat_door[door_type].num_jammed ? feat_door[door_type].jammed[randint0(feat_door[door_type].num_jammed)] : feat_none;
181 }
182
183 /*
184  * Determine if a "legal" grid is within "los" of the player *
185  * Note the use of comparison to zero to force a "boolean" result
186  */
187 static bool player_has_los_grid(grid_type *g_ptr) { return (g_ptr->info & CAVE_VIEW) != 0; }
188
189 /*
190  * Change the "feat" flag for a grid, and notice/redraw the grid
191  */
192 void cave_set_feat(player_type *player_ptr, POSITION y, POSITION x, FEAT_IDX feat)
193 {
194     floor_type *floor_ptr = player_ptr->current_floor_ptr;
195     grid_type *g_ptr = &floor_ptr->grid_array[y][x];
196     feature_type *f_ptr = &f_info[feat];
197     if (!current_world_ptr->character_dungeon) {
198         g_ptr->mimic = 0;
199         g_ptr->feat = feat;
200         if (has_flag(f_ptr->flags, FF_GLOW) && !(d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) {
201             for (DIRECTION i = 0; i < 9; i++) {
202                 POSITION yy = y + ddy_ddd[i];
203                 POSITION xx = x + ddx_ddd[i];
204                 if (!in_bounds2(floor_ptr, yy, xx))
205                     continue;
206
207                 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
208             }
209         }
210
211         return;
212     }
213
214     bool old_los = cave_has_flag_bold(floor_ptr, y, x, FF_LOS);
215     bool old_mirror = is_mirror_grid(g_ptr);
216
217     g_ptr->mimic = 0;
218     g_ptr->feat = feat;
219     g_ptr->info &= ~(CAVE_OBJECT);
220     if (old_mirror && (d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS)) {
221         g_ptr->info &= ~(CAVE_GLOW);
222         if (!view_torch_grids)
223             g_ptr->info &= ~(CAVE_MARK);
224
225         update_local_illumination(player_ptr, y, x);
226     }
227
228     if (!has_flag(f_ptr->flags, FF_REMEMBER))
229         g_ptr->info &= ~(CAVE_MARK);
230     if (g_ptr->m_idx)
231         update_monster(player_ptr, g_ptr->m_idx, FALSE);
232
233     note_spot(player_ptr, y, x);
234     lite_spot(player_ptr, y, x);
235     if (old_los ^ has_flag(f_ptr->flags, FF_LOS))
236         player_ptr->update |= PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS;
237
238     if (!has_flag(f_ptr->flags, FF_GLOW) || (d_info[player_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
239         return;
240
241     for (DIRECTION i = 0; i < 9; i++) {
242         POSITION yy = y + ddy_ddd[i];
243         POSITION xx = x + ddx_ddd[i];
244         if (!in_bounds2(floor_ptr, yy, xx))
245             continue;
246
247         grid_type *cc_ptr;
248         cc_ptr = &floor_ptr->grid_array[yy][xx];
249         cc_ptr->info |= CAVE_GLOW;
250
251         if (player_has_los_grid(cc_ptr)) {
252             if (cc_ptr->m_idx)
253                 update_monster(player_ptr, cc_ptr->m_idx, FALSE);
254             note_spot(player_ptr, yy, xx);
255             lite_spot(player_ptr, yy, xx);
256         }
257
258         update_local_illumination(player_ptr, yy, xx);
259     }
260
261     if (player_ptr->special_defense & NINJA_S_STEALTH) {
262         if (floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW)
263             set_superstealth(player_ptr, FALSE);
264     }
265 }
266
267 FEAT_IDX conv_dungeon_feat(floor_type *floor_ptr, FEAT_IDX newfeat)
268 {
269     feature_type *f_ptr = &f_info[newfeat];
270     if (!has_flag(f_ptr->flags, FF_CONVERT))
271         return newfeat;
272
273     switch (f_ptr->subtype) {
274     case CONVERT_TYPE_FLOOR:
275         return feat_ground_type[randint0(100)];
276     case CONVERT_TYPE_WALL:
277         return feat_wall_type[randint0(100)];
278     case CONVERT_TYPE_INNER:
279         return feat_wall_inner;
280     case CONVERT_TYPE_OUTER:
281         return feat_wall_outer;
282     case CONVERT_TYPE_SOLID:
283         return feat_wall_solid;
284     case CONVERT_TYPE_STREAM1:
285         return d_info[floor_ptr->dungeon_idx].stream1;
286     case CONVERT_TYPE_STREAM2:
287         return d_info[floor_ptr->dungeon_idx].stream2;
288     default:
289         return newfeat;
290     }
291 }