OSDN Git Service

[Refactor] #38997 place_floor_bold() に floor_type * 引数を追加. / Add floor_type * argumen...
[hengband/hengband.git] / src / floor.c
1 #include "angband.h"
2 #include "floor.h"
3 #include "floor-save.h"
4 #include "grid.h"
5 #include "dungeon.h"
6 #include "rooms.h"
7 #include "quest.h"
8
9 /*
10  * The array of floor [MAX_WID][MAX_HGT].
11  * Not completely allocated, that would be inefficient
12  * Not completely hardcoded, that would overflow memory
13  */
14 floor_type floor_info;
15
16 /*
17  * The array of saved floors
18  */
19 saved_floor_type saved_floors[MAX_SAVED_FLOORS];
20
21 /*!
22 * @brief 鍵のかかったドアを配置する
23 * @param y 配置したいフロアのY座標
24 * @param x 配置したいフロアのX座標
25 * @return なし
26 */
27 void place_locked_door(floor_type *floor_ptr, POSITION y, POSITION x)
28 {
29         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
30         {
31                 place_floor_bold(floor_ptr, y, x);
32         }
33         else
34         {
35                 set_cave_feat(floor_ptr, y, x, feat_locked_door_random((d_info[p_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
36                 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
37                 delete_monster(y, x);
38         }
39 }
40
41
42 /*!
43 * @brief 隠しドアを配置する
44 * @param y 配置したいフロアのY座標
45 * @param x 配置したいフロアのX座標
46 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
47 * @return なし
48 */
49 void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
50 {
51         if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
52         {
53                 place_floor_bold(floor_ptr, y, x);
54         }
55         else
56         {
57                 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
58
59                 if (type == DOOR_DEFAULT)
60                 {
61                         type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
62                                 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
63                                 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
64                 }
65
66                 /* Create secret door */
67                 place_closed_door(y, x, type);
68
69                 if (type != DOOR_CURTAIN)
70                 {
71                         /* Hide by inner wall because this is used in rooms only */
72                         g_ptr->mimic = feat_wall_inner;
73
74                         /* Floor type terrain cannot hide a door */
75                         if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
76                         {
77                                 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
78                                 {
79                                         g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
80                                 }
81                                 g_ptr->mimic = 0;
82                         }
83                 }
84
85                 g_ptr->info &= ~(CAVE_FLOOR);
86                 delete_monster(y, x);
87         }
88 }
89
90 static int scent_when = 0;
91
92 /*
93  * Characters leave scent trails for perceptive monsters to track.
94  *
95  * Smell is rather more limited than sound.  Many creatures cannot use
96  * it at all, it doesn't extend very far outwards from the character's
97  * current position, and monsters can use it to home in the character,
98  * but not to run away from him.
99  *
100  * Smell is valued according to age.  When a character takes his turn,
101  * scent is aged by one, and new scent of the current age is laid down.
102  * Speedy characters leave more scent, true, but it also ages faster,
103  * which makes it harder to hunt them down.
104  *
105  * Whenever the age count loops, most of the scent trail is erased and
106  * the age of the remainder is recalculated.
107  */
108 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
109 {
110         POSITION i, j;
111         POSITION y, x;
112
113         /* Create a table that controls the spread of scent */
114         const int scent_adjust[5][5] =
115         {
116                 { -1, 0, 0, 0,-1 },
117                 {  0, 1, 1, 1, 0 },
118                 {  0, 1, 2, 1, 0 },
119                 {  0, 1, 1, 1, 0 },
120                 { -1, 0, 0, 0,-1 },
121         };
122
123         /* Loop the age and adjust scent values when necessary */
124         if (++scent_when == 254)
125         {
126                 /* Scan the entire dungeon */
127                 for (y = 0; y < floor_ptr->height; y++)
128                 {
129                         for (x = 0; x < floor_ptr->width; x++)
130                         {
131                                 int w = floor_ptr->grid_array[y][x].when;
132                                 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
133                         }
134                 }
135
136                 /* Restart */
137                 scent_when = 126;
138         }
139
140
141         /* Lay down new scent */
142         for (i = 0; i < 5; i++)
143         {
144                 for (j = 0; j < 5; j++)
145                 {
146                         grid_type *g_ptr;
147
148                         /* Translate table to map grids */
149                         y = i + subject_ptr->y - 2;
150                         x = j + subject_ptr->x - 2;
151
152                         /* Check Bounds */
153                         if (!in_bounds(floor_ptr, y, x)) continue;
154
155                         g_ptr = &floor_ptr->grid_array[y][x];
156
157                         /* Walls, water, and lava cannot hold scent. */
158                         if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
159
160                         /* Grid must not be blocked by walls from the character */
161                         if (!player_has_los_bold(subject_ptr, y, x)) continue;
162
163                         /* Note grids that are too far away */
164                         if (scent_adjust[i][j] == -1) continue;
165
166                         /* Mark the grid with new scent */
167                         g_ptr->when = scent_when + scent_adjust[i][j];
168                 }
169         }
170 }
171
172
173 /*
174  * Hack -- forget the "flow" information
175  */
176 void forget_flow(floor_type *floor_ptr)
177 {
178         POSITION x, y;
179
180         /* Check the entire dungeon */
181         for (y = 0; y < floor_ptr->height; y++)
182         {
183                 for (x = 0; x < floor_ptr->width; x++)
184                 {
185                         /* Forget the old data */
186                         floor_ptr->grid_array[y][x].dist = 0;
187                         floor_ptr->grid_array[y][x].cost = 0;
188                         floor_ptr->grid_array[y][x].when = 0;
189                 }
190         }
191 }
192
193 /*
194  * Routine used by the random vault creators to add a door to a location
195  * Note that range checking has to be done in the calling routine.
196  *
197  * The doors must be INSIDE the allocated region.
198  */
199 void add_door(floor_type* floor_ptr, POSITION x, POSITION y)
200 {
201         /* Need to have a wall in the center square */
202         if (!is_outer_bold(floor_ptr, y, x)) return;
203
204         /* look at:
205         *  x#x
206         *  .#.
207         *  x#x
208         *
209         *  where x=don't care
210         *  .=floor, #=wall
211         */
212
213         if (is_floor_bold(floor_ptr, y - 1, x) && is_floor_bold(floor_ptr, y + 1, x) &&
214                 (is_outer_bold(floor_ptr, y, x - 1) && is_outer_bold(floor_ptr, y, x + 1)))
215         {
216                 /* secret door */
217                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
218
219                 /* set boundarys so don't get wide doors */
220                 place_solid_bold(y, x - 1);
221                 place_solid_bold(y, x + 1);
222         }
223
224
225         /* look at:
226         *  x#x
227         *  .#.
228         *  x#x
229         *
230         *  where x = don't care
231         *  .=floor, #=wall
232         */
233         if (is_outer_bold(floor_ptr, y - 1, x) && is_outer_bold(floor_ptr, y + 1, x) &&
234                 is_floor_bold(floor_ptr, y, x - 1) && is_floor_bold(floor_ptr, y, x + 1))
235         {
236                 /* secret door */
237                 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
238
239                 /* set boundarys so don't get wide doors */
240                 place_solid_bold(y - 1, x);
241                 place_solid_bold(y + 1, x);
242         }
243 }
244
245 /*!
246  * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
247  * @param y 配置を試みたいマスのY座標
248  * @param x 配置を試みたいマスのX座標
249  * @return なし
250  */
251 void place_random_stairs(floor_type *floor_ptr, POSITION y, POSITION x)
252 {
253         bool up_stairs = TRUE;
254         bool down_stairs = TRUE;
255         grid_type *g_ptr;
256         g_ptr = &floor_ptr->grid_array[y][x];
257         if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
258
259         if (!floor_ptr->dun_level) up_stairs = FALSE;
260         if (ironman_downward) up_stairs = FALSE;
261         if (floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
262         if (quest_number(floor_ptr->dun_level) && (floor_ptr->dun_level > 1)) down_stairs = FALSE;
263
264         /* We can't place both */
265         if (down_stairs && up_stairs)
266         {
267                 /* Choose a staircase randomly */
268                 if (randint0(100) < 50) up_stairs = FALSE;
269                 else down_stairs = FALSE;
270         }
271
272         /* Place the stairs */
273         if (up_stairs) set_cave_feat(floor_ptr, y, x, feat_up_stair);
274         else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
275 }
276