Repository navigation
fix(nav): a graph rebuild resumes walks in progress instead of snapping them (#60) - #66
leonardomag31-lab wants to merge 3 commits into
Conversation
…ng them (#60) A rebuild drops every live route and re-issues the saved orders, each from the node nearest the walker (at or below it). Partway along a segment that pick is often wrong: on a climb it's the node behind the walker, which walks it back down; on a descent toward its destination it's the destination itself, and the #207 same-node branch put the walker straight onto it in one frame (a 16-26 px jump on stairs and on the stern MovementLink). Before a rebuild, remember the waypoint each walker was heading to; the re-issue starts from it while a node still sits there, and a walker on the destination's node walks the rest instead of snapping. A fresh navigate is unchanged, #207 snap included. The two decisions are pulled out (`reissueFromNode`, `walksToSameNode`) and covered by State-level tests; each fails when the fix is undone. Closes #60
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Comment |
|
Reviewed head P2 — Revalidate graph-derived final segments on subsequent rebuilds. The new same-node reissue branch in
Reproduction scenario: a rebuild catches a descending walker on its final segment, creating the new direct-move entry; before arrival, another rebuild removes or moves its destination node. The walker retains the obsolete target instead of reissuing or failing its graph order, and can report arrival at the old location. Please distinguish graph-derived final segments from genuine Validation: the unchanged PR passes locally: 15/15 unit tests and 71/71 specs. A temporary State-level regression seeded the exact direct-move entry created by the new branch, ran Current CI is green. After integrating with #65, the combined controller changes also need regression coverage for rebuild continuity and prepared endpoint publication. |
There was a problem hiding this comment.
🟡 Changes recommended
Resumed final legs bypass graph tracking, and consecutive rebuilds can erase unconsumed waypoint hints.
2 open issues
What changed in this PR
Addresses #60 by preserving in-progress navigation across graph rebuilds without changing fresh navigate behavior.
Changes:
- Saves current waypoints for reissued routes.
- Walks remaining same-node distances instead of snapping.
- Extracts shared helpers and adds regression tests.
| File | Description |
|---|---|
src/nav/controller.zig |
Adds waypoint snapshots, reissue handling, shared helpers, and tests. |
Review effort: Balanced
| st.direct_moves.put(st.allocator, entity_id, .{ | ||
| .target = node_pos, | ||
| .speed = speedOf(game, entity), | ||
| }) catch return .{ .deferred = .pending_alloc_failed }; |
There was a problem hiding this comment.
Fixed in 510d723: the leg is now a one-waypoint graph route registered as pending, so later rebuilds re-validate it and it shows in pendingEntities/getMovementPath again.
| /// An allocation failure only loses the hint: those walkers fall | ||
| /// back to the nearest-node re-issue. | ||
| fn snapshotSegments(st: *State) void { | ||
| st.resume_at.clearRetainingCapacity(); |
There was a problem hiding this comment.
Fixed in a35967b: snapshotSegments keeps earlier hints (live routes overwrite theirs); rehydrateNavigating still clears them. Test added.
|
Updated numbers (re-measured 2026-10-19, as promised in the description). @apotema The 24 stair turn-backs in the first run were the test harness: the colony's wander script took the test walker over while its order was deferred mid-rebuild. The walkers are now plain entities (no Setup: Flying Platform
On 4.2.0 every rebuild sent both walkers back (two turn-backs per rebuild), so in 3 min neither ever reached the end of a walk. With this branch they walk through the rebuilds. (4.2.0's 0 jumps doesn't say much: its walkers never got close to a destination, where the old jump happened; the second unit test covers that case.) The harness and scene are throwaway, not committed. |
The same-node re-issue (#60) walked the rest of the last segment as a direct move while the order stayed `.graph`. `snapshotSegments` didn't see it, `reset` kept it and `rehydrateNavigating` skipped it, so a second rebuild that removed or moved the destination left the walker heading to the old spot and reporting arrival there. It also dropped out of `pendingEntities`/`getMovementPath`. Walk it as a one-waypoint graph route instead (identical endpoints are supported), so a later rebuild drops and re-issues it like any graph walk; genuine `moveTo` orders are untouched. Route start + pending registration move into `startRoute`, shared with `navigate`. Review on #66. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`snapshotSegments` cleared `resume_at` before filling it from the live routes. Two rebuilds can land before the next `advance` (an explicit one, then a node-count change): the first drops every route, so the second snapshot finds none and wiped the only saved hints, and a mid-stair climber resumed toward the node behind it — the #60 turn-back. Keep earlier hints (live routes overwrite theirs); `rehydrateNavigating` still clears them after the re-issue. Review on #66. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@apotema thanks, both fixed. New head is P2: graph-derived final segments ( New coverage:
The full Copilot: hints lost on a second rebuild (
Not done yet: the regression coverage you asked for after integrating with #65. That goes with whichever of the two lands second. |

Closes #60
What
A graph rebuild drops every live route and re-issues the saved
Navigatingorders, each from the node nearest the walker (at or below it). Partway along a segment that pick is often wrong:MovementLink).Fix, all in
src/nav/controller.zig:snapshotSegmentsremembers each walker's current waypoint before the rebuild (State.resume_at, kept acrossreset, cleared after the re-issue);navigateWith, private) starts from that waypoint while a node still sits there (reissueFromNode, 1 px tolerance), else falls back to the old nearest-node pick;walksToSameNode) instead of the #207 snap.The public
navigateis unchanged, #207 snap included.speedOf/withinDirectArrivalpulled out of two copies.Test
Two new
State-level tests: a climber partway up a stair resumes to the node ahead, not the one behind; a re-issue walks the last 40 px, a fresh navigate still snaps. Each fails when the fix is undone (no snapshot / ignore the waypoint / re-issue snaps).zig build test15/15,zig build spec71/71.Flying Platform test, re-measured 2026-10-19 (details in the comment below): two plain walkers (no
Worker, so nothing else commands them) at 40 px/s, one ping-ponging over the stair, one over the stern steps (MovementLink), while a node is added or removed every 0.4 s. 180 s, 444 rebuilds:(The first run's 24 leftover stair turn-backs were the test harness: wander took the walker over during a deferred re-issue. Fixed in the re-measurement.)
Heads-up
#65 also edits
src/nav/controller.zig; whichever lands second will need a small rebase.