Files
OpenFrontIO/tests/core/pathfinding
Raka HouriantoandGitHub 6dd9eb8323 Reuse cached TradeShip paths for motion plans (#4654)
**Approved and assigned issue:** #4643

Resolves #4643

## Description

`TradeShipExecution` currently calls `WaterPathFinder.next()` and then
performs a second one-shot `findPath()` for the same destination when it
records a motion plan. `next()` has already calculated and cached the
traversal route, so the second call repeats the expensive water-path
calculation solely to recreate the route for the client.

This change lets `PathFinderStepper` return a copy of the active path
after `next()` advances it. Numeric paths remain `Uint32Array`s,
matching the compact representation already used by the stepper and
supported by motion-plan packing.

`WaterPathFinder.pathForTraversal()` retains the existing second
water-graph freshness check. If the graph refresh replaces the stepper
between `next()` and motion-plan recording, it falls back to the
original one-shot query. Otherwise it returns the cached remainder. The
method also normalizes the result to begin at the tile returned by
`next()`, so `TradeShipExecution` does not need to mutate the path.

`findPath()` remains a stateless one-shot query. The change is limited
to TradeShip and the minimal pathfinder support; it includes no
TransportShip changes.

## Performance

Current upstream `main` (`da2e0918`) was compared with the same commit
plus only this change. Each variant was run once per replay on macOS
arm64 with CPU profiling disabled. The replay intents were identical
between variants, and the current-client final hash and hash tick
matched for every pair.

| Game ID | Workload | Whole replay | TradeShip execution | Throughput |
| --- | --- | ---: | ---: | ---: |
| `DWmULj4H` | Antarctica, TradeShip-heavy | 68.960 s → 60.271 s
(**-12.60%**) | 18.981 s → 11.844 s (**-37.60%**) | 446 → 510 ticks/s |
| `efA7EZv9` | Australia | 14.660 s → 14.346 s (**-2.14%**) | 1.216 s →
0.920 s (**-24.34%**) | 441 → 450 ticks/s |
| `waxvMCue` | Svalmel | 16.666 s → 16.537 s (**-0.77%**) | 1.169 s →
0.931 s (**-20.36%**) | 551 → 555 ticks/s |

Matched current-client final hashes:

- `DWmULj4H`: `49212092378184090` at tick 31,060
- `efA7EZv9`: `82334231069422620` at tick 6,760
- `waxvMCue`: `34697926985435590` at tick 9,480

## Validation

- `npm run build-prod`
- Full Node 24 coverage suite: 174 test files and 2,091 tests passed
- Full ESLint check
- Full Prettier check
- Current-main baseline/patched replay hashes matched for all three
benchmark games

## Checklist

- [x] No UI updates; screenshots are not applicable.
- [x] No user-facing text was added or changed.
- [x] Relevant tests were added.

## LLM disclosure

This change, PR description, and benchmark analysis were authored by
**GPT-5.6 Sol**, an LLM, under human direction.
2026-07-21 15:57:19 -07:00
..