3 #include "floor-save.h"
8 #include "object-hook.h"
10 #include "player-effects.h"
12 #include "object-hook.h"
14 #include "objectkind.h"
17 * The array of floor [MAX_WID][MAX_HGT].
18 * Not completely allocated, that would be inefficient
19 * Not completely hardcoded, that would overflow memory
21 floor_type floor_info;
24 * The array of saved floors
26 saved_floor_type saved_floors[MAX_SAVED_FLOORS];
29 * @brief 鍵のかかったドアを配置する
30 * @param y 配置したいフロアのY座標
31 * @param x 配置したいフロアのX座標
34 void place_locked_door(floor_type *floor_ptr, POSITION y, POSITION x)
36 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
38 place_floor_bold(floor_ptr, y, x);
42 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));
43 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
51 * @param y 配置したいフロアのY座標
52 * @param x 配置したいフロアのX座標
53 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
56 void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
58 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
60 place_floor_bold(floor_ptr, y, x);
64 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
66 if (type == DOOR_DEFAULT)
68 type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
69 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
70 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
73 /* Create secret door */
74 place_closed_door(y, x, type);
76 if (type != DOOR_CURTAIN)
78 /* Hide by inner wall because this is used in rooms only */
79 g_ptr->mimic = feat_wall_inner;
81 /* Floor type terrain cannot hide a door */
82 if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
84 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
86 g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
92 g_ptr->info &= ~(CAVE_FLOOR);
97 static int scent_when = 0;
100 * Characters leave scent trails for perceptive monsters to track.
102 * Smell is rather more limited than sound. Many creatures cannot use
103 * it at all, it doesn't extend very far outwards from the character's
104 * current position, and monsters can use it to home in the character,
105 * but not to run away from him.
107 * Smell is valued according to age. When a character takes his turn,
108 * scent is aged by one, and new scent of the current age is laid down.
109 * Speedy characters leave more scent, true, but it also ages faster,
110 * which makes it harder to hunt them down.
112 * Whenever the age count loops, most of the scent trail is erased and
113 * the age of the remainder is recalculated.
115 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
120 /* Create a table that controls the spread of scent */
121 const int scent_adjust[5][5] =
130 /* Loop the age and adjust scent values when necessary */
131 if (++scent_when == 254)
133 /* Scan the entire dungeon */
134 for (y = 0; y < floor_ptr->height; y++)
136 for (x = 0; x < floor_ptr->width; x++)
138 int w = floor_ptr->grid_array[y][x].when;
139 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
148 /* Lay down new scent */
149 for (i = 0; i < 5; i++)
151 for (j = 0; j < 5; j++)
155 /* Translate table to map grids */
156 y = i + subject_ptr->y - 2;
157 x = j + subject_ptr->x - 2;
160 if (!in_bounds(floor_ptr, y, x)) continue;
162 g_ptr = &floor_ptr->grid_array[y][x];
164 /* Walls, water, and lava cannot hold scent. */
165 if (!cave_have_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(g_ptr->feat)) continue;
167 /* Grid must not be blocked by walls from the character */
168 if (!player_has_los_bold(subject_ptr, y, x)) continue;
170 /* Note grids that are too far away */
171 if (scent_adjust[i][j] == -1) continue;
173 /* Mark the grid with new scent */
174 g_ptr->when = scent_when + scent_adjust[i][j];
181 * Hack -- forget the "flow" information
183 void forget_flow(floor_type *floor_ptr)
187 /* Check the entire dungeon */
188 for (y = 0; y < floor_ptr->height; y++)
190 for (x = 0; x < floor_ptr->width; x++)
192 /* Forget the old data */
193 floor_ptr->grid_array[y][x].dist = 0;
194 floor_ptr->grid_array[y][x].cost = 0;
195 floor_ptr->grid_array[y][x].when = 0;
201 * Routine used by the random vault creators to add a door to a location
202 * Note that range checking has to be done in the calling routine.
204 * The doors must be INSIDE the allocated region.
206 void add_door(floor_type* floor_ptr, POSITION x, POSITION y)
208 /* Need to have a wall in the center square */
209 if (!is_outer_bold(floor_ptr, y, x)) return;
220 if (is_floor_bold(floor_ptr, y - 1, x) && is_floor_bold(floor_ptr, y + 1, x) &&
221 (is_outer_bold(floor_ptr, y, x - 1) && is_outer_bold(floor_ptr, y, x + 1)))
224 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
226 /* set boundarys so don't get wide doors */
227 place_solid_bold(y, x - 1);
228 place_solid_bold(y, x + 1);
237 * where x = don't care
240 if (is_outer_bold(floor_ptr, y - 1, x) && is_outer_bold(floor_ptr, y + 1, x) &&
241 is_floor_bold(floor_ptr, y, x - 1) && is_floor_bold(floor_ptr, y, x + 1))
244 place_secret_door(floor_ptr, y, x, DOOR_DEFAULT);
246 /* set boundarys so don't get wide doors */
247 place_solid_bold(y - 1, x);
248 place_solid_bold(y + 1, x);
253 * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
254 * @param y 配置を試みたいマスのY座標
255 * @param x 配置を試みたいマスのX座標
258 void place_random_stairs(floor_type *floor_ptr, POSITION y, POSITION x)
260 bool up_stairs = TRUE;
261 bool down_stairs = TRUE;
263 g_ptr = &floor_ptr->grid_array[y][x];
264 if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
266 if (!floor_ptr->dun_level) up_stairs = FALSE;
267 if (ironman_downward) up_stairs = FALSE;
268 if (floor_ptr->dun_level >= d_info[p_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
269 if (quest_number(floor_ptr->dun_level) && (floor_ptr->dun_level > 1)) down_stairs = FALSE;
271 /* We can't place both */
272 if (down_stairs && up_stairs)
274 /* Choose a staircase randomly */
275 if (randint0(100) < 50) up_stairs = FALSE;
276 else down_stairs = FALSE;
279 /* Place the stairs */
280 if (up_stairs) set_cave_feat(floor_ptr, y, x, feat_up_stair);
281 else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
285 * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
290 * @return LOSが通っているならTRUEを返す。
292 * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,\n
293 * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n
295 * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
297 * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
298 * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line\n
299 * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
301 * We assume that the "mathematical corner" of a non-floor tile does not\n
302 * block line of sight.\n
304 * Because this function uses (short) ints for all calculations, overflow may\n
305 * occur if dx and dy exceed 90.\n
307 * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
308 * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
309 * we can use integer arithmetic.\n
311 * We travel from start to finish along the longer axis, starting at the border\n
312 * between the first and second tiles, where the y offset = .5 * slope, taking\n
313 * into account the scale factor. See below.\n
315 * Also note that this function and the "move towards target" code do NOT\n
316 * share the same properties. Thus, you can see someone, target them, and\n
317 * then fire a bolt at them, but the bolt may hit a wall, not them. However\n,
318 * by clever choice of target locations, you can sometimes throw a "curve".\n
320 * Note that "line of sight" is not "reflexive" in all cases.\n
322 * Use the "projectable()" routine to test "spell/missile line of sight".\n
324 * Use the "update_view()" function to determine player line-of-sight.\n
326 bool los(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
346 /* Slope, or 1/Slope, of LOS */
350 /* Extract the offset */
354 /* Extract the absolute offset */
359 /* Handle adjacent (or identical) grids */
360 if ((ax < 2) && (ay < 2)) return TRUE;
363 /* Paranoia -- require "safe" origin */
364 /* if (!in_bounds(floor_ptr, y1, x1)) return FALSE; */
365 /* if (!in_bounds(floor_ptr, y2, x2)) return FALSE; */
368 /* Directly South/North */
371 /* South -- check for walls */
374 for (ty = y1 + 1; ty < y2; ty++)
376 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
380 /* North -- check for walls */
383 for (ty = y1 - 1; ty > y2; ty--)
385 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
393 /* Directly East/West */
396 /* East -- check for walls */
399 for (tx = x1 + 1; tx < x2; tx++)
401 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
405 /* West -- check for walls */
408 for (tx = x1 - 1; tx > x2; tx--)
410 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
419 /* Extract some signs */
420 sx = (dx < 0) ? -1 : 1;
421 sy = (dy < 0) ? -1 : 1;
424 /* Vertical "knights" */
429 if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
433 /* Horizontal "knights" */
438 if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
443 /* Calculate scale factor div 2 */
446 /* Calculate scale factor */
450 /* Travel horizontally */
453 /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
459 /* Consider the special case where slope == 1. */
470 /* Note (below) the case (qy == f2), where */
471 /* the LOS exactly meets the corner of a tile. */
474 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
485 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
498 /* Travel vertically */
501 /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
517 /* Note (below) the case (qx == f2), where */
518 /* the LOS exactly meets the corner of a tile. */
521 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
532 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
551 * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
552 * at the final destination, assuming no monster gets in the way.
554 * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
556 bool projectable(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
563 /* Check the projection path */
564 grid_n = project_path(grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
567 if (!grid_n) return TRUE;
570 y = GRID_Y(grid_g[grid_n - 1]);
571 x = GRID_X(grid_g[grid_n - 1]);
573 /* May not end in an unrequested grid */
574 if ((y != y2) || (x != x2)) return (FALSE);
582 * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
583 * @param y1 モンスターを配置したいマスの中心Y座標
584 * @param x1 モンスターを配置したいマスの中心X座標
585 * @param num 配置したいモンスターの数
588 * Only really called by some of the "vault" routines.
590 void vault_monsters(floor_type *floor_ptr, POSITION y1, POSITION x1, int num)
596 /* Try to summon "num" monsters "near" the given location */
597 for (k = 0; k < num; k++)
599 /* Try nine locations */
600 for (i = 0; i < 9; i++)
604 /* Pick a nearby location */
605 scatter(&y, &x, y1, x1, d, 0);
607 /* Require "empty" floor grids */
608 g_ptr = &floor_ptr->grid_array[y][x];
609 if (!cave_empty_grid(g_ptr)) continue;
611 /* Place the monster (allow groups) */
612 floor_ptr->monster_level = floor_ptr->base_level + 2;
613 (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
614 floor_ptr->monster_level = floor_ptr->base_level;
621 * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
624 * @return 各種の変更が可能ならTRUEを返す。
626 * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
628 bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
630 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
631 OBJECT_IDX this_o_idx, next_o_idx = 0;
633 /* Forbid perma-grids */
634 if (cave_perma_grid(g_ptr)) return (FALSE);
637 for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
640 o_ptr = &floor_ptr->o_list[this_o_idx];
641 next_o_idx = o_ptr->next_o_idx;
643 /* Forbid artifact grids */
644 if (object_is_artifact(o_ptr)) return (FALSE);
652 * Change the "feat" flag for a grid, and notice/redraw the grid
654 void cave_set_feat(floor_type *floor_ptr, POSITION y, POSITION x, FEAT_IDX feat)
656 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
657 feature_type *f_ptr = &f_info[feat];
658 bool old_los, old_mirror;
660 if (!current_world_ptr->character_dungeon)
662 /* Clear mimic type */
665 /* Change the feature */
668 /* Hack -- glow the GLOW terrain */
669 if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
674 for (i = 0; i < 9; i++)
678 if (!in_bounds2(floor_ptr, yy, xx)) continue;
679 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
686 old_los = cave_have_flag_bold(y, x, FF_LOS);
687 old_mirror = is_mirror_grid(g_ptr);
689 /* Clear mimic type */
692 /* Change the feature */
695 /* Remove flag for mirror/glyph */
696 g_ptr->info &= ~(CAVE_OBJECT);
698 if (old_mirror && (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
700 g_ptr->info &= ~(CAVE_GLOW);
701 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
703 update_local_illumination(p_ptr, y, x);
706 /* Check for change to boring grid */
707 if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
708 if (g_ptr->m_idx) update_monster(p_ptr, g_ptr->m_idx, FALSE);
713 /* Check if los has changed */
714 if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
717 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
719 update_local_illumination(p_ptr, y, x);
721 #endif /* COMPLEX_WALL_ILLUMINATION */
723 /* Update the visuals */
724 p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
727 /* Hack -- glow the GLOW terrain */
728 if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
734 for (i = 0; i < 9; i++)
738 if (!in_bounds2(floor_ptr, yy, xx)) continue;
739 cc_ptr = &floor_ptr->grid_array[yy][xx];
740 cc_ptr->info |= CAVE_GLOW;
742 if (player_has_los_grid(cc_ptr))
744 if (cc_ptr->m_idx) update_monster(p_ptr, cc_ptr->m_idx, FALSE);
749 update_local_illumination(p_ptr, yy, xx);
752 if (p_ptr->special_defense & NINJA_S_STEALTH)
754 if (floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(p_ptr, FALSE);
761 * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
762 * @param y ドアの配置を試みたいマスのY座標
763 * @param x ドアの配置を試みたいマスのX座標
764 * @param room 部屋に接している場合向けのドア生成か否か
767 void place_random_door(floor_type *floor_ptr, POSITION y, POSITION x, bool room)
770 FEAT_IDX feat = feat_none;
771 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
773 /* Initialize mimic info */
776 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
778 place_floor_bold(floor_ptr, y, x);
782 type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
783 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
784 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
786 /* Choose an object */
787 tmp = randint0(1000);
789 /* Open doors (300/1000) */
792 /* Create open door */
793 feat = feat_door[type].open;
796 /* Broken doors (100/1000) */
799 /* Create broken door */
800 feat = feat_door[type].broken;
803 /* Secret doors (200/1000) */
806 /* Create secret door */
807 place_closed_door(y, x, type);
809 if (type != DOOR_CURTAIN)
811 /* Hide. If on the edge of room, use outer wall. */
812 g_ptr->mimic = room ? feat_wall_outer : feat_wall_type[randint0(100)];
814 /* Floor type terrain cannot hide a door */
815 if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
817 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
819 g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
826 /* Closed, locked, or stuck doors (400/1000) */
827 else place_closed_door(y, x, type);
831 if (feat != feat_none)
833 set_cave_feat(floor_ptr, y, x, feat);
837 place_floor_bold(floor_ptr, y, x);
841 delete_monster(y, x);
847 * @brief グローバルオブジェクト配列を初期化する /
848 * Delete all the items when player leaves the level
849 * @note we do NOT visually reflect these (irrelevant) changes
851 * Hack -- we clear the "g_ptr->o_idx" field for every grid,
852 * and the "m_ptr->next_o_idx" field for every monster, since
853 * we know we are clearing every object. Technically, we only
854 * clear those fields for grids/monsters containing objects,
855 * and we clear it once for every such object.
858 void wipe_o_list(floor_type *floor_ptr)
862 /* Delete the existing objects */
863 for (i = 1; i < floor_ptr->o_max; i++)
865 object_type *o_ptr = &floor_ptr->o_list[i];
867 if (!OBJECT_IS_VALID(o_ptr)) continue;
869 /* Mega-Hack -- preserve artifacts */
870 if (!current_world_ptr->character_dungeon || preserve_mode)
872 /* Hack -- Preserve unknown artifacts */
873 if (object_is_fixed_artifact(o_ptr) && !object_is_known(o_ptr))
875 /* Mega-Hack -- Preserve the artifact */
876 a_info[o_ptr->name1].cur_num = 0;
880 if (OBJECT_IS_HELD_MONSTER(o_ptr))
883 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
885 /* Hack -- see above */
886 m_ptr->hold_o_idx = 0;
894 /* Access location */
895 POSITION y = o_ptr->iy;
896 POSITION x = o_ptr->ix;
899 g_ptr = &floor_ptr->grid_array[y][x];
901 /* Hack -- see above */
907 /* Reset "floor_ptr->o_max" */
908 floor_ptr->o_max = 1;
910 /* Reset "floor_ptr->o_cnt" */
911 floor_ptr->o_cnt = 0;