Commit Graph
13 Commits
Author SHA1 Message Date
popertots e9ef5ebbcd fix: four interlocking pathfinding bugs causing panic, failure, and yo-yo teleportation
1. CSV Overflow Panic: Use saturating_sub to prevent underflow when total_failed_paths > n
2. Heuristic Scale Mismatch: octile_distance_3d now divides by ITILE_SIZE to match g-score units
3. Goal Z Offset: Correct target.as_ivec3() - ivec3(0,0,1) not ITILE_SIZE (target already has +1.0)
4. Gravity Yo-Yo: Clear current_path and target when entity falls to prevent teleportation loop
2026-03-18 17:49:07 +00:00
popertots 00cbd92491 refactor: simplify to time-sliced synchronous path queue
The async pathfinding with StandableBitGrid caused massive lag due to synchronous
bounding box calculation in the main thread (millions of hashmap lookups for long paths).
Additionally, the splicing logic had a catastrophic bug where it applied a single
finished path to ALL entities unconditionally.

Solution:
- Revert to thread-local synchronous A*
- Implement PathRequestQueue to process max 8 paths per frame
- Keep provisional paths for immediate movement
- Since entity walks provisional path, full path calculates from current position,
  eliminating the need for complex splicing logic.
2026-03-18 17:23:48 +00:00
popertots 31c93f7926 fix: remove goal standability check from provisional path
The is_standable_tile(goal) check was causing failures when goal position
wasn't directly standable (common case). A* doesn't require goal to be
standable - it finds the best path it can. Removed the check and return
fallback single-point path when start isn't standable.
2026-03-18 17:12:05 +00:00
popertots 9379c7be03 fix: add benchmark recording to calculate_provisional_path
Provisional paths were not being recorded to benchmark stats, causing
total_paths=0 while failed_paths accumulated. Now records:
- path_calc_times_us (timing)
- path_lengths (path length)
- nodes_expanded (A* nodes visited)
- failed_paths (when start/goal not standable)
2026-03-18 17:00:29 +00:00
popertots d2ec1fb5dc fix: correct inverted logic in prepare_paths - entities without paths were being skipped
The condition 'if ambulatory.current_path.is_none() || pending_async.is_some()' was backwards.
It should skip entities that ALREADY have a path, not entities WITHOUT a path.

Fixed to properly skip entities with existing paths or pending async tasks.
2026-03-18 16:47:51 +00:00
popertots c902cff908 feat: async pathfinding with provisional paths and bit-grid snapshots
- Add StandableBitGrid: O(1) bit-packed snapshot (~6KB per 50k tiles vs HashMap overhead)
- Implement two-tier pathfinding: sync for short paths (<64 tiles), provisional+async for long paths
- calculate_provisional_path: capped A* returning path to best heuristic node
- calculate_async_path: A* using bit-grid (Send+Sync, no thread_local)
- prepare_paths system: dispatches provisional paths immediately, spawns async for full paths
- poll_async_paths + splice_completed_async_paths: seamless path transition when async completes
- Entities start walking immediately on provisional path while full path computes in background

Architecture:
  FixedUpdate: prepare_paths → update_wandering_targets → movement
  PostUpdate: poll_async_paths → splice_completed_async_paths

Priority: DF-like pathing (immediate movement) > performance > memory
2026-03-18 16:35:39 +00:00
popertots 0550191c7a Fix update_wandering_targets target validation logic
- Restored original target selection logic that validates is_standable_tile
- Fixed target position z-level checking (check floor tile then standable)
- Re-added check for completed paths (path_index >= path.len)
- This was the cause of 50,297 failed paths - entities targeting invalid positions
2026-03-18 15:45:25 +00:00
popertots 367ab26d5e Fix performance regressions: remove TIER0, consolidate scratchpads, remove Arc trap
Key fixes based on benchmark analysis:
1. Remove TIER0 Vec-based pathfinding - O(N) linear scan was slower than FxHashMap for typical path lengths
2. Consolidate scratchpads into single AStarScratchpad struct - eliminates nested RefCell borrow overhead
3. Remove Arc wrapper from TileMap - eliminated Copy-on-Write trap causing 63ms stutters
4. Replace AHashMap with FxHashMap - FxHash is faster for small integer keys like IVec3
5. Simplify tier logic - single pathfinding function with scratchpad reuse

Benchmark analysis showed:
- Original: 1.95 µs/node, P99 1.1ms, Max 5ms
- TIER0/TIER1 regression: 2.89 µs/node (+48%), P99 5ms (+348%)
- Root causes: Vec linear scan in TIER0, nested RefCell borrows, Arc::make_mut CoW

This should restore and improve performance by using simple FxHashMap scratchpad for all paths.
2026-03-18 15:30:48 +00:00
popertots 8478b385bc Optimize TileMap: replace HashMap with AHashMap, pack tile data
- Replace std HashMap (SipHash) with ahash::AHashMap for fast non-crypto hashing
- Pack tile data from tuples to structs: FloorTileData (~35 bytes) and FixtureTileData (~18 bytes)
- FloorTileData: pack 3 bools into single flags byte, use u8 for id/weight
- FixtureTileData: pack 2 bools into single flags byte
- Update all accessors: is_standable_tile, visibility, terrain generation, forestry
- Preparation for async pathfinding (Arc wrapping to come in follow-up)

Memory reduction: ~54% for floor tiles (76→35 bytes), ~62% for fixtures (48→18 bytes)
Hash performance: AHashMap uses fxhash, faster than SipHash for game data
2026-03-18 14:52:46 +00:00
popertots 81b70a661c Implement tiered pathfinding with thread-local scratchpads
- TIER0 (<10 tiles): Vec-based linear search, zero hash overhead
- TIER1 (10-30 tiles): FxHashMap scratchpad with memory reuse
- TIER2 (30-100 tiles): AHashMap scratchpad for better collision resistance
- TIER3 (>100 tiles): Chunk waypoint decomposition
- Added benchmarking infrastructure with F8 report trigger
- Added async infrastructure: PendingPath, CompletedPaths resources
- Lowered MAX_NODES to 5000 to prevent runaway searches

Benchmarks show P50 improved 13%, max improved 53%
2026-03-18 14:37:15 +00:00
popertots 4ef68c4e04 migratetion to 0.18.0 2026-02-16 00:02:00 +00:00
popertots ee7ac39ad5 refactor file locations for readability 2025-09-11 18:23:53 +01:00
popertots e58f6804bf File cleanup 2025-09-10 20:03:29 +01:00