OSDN Git Service

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