switching paths: two routes to the same square
Builds docs/plans/switching-paths.md. A passing loop can offer two legal routes between the same two squares, coupling different cars — the engine only ever found one, an artifact of search order (Reported by Jesse, undo 379). exploreMoves now enumerates every simple route (per-path visited set, capped at 4000 frontier nodes) and dedupes on outcome — destination, entry side, and origin-tagged cars — rather than on reaching the square at all. switch.move gains an optional `via: GridCoord` naming one intermediate square on the chosen route; absent, it resolves exactly as before, so every existing save and bot decision replays identically (575/575, then 579/579 with the new tests). Threaded through the label, the action-list dedupe, the hover highlight (data-route), and the history (trayMoved.via). Ruling recorded as Gap 14 in docs/rules/open-questions.md: the player may choose the path; §A.4's "may not go around" a car does not reach a different track the player declined to enter. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SAt2YCXgd5qCjBcF2x34aK
This commit is contained in:
@@ -16,7 +16,14 @@ export type LocalOpsOption = 'switch' | 'draw' | 'freightAgent';
|
||||
export type Intent =
|
||||
| { type: 'localOps.choose'; option: LocalOpsOption }
|
||||
// -- switch (§6.1, Appendix A)
|
||||
| { type: 'switch.move'; trayId: TrayId; to: GridCoord; reverse: boolean }
|
||||
/**
|
||||
* `via` names one INTERMEDIATE card on the chosen route, for the rare case where two routes to
|
||||
* `to` couple different cars (see docs/plans/switching-paths.md) — never the start, never `to`
|
||||
* itself. Absent, it resolves exactly as it always has: the first route `legal.ts` enumerated to
|
||||
* `to`. An index into the destination list would do the same job worse — intents are the
|
||||
* canonical record `undo` replays against, and enumeration order is not a stable thing to save.
|
||||
*/
|
||||
| { type: 'switch.move'; trayId: TrayId; to: GridCoord; reverse: boolean; via?: GridCoord }
|
||||
/**
|
||||
* Set out a cut. `fromNose` takes it off the FRONT of the train rather than the back — Appendix A's
|
||||
* worked example does exactly this: "Back up and drop off everything on the nose of your train
|
||||
|
||||
Reference in New Issue
Block a user