OSDN Git Service

[Refactor] #38997 get_is_floor() に player_type * 引数を追加. / Add player_type * argument...
[hengband/hengband.git] / src / floor.c
index 3a90074..0e3d54b 100644 (file)
@@ -1,10 +1,19 @@
 #include "angband.h"
 #include "floor.h"
 #include "floor-save.h"
+#include "floor-generate.h"
 #include "grid.h"
 #include "dungeon.h"
 #include "rooms.h"
 #include "quest.h"
+#include "object-hook.h"
+#include "world.h"
+#include "player-effects.h"
+#include "object.h"
+#include "object-hook.h"
+#include "artifact.h"
+#include "objectkind.h"
+#include "trap.h"
 
 /*
  * The array of floor [MAX_WID][MAX_HGT].
@@ -28,7 +37,7 @@ void place_locked_door(floor_type *floor_ptr, POSITION y, POSITION x)
 {
        if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
        {
-               place_floor_bold(y, x);
+               place_floor_bold(floor_ptr, y, x);
        }
        else
        {
@@ -50,7 +59,7 @@ void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
 {
        if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
        {
-               place_floor_bold(y, x);
+               place_floor_bold(floor_ptr, y, x);
        }
        else
        {
@@ -64,7 +73,7 @@ void place_secret_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
                }
 
                /* Create secret door */
-               place_closed_door(y, x, type);
+               place_closed_door(floor_ptr, y, x, type);
 
                if (type != DOOR_CURTAIN)
                {
@@ -274,3 +283,754 @@ void place_random_stairs(floor_type *floor_ptr, POSITION y, POSITION x)
        else if (down_stairs) set_cave_feat(floor_ptr, y, x, feat_down_stair);
 }
 
