the Roster Pass: every train at the Office visible
Builds "The Roster Pass" / "Two Trains, One Card" (station display for multiple trains at one Office). The Office is the one square where more than one train may legally stand at once (one per A/D track), and CellView.train had room for exactly one — a second train at a busy Station was counted in the old A/D pips and never drawn. CellView.train -> CellView.trains: TrainView[], seat-filtered and collecting every match rather than the first (fixes a latent cross-district leak in the process: trainOnCard never checked seat). The A/D pips are replaced with one roster chip per A/D track, always, free or occupied; clicking a chip sets selectedCrew, wiring the board and the action panel to the same value. standingWest moves from CrewTray to TrackCard: two trays sharing one Office card need one shared split, not one each, and there is no such thing as "west of one particular A/D track". No save migration — Save replays through the engine — and a stale value on an emptied card is inert because nothing reads a split with no train standing there. The Division map's Office cell is now sized by A/D capacity rather than occupancy, so it holds still as trains arrive and leave; chips lay into fixed slots instead of centre-spreading onto the Limits cards either side. 584 tests, 0 failures. Verified end-to-end against the built app and a direct render of a 4-train Terminal (screenshotted). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SAt2YCXgd5qCjBcF2x34aK
This commit is contained in:
+1
-10
@@ -316,15 +316,6 @@ export type MoveContext = {
|
||||
consistSize: number;
|
||||
/** The tray making the move, so it does not block itself. */
|
||||
self: TrayId;
|
||||
/**
|
||||
* How many cars on the START card stand west of this train (`CrewTray.standingWest`).
|
||||
*
|
||||
* The walk begins at `neighbour(start, initialExit)` and never looked at the start card at all, so
|
||||
* a train drove straight through the cut it had just set out — in both directions, and without
|
||||
* counting it against the four-car limit. Coupling is mandatory (§A.4) and a cut on your own
|
||||
* square is no exception: pulling out through the end it sits at picks it up again.
|
||||
*/
|
||||
standingWest?: number;
|
||||
};
|
||||
|
||||
function cardAt(area: OfficeArea, c: GridCoord): TrackCard | undefined {
|
||||
@@ -459,7 +450,7 @@ export function exploreMoves(
|
||||
*
|
||||
* Ordered nearest-first like every other card's, so it simply seeds the accumulator.
|
||||
*/
|
||||
const ownCut = cutTowards({ standingWest: ctx.standingWest }, carsOn(startCard), initialExit);
|
||||
const ownCut = cutTowards(startCard, carsOn(startCard), initialExit);
|
||||
const startKey = coordKey(start);
|
||||
const queue: Frontier[] = [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user