#pragma once #include "global-coords.hpp" #include "object-id.hpp" #include "rotation.hpp" #include "world.hpp" #include "compat/function2.fwd.hpp" #include "path-search-result.hpp" #include "compat/int-hash.hpp" #include #include #include #include #include namespace Corrade::Containers { //template class Optional; //template class Pair; template class ArrayView; } // namespace Corrade::Containers namespace floormat { struct world; struct object; struct chunk; struct path_search_result; enum class path_search_continue : bool { pass = false, blocked = true }; struct astar { fm_DECLARE_DELETED_COPY_ASSIGNMENT(astar); struct position { global_coords coord; Vector2b offset; bool operator==(const position&) const = default; }; struct visited { uint32_t dist = (uint32_t)-1; uint32_t prev = (uint32_t)-1; global_coords coord; Vector2b offset; bool expanded = false; }; struct hash_op { size_t operator()(position coord) const; }; void reserve(size_t capacity) { nodes.reserve(capacity); indexes.reserve(capacity); Q.reserve(capacity); } astar() { constexpr auto capacity = TILE_COUNT * 16; indexes.max_load_factor(.4f); reserve(capacity); } void clear() { nodes.clear(); indexes.clear(); Q.clear(); } std::vector nodes; tsl::robin_map indexes; std::vector 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 data; uint8_t size = 0; operator ArrayView() const; }; template struct bbox { VectorTypeFor<2, T> min, max; }; using pred = fu2::function_view; 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, 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& 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& bb, object_id own_id, const pred& p = never_continue()); // todo move to test/path-search.cpp static bbox 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()); }; } // namespace floormat