* 2014 Deskull rearranged comment for Doxygen. \n
*/
-#include <assert.h>
+#include <algorithm>
+#include <array>
+#include <stack>
#include "dungeon/dungeon-flag-types.h"
#include "dungeon/dungeon.h"
#include "wizard/wizard-messages.h"
#include "world/world.h"
-//--------------------------------------------------------------------
-// 動的可変長配列
-//--------------------------------------------------------------------
-
-typedef struct Vec {
- size_t len;
- size_t cap;
- int *data;
-} Vec;
-
-// 容量 cap の空 Vec を返す。
-static Vec vec_with_capacity(const size_t cap)
-{
- assert(cap > 0);
-
- Vec vec = { .len = 0, .cap = cap, .data = NULL };
- vec.data = static_cast<int*>(malloc(sizeof(int) * cap));
- if (!vec.data)
- rpanic(cap);
-
- return vec;
-}
-
-// サイズ len で、全要素が init で初期化された Vec を返す。
-static Vec vec_new(const size_t len, const int init)
-{
- assert(len > 0);
-
- const size_t cap = 2 * len;
- Vec vec = vec_with_capacity(cap);
-
- vec.len = len;
- for (size_t i = 0; i < len; ++i)
- vec.data[i] = init;
-
- return vec;
-}
-
-static void vec_delete(Vec *const vec)
-{
- free(vec->data);
-
- vec->len = 0;
- vec->cap = 0;
- vec->data = NULL;
-}
-
-static size_t vec_size(const Vec *const vec) { return vec->len; }
-
-static bool vec_is_empty(const Vec *const vec) { return vec_size(vec) == 0; }
-
-static void vec_push_back(Vec *const vec, const int e)
-{
- // 容量不足になったら容量を拡張する。
- if (vec->len == vec->cap) {
- vec->cap = vec->cap > 0 ? 2 * vec->cap : 1;
- vec->data = static_cast<int*>(realloc(vec->data, sizeof(int) * vec->cap));
- if (!vec->data)
- rpanic(vec->cap);
- }
-
- vec->data[vec->len++] = e;
-}
-
-static int vec_pop_back(Vec *const vec)
-{
- assert(!vec_is_empty(vec));
-
- return vec->data[vec->len-- - 1];
-}
-
-//--------------------------------------------------------------------
-
/*!
* @brief 闘技場用のアリーナ地形を作成する / Builds the on_defeat_arena_monster after it is entered -KMW-
* @param player_ptr プレーヤーへの参照ポインタ
return has_flag(flags, FF_PERMANENT) && !has_flag(flags, FF_MOVE);
}
-static void floor_is_connected_dfs(
- const floor_type *const floor_ptr, const IsWallFunc is_wall, const int y_start, const int x_start, Vec *const stk, const Vec *const visited)
+static void floor_is_connected_dfs(const floor_type *const floor_ptr, const IsWallFunc is_wall, const int y_start, const int x_start, bool *const visited)
{
// clang-format off
static const int DY[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int w = floor_ptr->width;
const int start = w * y_start + x_start;
- vec_push_back(stk, start);
- visited->data[start] = 1;
+ // 深さ優先探索用のスタック。
+ // 最大フロアサイズが h=66, w=198 なので、スタックオーバーフロー防止のため再帰は使わない。
+ std::stack<int> stk;
- while (!vec_is_empty(stk)) {
- const int cur = vec_pop_back(stk);
+ stk.emplace(start);
+ visited[start] = TRUE;
+
+ while (!stk.empty()) {
+ const int cur = stk.top();
+ stk.pop();
const int y = cur / w;
const int x = cur % w;
if (y_nxt < 0 || h <= y_nxt || x_nxt < 0 || w <= x_nxt)
continue;
const int nxt = w * y_nxt + x_nxt;
- if (visited->data[nxt])
+ if (visited[nxt])
continue;
if (is_wall(floor_ptr, y_nxt, x_nxt))
continue;
- vec_push_back(stk, nxt);
- visited->data[nxt] = 1;
+ stk.emplace(nxt);
+ visited[nxt] = TRUE;
}
}
}
// 連結成分数が 0 の場合、偽を返す。
static bool floor_is_connected(const floor_type *const floor_ptr, const IsWallFunc is_wall)
{
+ static std::array<bool, MAX_HGT * MAX_WID> visited;
+
const int h = floor_ptr->height;
const int w = floor_ptr->width;
- // ヒープ上に確保したスタックを用いてDFSする。
- // 最大フロアサイズが h=66, w=198 なので、単純に再帰DFSするとスタックオーバーフローが不安。
- Vec stk = vec_with_capacity(1024);
- Vec visited = vec_new((size_t)h * (size_t)w, 0);
+ std::fill(begin(visited), end(visited), false);
+
int n_component = 0; // 連結成分数
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
const int idx = w * y + x;
- if (visited.data[idx])
+ if (visited[idx])
continue;
if (is_wall(floor_ptr, y, x))
continue;
if (++n_component >= 2)
- goto finish;
- floor_is_connected_dfs(floor_ptr, is_wall, y, x, &stk, &visited);
+ break;
+ floor_is_connected_dfs(floor_ptr, is_wall, y, x, visited.data());
}
}
-finish:
- vec_delete(&visited);
- vec_delete(&stk);
-
return n_component == 1;
}