3 #include "floor-save.h"
4 #include "floor-generate.h"
9 #include "object-hook.h"
11 #include "player-effects.h"
13 #include "object-hook.h"
15 #include "objectkind.h"
19 * The array of floor [MAX_WID][MAX_HGT].
20 * Not completely allocated, that would be inefficient
21 * Not completely hardcoded, that would overflow memory
23 floor_type floor_info;
26 * The array of saved floors
28 saved_floor_type saved_floors[MAX_SAVED_FLOORS];
31 * @brief 鍵のかかったドアを配置する
32 * @param player_ptr プレーヤーへの参照ポインタ
33 * @param y 配置したいフロアのY座標
34 * @param x 配置したいフロアのX座標
37 void place_locked_door(player_type *player_ptr, POSITION y, POSITION x)
39 floor_type *floor_ptr = player_ptr->current_floor_ptr;
40 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
42 place_bold(player_ptr, y, x, floor);
46 set_cave_feat(floor_ptr, y, x, feat_locked_door_random((d_info[player_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR));
47 floor_ptr->grid_array[y][x].info &= ~(CAVE_FLOOR);
48 delete_monster(player_ptr, y, x);
54 * @param player_ptr プレーヤーへの参照ポインタ
55 * @param y 配置したいフロアのY座標
56 * @param x 配置したいフロアのX座標
57 * @param type DOOR_DEFAULT / DOOR_DOOR / DOOR_GLASS_DOOR / DOOR_CURTAIN のいずれか
60 void place_secret_door(player_type *player_ptr, POSITION y, POSITION x, int type)
62 floor_type *floor_ptr = player_ptr->current_floor_ptr;
63 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
65 place_bold(player_ptr, y, x, floor);
69 if (type == DOOR_DEFAULT)
71 type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
72 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
73 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
76 /* Create secret door */
77 place_closed_door(player_ptr, y, x, type);
79 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
80 if (type != DOOR_CURTAIN)
82 /* Hide by inner wall because this is used in rooms only */
83 g_ptr->mimic = feat_wall_inner;
85 /* Floor type terrain cannot hide a door */
86 if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
88 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
90 g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
97 g_ptr->info &= ~(CAVE_FLOOR);
98 delete_monster(player_ptr, y, x);
101 static int scent_when = 0;
104 * Characters leave scent trails for perceptive monsters to track.
106 * Smell is rather more limited than sound. Many creatures cannot use
107 * it at all, it doesn't extend very far outwards from the character's
108 * current position, and monsters can use it to home in the character,
109 * but not to run away from him.
111 * Smell is valued according to age. When a character takes his turn,
112 * scent is aged by one, and new scent of the current age is laid down.
113 * Speedy characters leave more scent, true, but it also ages faster,
114 * which makes it harder to hunt them down.
116 * Whenever the age count loops, most of the scent trail is erased and
117 * the age of the remainder is recalculated.
119 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
121 /* Create a table that controls the spread of scent */
122 const int scent_adjust[5][5] =
131 /* Loop the age and adjust scent values when necessary */
132 if (++scent_when == 254)
134 /* Scan the entire dungeon */
135 for (POSITION y = 0; y < floor_ptr->height; y++)
137 for (POSITION x = 0; x < floor_ptr->width; x++)
139 int w = floor_ptr->grid_array[y][x].when;
140 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
148 /* Lay down new scent */
149 for (POSITION i = 0; i < 5; i++)
151 for (POSITION j = 0; j < 5; j++)
155 /* Translate table to map grids */
156 POSITION y = i + subject_ptr->y - 2;
157 POSITION 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)
185 /* Check the entire dungeon */
186 for (POSITION y = 0; y < floor_ptr->height; y++)
188 for (POSITION x = 0; x < floor_ptr->width; x++)
190 /* Forget the old data */
191 floor_ptr->grid_array[y][x].dist = 0;
192 floor_ptr->grid_array[y][x].cost = 0;
193 floor_ptr->grid_array[y][x].when = 0;
200 * Routine used by the random vault creators to add a door to a location
201 * Note that range checking has to be done in the calling routine.
203 * The doors must be INSIDE the allocated region.
205 void add_door(player_type *player_ptr, POSITION x, POSITION y)
207 /* Need to have a wall in the center square */
208 floor_type *floor_ptr = player_ptr->current_floor_ptr;
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(player_ptr, y, x, DOOR_DEFAULT);
226 /* set boundarys so don't get wide doors */
227 place_bold(player_ptr, y, x - 1, solid);
228 place_bold(player_ptr, y, x + 1, solid);
236 * where x = don't care
239 if (is_outer_bold(floor_ptr, y - 1, x) && is_outer_bold(floor_ptr, y + 1, x) &&
240 is_floor_bold(floor_ptr, y, x - 1) && is_floor_bold(floor_ptr, y, x + 1))
243 place_secret_door(player_ptr, y, x, DOOR_DEFAULT);
245 /* set boundarys so don't get wide doors */
246 place_bold(player_ptr, y - 1, x, solid);
247 place_bold(player_ptr, y + 1, x, solid);
253 * @brief 所定の位置に上り階段か下り階段を配置する / Place an up/down staircase at given location
254 * @param player_ptr プレーヤーへの参照ポインタ
255 * @param y 配置を試みたいマスのY座標
256 * @param x 配置を試みたいマスのX座標
259 void place_random_stairs(player_type *player_ptr, POSITION y, POSITION x)
261 bool up_stairs = TRUE;
262 bool down_stairs = TRUE;
264 floor_type *floor_ptr = player_ptr->current_floor_ptr;
265 g_ptr = &floor_ptr->grid_array[y][x];
266 if (!is_floor_grid(g_ptr) || g_ptr->o_idx) return;
268 if (!floor_ptr->dun_level) up_stairs = FALSE;
269 if (ironman_downward) up_stairs = FALSE;
270 if (floor_ptr->dun_level >= d_info[player_ptr->dungeon_idx].maxdepth) down_stairs = FALSE;
271 if (quest_number(player_ptr, floor_ptr->dun_level) && (floor_ptr->dun_level > 1)) down_stairs = FALSE;
273 /* We can't place both */
274 if (down_stairs && up_stairs)
276 /* Choose a staircase randomly */
277 if (randint0(100) < 50) up_stairs = FALSE;
278 else down_stairs = FALSE;
281 /* Place the stairs */
282 if (up_stairs) set_cave_feat(floor_ptr, y, x, feat_up_stair);
283 else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
288 * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
289 * @param player_ptr プレーヤーへの参照ポインタ
294 * @return LOSが通っているならTRUEを返す。
296 * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall,\n
297 * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n
299 * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
301 * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
302 * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line\n
303 * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
305 * We assume that the "mathematical corner" of a non-floor tile does not\n
306 * block line of sight.\n
308 * Because this function uses (short) ints for all calculations, overflow may\n
309 * occur if dx and dy exceed 90.\n
311 * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
312 * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
313 * we can use integer arithmetic.\n
315 * We travel from start to finish along the longer axis, starting at the border\n
316 * between the first and second tiles, where the y offset = .5 * slope, taking\n
317 * into account the scale factor. See below.\n
319 * Also note that this function and the "move towards target" code do NOT\n
320 * share the same properties. Thus, you can see someone, target them, and\n
321 * then fire a bolt at them, but the bolt may hit a wall, not them. However\n,
322 * by clever choice of target locations, you can sometimes throw a "curve".\n
324 * Note that "line of sight" is not "reflexive" in all cases.\n
326 * Use the "projectable()" routine to test "spell/missile line of sight".\n
328 * Use the "update_view()" function to determine player line-of-sight.\n
330 bool los(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
332 /* Extract the offset */
333 POSITION dy = y2 - y1;
334 POSITION dx = x2 - x1;
336 /* Extract the absolute offset */
337 POSITION ay = ABS(dy);
338 POSITION ax = ABS(dx);
340 /* Handle adjacent (or identical) grids */
341 if ((ax < 2) && (ay < 2)) return TRUE;
343 /* Directly South/North */
344 floor_type *floor_ptr = player_ptr->current_floor_ptr;
348 /* South -- check for walls */
351 for (ty = y1 + 1; ty < y2; ty++)
353 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
357 /* North -- check for walls */
360 for (ty = y1 - 1; ty > y2; ty--)
362 if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
370 /* Directly East/West */
373 /* East -- check for walls */
376 for (tx = x1 + 1; tx < x2; tx++)
378 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
382 /* West -- check for walls */
385 for (tx = x1 - 1; tx > x2; tx--)
387 if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
395 /* Extract some signs */
396 POSITION sx = (dx < 0) ? -1 : 1;
397 POSITION sy = (dy < 0) ? -1 : 1;
399 /* Vertical "knights" */
404 if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
408 /* Horizontal "knights" */
413 if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
417 /* Calculate scale factor div 2 */
418 POSITION f2 = (ax * ay);
420 /* Calculate scale factor */
421 POSITION f1 = f2 << 1;
423 /* Travel horizontally */
428 /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
434 /* Consider the special case where slope == 1. */
445 /* Note (below) the case (qy == f2), where */
446 /* the LOS exactly meets the corner of a tile. */
449 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
462 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
476 /* Travel vertically */
477 /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
478 POSITION qx = ax * ax;
493 /* Note (below) the case (qx == f2), where */
494 /* the LOS exactly meets the corner of a tile. */
497 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
510 if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
526 * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
527 * at the final destination, assuming no monster gets in the way.
529 * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
531 bool projectable(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
533 /* Check the projection path */
535 int grid_n = project_path(player_ptr, grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
538 if (!grid_n) return TRUE;
541 POSITION y = GRID_Y(grid_g[grid_n - 1]);
542 POSITION x = GRID_X(grid_g[grid_n - 1]);
544 /* May not end in an unrequested grid */
545 if ((y != y2) || (x != x2)) return FALSE;
552 * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
553 * @param player_ptr プレーヤーへの参照ポインタ
554 * @param y1 モンスターを配置したいマスの中心Y座標
555 * @param x1 モンスターを配置したいマスの中心X座標
556 * @param num 配置したいモンスターの数
559 * Only really called by some of the "vault" routines.
561 void vault_monsters(player_type *player_ptr, POSITION y1, POSITION x1, int num)
563 /* Try to summon "num" monsters "near" the given location */
564 floor_type *floor_ptr = player_ptr->current_floor_ptr;
565 for (int k = 0; k < num; k++)
567 /* Try nine locations */
568 for (int i = 0; i < 9; i++)
572 /* Pick a nearby location */
574 scatter(player_ptr, &y, &x, y1, x1, d, 0);
576 /* Require "empty" floor grids */
578 g_ptr = &player_ptr->current_floor_ptr->grid_array[y][x];
579 if (!cave_empty_grid(g_ptr)) continue;
581 /* Place the monster (allow groups) */
582 floor_ptr->monster_level = floor_ptr->base_level + 2;
583 (void)place_monster(player_ptr, y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
584 floor_ptr->monster_level = floor_ptr->base_level;
591 * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
592 * @param player_ptr プレーヤーへの参照ポインタ
595 * @return 各種の変更が可能ならTRUEを返す。
597 * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
599 bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
601 /* Forbid perma-grids */
602 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
603 if (cave_perma_grid(g_ptr)) return FALSE;
606 OBJECT_IDX next_o_idx = 0;
607 for (OBJECT_IDX this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
610 o_ptr = &floor_ptr->o_list[this_o_idx];
611 next_o_idx = o_ptr->next_o_idx;
613 /* Forbid artifact grids */
614 if (object_is_artifact(o_ptr)) return FALSE;
622 * Change the "feat" flag for a grid, and notice/redraw the grid
624 void cave_set_feat(player_type *player_ptr, POSITION y, POSITION x, FEAT_IDX feat)
626 floor_type *floor_ptr = player_ptr->current_floor_ptr;
627 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
628 feature_type *f_ptr = &f_info[feat];
629 if (!current_world_ptr->character_dungeon)
631 /* Clear mimic type */
634 /* Change the feature */
637 /* Hack -- glow the GLOW terrain */
638 if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
643 for (i = 0; i < 9; i++)
647 if (!in_bounds2(floor_ptr, yy, xx)) continue;
648 floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
655 bool old_los = cave_have_flag_bold(floor_ptr, y, x, FF_LOS);
656 bool old_mirror = is_mirror_grid(g_ptr);
658 /* Clear mimic type */
661 /* Change the feature */
664 /* Remove flag for mirror/glyph */
665 g_ptr->info &= ~(CAVE_OBJECT);
667 if (old_mirror && (d_info[floor_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
669 g_ptr->info &= ~(CAVE_GLOW);
670 if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
672 update_local_illumination(player_ptr, y, x);
675 /* Check for change to boring grid */
676 if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
677 if (g_ptr->m_idx) update_monster(player_ptr, g_ptr->m_idx, FALSE);
682 /* Check if los has changed */
683 if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
686 #ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
688 update_local_illumination(player_ptr, y, x);
690 #endif /* COMPLEX_WALL_ILLUMINATION */
692 /* Update the visuals */
693 player_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
696 /* Hack -- glow the GLOW terrain */
697 if (!have_flag(f_ptr->flags, FF_GLOW) || (d_info[player_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
700 for (DIRECTION i = 0; i < 9; i++)
702 POSITION yy = y + ddy_ddd[i];
703 POSITION xx = x + ddx_ddd[i];
704 if (!in_bounds2(floor_ptr, yy, xx)) continue;
707 cc_ptr = &floor_ptr->grid_array[yy][xx];
708 cc_ptr->info |= CAVE_GLOW;
710 if (player_has_los_grid(cc_ptr))
712 if (cc_ptr->m_idx) update_monster(player_ptr, cc_ptr->m_idx, FALSE);
717 update_local_illumination(player_ptr, yy, xx);
720 if (player_ptr->special_defense & NINJA_S_STEALTH)
722 if (floor_ptr->grid_array[player_ptr->y][player_ptr->x].info & CAVE_GLOW) set_superstealth(player_ptr, FALSE);
728 * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
729 * @param player_ptr プレーヤーへの参照ポインタ
730 * @param y ドアの配置を試みたいマスのY座標
731 * @param x ドアの配置を試みたいマスのX座標
732 * @param room 部屋に接している場合向けのドア生成か否か
735 void place_random_door(player_type *player_ptr, POSITION y, POSITION x, bool room)
737 floor_type *floor_ptr = player_ptr->current_floor_ptr;
738 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
741 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
743 place_bold(player_ptr, y, x, floor);
747 int type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
748 one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
749 ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
751 /* Choose an object */
752 int tmp = randint0(1000);
754 /* Open doors (300/1000) */
755 FEAT_IDX feat = feat_none;
758 /* Create open door */
759 feat = feat_door[type].open;
762 /* Broken doors (100/1000) */
765 /* Create broken door */
766 feat = feat_door[type].broken;
769 /* Secret doors (200/1000) */
772 /* Create secret door */
773 place_closed_door(player_ptr, y, x, type);
775 if (type != DOOR_CURTAIN)
777 /* Hide. If on the edge of room, use outer wall. */
778 g_ptr->mimic = room ? feat_wall_outer : feat_wall_type[randint0(100)];
780 /* Floor type terrain cannot hide a door */
781 if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
783 if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
785 g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
792 /* Closed, locked, or stuck doors (400/1000) */
793 else place_closed_door(player_ptr, y, x, type);
797 delete_monster(player_ptr, y, x);
801 if (feat != feat_none)
803 set_cave_feat(floor_ptr, y, x, feat);
807 place_bold(player_ptr, y, x, floor);
810 delete_monster(player_ptr, y, x);
815 * @brief グローバルオブジェクト配列を初期化する /
816 * Delete all the items when player leaves the level
817 * @note we do NOT visually reflect these (irrelevant) changes
819 * Hack -- we clear the "g_ptr->o_idx" field for every grid,
820 * and the "m_ptr->next_o_idx" field for every monster, since
821 * we know we are clearing every object. Technically, we only
822 * clear those fields for grids/monsters containing objects,
823 * and we clear it once for every such object.
826 void wipe_o_list(floor_type *floor_ptr)
828 /* Delete the existing objects */
829 for (int i = 1; i < floor_ptr->o_max; i++)
831 object_type *o_ptr = &floor_ptr->o_list[i];
833 if (!OBJECT_IS_VALID(o_ptr)) continue;
835 /* Mega-Hack -- preserve artifacts */
836 if (!current_world_ptr->character_dungeon || preserve_mode)
838 /* Hack -- Preserve unknown artifacts */
839 if (object_is_fixed_artifact(o_ptr) && !object_is_known(o_ptr))
841 /* Mega-Hack -- Preserve the artifact */
842 a_info[o_ptr->name1].cur_num = 0;
846 if (OBJECT_IS_HELD_MONSTER(o_ptr))
849 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
851 /* Hack -- see above */
852 m_ptr->hold_o_idx = 0;
860 /* Access location */
861 POSITION y = o_ptr->iy;
862 POSITION x = o_ptr->ix;
865 g_ptr = &floor_ptr->grid_array[y][x];
867 /* Hack -- see above */
872 floor_ptr->o_max = 1;
873 floor_ptr->o_cnt = 0;
878 * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
879 * @param player_ptr プレーヤーへの参照ポインタ
880 * @param y ドアの配置を試みたいマスのY座標
881 * @param x ドアの配置を試みたいマスのX座標
882 * @param type ドアの地形ID
885 void place_closed_door(player_type *player_ptr, POSITION y, POSITION x, int type)
887 floor_type *floor_ptr = player_ptr->current_floor_ptr;
888 if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
890 place_bold(player_ptr, y, x, floor);
894 /* Choose an object */
895 int tmp = randint0(400);
897 /* Closed doors (300/400) */
898 FEAT_IDX feat = feat_none;
901 /* Create closed door */
902 feat = feat_door[type].closed;
905 /* Locked doors (99/400) */
908 /* Create locked door */
909 feat = feat_locked_door_random(type);
912 /* Stuck doors (1/400) */
915 /* Create jammed door */
916 feat = feat_jammed_door_random(type);
919 if (feat == feat_none)
921 place_bold(player_ptr, y, x, floor);
925 cave_set_feat(player_ptr, y, x, feat);
926 floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
931 * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
932 * @param y トラップを配置したいマスの中心Y座標
933 * @param x トラップを配置したいマスの中心X座標
934 * @param yd Y方向の配置分散マス数
935 * @param xd X方向の配置分散マス数
938 * Only really called by some of the "vault" routines.
940 void vault_trap_aux(player_type *player_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd)
945 floor_type *floor_ptr = player_ptr->current_floor_ptr;
948 for (int count = 0; count <= 5; count++)
951 while (dummy < SAFE_MAX_ATTEMPTS)
953 y1 = rand_spread(y, yd);
954 x1 = rand_spread(x, xd);
956 if (!in_bounds(floor_ptr, y1, x1)) continue;
960 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
962 msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
965 /* Require "naked" floor grids */
966 g_ptr = &floor_ptr->grid_array[y1][x1];
967 if (!is_floor_grid(g_ptr) || g_ptr->o_idx || g_ptr->m_idx) continue;
970 place_trap(player_ptr, y1, x1);
978 * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor. (Includes range checking.)
979 * @param x チェックするマスのX座標
980 * @param y チェックするマスのY座標
981 * @return 床系地形ならばTRUE
983 bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
985 if (!in_bounds(floor_ptr, y, x))
991 /* Do the real check */
992 if (is_floor_bold(floor_ptr, y, x)) return TRUE;
999 * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
1000 * @param y1 基準となるマスのY座標
1001 * @param x1 基準となるマスのX座標
1003 * @note Assumes "in_bounds(y1, x1)"
1005 * XXX XXX This routine currently only counts actual "empty floor"\n
1006 * grids which are not in rooms. We might want to also count stairs,\n
1007 * open doors, closed doors, etc.
1009 static int next_to_corr(floor_type *floor_ptr, POSITION y1, POSITION x1)
1011 /* Scan adjacent grids */
1013 for (int i = 0; i < 4; i++)
1015 POSITION y = y1 + ddy_ddd[i];
1016 POSITION x = x1 + ddx_ddd[i];
1018 g_ptr = &floor_ptr->grid_array[y][x];
1020 /* Skip non floors */
1021 if (cave_have_flag_grid(g_ptr, FF_WALL)) continue;
1023 /* Skip non "empty floor" grids */
1024 if (!is_floor_grid(g_ptr))
1027 /* Skip grids inside rooms */
1028 if (g_ptr->info & (CAVE_ROOM)) continue;
1030 /* Count these grids */
1034 /* Return the number of corridors */
1039 * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
1040 * @param y 判定を行いたいマスのY座標
1041 * @param x 判定を行いたいマスのX座標
1042 * @return ドアを設置可能ならばTRUEを返す
1043 * @note Assumes "in_bounds()"
1046 * Assumes "in_bounds()"\n
1048 static bool possible_doorway(floor_type *floor_ptr, POSITION y, POSITION x)
1050 /* Count the adjacent corridors */
1051 if (next_to_corr(floor_ptr, y, x) < 2) return FALSE;
1053 /* Check Vertical */
1054 if (cave_have_flag_bold(floor_ptr, y - 1, x, FF_WALL) &&
1055 cave_have_flag_bold(floor_ptr, y + 1, x, FF_WALL))
1060 /* Check Horizontal */
1061 if (cave_have_flag_bold(floor_ptr, y, x - 1, FF_WALL) &&
1062 cave_have_flag_bold(floor_ptr, y, x + 1, FF_WALL))
1072 * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
1073 * @param player_ptr プレーヤーへの参照ポインタ
1074 * @param y 設置を行いたいマスのY座標
1075 * @param x 設置を行いたいマスのX座標
1078 void try_door(player_type *player_ptr, POSITION y, POSITION x)
1080 floor_type *floor_ptr = player_ptr->current_floor_ptr;
1081 if (!in_bounds(floor_ptr, y, x)) return;
1084 if (cave_have_flag_bold(floor_ptr, y, x, FF_WALL)) return;
1086 /* Ignore room grids */
1087 if (floor_ptr->grid_array[y][x].info & (CAVE_ROOM)) return;
1089 /* Occasional door (if allowed) */
1090 if ((randint0(100) < dun_tun_jct) && possible_doorway(floor_ptr, y, x) && !(d_info[player_ptr->dungeon_idx].flags1 & DF1_NO_DOORS))
1093 place_random_door(player_ptr, y, x, FALSE);
1098 FEAT_IDX conv_dungeon_feat(floor_type *floor_ptr, FEAT_IDX newfeat)
1100 feature_type *f_ptr = &f_info[newfeat];
1101 if (have_flag(f_ptr->flags, FF_CONVERT))
1103 switch (f_ptr->subtype)
1105 case CONVERT_TYPE_FLOOR:
1106 return feat_ground_type[randint0(100)];
1107 case CONVERT_TYPE_WALL:
1108 return feat_wall_type[randint0(100)];
1109 case CONVERT_TYPE_INNER:
1110 return feat_wall_inner;
1111 case CONVERT_TYPE_OUTER:
1112 return feat_wall_outer;
1113 case CONVERT_TYPE_SOLID:
1114 return feat_wall_solid;
1115 case CONVERT_TYPE_STREAM1:
1116 return d_info[floor_ptr->dungeon_idx].stream1;
1117 case CONVERT_TYPE_STREAM2:
1118 return d_info[floor_ptr->dungeon_idx].stream2;
1123 else return newfeat;
1128 * @brief 特殊な部屋向けに各種アイテムを配置する / Create up to "num" objects near the given coordinates
1129 * @param player_ptr プレーヤーへの参照ポインタ
1130 * @param y 配置したい中心マスのY座標
1131 * @param x 配置したい中心マスのX座標
1135 * Only really called by some of the "vault" routines.
1137 void vault_objects(player_type *player_ptr, POSITION y, POSITION x, int num)
1139 floor_type *floor_ptr = player_ptr->current_floor_ptr;
1141 /* Attempt to place 'num' objects */
1142 for (; num > 0; --num)
1144 /* Try up to 11 spots looking for empty space */
1147 for (int i = 0; i < 11; ++i)
1149 /* Pick a random location */
1150 while (dummy < SAFE_MAX_ATTEMPTS)
1152 j = rand_spread(y, 2);
1153 k = rand_spread(x, 3);
1155 if (!in_bounds(floor_ptr, j, k)) continue;
1159 if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
1161 msg_print(_("警告!地下室のアイテムを配置できません!", "Warning! Could not place vault object!"));
1164 /* Require "clean" floor space */
1166 g_ptr = &floor_ptr->grid_array[j][k];
1167 if (!is_floor_grid(g_ptr) || g_ptr->o_idx) continue;
1169 if (randint0(100) < 75)
1171 place_object(player_ptr, j, k, 0L);
1175 place_gold(floor_ptr, j, k);
1178 /* Placement accomplished */
1186 * @brief 始点から終点への直線経路を返す /
1187 * Determine the path taken by a projection.
1188 * @param player_ptr プレーヤーへの参照ポインタ
1189 * @param gp 経路座標リストを返す参照ポインタ
1199 * The projection will always start from the grid (y1,x1), and will travel
1200 * towards the grid (y2,x2), touching one grid per unit of distance along
1201 * the major axis, and stopping when it enters the destination grid or a
1202 * wall grid, or has travelled the maximum legal distance of "range".
1204 * Note that "distance" in this function (as in the "update_view()" code)
1205 * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
1206 * actually has an "octagon of projection" not a "circle of projection".
1208 * The path grids are saved into the grid array pointed to by "gp", and
1209 * there should be room for at least "range" grids in "gp". Note that
1210 * due to the way in which distance is calculated, this function normally
1211 * uses fewer than "range" grids for the projection path, so the result
1212 * of this function should never be compared directly to "range". Note
1213 * that the initial grid (y1,x1) is never saved into the grid array, not
1214 * even if the initial grid is also the final grid.
1216 * The "flg" flags can be used to modify the behavior of this function.
1218 * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
1219 * semantics as they do for the "project" function, namely, that the path
1220 * will stop as soon as it hits a monster, or that the path will continue
1221 * through the destination grid, respectively.
1223 * The "PROJECT_JUMP" flag, which for the "project()" function means to
1224 * start at a special grid (which makes no sense in this function), means
1225 * that the path should be "angled" slightly if needed to avoid any wall
1226 * grids, allowing the player to "target" any grid which is in "view".
1227 * This flag is non-trivial and has not yet been implemented, but could
1228 * perhaps make use of the "vinfo" array (above).
1230 * This function returns the number of grids (if any) in the path. This
1231 * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
1233 * This algorithm is similar to, but slightly different from, the one used
1234 * by "update_view_los()", and very different from the one used by "los()".
1237 sint project_path(player_type *player_ptr, u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
1239 /* No path necessary (or allowed) */
1240 if ((x1 == x2) && (y1 == y2)) return 0;
1272 /* Number of "units" in one "half" grid */
1273 int half = (ay * ax);
1275 /* Number of "units" in one "full" grid */
1276 int full = half << 1;
1279 floor_type *floor_ptr = player_ptr->current_floor_ptr;
1284 /* Let m = ((dx/dy) * full) = (dx * dx * 2) */
1295 /* Advance (X) part 2 */
1298 /* Advance (X) part 3 */
1301 /* Track distance */
1305 /* Create the projection path */
1309 gp[n++] = GRID(y, x);
1311 /* Hack -- Check maximum range */
1312 if ((n + (k >> 1)) >= range) break;
1314 /* Sometimes stop at destination grid */
1315 if (!(flg & (PROJECT_THRU)))
1317 if ((x == x2) && (y == y2)) break;
1320 if (flg & (PROJECT_DISI))
1322 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1324 else if (flg & (PROJECT_LOS))
1326 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1328 else if (!(flg & (PROJECT_PATH)))
1330 /* Always stop at non-initial wall grids */
1331 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1334 /* Sometimes stop at non-initial monsters/players */
1335 if (flg & (PROJECT_STOP))
1338 (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1342 if (!in_bounds(floor_ptr, y, x)) break;
1347 /* Advance (X) part 1 */
1350 /* Horizontal change */
1353 /* Advance (X) part 2 */
1356 /* Advance (X) part 3 */
1359 /* Track distance */
1374 /* Let m = ((dy/dx) * full) = (dy * dy * 2) */
1383 /* Vertical change */
1386 /* Advance (Y) part 2 */
1389 /* Advance (Y) part 3 */
1392 /* Track distance */
1396 /* Create the projection path */
1400 gp[n++] = GRID(y, x);
1402 /* Hack -- Check maximum range */
1403 if ((n + (k >> 1)) >= range) break;
1405 /* Sometimes stop at destination grid */
1406 if (!(flg & (PROJECT_THRU)))
1408 if ((x == x2) && (y == y2)) break;
1411 if (flg & (PROJECT_DISI))
1413 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1415 else if (flg & (PROJECT_LOS))
1417 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1419 else if (!(flg & (PROJECT_PATH)))
1421 /* Always stop at non-initial wall grids */
1422 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1425 /* Sometimes stop at non-initial monsters/players */
1426 if (flg & (PROJECT_STOP))
1429 (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1433 if (!in_bounds(floor_ptr, y, x)) break;
1438 /* Advance (Y) part 1 */
1441 /* Vertical change */
1444 /* Advance (Y) part 2 */
1447 /* Advance (Y) part 3 */
1450 /* Track distance */
1466 /* Create the projection path */
1470 gp[n++] = GRID(y, x);
1472 /* Hack -- Check maximum range */
1473 if ((n + (n >> 1)) >= range) break;
1475 /* Sometimes stop at destination grid */
1476 if (!(flg & (PROJECT_THRU)))
1478 if ((x == x2) && (y == y2)) break;
1481 if (flg & (PROJECT_DISI))
1483 if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x)) break;
1485 else if (flg & (PROJECT_LOS))
1487 if ((n > 0) && !cave_los_bold(floor_ptr, y, x)) break;
1489 else if (!(flg & (PROJECT_PATH)))
1491 /* Always stop at non-initial wall grids */
1492 if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT)) break;
1495 /* Sometimes stop at non-initial monsters/players */
1496 if (flg & (PROJECT_STOP))
1499 (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
1503 if (!in_bounds(floor_ptr, y, x)) break;
1514 * @brief 指定のマスを床地形に変える / Set a square to be floor. (Includes range checking.)
1515 * @param player_ptr プレーヤーへの参照ポインタ
1516 * @param x 地形を変えたいマスのX座標
1517 * @param y 地形を変えたいマスのY座標
1520 void set_floor(player_type *player_ptr, POSITION x, POSITION y)
1522 floor_type *floor_ptr = player_ptr->current_floor_ptr;
1523 if (!in_bounds(floor_ptr, y, x))
1529 if (floor_ptr->grid_array[y][x].info & CAVE_ROOM)
1531 /* A room border don't touch. */
1535 /* Set to be floor if is a wall (don't touch lakes). */
1536 if (is_extra_bold(floor_ptr, y, x))
1537 place_bold(player_ptr, y, x, floor);
1542 * @brief フロアの指定位置に生成階に応じたベースアイテムの生成を行う。
1543 * Attempt to place an object (normal or good/great) at the given location.
1544 * @param owner_ptr プレーヤーへの参照ポインタ
1545 * @param y 配置したいフロアのY座標
1546 * @param x 配置したいフロアのX座標
1547 * @param mode オプションフラグ
1548 * @return 生成に成功したらTRUEを返す。
1550 * This routine plays nasty games to generate the "special artifacts".\n
1551 * This routine uses "object_level" for the "generation level".\n
1552 * This routine requires a clean floor grid destination.\n
1554 void place_object(player_type *owner_ptr, POSITION y, POSITION x, BIT_FLAGS mode)
1556 floor_type *floor_ptr = owner_ptr->current_floor_ptr;
1559 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1564 /* Paranoia -- check bounds */
1565 if (!in_bounds(floor_ptr, y, x)) return;
1567 /* Require floor space */
1568 if (!cave_drop_bold(floor_ptr, y, x)) return;
1570 /* Avoid stacking on other objects */
1571 if (g_ptr->o_idx) return;
1576 /* Make an object (if possible) */
1577 if (!make_object(owner_ptr, q_ptr, mode)) return;
1579 OBJECT_IDX o_idx = o_pop(floor_ptr);
1584 /* Hack -- Preserve artifacts */
1585 if (object_is_fixed_artifact(q_ptr))
1587 a_info[q_ptr->name1].cur_num = 0;
1594 o_ptr = &floor_ptr->o_list[o_idx];
1596 /* Structure Copy */
1597 object_copy(o_ptr, q_ptr);
1603 o_ptr->next_o_idx = g_ptr->o_idx;
1605 g_ptr->o_idx = o_idx;
1612 * @brief フロアの指定位置に生成階に応じた財宝オブジェクトの生成を行う。
1613 * Places a treasure (Gold or Gems) at given location
1614 * @param floor_ptr 現在フロアへの参照ポインタ
1615 * @param y 配置したいフロアのY座標
1616 * @param x 配置したいフロアのX座標
1617 * @return 生成に成功したらTRUEを返す。
1619 * The location must be a legal, clean, floor grid.
1621 void place_gold(floor_type *floor_ptr, POSITION y, POSITION x)
1624 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
1626 /* Paranoia -- check bounds */
1627 if (!in_bounds(floor_ptr, y, x)) return;
1629 /* Require floor space */
1630 if (!cave_drop_bold(floor_ptr, y, x)) return;
1632 /* Avoid stacking on other objects */
1633 if (g_ptr->o_idx) return;
1640 /* Make some gold */
1641 if (!make_gold(floor_ptr, q_ptr)) return;
1643 OBJECT_IDX o_idx = o_pop(floor_ptr);
1646 if (o_idx == 0) return;
1649 o_ptr = &floor_ptr->o_list[o_idx];
1650 object_copy(o_ptr, q_ptr);
1657 o_ptr->next_o_idx = g_ptr->o_idx;
1659 g_ptr->o_idx = o_idx;
1666 * @brief 指定位置に存在するモンスターを削除する / Delete the monster, if any, at a given location
1667 * @param player_ptr プレーヤーへの参照ポインタ
1672 void delete_monster(player_type *player_ptr, POSITION y, POSITION x)
1675 floor_type *floor_ptr = player_ptr->current_floor_ptr;
1676 if (!in_bounds(floor_ptr, y, x)) return;
1678 /* Check the grid */
1679 g_ptr = &floor_ptr->grid_array[y][x];
1681 /* Delete the monster (if any) */
1682 if (g_ptr->m_idx) delete_monster_idx(player_ptr, g_ptr->m_idx);
1687 * @brief グローバルオブジェクト配列に対し指定範囲のオブジェクトを整理してIDの若い順に寄せる /
1688 * Move an object from index i1 to index i2 in the object list
1689 * @param i1 整理したい配列の始点
1690 * @param i2 整理したい配列の終点
1693 static void compact_objects_aux(floor_type *floor_ptr, OBJECT_IDX i1, OBJECT_IDX i2)
1696 if (i1 == i2) return;
1698 /* Repair objects */
1700 for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++)
1702 o_ptr = &floor_ptr->o_list[i];
1704 /* Skip "dead" objects */
1705 if (!o_ptr->k_idx) continue;
1707 /* Repair "next" pointers */
1708 if (o_ptr->next_o_idx == i1)
1711 o_ptr->next_o_idx = i2;
1715 o_ptr = &floor_ptr->o_list[i1];
1717 if (OBJECT_IS_HELD_MONSTER(o_ptr))
1719 monster_type *m_ptr;
1720 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1722 /* Repair monster */
1723 if (m_ptr->hold_o_idx == i1)
1726 m_ptr->hold_o_idx = i2;
1735 /* Acquire location */
1741 g_ptr = &floor_ptr->grid_array[y][x];
1744 if (g_ptr->o_idx == i1)
1751 floor_ptr->o_list[i2] = floor_ptr->o_list[i1];
1757 * @brief グローバルオブジェクト配列から優先度の低いものを削除し、データを圧縮する。 /
1758 * Compact and Reorder the object list.
1759 * @param player_ptr プレーヤーへの参照ポインタ
1760 * @param size 最低でも減らしたいオブジェクト数の水準
1764 * This function can be very dangerous, use with caution!\n
1766 * When actually "compacting" objects, we base the saving throw on a\n
1767 * combination of object level, distance from player, and current\n
1770 * After "compacting" (if needed), we "reorder" the objects into a more\n
1771 * compact order, and we reset the allocation info, and the "live" array.\n
1773 void compact_objects(player_type *player_ptr, int size)
1780 msg_print(_("アイテム情報を圧縮しています...", "Compacting objects..."));
1781 player_ptr->redraw |= (PR_MAP);
1782 player_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
1785 /* Compact at least 'size' objects */
1786 floor_type *floor_ptr = player_ptr->current_floor_ptr;
1787 for (int num = 0, cnt = 1; num < size; cnt++)
1789 /* Get more vicious each iteration */
1790 int cur_lev = 5 * cnt;
1792 /* Get closer each iteration */
1793 int cur_dis = 5 * (20 - cnt);
1795 /* Examine the objects */
1796 for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++)
1798 o_ptr = &floor_ptr->o_list[i];
1800 if (!OBJECT_IS_VALID(o_ptr)) continue;
1802 /* Hack -- High level objects start out "immune" */
1803 if (k_info[o_ptr->k_idx].level > cur_lev) continue;
1806 if (OBJECT_IS_HELD_MONSTER(o_ptr))
1808 monster_type *m_ptr;
1809 m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
1814 /* Monsters protect their objects */
1815 if (randint0(100) < 90) continue;
1825 /* Nearby objects start out "immune" */
1826 if ((cur_dis > 0) && (distance(player_ptr->y, player_ptr->x, y, x) < cur_dis)) continue;
1831 /* Hack -- only compact artifacts in emergencies */
1832 if ((object_is_fixed_artifact(o_ptr) || o_ptr->art_name) &&
1833 (cnt < 1000)) chance = 100;
1835 /* Apply the saving throw */
1836 if (randint0(100) < chance) continue;
1838 delete_object_idx(floor_ptr, i);
1843 /* Excise dead objects (backwards!) */
1844 for (OBJECT_IDX i = floor_ptr->o_max - 1; i >= 1; i--)
1846 o_ptr = &floor_ptr->o_list[i];
1848 /* Skip real objects */
1849 if (o_ptr->k_idx) continue;
1851 /* Move last object into open hole */
1852 compact_objects_aux(floor_ptr, floor_ptr->o_max - 1, i);
1854 /* Compress "floor_ptr->o_max" */
1861 * @brief 特殊な部屋向けに各種アイテムを配置する(メインルーチン) / Place some traps with a given displacement of given location
1862 * @param player_ptr プレーヤーへの参照ポインタ
1863 * @param y トラップを配置したいマスの中心Y座標
1864 * @param x トラップを配置したいマスの中心X座標
1865 * @param yd Y方向の配置分散マス数
1866 * @param xd X方向の配置分散マス数
1867 * @param num 配置したいトラップの数
1870 * Only really called by some of the "vault" routines.
1872 void vault_traps(player_type *player_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd, int num)
1874 for (int i = 0; i < num; i++)
1876 vault_trap_aux(player_ptr, y, x, yd, xd);
1882 * Standard "find me a location" function
1884 * Obtains a legal location within the given distance of the initial
1885 * location, and with "los()" from the source to destination location.
1887 * This function is often called from inside a loop which searches for
1888 * locations while increasing the "d" distance.
1890 * Currently the "m" parameter is unused.
1892 void scatter(player_type *player_ptr, POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode)
1894 /* Pick a location */
1895 floor_type *floor_ptr = player_ptr->current_floor_ptr;
1899 /* Pick a new location */
1900 ny = rand_spread(y, d);
1901 nx = rand_spread(x, d);
1903 /* Ignore annoying locations */
1904 if (!in_bounds(floor_ptr, ny, nx)) continue;
1906 /* Ignore "excessively distant" locations */
1907 if ((d > 1) && (distance(y, x, ny, nx) > d)) continue;
1909 if (mode & PROJECT_LOS)
1911 if (los(player_ptr, y, x, ny, nx)) break;
1915 if (projectable(player_ptr, y, x, ny, nx)) break;