#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"
#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"
*/
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 プレーヤーへの参照ポインタ
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;
}
/*
+ * 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)
}
/*
+ * 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)
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];
}
/*!
- * @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座標