summaryrefslogtreecommitdiffhomepage
path: root/src/path-search.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/path-search.hpp')
-rw-r--r--src/path-search.hpp108
1 files changed, 57 insertions, 51 deletions
diff --git a/src/path-search.hpp b/src/path-search.hpp
index adcda8a0..1d48857a 100644
--- a/src/path-search.hpp
+++ b/src/path-search.hpp
@@ -24,21 +24,44 @@ namespace floormat {
struct world;
struct object;
struct chunk;
-struct path_search_result;
+// todo add pathfinding sub-namespace
+
+struct path_search_result;
enum class path_search_continue : bool { pass = false, blocked = true };
-struct astar
+class path_search final
{
- fm_DECLARE_DELETED_COPY_ASSIGNMENT(astar);
+ friend struct path_search_result;
+
+public:
+ static constexpr int subdivide_factor = 4;
+ static constexpr auto div_size = iTILE_SIZE2 / subdivide_factor;
+ static constexpr auto min_size = div_size / 2;
+
+ template<typename T> struct bbox { VectorTypeFor<2, T> min, max; };
+
+ using pred = fu2::function_view<path_search_continue(collision_data) const>;
+
+ static const pred& never_continue() noexcept;
+ static const pred& always_continue() noexcept;
+
+ 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,
+ Vector2 min, Vector2 max, object_id own_id, const pred& p = never_continue());
+ static bool is_passable(world& w, chunk_coords_ ch0, Vector2 min, Vector2 max, object_id own_id, const pred& p = never_continue());
+ static bool is_passable(world& w, global_coords coord, Vector2b offset, Vector2ub size, object_id own_id, const pred& p = never_continue());
+ static bool is_passable(world& w, chunk_coords_ ch0, const bbox<float>& bb, object_id own_id, const pred& p = never_continue());
+};
+class astar
+{
struct visited
{
uint32_t dist = (uint32_t)-1;
uint32_t prev = (uint32_t)-1;
global_coords coord;
Vector2b offset;
- bool expanded = false;
};
struct edge
@@ -49,13 +72,39 @@ struct astar
bool operator==(const edge& other) const;
};
+ enum class edge_status : uint8_t
+ {
+ // good, bad, I'm the man with the gun.
+ unknown, good, bad,
+ };
+
struct point_hash { size_t operator()(point pt) const; };
struct edge_hash { size_t operator()(const edge& e) const; };
+ std::vector<visited> nodes;
+ tsl::robin_map<edge, edge_status, edge_hash> edges;
+ tsl::robin_map<point, uint32_t, point_hash> indexes;
+ std::vector<uint32_t> Q;
+
+ using pred = path_search::pred;
+ template<typename T> using bbox = path_search::bbox<T>;
+
+public:
+ fm_DECLARE_DELETED_COPY_ASSIGNMENT(astar);
+
+ static edge make_edge(const point& a, const point& b)
+ {
+ if (a < b)
+ return { a.coord, b.coord, a.offset, b.offset };
+ else
+ return { b.coord, a.coord, b.offset, a.offset };
+ }
+
void reserve(size_t capacity)
{
nodes.reserve(capacity);
indexes.reserve(capacity);
+ edges.reserve(capacity);
Q.reserve(capacity);
}
astar()
@@ -68,57 +117,14 @@ struct astar
{
nodes.clear();
indexes.clear();
+ edges.clear();
Q.clear();
}
- std::vector<visited> nodes;
- tsl::robin_set<edge, edge_hash> edges;
- tsl::robin_map<point, uint32_t, point_hash> indexes;
- std::vector<uint32_t> Q;
-};
-
-class path_search final
-{
- friend struct path_search_result;
-
-public:
- static constexpr int subdivide_factor = 4;
- static constexpr auto div_size = iTILE_SIZE2 / subdivide_factor;
- static constexpr auto min_size = div_size / 2;
-
- 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;
-
- operator ArrayView<const global_coords>() const;
- };
-
- template<typename T> struct bbox { VectorTypeFor<2, T> min, max; };
-
- using pred = fu2::function_view<path_search_continue(collision_data) const>;
-
- struct astar astar;
-
- static const pred& never_continue() noexcept;
- static const pred& always_continue() noexcept;
-
// todo add simple bresenham short-circuit
- path_search_result Dijkstra(world& w, Vector2ub own_size, object_id own_id, point from, point to, 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,
- Vector2 min, Vector2 max, object_id own_id, const pred& p = never_continue());
- static bool is_passable(world& w, chunk_coords_ ch0, Vector2 min, Vector2 max, object_id own_id, const pred& p = never_continue());
- static bool is_passable(world& w, global_coords coord, Vector2b offset, Vector2ub size, object_id own_id, const pred& p = never_continue());
- static bool is_passable(world& w, chunk_coords_ ch0, const bbox<float>& bb, object_id own_id, const pred& p = never_continue());
-
- // todo move to test/path-search.cpp
- static bbox<float> neighbor_tile_bbox(Vector2i coord, Vector2ub own_size, Vector2ub div, rotation r);
- static neighbors neighbor_tiles(world& w, global_coords coord, Vector2ub size, object_id own_id, const pred& p = never_continue());
+ path_search_result Dijkstra(world& w, Vector2ub own_size, object_id own_id,
+ point from, point to, uint32_t max_dist = (uint32_t)-1,
+ const pred& p = path_search::never_continue());
};
} // namespace floormat