summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--compat/prelude.hpp2
-rw-r--r--src/path-search-result.cpp68
-rw-r--r--src/path-search-result.hpp35
-rw-r--r--src/path-search.cpp147
-rw-r--r--src/path-search.hpp61
-rw-r--r--test/app.hpp1
-rw-r--r--test/main.cpp1
-rw-r--r--test/path-search-result.cpp26
-rw-r--r--test/path-search.cpp2
10 files changed, 261 insertions, 84 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f83051b..fb64dc2f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -151,6 +151,8 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL
add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:$<$<CONFIG:DEBUG,Debug>:_LIBCPP_ENABLE_ASSERTIONS>>)
add_compile_options(-Wno-reserved-macro-identifier)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wno-ambiguous-reversed-operator>)
+ add_compile_options(-fmodules)
+ add_link_options(-fmodules)
endif()
set_directory_properties(PROPERTIES CORRADE_USE_PEDANTIC_FLAGS OFF)
diff --git a/compat/prelude.hpp b/compat/prelude.hpp
index 969c0cb8..a1c5e436 100644
--- a/compat/prelude.hpp
+++ b/compat/prelude.hpp
@@ -22,7 +22,7 @@ namespace Magnum {
using Vector2uz = ::Magnum::Math::Vector2<size_t>;
using Vector3uz = ::Magnum::Math::Vector3<size_t>;
using Vector4uz = ::Magnum::Math::Vector4<size_t>;
-}
+} // namespace Magnum
namespace floormat {
using namespace ::Magnum;
diff --git a/src/path-search-result.cpp b/src/path-search-result.cpp
index 2d9f6ebd..fb2c41ca 100644
--- a/src/path-search-result.cpp
+++ b/src/path-search-result.cpp
@@ -1,38 +1,70 @@
#include "path-search.hpp"
#include "path-search-result.hpp"
#include "compat/assert.hpp"
+#include <utility>
namespace floormat {
-path_search_result::path_search_result() : _next{nullptr} {}
-size_t path_search_result::size() const { return _path.size(); }
-path_search_result::operator bool() const { return !_path.empty(); }
-path_search_result::operator ArrayView<const global_coords>() const { return {_path.data(), _path.size()}; }
-const global_coords* path_search_result::begin() const { return _path.data(); }
-const global_coords* path_search_result::end() const { return _path.data() + _path.size(); }
+std::unique_ptr<path_search_result::node> path_search_result::_pool; // NOLINT
-const global_coords& path_search_result::operator[](size_t index) const
+path_search_result::path_search_result()
{
- fm_debug_assert(index < _path.size());
- return data()[index];
+ if (_pool)
+ {
+ auto ptr = std::move(_pool);
+ fm_debug_assert(ptr->vec.empty());
+ auto next = std::move(ptr->_next);
+ _node = std::move(ptr);
+ _pool = std::move(next);
+ }
+ else
+ {
+ _node = std::make_unique<node>();
+ _node->vec.reserve(min_length);
+ }
+}
+
+path_search_result::~path_search_result() noexcept
+{
+ fm_debug_assert(_node);
+ _node->vec.clear();
+ _node->_next = std::move(_pool);
+ _pool = std::move(_node);
}
-const global_coords* path_search_result::data() const
+path_search_result::path_search_result(const path_search_result& x) noexcept
{
- fm_debug_assert(!_next);
- return _path.data();
+ fm_debug_assert(x._node);
+ auto self = path_search_result{};
+ self._node->vec = x._node->vec;
+ _node = std::move(self._node);
}
-path_search_result::path_search_result(ArrayView<const global_coords> array) : _next{nullptr}
+path_search_result& path_search_result::operator=(const path_search_result& x) noexcept
{
- _path.reserve(std::max(array.size(), min_length));
- _path = {array.begin(), array.end()};
+ fm_debug_assert(_node);
+ fm_debug_assert(!_node->_next);
+ if (&x != this)
+ _node->vec = x._node->vec;
+ return *this;
}
-path_search_result::path_search_result(const path_search_result& other) : _next{nullptr}
+path_search_result::node::node() noexcept = default;
+size_t path_search_result::size() const { return _node->vec.size(); }
+const global_coords* path_search_result::data() const { return _node->vec.data(); }
+path_search_result::operator bool() const { return !_node->vec.empty(); }
+
+path_search_result::operator ArrayView<const global_coords>() const
{
- _path.reserve(std::max(min_length, other._path.size()));
- _path = {other._path.begin(), other._path.end()};
+ fm_debug_assert(_node);
+ return {_node->vec.data(), _node->vec.size()};
+}
+
+const global_coords& path_search_result::operator[](size_t index) const
+{
+ fm_debug_assert(_node);
+ fm_debug_assert(index < _node->vec.size());
+ return data()[index];
}
} // namespace floormat
diff --git a/src/path-search-result.hpp b/src/path-search-result.hpp
index 7e3f30a7..ea00cd85 100644
--- a/src/path-search-result.hpp
+++ b/src/path-search-result.hpp
@@ -1,5 +1,6 @@
#pragma once
#include "src/global-coords.hpp"
+#include <memory>
#include <vector>
namespace floormat {
@@ -7,10 +8,7 @@ namespace floormat {
struct path_search_result final
{
friend class path_search;
-
- path_search_result();
- path_search_result(ArrayView<const global_coords> array);
- path_search_result(const path_search_result& other);
+ friend struct test_app;
const global_coords* data() const;
const global_coords& operator[](size_t index) const;
@@ -19,14 +17,33 @@ struct path_search_result final
explicit operator ArrayView<const global_coords>() const;
explicit operator bool() const;
- const global_coords* begin() const;
- const global_coords* end() const;
-
private:
+ fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(path_search_result);
+ path_search_result(const path_search_result& x) noexcept;
+ path_search_result& operator=(const path_search_result& x) noexcept;
+
static constexpr size_t min_length = TILE_MAX_DIM*2;
- path_search_result* _next;
- std::vector<global_coords> _path;
+ struct node
+ {
+ friend struct path_search_result;
+
+ node() noexcept;
+ fm_DECLARE_DELETED_COPY_ASSIGNMENT(node);
+ fm_DECLARE_DEFAULT_MOVE_ASSIGNMENT_(node);
+
+ std::vector<global_coords> vec;
+
+ private:
+ std::unique_ptr<node> _next;
+ };
+
+ static std::unique_ptr<node> _pool; // NOLINT(*-avoid-non-const-global-variables)
+
+ path_search_result();
+ ~path_search_result() noexcept;
+
+ std::unique_ptr<node> _node;
};
} // namespace floormat
diff --git a/src/path-search.cpp b/src/path-search.cpp
index 03f54422..f7b61c4e 100644
--- a/src/path-search.cpp
+++ b/src/path-search.cpp
@@ -3,7 +3,9 @@
#include "object.hpp"
#include "world.hpp"
#include "RTree-search.hpp"
+#include "compat/math.hpp"
#include "compat/function2.hpp"
+#include "object.hpp"
#include <bit>
#include <algorithm>
#include <Corrade/Containers/Optional.h>
@@ -18,14 +20,12 @@ constexpr auto div = path_search::subdivide_factor;
constexpr int div_BITS = 2;
static_assert(1 << div_BITS == div);
-static_assert(path_search::min_size.x() % 2 == 0 && path_search::min_size.x() * div * 2 == iTILE_SIZE2.x());
-
constexpr auto never_continue_1 = [](collision_data) constexpr { return path_search_continue::blocked; };
constexpr auto never_continue_ = path_search::pred{never_continue_1};
constexpr auto always_continue_1 = [](collision_data) constexpr { return path_search_continue::pass; };
constexpr auto always_continue_ = path_search::pred{always_continue_1};
-constexpr Pair<Vector2i, Vector2i> get_value(Vector2i sz, Vector2ub div, rotation r)
+constexpr Pair<Vector2i, Vector2i> get_value(Vector2ub sz, Vector2ub div, rotation r)
{
const int offset_W = iTILE_SIZE2.x()/(int)div.x(), offset_N = iTILE_SIZE2.y()/(int)div.y();
@@ -56,7 +56,7 @@ constexpr Pair<Vector2i, Vector2i> get_value(Vector2i sz, Vector2ub div, rotatio
}
case (uint8_t)rotation_COUNT: {
auto min_C = Vector2i(-sz.x()/2, -sz.y()/2 );
- auto max_C = min_C + sz;
+ auto max_C = min_C + Vector2i(sz);
return {min_C, max_C};
}
default:
@@ -66,7 +66,7 @@ constexpr Pair<Vector2i, Vector2i> get_value(Vector2i sz, Vector2ub div, rotatio
[[maybe_unused]] constexpr bool test_offsets()
{
- constexpr auto sz_ = path_search::min_size;
+ constexpr auto sz_ = Vector2ub(path_search::min_size);
constexpr Vector2i shift = Vector2i(0, 0) * iTILE_SIZE2 + Vector2i(0, 0);
[[maybe_unused]] constexpr auto N = get_value(sz_, {1,1}, rotation::N);
@@ -98,7 +98,7 @@ static_assert(test_offsets());
{
using enum rotation;
constexpr auto tile_start = iTILE_SIZE2/-2;
- constexpr auto sz = Vector2i(8, 16);
+ constexpr auto sz = Vector2ub(8, 16);
{
constexpr auto bb = get_value(sz, Vector2ub(div), N);
@@ -122,8 +122,48 @@ static_assert(test_offsets());
static_assert(test_offsets2());
+constexpr auto tile_bbox(local_coords tile, Vector2b offset, Vector2ub size)
+{
+ constexpr auto tile_start = TILE_SIZE2*.5f;
+ auto size_ = Vector2(size), half_size = Vector2(size/2);
+ auto pos = tile_start + Vector2(tile) * TILE_SIZE2 + Vector2(offset);
+ auto bb = path_search::bbox<float>{pos - half_size, pos + size_};
+ return bb;
+};
+
+void push_heap(std::vector<search_astar::vertex_tuple>& vec, search_astar::vertex_tuple value)
+{
+ vec.push_back(value);
+ std::push_heap(vec.begin(), vec.end());
+}
+
+auto pop_heap(std::vector<search_astar::vertex_tuple>& vec)
+{
+ auto ret = vec.back();
+ std::pop_heap(vec.begin(), vec.end());
+ return ret;
+}
+
} // namespace
+bool operator<(const search_astar::vertex_tuple& a, const search_astar::vertex_tuple& b) noexcept
+{
+ return b.dist <= a.dist;
+}
+
+path_search::neighbors::operator ArrayView<const global_coords>() const { return {data.data(), size}; }
+auto path_search::never_continue() noexcept -> const pred& { return never_continue_; }
+auto path_search::always_continue() noexcept -> const pred& { return always_continue_; }
+
+search_astar::vertex_tuple::vertex_tuple(global_coords coord1, Vector2b offset1,
+ global_coords coord2, Vector2b offset2,
+ float dist) :
+ coord1{coord1}, coord2{coord2}, dist{dist},
+ offset1{offset1}, offset2{offset2}
+{
+}
+
+#if 0
size_t path_search::cache_chunk_index(chunk_coords ch)
{
auto ch_ = Vector2i(ch) - cache.start;
@@ -142,9 +182,6 @@ size_t path_search::cache_tile_index(local_coords tile, Vector2i subdiv)
return index;
}
-auto path_search::never_continue() noexcept -> const pred& { return never_continue_; }
-auto path_search::always_continue() noexcept -> const pred& { return always_continue_; }
-
void path_search::ensure_allocated(chunk_coords a, chunk_coords b)
{
constexpr auto max_chunks = 1uz << 26;
@@ -164,6 +201,7 @@ void path_search::ensure_allocated(chunk_coords a, chunk_coords b)
fm_assert(cache.size.product() > 0);
}
+#endif
bool path_search::is_passable_1(chunk& c, Vector2 min, Vector2 max, object_id own_id, const pred& p)
{
@@ -242,9 +280,9 @@ bool path_search::is_passable(world& w, global_coords coord, Vector2b offset, Ve
auto path_search::neighbor_tile_bbox(Vector2i coord, Vector2ub own_size, Vector2ub div, rotation r) -> bbox<float>
{
+ own_size = Math::max(own_size, Vector2ub(min_size));
const auto shift = coord * iTILE_SIZE2;
- auto sz = Math::max(Vector2i(own_size), min_size);
- auto [min, max] = get_value(sz, div, r);
+ auto [min, max] = get_value(own_size, div, r);
return { Vector2(min + shift), Vector2(max + shift) };
}
@@ -255,12 +293,6 @@ auto path_search::neighbor_tiles(world& w, global_coords coord, Vector2ub size,
constexpr auto min_size = Vector2ub(iTILE_SIZE2/4);
size = Math::max(size, min_size);
-#if 0
- if (auto [min, max] = neighbor_tile_bbox(pos, size, rotation_COUNT);
- !is_passable(w, ch, min, max, own_id))
- return {};
-#endif
-
neighbors ns;
using enum rotation;
@@ -278,23 +310,35 @@ auto path_search::neighbor_tiles(world& w, global_coords coord, Vector2ub size,
{
auto [min, max] = neighbor_tile_bbox(pos, size, { 1, 1 }, dir);
if (is_passable(w, ch, min, max, own_id, p))
- ns.neighbors[ns.size++] = coord + off;
+ ns.data[ns.size++] = { coord + off, {} };
}
return ns;
}
-auto path_search::bbox_union(bbox<float> bb, Vector2i coord, Vector2b offset, Vector2ub size) -> bbox<float>
+template<typename T = float>
+requires std::is_arithmetic_v<T>
+auto path_search::bbox_union(bbox<T> bb, Vector2i coord, Vector2b offset, Vector2ub size) -> bbox<T>
{
auto center = coord * iTILE_SIZE2 + Vector2i(offset);
- auto min = center - Vector2i(size / 2u);
+ auto min = center - Vector2i(size / 2);
auto max = center + Vector2i(size);
+ using Vec = VectorTypeFor<2, T>;
return {
- .min = Math::min(bb.min, Vector2(min)),
- .max = Math::max(bb.max, Vector2(max)),
+ .min = Math::min(Vec(bb.min), Vec(min)),
+ .max = Math::max(Vec(bb.max), Vec(max)),
};
}
+template auto path_search::bbox_union(bbox<int> bb, Math::Vector2<int> coord, Vector2b offset, Vector2ub size) -> bbox<int>;
+template auto path_search::bbox_union(bbox<float> bb, Vector2i coord, Vector2b offset, Vector2ub size) -> bbox<float>;
+
+auto path_search::bbox_union(bbox<int> bb1, bbox<int> bb2) -> bbox<int>
+{
+ return { Math::min(bb1.min, bb2.min), Math::max(bb1.max, bb2.max) };
+}
+
+#if 0
void path_search::fill_cache_(world& w, chunk_coords_ coord, Vector2ub own_size_, object_id own_id, const pred& p)
{
auto own_size = Math::max(Vector2i(own_size_), path_search::min_size);
@@ -353,38 +397,75 @@ void path_search::fill_cache(world& w, Vector2i cmin, Vector2i cmax, int8_t z,
for (int32_t x = cmin.x(); x <= cmax.x(); x++)
fill_cache_(w, {(int16_t)x, (int16_t)y, z}, own_size, own_id, p);
}
+#endif
-Optional<path_search_result> path_search::Dijkstra(world& w, Vector2ub own_size, object_id own_id,
- global_coords from, Vector2b from_offset,
- global_coords to, Vector2b to_offset,
- const pred& p)
+path_search_result path_search::Dijkstra(world& w, Vector2ub own_size, object_id own_id,
+ global_coords from, Vector2b from_offset,
+ global_coords to, Vector2b to_offset,
+ const pred& p)
{
fm_assert(from.x <= to.x && from.y <= to.y);
+ own_size = Math::max(own_size, Vector2ub(min_size));
if (from.z() != to.z()) [[unlikely]]
return {};
+
// todo try removing this eventually
if (from.z() != 0) [[unlikely]]
return {};
- // check if obj can actually move at all
if (!is_passable(w, from, from_offset, own_size, own_id, p))
return {};
+
if (!is_passable(w, to, to_offset, own_size, own_id, p))
return {};
- ensure_allocated(from.chunk(), to.chunk());
+ _astar.Q.clear();
+ _astar.Q.reserve(TILE_COUNT*(size_t)(subdivide_factor*subdivide_factor));
+
+ const auto pos0 = Vector2(from.local()) * TILE_SIZE2;
+ const auto start_bbox = bbox<float>{pos0 - Vector2(own_size/2), pos0 + Vector2(own_size)};
+
+ constexpr auto div = Vector2ub{subdivide_factor};
+ constexpr auto sub_size = Vector2(Vector2ub(iTILE_SIZE2) / div);
+ constexpr auto sqrt_2 = (float)math::sqrt(2);
+
+ constexpr Vector2 directions[8] = {
+ sub_size * Vector2{ -1, 0 },
+ sub_size * Vector2{ 0, -1 },
+ sub_size * Vector2{ 1, 0 },
+ sub_size * Vector2{ 0, 1 },
+ sub_size * Vector2{ sqrt_2, sqrt_2, },
+ sub_size * Vector2{ -sqrt_2, -sqrt_2 },
+ sub_size * Vector2{ sqrt_2, -sqrt_2 },
+ sub_size * Vector2{ -sqrt_2, sqrt_2 },
+ };
+
+ const auto bb0 = bbox_union(start_bbox, Vector2i(from.local()), {}, own_size);
+ if (is_passable(w, chunk_coords_{from}, bb0.min, bb0.max, own_id, p))
+ push_heap(_astar.Q, {from, from_offset, from, {}, 0});
+
+ path_search_result result;
+ auto& path = result._node->vec;
+ path.clear();
+
+ auto& Q = _astar.Q;
+
+ while (!Q.empty())
+ {
+ auto cur = pop_heap(Q);
+ }
+
auto [cmin, cmax] = Math::minmax(Vector2i(from.chunk()) - Vector2i(1, 1),
Vector2i(to.chunk()) + Vector2i(1, 1));
- fill_cache(w, cmin, cmax, from.z(), own_size, own_id, p);
// todo...
- return {};
+ return result;
}
-Optional<path_search_result> path_search::Dijkstra(world& w, const object& obj,
- global_coords to, Vector2b to_offset,
- const pred& p)
+path_search_result path_search::Dijkstra(world& w, const object& obj,
+ global_coords to, Vector2b to_offset,
+ const pred& p)
{
constexpr auto full_tile = Vector2ub(iTILE_SIZE2*3/4);
auto size = Math::max(obj.bbox_size, full_tile);
diff --git a/src/path-search.hpp b/src/path-search.hpp
index bea1b76b..574cd133 100644
--- a/src/path-search.hpp
+++ b/src/path-search.hpp
@@ -32,20 +32,20 @@ struct search_astar final
{
struct vertex_tuple
{
- static constexpr auto INF = (uint32_t)-1;
+ vertex_tuple(global_coords coord1, Vector2b offset1,
+ global_coords coord2, Vector2b offset2,
+ float dist = INF);
- const chunk *c1 = nullptr, *c2 = nullptr;
- uint32_t dist = 0;
- };
+ static constexpr float INF = 1 << 24;
+
+ global_coords coord1, coord2;
+ float dist = INF;
+ Vector2b offset1, offset2;
- [[nodiscard]] bool reserve(chunk_coords_ c1, chunk_coords_ c2);
- void insert(const chunk& c1, const chunk& c2);
- vertex_tuple delete_min();
- void add_edges();
- bool find(chunk_coords_);
+ friend bool operator<(const vertex_tuple& a, const vertex_tuple& b) noexcept;
+ };
std::vector<vertex_tuple> Q;
- std::vector<global_coords> output;
};
enum class path_search_continue : bool { pass = false, blocked = true };
@@ -55,22 +55,32 @@ class path_search final
friend struct path_search_result;
// todo bucketize by array length
- path_search_result* pool = nullptr;
+ search_astar _astar;
public:
static constexpr int subdivide_factor = 4;
- static constexpr auto min_size = iTILE_SIZE2 / subdivide_factor / 2;
+ static constexpr auto min_size = iTILE_SIZE2 / subdivide_factor;
static constexpr size_t tile_count = Vector2i(subdivide_factor * TILE_MAX_DIM).product();
struct neighbors final
{
- auto begin() const { return neighbors.data(); }
- auto end() const { return neighbors.data() + size; }
+ auto begin() const { return data.data(); }
+ auto end() const { return data.data() + size; }
- std::array<global_coords, 4> neighbors;
+ std::array<global_coords, 5> data;
uint8_t size = 0;
+
+ operator ArrayView<const global_coords>() const;
+ };
+
+ struct positions
+ {
+ size_t size = 0;
+ std::array<global_coords, 5> coords;
+ std::array<Vector2b, 5> offsets;
};
+#if 0
struct chunk_tiles_cache
{
std::bitset<tile_count> can_go_north{true}, can_go_west{true};
@@ -81,28 +91,32 @@ public:
Array<chunk_tiles_cache> array;
Vector2i start, size; // in chunks
};
+#endif
struct obj_position { Vector2 center, size; };
template<typename T> struct bbox { VectorTypeFor<2, T> min, max; };
+#if 0
chunk_cache cache;
-
- size_t cache_chunk_index(chunk_coords coord);
- static size_t cache_tile_index(local_coords tile, Vector2i subdiv);
+#endif
using pred = fu2::function_view<path_search_continue(collision_data) const>;
static const pred& never_continue() noexcept;
static const pred& always_continue() noexcept;
+#if 0
+ size_t cache_chunk_index(chunk_coords coord);
+ static size_t cache_tile_index(local_coords tile, Vector2i subdiv);
+
void ensure_allocated(chunk_coords a, chunk_coords b);
- void fill_cache(world& w, Vector2i cmin, Vector2i cmax, int8_t z, Vector2ub own_size, object_id own_id, const pred& p = never_continue());
+ void fill_cac`he(world& w, Vector2i cmin, Vector2i cmax, int8_t z, Vector2ub own_size, object_id own_id, const pred& p = never_continue());
void fill_cache_(world& w, chunk_coords_ coord, Vector2ub own_size, object_id own_id, const pred& p = never_continue());
+#endif
- // todo remember to check from.z() == to.z()
// todo add simple bresenham short-circuit
- Optional<path_search_result> Dijkstra(world& w, Vector2ub own_size, object_id own_id, global_coords from, Vector2b from_offset, global_coords to, Vector2b to_offset, const pred& p = never_continue());
- Optional<path_search_result> Dijkstra(world& w, const object& obj, global_coords to, Vector2b to_offset, const pred& p = never_continue());
+ path_search_result Dijkstra(world& w, Vector2ub own_size, object_id own_id, global_coords from, Vector2b from_offset, global_coords to, Vector2b to_offset, const pred& p = never_continue());
+ path_search_result Dijkstra(world& w, const object& obj, global_coords to, Vector2b to_offset, const pred& p = never_continue());
static bool is_passable_1(chunk& c, Vector2 min, Vector2 max, object_id own_id, const pred& p = never_continue());
static bool is_passable_(chunk* c0, const std::array<world::neighbor_pair, 8>& neighbors,
@@ -111,7 +125,8 @@ public:
static bool is_passable(world& w, global_coords coord, Vector2b offset, Vector2ub size, object_id own_id, const pred& p = never_continue());
static bbox<float> neighbor_tile_bbox(Vector2i coord, Vector2ub own_size, Vector2ub div, rotation r);
- static bbox<float> bbox_union(bbox<float> bb, Vector2i coord, Vector2b offset, Vector2ub size);
+ template<typename T> requires std::is_arithmetic_v<T> static bbox<T> bbox_union(bbox<T> bb, Vector2i coord, Vector2b offset, Vector2ub size);
+ static bbox<int> bbox_union(bbox<int> bb1, bbox<int> bb2);
static neighbors neighbor_tiles(world& w, global_coords coord, Vector2ub size, object_id own_id, const pred& p = never_continue());
};
diff --git a/test/app.hpp b/test/app.hpp
index 2a2e39c8..fbce503b 100644
--- a/test/app.hpp
+++ b/test/app.hpp
@@ -42,6 +42,7 @@ struct test_app final : private FM_APPLICATION
static void test_bitmask();
static void test_path_search();
static void test_hash();
+ static void test_path_search_node_pool();
static void zzz_test_misc();
};
} // namespace floormat
diff --git a/test/main.cpp b/test/main.cpp
index 4ff866bf..928ff565 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -32,6 +32,7 @@ int test_app::exec()
test_path_search();
test_math();
test_hash();
+ test_path_search_node_pool();
zzz_test_misc();
return 0;
diff --git a/test/path-search-result.cpp b/test/path-search-result.cpp
new file mode 100644
index 00000000..1d464e8c
--- /dev/null
+++ b/test/path-search-result.cpp
@@ -0,0 +1,26 @@
+#include "app.hpp"
+#include "compat/assert.hpp"
+#include "path-search-result.hpp"
+
+namespace floormat {
+
+void test_app::test_path_search_node_pool()
+{
+ auto& pool = path_search_result::_pool;
+ fm_debug_assert(!pool);
+ {
+ auto a = path_search_result{};
+ fm_debug_assert(!pool);
+ }
+ fm_debug_assert(pool);
+ {
+ auto* pool2 = pool.get();
+ auto b = path_search_result{};
+ fm_debug_assert(b._node.get() == pool2);
+ auto c = path_search_result{};
+ fm_debug_assert(c._node.get() != pool2);
+ fm_debug_assert(b._node.get() == pool2);
+ }
+}
+
+} // namespace floormat
diff --git a/test/path-search.cpp b/test/path-search.cpp
index 9ff918e5..28ea01de 100644
--- a/test/path-search.cpp
+++ b/test/path-search.cpp
@@ -113,6 +113,7 @@ void test_bbox()
fm_assert(neighbor_tiles(w, ch, {2, 4}).size == 3);
fm_assert(neighbor_tiles(w, ch, {4, 4}).size == 3);
}
+#if 0
{
constexpr auto ch = chunk_coords_{};
auto w = world();
@@ -183,6 +184,7 @@ void test_bbox()
fm_assert( check_N(search, {}, {K+2, K+2 }, s00 ));
fm_assert( check_W(search, {}, {K+2, K+2 }, s00 ));
}
+#endif
}
} // namespace