tess 0.4.0
Performance-first tile and path simulation substrate
Loading...
Searching...
No Matches
precheck.h
1#pragma once
2
3#include <tess/topology/topology.h>
4
5#include <cstdint>
6
7namespace tess {
8
9// Outcome of a topology precheck: a cheap region-graph reachability query run
10// before A* so a definitively unreachable goal is rejected without expanding
11// the grid. Only `Unreachable` licenses skipping A* -- every other value is
12// "inconclusive, run A*" -- so the precheck can never turn a solvable query
13// into a wrong failure (see precheck_rules_out_path).
15enum class PrecheckStatus : std::uint8_t {
16 // The graph admits a region path from start to goal; run A* to realize it.
17 Reachable,
18 // The graph definitively rules out any route within known topology. This is
19 // the ONLY status that lets the caller skip A*.
20 Unreachable,
21 // The search reached the edge of the resident set (a boundary exit into a
22 // non-resident chunk): a route through the unloaded region cannot be ruled
23 // out, so run A*. Sparse worlds only.
24 MissingChunk,
25 // Start not resolvable in the graph; run A* (it is authoritative on the
26 // start tile's validity/passability).
27 InvalidStart,
28 // Goal not resolvable in the graph; run A*.
29 InvalidGoal,
30 // The graph no longer matches the world (a topology edit or residency change
31 // since it was built); run A* rather than trust a stale snapshot.
32 GraphStale,
33 // No built graph was supplied; run A*.
34 NoGraph,
35};
36
37// True iff the precheck definitively established that no path exists, so the
38// caller may skip A* entirely. Every other status means "run A*".
40[[nodiscard]] constexpr bool precheck_rules_out_path(
41 PrecheckStatus status) noexcept {
42 return status == PrecheckStatus::Unreachable;
43}
44
45// Cheap pre-A* topology gate. Consults `graph` (built over `world`) for whether
46// `start` can reach `goal` through region connectivity, WITHOUT expanding the
47// grid. Staleness is resolved first and conservatively: an empty graph is
48// NoGraph and a graph that no longer matches the world is GraphStale -- both
49// BEFORE calling reachable(), because a stale graph can otherwise return a
50// definitive but wrong Unreachable from an outdated snapshot. `scratch` is
51// caller-owned and reused across queries (allocation-free once warm); it must
52// not be shared across concurrent queries.
53//
54// `ClassOrTag` (explicit first template argument; `World` stays deduced) is
55// the movement class the SEARCH uses -- a raw passable tag normalizes to its
56// WalkableField identity, exactly as in astar_path. The historical
57// precondition that the graph be built over the same passability is now
58// ENFORCED through the graph's class stamp: a graph built for a different
59// movement class (or predating any stamp) reports GraphStale via
60// is_region_graph_fresh_for, so it degrades to running A* rather than letting
61// `Unreachable` prune a route the search's own class could walk. Cost
62// weighting remains irrelevant (weights only order passable tiles).
67template <typename ClassOrTag, typename World>
68[[nodiscard]] auto precheck_path(
70 const World& world, Coord3 start, Coord3 goal, RegionGraphScratch& scratch)
71 -> PrecheckStatus {
72 if (graph.local_topologies().empty()) {
73 return PrecheckStatus::NoGraph;
74 }
75 if (!is_region_graph_fresh_for<ClassOrTag>(world, graph)) {
76 return PrecheckStatus::GraphStale;
77 }
78 const auto result =
79 reachable<typename World::shape_type>(graph, start, goal, scratch);
80 switch (result.status) {
81 case ReachabilityStatus::Reachable:
82 return PrecheckStatus::Reachable;
83 case ReachabilityStatus::Unreachable:
84 return PrecheckStatus::Unreachable;
85 case ReachabilityStatus::Indeterminate:
86 return PrecheckStatus::MissingChunk;
87 case ReachabilityStatus::InvalidStart:
88 return PrecheckStatus::InvalidStart;
89 case ReachabilityStatus::InvalidGoal:
90 return PrecheckStatus::InvalidGoal;
91 }
92 return PrecheckStatus::NoGraph; // unreachable: all statuses handled above
93}
94
95} // namespace tess
Reusable frontier and visitation storage for graph reachability queries.
Definition topology.h:161
Region graph storage specialized by dense or sparse residency policy.
Definition topology.h:309
Definition world.h:22
Definition shape.h:30