3 #include "floor-save.h"
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
14 floor_type floor_info;
17 * The array of saved floors
19 saved_floor_type saved_floors[MAX_SAVED_FLOORS];
22 * @brief 鍵のかかったドアを配置する
23 * @param y 配置したいフロアのY座標
24 * @param x 配置したいフロアのX座標
27 void place_locked_door(floor_type *floor_ptr, POSITION y, POSITION x)
29 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
31 place_floor_bold(floor_ptr, y, x);
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);
44 * @param y 配置したいフロアのY座標
45 * @param x 配置したいフロアのX座標
46 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
49 void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
51 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
53 place_floor_bold(floor_ptr, y, x);
57 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
59 if (type == DOOR_DEFAULT)
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);
66 /* Create secret door */
67 place_closed_door(y, x, type);
69 if (type != DOOR_CURTAIN)
71 /* Hide by inner wall because this is used in rooms only */
72 g_ptr->mimic = feat_wall_inner;
74 /* Floor type terrain cannot hide a door */
75 if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
77 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
79 g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
85 g_ptr->info &= ~(CAVE_FLOOR);
90 static int scent_when = 0;
93 * Characters leave scent trails for perceptive monsters to track.
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.
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.
105 * Whenever the age count loops, most of the scent trail is erased and
106 * the age of the remainder is recalculated.
108 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
113 /* Create a table that controls the spread of scent */
114 const int scent_adjust[5][5] =
123 /* Loop the age and adjust scent values when necessary */
124 if (++scent_when == 254)
126 /* Scan the entire dungeon */
127 for (y = 0; y < floor_ptr->height; y++)
129 for (x = 0; x < floor_ptr->width; x++)
131 int w = floor_ptr->grid_array[y][x].when;
132 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
141 /* Lay down new scent */
142 for (i = 0; i < 5; i++)
144 for (j = 0; j < 5; j++)
148 /* Translate table to map grids */
149 y = i + subject_ptr->y - 2;
150 x = j + subject_ptr->x - 2;
153 if (!in_bounds(floor_ptr, y, x)) continue;
155 g_ptr = &floor_ptr->grid_array[y][x];
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;
160 /* Grid must not be blocked by walls from the character */
161 if (!player_has_los_bold(subject_ptr, y, x)) continue;
163 /* Note grids that are too far away */
164 if (scent_adjust[i][j] == -1) continue;
166 /* Mark the grid with new scent */
167 g_ptr->when = scent_when + scent_adjust[i][j];
174 * Hack -- forget the "flow" information
176 void forget_flow(floor_type *floor_ptr)
180 /* Check the entire dungeon */
181 for (y = 0; y < floor_ptr->height; y++)
183 for (x = 0; x < floor_ptr->width; x++)
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;
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.
197 * The doors must be INSIDE the allocated region.
199 void add_door(floor_type* floor_ptr, POSITION x, POSITION y)
201 /* Need to have a wall in the center square */
202 if (!is_outer_bold(floor_ptr, y, x)) return;
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)))
217 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
219 /* set boundarys so don't get wide doors */
220 place_solid_bold(y, x - 1);
221 place_solid_bold(y, x + 1);
230 * where x = don't care
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))
237 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
239 /* set boundarys so don't get wide doors */
240 place_solid_bold(y - 1, x);
241 place_solid_bold(y + 1, x);
246 * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
247 * @param y 配置を試みたいマスのY座標
248 * @param x 配置を試みたいマスのX座標
251 void place_random_stairs(floor_type *floor_ptr, POSITION y, POSITION x)
253 bool up_stairs = TRUE;
254 bool down_stairs = TRUE;
256 g_ptr = &floor_ptr->grid_array[y][x];
257 if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
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;
264 /* We can't place both */
265 if (down_stairs && up_stairs)
267 /* Choose a staircase randomly */
268 if (randint0(100) < 50) up_stairs = FALSE;
269 else down_stairs = FALSE;
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);
278 * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
283 * @return LOSが通っているならTRUEを返す。
285 * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,\n
286 * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n
288 * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
290 * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
291 * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line\n
292 * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
294 * We assume that the "mathematical corner" of a non-floor tile does not\n
295 * block line of sight.\n
297 * Because this function uses (short) ints for all calculations, overflow may\n
298 * occur if dx and dy exceed 90.\n
300 * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
301 * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
302 * we can use integer arithmetic.\n
304 * We travel from start to finish along the longer axis, starting at the border\n
305 * between the first and second tiles, where the y offset = .5 * slope, taking\n
306 * into account the scale factor. See below.\n
308 * Also note that this function and the "move towards target" code do NOT\n
309 * share the same properties. Thus, you can see someone, target them, and\n
310 * then fire a bolt at them, but the bolt may hit a wall, not them. However\n,
311 * by clever choice of target locations, you can sometimes throw a "curve".\n
313 * Note that "line of sight" is not "reflexive" in all cases.\n
315 * Use the "projectable()" routine to test "spell/missile line of sight".\n
317 * Use the "update_view()" function to determine player line-of-sight.\n
319 bool los(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
339 /* Slope, or 1/Slope, of LOS */
343 /* Extract the offset */
347 /* Extract the absolute offset */
352 /* Handle adjacent (or identical) grids */
353 if ((ax < 2) && (ay < 2)) return TRUE;
356 /* Paranoia -- require "safe" origin */
357 /* if (!in_bounds(floor_ptr, y1, x1)) return FALSE; */
358 /* if (!in_bounds(floor_ptr, y2, x2)) return FALSE; */
361 /* Directly South/North */
364 /* South -- check for walls */
367 for (ty = y1 + 1; ty < y2; ty++)
369 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
373 /* North -- check for walls */
376 for (ty = y1 - 1; ty > y2; ty--)
378 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
386 /* Directly East/West */
389 /* East -- check for walls */
392 for (tx = x1 + 1; tx < x2; tx++)
394 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
398 /* West -- check for walls */
401 for (tx = x1 - 1; tx > x2; tx--)
403 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
412 /* Extract some signs */
413 sx = (dx < 0) ? -1 : 1;
414 sy = (dy < 0) ? -1 : 1;
417 /* Vertical "knights" */
422 if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
426 /* Horizontal "knights" */
431 if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
436 /* Calculate scale factor div 2 */
439 /* Calculate scale factor */
443 /* Travel horizontally */
446 /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
452 /* Consider the special case where slope == 1. */
463 /* Note (below) the case (qy == f2), where */
464 /* the LOS exactly meets the corner of a tile. */
467 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
478 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
491 /* Travel vertically */
494 /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
510 /* Note (below) the case (qx == f2), where */
511 /* the LOS exactly meets the corner of a tile. */
514 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
525 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
544 * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
545 * at the final destination, assuming no monster gets in the way.
547 * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
549 bool projectable(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
556 /* Check the projection path */
557 grid_n = project_path(grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
560 if (!grid_n) return TRUE;
563 y = GRID_Y(grid_g[grid_n - 1]);
564 x = GRID_X(grid_g[grid_n - 1]);
566 /* May not end in an unrequested grid */
567 if ((y != y2) || (x != x2)) return (FALSE);
575 * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
576 * @param y1 モンスターを配置したいマスの中心Y座標
577 * @param x1 モンスターを配置したいマスの中心X座標
578 * @param num 配置したいモンスターの数
581 * Only really called by some of the "vault" routines.
583 void vault_monsters(floor_type *floor_ptr, POSITION y1, POSITION x1, int num)
589 /* Try to summon "num" monsters "near" the given location */
590 for (k = 0; k < num; k++)
592 /* Try nine locations */
593 for (i = 0; i < 9; i++)
597 /* Pick a nearby location */
598 scatter(&y, &x, y1, x1, d, 0);
600 /* Require "empty" floor grids */
601 g_ptr = &floor_ptr->grid_array[y][x];
602 if (!cave_empty_grid(g_ptr)) continue;
604 /* Place the monster (allow groups) */
605 floor_ptr->monster_level = floor_ptr->base_level + 2;
606 (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
607 floor_ptr->monster_level = floor_ptr->base_level;