OSDN Git Service

[Refactor] #40577 Separated projection-path-calculator.c/h from floor.c/h
[hengband/hengband.git] / src / floor / floor.c
index 21e3d2c..bac1ef4 100644 (file)
@@ -8,7 +8,7 @@
 #include "effect/effect-characteristics.h"
 #include "effect/spells-effect-util.h"
 #include "floor/cave.h"
-#include "floor/floor-generate.h"
+#include "floor/floor-generator-util.h"
 #include "floor/floor-object.h"
 #include "game-option/birth-options.h"
 #include "game-option/cheat-options.h"
@@ -30,6 +30,7 @@
 #include "room/door-definition.h"
 #include "system/artifact-type-definition.h"
 #include "system/floor-type-definition.h"
+#include "target/projection-path-calculator.h"
 #include "util/bit-flags-calculator.h"
 #include "view/display-messages.h"
 #include "world/world-object.h"
@@ -42,8 +43,6 @@
  */
 floor_type floor_info;
 
-bool pattern_tile(floor_type *floor_ptr, POSITION y, POSITION x) { return cave_have_flag_bold(floor_ptr, y, x, FF_PATTERN); }
-
 /*!
  * @brief 鍵のかかったドアを配置する
  * @param player_ptr プレーヤーへの参照ポインタ
@@ -474,7 +473,7 @@ int get_max_range(player_type *creature_ptr) { return creature_ptr->phase_out ?
 bool projectable(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2, POSITION x2)
 {
     u16b grid_g[512];
-    int grid_n = project_path(player_ptr, grid_g, (project_length ? project_length : get_max_range(player_ptr)), y1, x1, y2, x2, 0);
+    int grid_n = projection_path(player_ptr, grid_g, (project_length ? project_length : get_max_range(player_ptr)), y1, x1, y2, x2, 0);
     if (!grid_n)
         return TRUE;
 
@@ -487,6 +486,11 @@ bool projectable(player_type *player_ptr, POSITION y1, POSITION x1, POSITION y2,
 }
 
 /*
+ * Grid based version of "creature_bold()"
+ */
+static bool player_grid(player_type *player_ptr, grid_type *g_ptr) { return g_ptr == &player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x]; }
+
+/*
  * Grid based version of "cave_empty_bold()"
  */
 static bool is_cave_empty_grid(player_type *player_ptr, grid_type *g_ptr)
@@ -555,6 +559,12 @@ bool cave_valid_bold(floor_type *floor_ptr, POSITION y, POSITION x)
 }
 
 /*
+ * Determine if a "legal" grid is within "los" of the player *
+ * Note the use of comparison to zero to force a "boolean" result
+ */
+static bool player_has_los_grid(grid_type *g_ptr) { return (g_ptr->info & CAVE_VIEW) != 0; }
+
+/*
  * Change the "feat" flag for a grid, and notice/redraw the grid
  */
 void cave_set_feat(player_type *player_ptr, POSITION y, POSITION x, FEAT_IDX feat)
@@ -798,93 +808,6 @@ bool get_is_floor(floor_type *floor_ptr, POSITION x, POSITION y)
     return FALSE;
 }
 
