OSDN Git Service

[Refactor] #37353 los() を geometry.c/h へ移動。
authordeskull <deskull@users.sourceforge.jp>
Thu, 18 Apr 2019 05:23:47 +0000 (14:23 +0900)
committerdeskull <deskull@users.sourceforge.jp>
Thu, 18 Apr 2019 05:23:47 +0000 (14:23 +0900)
src/externs.h
src/geometry.c
src/geometry.h
src/grid.c

index 0ebb5c5..1d11c22 100644 (file)
@@ -415,7 +415,6 @@ extern void dump_yourself(FILE *fff);
 
 
 /* grids.c */
-extern bool los(POSITION y1, POSITION x1, POSITION y2, POSITION x2);
 extern void update_local_illumination(POSITION y, POSITION x);
 extern bool player_can_see_bold(POSITION y, POSITION x);
 extern bool cave_valid_bold(POSITION y, POSITION x);
index 9688a9b..4d4fe81 100644 (file)
@@ -403,6 +403,271 @@ sint project_path(u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y
        return (n);
 }
 
+/*!
+ * @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(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(y1, x1)) return FALSE; */
+       /* if (!in_bounds(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(ty, x1)) return FALSE;
+                       }
+               }
+
+               /* North -- check for walls */
+               else
+               {
+                       for (ty = y1 - 1; ty > y2; ty--)
+                       {
+                               if (!cave_los_bold(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(y1, tx)) return FALSE;
+                       }
+               }
+
+               /* West -- check for walls */
+               else
+               {
+                       for (tx = x1 - 1; tx > x2; tx--)
+                       {
+                               if (!cave_los_bold(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(y1 + sy, x1)) return TRUE;
+               }
+       }
+
+       /* Horizontal "knights" */
+       else if (ay == 1)
+       {
+               if (ax == 2)
+               {
+                       if (cave_los_bold(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(ty, tx)) return FALSE;
+
+                       qy += m;
+
+                       if (qy < f2)
+                       {
+                               tx += sx;
+                       }
+                       else if (qy > f2)
+                       {
+                               ty += sy;
+                               if (!cave_los_bold(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(ty, tx)) return FALSE;
+
+                       qx += m;
+
+                       if (qx < f2)
+                       {
+                               ty += sy;
+                       }
+                       else if (qx > f2)
+                       {
+                               tx += sx;
+                               if (!cave_los_bold(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.
index 747b160..dd45f28 100644 (file)
@@ -24,6 +24,8 @@ extern DIRECTION coords_to_dir(POSITION y, POSITION x);
 extern sint project_path(u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg);
 
 extern POSITION distance(POSITION y1, POSITION x1, POSITION y2, POSITION x2);
+extern bool los(POSITION y1, POSITION x1, POSITION y2, POSITION x2);
+
 extern bool projectable(POSITION y1, POSITION x1, POSITION y2, POSITION x2);
 extern void scatter(POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode);
 extern void mmove2(POSITION *y, POSITION *x, POSITION y1, POSITION x1, POSITION y2, POSITION x2);
index 2b25e3a..7597bbc 100644 (file)
@@ -822,271 +822,6 @@ bool is_hidden_door(grid_type *g_ptr)
                return FALSE;
 }
 
-/*!
- * @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(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(y1, x1)) return FALSE; */
-       /* if (!in_bounds(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(ty, x1)) return FALSE;
-                       }
-               }
-
-               /* North -- check for walls */
-               else
-               {
-                       for (ty = y1 - 1; ty > y2; ty--)
-                       {
-                               if (!cave_los_bold(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(y1, tx)) return FALSE;
-                       }
-               }
-
-               /* West -- check for walls */
-               else
-               {
-                       for (tx = x1 - 1; tx > x2; tx--)
-                       {
-                               if (!cave_los_bold(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(y1 + sy, x1)) return TRUE;
-               }
-       }
-
-       /* Horizontal "knights" */
-       else if (ay == 1)
-       {
-               if (ax == 2)
-               {
-                       if (cave_los_bold(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(ty, tx)) return FALSE;
-
-                       qy += m;
-
-                       if (qy < f2)
-                       {
-                               tx += sx;
-                       }
-                       else if (qy > f2)
-                       {
-                               ty += sy;
-                               if (!cave_los_bold(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(ty, tx)) return FALSE;
-
-                       qx += m;
-
-                       if (qx < f2)
-                       {
-                               ty += sy;
-                       }
-                       else if (qx > f2)
-                       {
-                               tx += sx;
-                               if (!cave_los_bold(ty, tx)) return FALSE;
-                               qx -= f1;
-                               ty += sy;
-                       }
-                       else
-                       {
-                               tx += sx;
-                               qx -= f1;
-                               ty += sy;
-                       }
-               }
-       }
-
-       /* Assume los */
-       return TRUE;
-}
-
 #define COMPLEX_WALL_ILLUMINATION /*!< 照明状態を壁により影響を受ける、より複雑な判定に切り替えるマクロ */