+/*!
+ * @brief LOS(Line Of Sight / 視線が通っているか)の判定を行う。
+ * @param y1 始点のy座標
+ * @param x1 始点のx座標
+ * @param y2 終点のy座標
+ * @param x2 終点のx座標
+ * @return LOSが通っているならTRUEを返す。
+ * @details
+ * A simple, fast, integer-based line-of-sight algorithm.  By Joseph Hall,\n
+ * 4116 Brewster Drive, Raleigh NC 27606.  Email to jnh@ecemwl.ncsu.edu.\n
+ *\n
+ * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n
+ *\n
+ * The LOS begins at the center of the tile (x1,y1) and ends at the center of\n
+ * the tile (x2,y2).  If los() is to return TRUE, all of the tiles this line\n
+ * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n
+ *\n
+ * We assume that the "mathematical corner" of a non-floor tile does not\n
+ * block line of sight.\n
+ *\n
+ * Because this function uses (short) ints for all calculations, overflow may\n
+ * occur if dx and dy exceed 90.\n
+ *\n
+ * Once all the degenerate cases are eliminated, the values "qx", "qy", and\n
+ * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that\n
+ * we can use integer arithmetic.\n
+ *\n
+ * We travel from start to finish along the longer axis, starting at the border\n
+ * between the first and second tiles, where the y offset = .5 * slope, taking\n
+ * into account the scale factor.  See below.\n
+ *\n
+ * Also note that this function and the "move towards target" code do NOT\n
+ * share the same properties.  Thus, you can see someone, target them, and\n
+ * then fire a bolt at them, but the bolt may hit a wall, not them.  However\n,
+ * by clever choice of target locations, you can sometimes throw a "curve".\n
+ *\n
+ * Note that "line of sight" is not "reflexive" in all cases.\n
+ *\n
+ * Use the "projectable()" routine to test "spell/missile line of sight".\n
+ *\n
+ * Use the "update_view()" function to determine player line-of-sight.\n
+ */
+bool los(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
+{
+       /* Delta */
+       POSITION dx, dy;
+
+       /* Absolute */
+       POSITION ax, ay;
+
+       /* Signs */
+       POSITION sx, sy;
+
+       /* Fractions */
+       POSITION qx, qy;
+
+       /* Scanners */
+       POSITION tx, ty;
+
+       /* Scale factors */
+       POSITION f1, f2;
+
+       /* Slope, or 1/Slope, of LOS */
+       POSITION m;
+
+
+       /* Extract the offset */
+       dy = y2 - y1;
+       dx = x2 - x1;
+
+       /* Extract the absolute offset */
+       ay = ABS(dy);
+       ax = ABS(dx);
+
+
+       /* Handle adjacent (or identical) grids */
+       if ((ax < 2) && (ay < 2)) return TRUE;
+
+
+       /* Paranoia -- require "safe" origin */
+       /* if (!in_bounds(floor_ptr, y1, x1)) return FALSE; */
+       /* if (!in_bounds(floor_ptr, y2, x2)) return FALSE; */
+
+
+       /* Directly South/North */
+       if (!dx)
+       {
+               /* South -- check for walls */
+               if (dy > 0)
+               {
+                       for (ty = y1 + 1; ty < y2; ty++)
+                       {
+                               if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
+                       }
+               }
+
+               /* North -- check for walls */
+               else
+               {
+                       for (ty = y1 - 1; ty > y2; ty--)
+                       {
+                               if (!cave_los_bold(floor_ptr, ty, x1)) return FALSE;
+                       }
+               }
+
+               /* Assume los */
+               return TRUE;
+       }
+
+       /* Directly East/West */
+       if (!dy)
+       {
+               /* East -- check for walls */
+               if (dx > 0)
+               {
+                       for (tx = x1 + 1; tx < x2; tx++)
+                       {
+                               if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
+                       }
+               }
+
+               /* West -- check for walls */
+               else
+               {
+                       for (tx = x1 - 1; tx > x2; tx--)
+                       {
+                               if (!cave_los_bold(floor_ptr, y1, tx)) return FALSE;
+                       }
+               }
+
+               /* Assume los */
+               return TRUE;
+       }
+
+
+       /* Extract some signs */
+       sx = (dx < 0) ? -1 : 1;
+       sy = (dy < 0) ? -1 : 1;
+
+
+       /* Vertical "knights" */
+       if (ax == 1)
+       {
+               if (ay == 2)
+               {
+                       if (cave_los_bold(floor_ptr, y1 + sy, x1)) return TRUE;
+               }
+       }
+
+       /* Horizontal "knights" */
+       else if (ay == 1)
+       {
+               if (ax == 2)
+               {
+                       if (cave_los_bold(floor_ptr, y1, x1 + sx)) return TRUE;
+               }
+       }
+
+
+       /* Calculate scale factor div 2 */
+       f2 = (ax * ay);
+
+       /* Calculate scale factor */
+       f1 = f2 << 1;
+
+
+       /* Travel horizontally */
+       if (ax >= ay)
+       {
+               /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */
+               qy = ay * ay;
+               m = qy << 1;
+
+               tx = x1 + sx;
+
+               /* Consider the special case where slope == 1. */
+               if (qy == f2)
+               {
+                       ty = y1 + sy;
+                       qy -= f1;
+               }
+               else
+               {
+                       ty = y1;
+               }
+
+               /* Note (below) the case (qy == f2), where */
+               /* the LOS exactly meets the corner of a tile. */
+               while (x2 - tx)
+               {
+                       if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
+
+                       qy += m;
+
+                       if (qy < f2)
+                       {
+                               tx += sx;
+                       }
+                       else if (qy > f2)
+                       {
+                               ty += sy;
+                               if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
+                               qy -= f1;
+                               tx += sx;
+                       }
+                       else
+                       {
+                               ty += sy;
+                               qy -= f1;
+                               tx += sx;
+                       }
+               }
+       }
+
+       /* Travel vertically */
+       else
+       {
+               /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */
+               qx = ax * ax;
+               m = qx << 1;
+
+               ty = y1 + sy;
+
+               if (qx == f2)
+               {
+                       tx = x1 + sx;
+                       qx -= f1;
+               }
+               else
+               {
+                       tx = x1;
+               }
+
+               /* Note (below) the case (qx == f2), where */
+               /* the LOS exactly meets the corner of a tile. */
+               while (y2 - ty)
+               {
+                       if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
+
+                       qx += m;
+
+                       if (qx < f2)
+                       {
+                               ty += sy;
+                       }
+                       else if (qx > f2)
+                       {
+                               tx += sx;
+                               if (!cave_los_bold(floor_ptr, ty, tx)) return FALSE;
+                               qx -= f1;
+                               ty += sy;
+                       }
+                       else
+                       {
+                               tx += sx;
+                               qx -= f1;
+                               ty += sy;
+                       }
+               }
+       }
+
+       /* Assume los */
+       return TRUE;
+}
+
+
+/*
+ * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive
+ * at the final destination, assuming no monster gets in the way.
+ *
+ * This is slightly (but significantly) different from "los(y1,x1,y2,x2)".
+ */
+bool projectable(floor_type *floor_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
+{
+       POSITION y, x;
+
+       int grid_n = 0;
+       u16b grid_g[512];
+
+       /* Check the projection path */
+       grid_n = project_path(grid_g, (project_length ? project_length : MAX_RANGE), y1, x1, y2, x2, 0);
+
+       /* Identical grid */
+       if (!grid_n) return TRUE;
+
+       /* Final grid */
+       y = GRID_Y(grid_g[grid_n - 1]);
+       x = GRID_X(grid_g[grid_n - 1]);
+
+       /* May not end in an unrequested grid */
+       if ((y != y2) || (x != x2)) return (FALSE);
+
+       /* Assume okay */
+       return (TRUE);
+}
+
+
+/*!
+ * @brief 特殊な部屋地形向けにモンスターを配置する / Hack -- Place some sleeping monsters near the given location
+ * @param y1 モンスターを配置したいマスの中心Y座標
+ * @param x1 モンスターを配置したいマスの中心X座標
+ * @param num 配置したいモンスターの数
+ * @return なし
+ * @details
+ * Only really called by some of the "vault" routines.
+ */
+void vault_monsters(floor_type *floor_ptr, POSITION y1, POSITION x1, int num)
+{
+       int k, i;
+       POSITION y, x;
+       grid_type *g_ptr;
+
+       /* Try to summon "num" monsters "near" the given location */
+       for (k = 0; k < num; k++)
+       {
+               /* Try nine locations */
+               for (i = 0; i < 9; i++)
+               {
+                       int d = 1;
+
+                       /* Pick a nearby location */
+                       scatter(&y, &x, y1, x1, d, 0);
+
+                       /* Require "empty" floor grids */
+                       g_ptr = &floor_ptr->grid_array[y][x];
+                       if (!cave_empty_grid(g_ptr)) continue;
+
+                       /* Place the monster (allow groups) */
+                       floor_ptr->monster_level = floor_ptr->base_level + 2;
+                       (void)place_monster(y, x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
+                       floor_ptr->monster_level = floor_ptr->base_level;
+               }
+       }
+}
+
+
+/*!
+ * @brief 指定された座標が地震や階段生成の対象となるマスかを返す。 / Determine if a given location may be "destroyed"
+ * @param y y座標
+ * @param x x座標
+ * @return 各種の変更が可能ならTRUEを返す。
+ * @details
+ * 条件は永久地形でなく、なおかつ該当のマスにアーティファクトが存在しないか、である。英語の旧コメントに反して*破壊*の抑止判定には現在使われていない。
+ */
+bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
+{
+       grid_type *g_ptr = &floor_ptr->grid_array[y][x];
+       OBJECT_IDX this_o_idx, next_o_idx = 0;
+
+       /* Forbid perma-grids */
+       if (cave_perma_grid(g_ptr)) return (FALSE);
+
+       /* Check objects */
+       for (this_o_idx = g_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
+       {
+               object_type *o_ptr;
+               o_ptr = &floor_ptr->o_list[this_o_idx];
+               next_o_idx = o_ptr->next_o_idx;
+
+               /* Forbid artifact grids */
+               if (object_is_artifact(o_ptr)) return (FALSE);
+       }
+
+       /* Accept */
+       return (TRUE);
+}
+
+/*
+ * Change the "feat" flag for a grid, and notice/redraw the grid
+ */
+void cave_set_feat(floor_type *floor_ptr, POSITION y, POSITION x, FEAT_IDX feat)
+{
+       grid_type *g_ptr = &floor_ptr->grid_array[y][x];
+       feature_type *f_ptr = &f_info[feat];
+       bool old_los, old_mirror;
+
+       if (!current_world_ptr->character_dungeon)
+       {
+               /* Clear mimic type */
+               g_ptr->mimic = 0;
+
+               /* Change the feature */
+               g_ptr->feat = feat;
+
+               /* Hack -- glow the GLOW terrain */
+               if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
+               {
+                       DIRECTION i;
+                       POSITION yy, xx;
+
+                       for (i = 0; i < 9; i++)
+                       {
+                               yy = y + ddy_ddd[i];
+                               xx = x + ddx_ddd[i];
+                               if (!in_bounds2(floor_ptr, yy, xx)) continue;
+                               floor_ptr->grid_array[yy][xx].info |= CAVE_GLOW;
+                       }
+               }
+
+               return;
+       }
+
+       old_los = cave_have_flag_bold(y, x, FF_LOS);
+       old_mirror = is_mirror_grid(g_ptr);
+
+       /* Clear mimic type */
+       g_ptr->mimic = 0;
+
+       /* Change the feature */
+       g_ptr->feat = feat;
+
+       /* Remove flag for mirror/glyph */
+       g_ptr->info &= ~(CAVE_OBJECT);
+
+       if (old_mirror && (d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
+       {
+               g_ptr->info &= ~(CAVE_GLOW);
+               if (!view_torch_grids) g_ptr->info &= ~(CAVE_MARK);
+
+               update_local_illumination(p_ptr, y, x);
+       }
+
+       /* Check for change to boring grid */
+       if (!have_flag(f_ptr->flags, FF_REMEMBER)) g_ptr->info &= ~(CAVE_MARK);
+       if (g_ptr->m_idx) update_monster(p_ptr, g_ptr->m_idx, FALSE);
+
+       note_spot(y, x);
+       lite_spot(y, x);
+
+       /* Check if los has changed */
+       if (old_los ^ have_flag(f_ptr->flags, FF_LOS))
+       {
+
+#ifdef COMPLEX_WALL_ILLUMINATION /* COMPLEX_WALL_ILLUMINATION */
+
+               update_local_illumination(p_ptr, y, x);
+
+#endif /* COMPLEX_WALL_ILLUMINATION */
+
+               /* Update the visuals */
+               p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE | PU_MONSTERS);
+       }
+
+       /* Hack -- glow the GLOW terrain */
+       if (have_flag(f_ptr->flags, FF_GLOW) && !(d_info[p_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
+       {
+               DIRECTION i;
+               POSITION yy, xx;
+               grid_type *cc_ptr;
+
+               for (i = 0; i < 9; i++)
+               {
+                       yy = y + ddy_ddd[i];
+                       xx = x + ddx_ddd[i];
+                       if (!in_bounds2(floor_ptr, yy, xx)) continue;
+                       cc_ptr = &floor_ptr->grid_array[yy][xx];
+                       cc_ptr->info |= CAVE_GLOW;
+
+                       if (player_has_los_grid(cc_ptr))
+                       {
+                               if (cc_ptr->m_idx) update_monster(p_ptr, cc_ptr->m_idx, FALSE);
+                               note_spot(yy, xx);
+                               lite_spot(yy, xx);
+                       }
+
+                       update_local_illumination(p_ptr, yy, xx);
+               }
+
+               if (p_ptr->special_defense & NINJA_S_STEALTH)
+               {
+                       if (floor_ptr->grid_array[p_ptr->y][p_ptr->x].info & CAVE_GLOW) set_superstealth(p_ptr, FALSE);
+               }
+       }
+}
+
+
+/*!
+ * @brief 所定の位置にさまざまな状態や種類のドアを配置する / Place a random type of door at the given location
+ * @param y ドアの配置を試みたいマスのY座標
+ * @param x ドアの配置を試みたいマスのX座標
+ * @param room 部屋に接している場合向けのドア生成か否か
+ * @return なし
+ */
+void place_random_door(floor_type *floor_ptr, POSITION y, POSITION x, bool room)
+{
+       int tmp, type;
+       FEAT_IDX feat = feat_none;
+       grid_type *g_ptr = &floor_ptr->grid_array[y][x];
+
+       /* Initialize mimic info */
+       g_ptr->mimic = 0;
+
+       if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
+       {
+               place_floor_bold(floor_ptr, y, x);
+               return;
+       }
+
+       type = ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_CURTAIN) &&
+               one_in_((d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
+               ((d_info[floor_ptr->dungeon_idx].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);
+
+       /* Choose an object */
+       tmp = randint0(1000);
+
+       /* Open doors (300/1000) */
+       if (tmp < 300)
+       {
+               /* Create open door */
+               feat = feat_door[type].open;
+       }
+
+       /* Broken doors (100/1000) */
+       else if (tmp < 400)
+       {
+               /* Create broken door */
+               feat = feat_door[type].broken;
+       }
+
+       /* Secret doors (200/1000) */
+       else if (tmp < 600)
+       {
+               /* Create secret door */
+               place_closed_door(floor_ptr, y, x, type);
+
+               if (type != DOOR_CURTAIN)
+               {
+                       /* Hide. If on the edge of room, use outer wall. */
+                       g_ptr->mimic = room ? feat_wall_outer : feat_wall_type[randint0(100)];
+
+                       /* Floor type terrain cannot hide a door */
+                       if (feat_supports_los(g_ptr->mimic) && !feat_supports_los(g_ptr->feat))
+                       {
+                               if (have_flag(f_info[g_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[g_ptr->mimic].flags, FF_CAN_FLY))
+                               {
+                                       g_ptr->feat = one_in_(2) ? g_ptr->mimic : feat_ground_type[randint0(100)];
+                               }
+                               g_ptr->mimic = 0;
+                       }
+               }
+       }
+
+       /* Closed, locked, or stuck doors (400/1000) */
+       else place_closed_door(floor_ptr, y, x, type);
+
+       if (tmp < 400)
+       {
+               if (feat != feat_none)
+               {
+                       set_cave_feat(floor_ptr, y, x, feat);
+               }
+               else
+               {
+                       place_floor_bold(floor_ptr, y, x);
+               }
+       }
+
+       delete_monster(y, x);
+}
+
+
+
+/*!
+ * @brief グローバルオブジェクト配列を初期化する /
+ * Delete all the items when player leaves the level
+ * @note we do NOT visually reflect these (irrelevant) changes
+ * @details
+ * Hack -- we clear the "g_ptr->o_idx" field for every grid,
+ * and the "m_ptr->next_o_idx" field for every monster, since
+ * we know we are clearing every object.  Technically, we only
+ * clear those fields for grids/monsters containing objects,
+ * and we clear it once for every such object.
+ * @return なし
+ */
+void wipe_o_list(floor_type *floor_ptr)
+{
+       int i;
+
+       /* Delete the existing objects */
+       for (i = 1; i < floor_ptr->o_max; i++)
+       {
+               object_type *o_ptr = &floor_ptr->o_list[i];
+
+               if (!OBJECT_IS_VALID(o_ptr)) continue;
+
+               /* Mega-Hack -- preserve artifacts */
+               if (!current_world_ptr->character_dungeon || preserve_mode)
+               {
+                       /* Hack -- Preserve unknown artifacts */
+                       if (object_is_fixed_artifact(o_ptr) && !object_is_known(o_ptr))
+                       {
+                               /* Mega-Hack -- Preserve the artifact */
+                               a_info[o_ptr->name1].cur_num = 0;
+                       }
+               }
+
+               if (OBJECT_IS_HELD_MONSTER(o_ptr))
+               {
+                       monster_type *m_ptr;
+                       m_ptr = &floor_ptr->m_list[o_ptr->held_m_idx];
+
+                       /* Hack -- see above */
+                       m_ptr->hold_o_idx = 0;
+               }
+
+               /* Dungeon */
+               else
+               {
+                       grid_type *g_ptr;
+
+                       /* Access location */
+                       POSITION y = o_ptr->iy;
+                       POSITION x = o_ptr->ix;
+
+                       /* Access grid */
+                       g_ptr = &floor_ptr->grid_array[y][x];
+
+                       /* Hack -- see above */
+                       g_ptr->o_idx = 0;
+               }
+               object_wipe(o_ptr);
+       }
+
+       /* Reset "floor_ptr->o_max" */
+       floor_ptr->o_max = 1;
+
+       /* Reset "floor_ptr->o_cnt" */
+       floor_ptr->o_cnt = 0;
+}
+
+
+/*!
+ * @brief 所定の位置に各種の閉じたドアを配置する / Place a random type of normal door at the given location.
+ * @param y ドアの配置を試みたいマスのY座標
+ * @param x ドアの配置を試みたいマスのX座標
+ * @param type ドアの地形ID
+ * @return なし
+ */
+void place_closed_door(floor_type *floor_ptr, POSITION y, POSITION x, int type)
+{
+       int tmp;
+       FEAT_IDX feat = feat_none;
+
+       if (d_info[floor_ptr->dungeon_idx].flags1 & DF1_NO_DOORS)
+       {
+               place_floor_bold(floor_ptr, y, x);
+               return;
+       }
+
+       /* Choose an object */
+       tmp = randint0(400);
+
+       /* Closed doors (300/400) */
+       if (tmp < 300)
+       {
+               /* Create closed door */
+               feat = feat_door[type].closed;
+       }
+
+       /* Locked doors (99/400) */
+       else if (tmp < 399)
+       {
+               /* Create locked door */
+               feat = feat_locked_door_random(type);
+       }
+
+       /* Stuck doors (1/400) */
+       else
+       {
+               /* Create jammed door */
+               feat = feat_jammed_door_random(type);
+       }
+
+       if (feat != feat_none)
+       {
+               cave_set_feat(floor_ptr, y, x, feat);
+
+               /* Now it is not floor */
+               floor_ptr->grid_array[y][x].info &= ~(CAVE_MASK);
+       }
+       else
+       {
+               place_floor_bold(floor_ptr, y, x);
+       }
+}
+
+/*!
+ * @brief 特殊な部屋向けに各種アイテムを配置する(vault_trapのサブセット) / Place a trap with a given displacement of point
+ * @param y トラップを配置したいマスの中心Y座標
+ * @param x トラップを配置したいマスの中心X座標
+ * @param yd Y方向の配置分散マス数
+ * @param xd X方向の配置分散マス数
+ * @return なし
+ * @details
+ * Only really called by some of the "vault" routines.
+ */
+void vault_trap_aux(floor_type *floor_ptr, POSITION y, POSITION x, POSITION yd, POSITION xd)
+{
+       int count = 0, y1 = y, x1 = x;
+       int dummy = 0;
+
+       grid_type *g_ptr;
+
+       /* Place traps */
+       for (count = 0; count <= 5; count++)
+       {
+               /* Get a location */
+               while (dummy < SAFE_MAX_ATTEMPTS)
+               {
+                       y1 = rand_spread(y, yd);
+                       x1 = rand_spread(x, xd);
+                       dummy++;
+                       if (!in_bounds(floor_ptr, y1, x1)) continue;
+                       break;
+               }
+
+               if (dummy >= SAFE_MAX_ATTEMPTS && cheat_room)
+               {
+                       msg_print(_("警告!地下室のトラップを配置できません!", "Warning! Could not place vault trap!"));
+               }
+
+               /* Require "naked" floor grids */
+               g_ptr = &floor_ptr->grid_array[y1][x1];
+               if (!is_floor_grid(g_ptr) || g_ptr->o_idx || g_ptr->m_idx) continue;
+
+               /* Place the trap */
+               place_trap(floor_ptr, y1, x1);
+
+               break;
+       }
+}
+
+/*!
+ * @brief 指定のマスが床系地形であるかを返す / Function that sees if a square is a floor.  (Includes range checking.)
+ * @param x チェックするマスのX座標
+ * @param y チェックするマスのY座標
+ * @return 床系地形ならばTRUE
+ */
+bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
+{
+       if (!in_bounds(p_ptr->current_floor_ptr, y, x))
+       {
+               /* Out of bounds */
+               return (FALSE);
+       }
+
+       /* Do the real check */
+       if (is_floor_bold(p_ptr->current_floor_ptr, y, x)) return (TRUE);
+
+       return (FALSE);
+}