-/*!
- * @brief 隣接4マスに存在する通路の数を返す / Count the number of "corridor" grids adjacent to the given grid.
- * @param y1 基準となるマスのY座標
- * @param x1 基準となるマスのX座標
- * @return 通路の数
- * @note Assumes "in_bounds(y1, x1)"
- * @details
- * XXX XXX This routine currently only counts actual "empty floor"\n
- * grids which are not in rooms.  We might want to also count stairs,\n
- * open doors, closed doors, etc.
- */
-static int next_to_corr(floor_type *floor_ptr, POSITION y1, POSITION x1)
-{
-    int k = 0;
-    for (int i = 0; i < 4; i++) {
-        POSITION y = y1 + ddy_ddd[i];
-        POSITION x = x1 + ddx_ddd[i];
-        grid_type *g_ptr;
-        g_ptr = &floor_ptr->grid_array[y][x];
-
-        if (cave_have_flag_grid(g_ptr, FF_WALL))
-            continue;
-        if (!is_floor_grid(g_ptr))
-            continue;
-        if (g_ptr->info & (CAVE_ROOM))
-            continue;
-
-        k++;
-    }
-
-    return k;
-}
-
-/*!
- * @brief ドアを設置可能な地形かを返す / Determine if the given location is "between" two walls, and "next to" two corridor spaces.
- * @param y 判定を行いたいマスのY座標
- * @param x 判定を行いたいマスのX座標
- * @return ドアを設置可能ならばTRUEを返す
- * @note Assumes "in_bounds()"
- * @details
- * \n
- * Assumes "in_bounds()"\n
- */
-static bool possible_doorway(floor_type *floor_ptr, POSITION y, POSITION x)
-{
-    if (next_to_corr(floor_ptr, y, x) < 2)
-        return FALSE;
-
-    /* Check Vertical */
-    if (cave_have_flag_bold(floor_ptr, y - 1, x, FF_WALL) && cave_have_flag_bold(floor_ptr, y + 1, x, FF_WALL)) {
-        return TRUE;
-    }
-
-    /* Check Horizontal */
-    if (cave_have_flag_bold(floor_ptr, y, x - 1, FF_WALL) && cave_have_flag_bold(floor_ptr, y, x + 1, FF_WALL)) {
-        return TRUE;
-    }
-
-    return FALSE;
-}
-
-/*!
- * @brief ドアの設置を試みる / Places door at y, x position if at least 2 walls found
- * @param player_ptr プレーヤーへの参照ポインタ
- * @param y 設置を行いたいマスのY座標
- * @param x 設置を行いたいマスのX座標
- * @return なし
- */
-void try_door(player_type *player_ptr, POSITION y, POSITION x)
-{
-    floor_type *floor_ptr = player_ptr->current_floor_ptr;
-    if (!in_bounds(floor_ptr, y, x))
-        return;
-
-    if (cave_have_flag_bold(floor_ptr, y, x, FF_WALL))
-        return;
-    if (floor_ptr->grid_array[y][x].info & (CAVE_ROOM))
-        return;
-
-    bool can_place_door = randint0(100) < dun_tun_jct;
-    can_place_door &= possible_doorway(floor_ptr, y, x);
-    can_place_door &= (d_info[player_ptr->dungeon_idx].flags1 & DF1_NO_DOORS) == 0;
-    if (can_place_door) {
-        place_random_door(player_ptr, y, x, FALSE);
-    }
-}
-
 FEAT_IDX conv_dungeon_feat(floor_type *floor_ptr, FEAT_IDX newfeat)
 {
     feature_type *f_ptr = &f_info[newfeat];
@@ -958,242 +881,6 @@ void vault_objects(player_type *player_ptr, POSITION y, POSITION x, int num)
 }
 
 /*!
- * @brief 始点から終点への直線経路を返す /
- * Determine the path taken by a projection.
- * @param player_ptr プレーヤーへの参照ポインタ
- * @param gp 経路座標リストを返す参照ポインタ
- * @param range 距離
- * @param y1 始点Y座標
- * @param x1 始点X座標
- * @param y2 終点Y座標
- * @param x2 終点X座標
- * @param flg フラグID
- * @return リストの長さ
- * @details
- * <pre>
- * The projection will always start from the grid (y1,x1), and will travel
- * towards the grid (y2,x2), touching one grid per unit of distance along
- * the major axis, and stopping when it enters the destination grid or a
- * wall grid, or has travelled the maximum legal distance of "range".
- *
- * Note that "distance" in this function (as in the "update_view()" code)
- * is defined as "MAX(dy,dx) + MIN(dy,dx)/2", which means that the player
- * actually has an "octagon of projection" not a "circle of projection".
- *
- * The path grids are saved into the grid array pointed to by "gp", and
- * there should be room for at least "range" grids in "gp".  Note that
- * due to the way in which distance is calculated, this function normally
- * uses fewer than "range" grids for the projection path, so the result
- * of this function should never be compared directly to "range".  Note
- * that the initial grid (y1,x1) is never saved into the grid array, not
- * even if the initial grid is also the final grid.
- *
- * The "flg" flags can be used to modify the behavior of this function.
- *
- * In particular, the "PROJECT_STOP" and "PROJECT_THRU" flags have the same
- * semantics as they do for the "project" function, namely, that the path
- * will stop as soon as it hits a monster, or that the path will continue
- * through the destination grid, respectively.
- *
- * The "PROJECT_JUMP" flag, which for the "project()" function means to
- * start at a special grid (which makes no sense in this function), means
- * that the path should be "angled" slightly if needed to avoid any wall
- * grids, allowing the player to "target" any grid which is in "view".
- * This flag is non-trivial and has not yet been implemented, but could
- * perhaps make use of the "vinfo" array (above).
- *
- * This function returns the number of grids (if any) in the path.  This
- * function will return zero if and only if (y1,x1) and (y2,x2) are equal.
- *
- * This algorithm is similar to, but slightly different from, the one used
- * by "update_view_los()", and very different from the one used by "los()".
- * </pre>
- */
-int project_path(player_type *player_ptr, u16b *gp, POSITION range, POSITION y1, POSITION x1, POSITION y2, POSITION x2, BIT_FLAGS flg)
-{
-    if ((x1 == x2) && (y1 == y2))
-        return 0;
-
-    POSITION y, x;
-    POSITION ay, ax;
-    POSITION sy, sx;
-    int frac;
-    int m;
-
-    if (y2 < y1) {
-        ay = (y1 - y2);
-        sy = -1;
-    } else {
-        ay = (y2 - y1);
-        sy = 1;
-    }
-
-    if (x2 < x1) {
-        ax = (x1 - x2);
-        sx = -1;
-    } else {
-        ax = (x2 - x1);
-        sx = 1;
-    }
-
-    int half = (ay * ax);
-    int full = half << 1;
-
-    /* Vertical */
-    floor_type *floor_ptr = player_ptr->current_floor_ptr;
-    int n = 0;
-    int k = 0;
-    if (ay > ax) {
-        m = ax * ax * 2;
-        y = y1 + sy;
-        x = x1;
-        frac = m;
-        if (frac > half) {
-            x += sx;
-            frac -= full;
-            k++;
-        }
-
-        while (TRUE) {
-            gp[n++] = GRID(y, x);
-            if ((n + (k >> 1)) >= range)
-                break;
-
-            if (!(flg & (PROJECT_THRU))) {
-                if ((x == x2) && (y == y2))
-                    break;
-            }
-
-            if (flg & (PROJECT_DISI)) {
-                if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x))
-                    break;
-            } else if (flg & (PROJECT_LOS)) {
-                if ((n > 0) && !cave_los_bold(floor_ptr, y, x))
-                    break;
-            } else if (!(flg & (PROJECT_PATH))) {
-                if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT))
-                    break;
-            }
-
-            if (flg & (PROJECT_STOP)) {
-                if ((n > 0) && (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
-                    break;
-            }
-
-            if (!in_bounds(floor_ptr, y, x))
-                break;
-
-            if (m) {
-                frac += m;
-                if (frac > half) {
-                    x += sx;
-                    frac -= full;
-                    k++;
-                }
-            }
-
-            y += sy;
-        }
-
-        return n;
-    }
-
-    /* Horizontal */
-    if (ax > ay) {
-        m = ay * ay * 2;
-        y = y1;
-        x = x1 + sx;
-        frac = m;
-        if (frac > half) {
-            y += sy;
-            frac -= full;
-            k++;
-        }
-
-        while (TRUE) {
-            gp[n++] = GRID(y, x);
-            if ((n + (k >> 1)) >= range)
-                break;
-
-            if (!(flg & (PROJECT_THRU))) {
-                if ((x == x2) && (y == y2))
-                    break;
-            }
-
-            if (flg & (PROJECT_DISI)) {
-                if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x))
-                    break;
-            } else if (flg & (PROJECT_LOS)) {
-                if ((n > 0) && !cave_los_bold(floor_ptr, y, x))
-                    break;
-            } else if (!(flg & (PROJECT_PATH))) {
-                if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT))
-                    break;
-            }
-
-            if (flg & (PROJECT_STOP)) {
-                if ((n > 0) && (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
-                    break;
-            }
-
-            if (!in_bounds(floor_ptr, y, x))
-                break;
-
-            if (m) {
-                frac += m;
-                if (frac > half) {
-                    y += sy;
-                    frac -= full;
-                    k++;
-                }
-            }
-
-            x += sx;
-        }
-
-        return n;
-    }
-
-    y = y1 + sy;
-    x = x1 + sx;
-
-    while (TRUE) {
-        gp[n++] = GRID(y, x);
-        if ((n + (n >> 1)) >= range)
-            break;
-
-        if (!(flg & (PROJECT_THRU))) {
-            if ((x == x2) && (y == y2))
-                break;
-        }
-
-        if (flg & (PROJECT_DISI)) {
-            if ((n > 0) && cave_stop_disintegration(floor_ptr, y, x))
-                break;
-        } else if (flg & (PROJECT_LOS)) {
-            if ((n > 0) && !cave_los_bold(floor_ptr, y, x))
-                break;
-        } else if (!(flg & (PROJECT_PATH))) {
-            if ((n > 0) && !cave_have_flag_bold(floor_ptr, y, x, FF_PROJECT))
-                break;
-        }
-
-        if (flg & (PROJECT_STOP)) {
-            if ((n > 0) && (player_bold(player_ptr, y, x) || floor_ptr->grid_array[y][x].m_idx != 0))
-                break;
-        }
-
-        if (!in_bounds(floor_ptr, y, x))
-            break;
-
-        y += sy;
-        x += sx;
-    }
-
-    return n;
-}
-
-/*!
  * @brief 指定のマスを床地形に変える / Set a square to be floor.  (Includes range checking.)
  * @param player_ptr プレーヤーへの参照ポインタ
  * @param x 地形を変えたいマスのX座標