summaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-10-08 02:19:27 +0200
committerStanislaw Halik <sthalik@misaki.pl>2023-10-08 02:19:27 +0200
commitc1547424b843de09ab4cded654b4f3575ecbcbe7 (patch)
tree307a971b569979c43585337759df63dd8c8177b4 /test
parentef47c7d8bcf5c60d086ab24b5d2f9c31a65c57c0 (diff)
a
Diffstat (limited to 'test')
-rw-r--r--test/path-search.cpp170
1 files changed, 160 insertions, 10 deletions
diff --git a/test/path-search.cpp b/test/path-search.cpp
index 28ea01de..c91bb6cb 100644
--- a/test/path-search.cpp
+++ b/test/path-search.cpp
@@ -5,13 +5,159 @@
#include "src/world.hpp"
#include "src/scenery.hpp"
#include "src/path-search.hpp"
+#include <Magnum/Math/Functions.h>
namespace floormat {
namespace {
-constexpr auto div = path_search::subdivide_factor;
template<typename T> using bbox = path_search::bbox<T>;
+using pred = path_search::pred;
+constexpr auto div = path_search::subdivide_factor;
+constexpr auto min_size = path_search::min_size;
+
+constexpr bbox<int> 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();
+
+ const auto r_ = (uint8_t)r;
+ CORRADE_ASSUME(r_ <= (uint8_t)rotation_COUNT);
+
+ switch (r_)
+ {
+ case (uint8_t)rotation::N: {
+ auto min_N = Vector2i(-sz.x()/2, -offset_N - sz.y()/2 );
+ auto max_N = Vector2i(min_N.x() + sz.x(), sz.y() - sz.y()/2 );
+ return {min_N, max_N};
+ }
+ case (uint8_t)rotation::S: {
+ auto min_S = Vector2i(-sz.x()/2, -sz.y() );
+ auto max_S = Vector2i(min_S.x() + sz.x(), offset_N + sz.y() - sz.y()/2 );
+ return {min_S, max_S};
+ }
+ case (uint8_t)rotation::W: {
+ auto min_W = Vector2i(-offset_W - sz.x()/2, -sz.y()/2 );
+ auto max_W = Vector2i(sz.x() - sz.x()/2, min_W.y() + sz.y() );
+ return {min_W, max_W};
+ }
+ case (uint8_t)rotation::E: {
+ auto min_E = Vector2i(-sz.x()/2, -sz.y()/2 );
+ auto max_E = Vector2i(offset_W + sz.x() - sz.x()/2, min_E.y() + sz.y() );
+ return {min_E, max_E};
+ }
+ case (uint8_t)rotation_COUNT: {
+ auto min_C = Vector2i(-sz.x()/2, -sz.y()/2 );
+ auto max_C = min_C + Vector2i(sz);
+ return {min_C, max_C};
+ }
+ default:
+ fm_abort("wrong 4-way rotation enum '%d'", (int)r);
+ }
+}
+
+constexpr bool test_offsets()
+{
+ 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);
+ [[maybe_unused]] constexpr auto min_N = N.min + shift, max_N = N.max + shift;
+ [[maybe_unused]] constexpr auto N_min_x = min_N.x(), N_min_y = min_N.y();
+ [[maybe_unused]] constexpr auto N_max_x = max_N.x(), N_max_y = max_N.y();
+
+ [[maybe_unused]] constexpr auto E = get_value(sz_, {1,1}, rotation::E);
+ [[maybe_unused]] constexpr auto min_E = E.min + shift, max_E = E.max + shift;
+ [[maybe_unused]] constexpr auto E_min_x = min_E.x(), E_min_y = min_E.y();
+ [[maybe_unused]] constexpr auto E_max_x = max_E.x(), E_max_y = max_E.y();
+
+ [[maybe_unused]] constexpr auto S = get_value(sz_, {1,1}, rotation::S);
+ [[maybe_unused]] constexpr auto min_S = S.min + shift, max_S = S.max + shift;
+ [[maybe_unused]] constexpr auto S_min_x = min_S.x(), S_min_y = min_S.y();
+ [[maybe_unused]] constexpr auto S_max_x = max_S.x(), S_max_y = max_S.y();
+
+ [[maybe_unused]] constexpr auto W = get_value(sz_, {1,1}, rotation::W);
+ [[maybe_unused]] constexpr auto min_W = W.min + shift, max_W = W.max + shift;
+ [[maybe_unused]] constexpr auto W_min_x = min_W.x(), W_min_y = min_W.y();
+ [[maybe_unused]] constexpr auto W_max_x = max_W.x(), W_max_y = max_W.y();
+
+ return true;
+}
+
+constexpr bool test_offsets2()
+{
+ using enum rotation;
+ constexpr auto tile_start = iTILE_SIZE2/-2;
+ constexpr auto sz = Vector2ub(8, 16);
+
+ {
+ constexpr auto bb = get_value(sz, Vector2ub(div), N);
+ constexpr auto min = tile_start + bb.min, max = tile_start + bb.max;
+ static_assert(min.x() == -32 - sz.x()/2);
+ static_assert(max.x() == -32 + sz.x()/2);
+ static_assert(min.y() == -48 - sz.y()/2);
+ static_assert(max.y() == -32 + sz.y()/2);
+ }
+ {
+ constexpr auto bb = get_value(sz, Vector2ub(div), W);
+ constexpr auto min = tile_start + bb.min, max = tile_start + bb.max;
+ static_assert(min.x() == -32 - 16 - sz.x()/2);
+ static_assert(max.x() == -32 + sz.x()/2);
+ static_assert(min.y() == -32 - sz.y()/2);
+ static_assert(max.y() == -32 + sz.y()/2);
+ }
+
+ return true;
+}
+
+struct neighbors final
+{
+ auto begin() const { return data.data(); }
+ auto end() const { return data.data() + size; }
+
+ std::array<global_coords, 5> data;
+ uint8_t size = 0;
+};
+
+bbox<float> neighbor_tile_bbox(Vector2i coord, Vector2ub own_size, Vector2ub div, rotation r);
+neighbors neighbor_tiles(world& w, global_coords coord, Vector2ub size, object_id own_id, const pred& p);
+
+auto 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 [min, max] = get_value(own_size, div, r);
+ return { Vector2(min + shift), Vector2(max + shift) };
+}
+
+auto neighbor_tiles(world& w, global_coords coord, Vector2ub size, object_id own_id, const pred& p) -> neighbors
+{
+ auto ch = chunk_coords_{ coord.chunk(), coord.z() };
+ auto pos = Vector2i(coord.local());
+ constexpr auto min_size = Vector2ub(iTILE_SIZE2/4);
+ size = Math::max(size, min_size);
+
+ neighbors ns;
+
+ using enum rotation;
+ constexpr struct {
+ Vector2i off;
+ rotation r = {};
+ } nbs[] = {
+ { { 0, -1 }, N },
+ { { 1, 0 }, E },
+ { { 0, 1 }, S },
+ { { -1, 0 }, W },
+ };
+
+ for (auto [off, r] : nbs)
+ {
+ auto [min, max] = neighbor_tile_bbox(pos, size, { 1, 1 }, r);
+ if (path_search::is_passable(w, ch, min, max, own_id, p))
+ ns.data[ns.size++] = { coord + off, {} };
+ }
+
+ return ns;
+}
void test_bbox()
{
@@ -24,11 +170,11 @@ void test_bbox()
};
static constexpr auto bbox = [](Vector2i coord, rotation r) {
- return path_search::neighbor_tile_bbox(coord, {}, { 1, 1 }, r);
+ return neighbor_tile_bbox(coord, {}, { 1, 1 }, r);
};
- constexpr auto neighbor_tiles = [](world& w, chunk_coords_ ch, Vector2i pos) {
- return path_search::neighbor_tiles(w, { ch, pos }, {}, (object_id)-1);
+ constexpr auto neighbors = [](world& w, chunk_coords_ ch, Vector2i pos) {
+ return neighbor_tiles(w, { ch, pos }, {}, (object_id)-1, path_search::never_continue());
};
const auto metal2 = loader.tile_atlas("metal2", {2, 2}, pass_mode::blocked);
@@ -75,7 +221,7 @@ void test_bbox()
fm_assert( !is_passable_1(c, bbox({8, 8}, S)) );
fm_assert( is_passable_1(c, bbox({8, 8}, W)) );
- fm_assert(neighbor_tiles(w, ch, {8, 8}).size == 3);
+ fm_assert(neighbors(w, ch, {8, 8}).size == 3);
c[{8, 8}].wall_north() = {metal2,0};
c.mark_passability_modified();
@@ -87,7 +233,7 @@ void test_bbox()
fm_assert( !is_passable_1(c, bbox({8, 8}, S)) );
fm_assert( is_passable_1(c, bbox({8, 8}, W)) );
- fm_assert(neighbor_tiles(w, ch, {8, 8}).size == 2);
+ fm_assert(neighbors(w, ch, {8, 8}).size == 2);
}
{
using enum rotation;
@@ -108,11 +254,15 @@ void test_bbox()
is_passable_NESW(c, {2, 4}, { true, false, true, true });
is_passable_NESW(c, {4, 4}, { true, true, true, false });
- fm_assert(neighbor_tiles(w, ch, {8, 8}).size == 0);
- fm_assert(neighbor_tiles(w, ch, {8, 9}).size == 3);
- fm_assert(neighbor_tiles(w, ch, {2, 4}).size == 3);
- fm_assert(neighbor_tiles(w, ch, {4, 4}).size == 3);
+ fm_assert(neighbors(w, ch, {8, 8}).size == 0);
+ fm_assert(neighbors(w, ch, {8, 9}).size == 3);
+ fm_assert(neighbors(w, ch, {2, 4}).size == 3);
+ fm_assert(neighbors(w, ch, {4, 4}).size == 3);
}
+
+ fm_assert(test_offsets2());
+ fm_assert(test_offsets());
+
#if 0
{
constexpr auto ch = chunk_coords_{};