import { IMPOSSIBLE, VersionInfo } from '@start9labs/start-sdk' export const current = VersionInfo.of({ // `:` — the upstream half tracks the bundled Station Master tag exactly // (`versions.md`'s consistency checklist), so bumping the submodule pin and bumping this are one // action. The downstream half moves only for packaging-only changes, and RESETS to `:0` when the // upstream half moves. // // FOUR COMPONENTS IS FINE. ExVer's upstream half is an arbitrary-length dotted number, not semver // — checked against the SDK's own parser rather than assumed, since every example in `versions.md` // has three: `0.7.9.8:0` parses to upstream `[0,7,9,8]`, which sorts above `[0,7,9]`, so a box on // 0.7.9:0 sees this as an update rather than refusing it as a downgrade. version: '0.8.0.10:0', releaseNotes: { en_US: 'Bundles Station Master v0.8.0.10 — fixes from the first multiplayer playtests. **GAMES IN ' + 'PROGRESS ON THIS SERVER WILL OFTEN NOT RESUME AFTER THIS UPDATE**, because a rule about when ' + 'the Superintendent is asked to rule has been corrected, and a saved game is replayed through ' + 'the current rules: a game holding a ruling the rules no longer ask for stops there. The ' + 'server says which move it stopped at and leaves the game\u2019s file untouched, so nothing ' + 'is lost — and putting v0.8.0.9 back lets such a game be finished. The fix: the ' + 'Superintendent was asked to rule on a train BEHIND the one departing, which is nobody\u2019s ' + 'concern — it cost a real game a collision, because holding the departing train kept the only ' + 'arrival track full and the train behind it arrived into it and was destroyed. A train moving ' + 'away behind you no longer holds you either. Also in this release: while your board is ' + 'catching up on other players\u2019 moves, the screen now says whose move you are watching ' + 'instead of naming whoever the game is really waiting on, and the history no longer races ' + 'ahead of the board — lines appear as their moves are drawn, and Skip still shows everything ' + 'at once. The name on the Division map is readable again. A Realignment says which card it ' + 'converted — “Mainline card 3, Curves, converted to Plains” — and the card flashes on the map ' + 'as it changes. A move made by holding the Superintendent\u2019s office reads “Superintendent ' + 'Player Tom”, so it is clear it was not their ordinary turn, and no line names a player twice ' + 'any more. And a seated player can now download their own game as a save file from the play ' + 'screen, which previously only solitaire could do.', es_ES: 'Incluye Station Master v0.8.0.10 — correcciones de las primeras partidas de prueba ' + 'multijugador. **LAS PARTIDAS EN CURSO EN ESTE SERVIDOR A MENUDO NO SE REANUDARÁN TRAS ESTA ' + 'ACTUALIZACIÓN**, porque se ha corregido una regla sobre cuándo se pide una decisión al ' + 'Superintendente, y una partida guardada se reproduce con las reglas actuales: una partida ' + 'que contenga una decisión que ya no se pide se detiene ahí. El servidor indica en qué ' + 'movimiento se detuvo y deja intacto el archivo, así que no se pierde nada; volver a la ' + 'v0.8.0.9 permite terminar esa partida. La corrección: se pedía decidir sobre un tren DETRÁS ' + 'del que salía, lo que no afecta a nadie — y costó una colisión real, porque retener el tren ' + 'que salía mantenía ocupada la única vía de llegada y el tren de atrás llegaba y quedaba ' + 'destruido. Un tren que se aleja por detrás tampoco te retiene ya. Además: mientras tu ' + 'tablero se pone al día con los movimientos de otros, la pantalla dice de quién es el ' + 'movimiento que estás viendo en lugar de nombrar a quien realmente espera la partida, y el ' + 'historial ya no se adelanta al tablero — las líneas aparecen según se dibujan sus ' + 'movimientos, y Saltar sigue mostrándolo todo de golpe. El nombre en el mapa de la División ' + 'vuelve a leerse bien. Una Realineación dice qué carta convirtió y la carta parpadea en el ' + 'mapa. Una jugada hecha como Superintendente se lee «Superintendent Player Tom», y ninguna ' + 'línea nombra dos veces al jugador. Y quien ocupa un asiento puede descargar su propia ' + 'partida como archivo desde la pantalla de juego, algo que antes solo podía el solitario.', de_DE: 'Enthält Station Master v0.8.0.10 — Korrekturen aus den ersten Mehrspieler-Testpartien. ' + '**LAUFENDE SPIELE AUF DIESEM SERVER WERDEN NACH DIESEM UPDATE OFT NICHT FORTGESETZT**, weil ' + 'eine Regel dazu korrigiert wurde, wann der Superintendent entscheiden muss, und ein ' + 'gespeichertes Spiel mit den aktuellen Regeln nachgespielt wird: ein Spiel mit einer ' + 'Entscheidung, die es nicht mehr gibt, bricht dort ab. Der Server nennt den Zug, an dem er ' + 'stehen blieb, und lässt die Datei unangetastet — nichts geht verloren, und mit v0.8.0.9 ' + 'lässt sich ein solches Spiel zu Ende spielen. Die Korrektur: Es wurde über einen Zug HINTER ' + 'dem abfahrenden entschieden, was niemanden betrifft — und kostete real eine Kollision, weil ' + 'das Halten des abfahrenden Zuges das einzige Ankunftsgleis belegt hielt und der Zug dahinter ' + 'hineinfuhr und zerstört wurde. Auch ein entgegenkommender Zug hinter Ihnen hält Sie nicht ' + 'mehr auf. Außerdem: Während Ihr Spielfeld die Züge der anderen nachholt, zeigt der ' + 'Bildschirm, wessen Zug Sie gerade sehen, statt den zu nennen, auf den das Spiel wirklich ' + 'wartet; und die Historie eilt dem Spielfeld nicht mehr voraus — Zeilen erscheinen, während ' + 'ihre Züge gezeichnet werden, und Überspringen zeigt weiterhin alles sofort. Der Name auf der ' + 'Divisionskarte ist wieder lesbar. Eine Neutrassierung nennt die umgewandelte Karte, und die ' + 'Karte blinkt auf der Landkarte. Ein Zug als Superintendent liest sich „Superintendent Player ' + 'Tom“, und keine Zeile nennt einen Spieler doppelt. Und wer einen Platz hat, kann sein Spiel ' + 'jetzt als Datei vom Spielbildschirm herunterladen — bisher konnte das nur das Solospiel.', pl_PL: 'Zawiera Station Master v0.8.0.10 — poprawki z pierwszych testowych partii wieloosobowych. ' + '**GRY W TOKU NA TYM SERWERZE CZĘSTO NIE ZOSTANĄ WZNOWIONE PO TEJ AKTUALIZACJI**, ponieważ ' + 'poprawiono zasadę mówiącą, kiedy Superintendent ma rozstrzygać, a zapis gry jest odtwarzany ' + 'według bieżących zasad: gra zawierająca rozstrzygnięcie, o które już się nie pyta, ' + 'zatrzymuje się w tym miejscu. Serwer podaje, przy którym ruchu stanął, i zostawia plik ' + 'nietknięty — nic nie ginie, a powrót do v0.8.0.9 pozwala taką grę dokończyć. Poprawka: ' + 'pytano o pociąg ZA odjeżdżającym, co nikogo nie dotyczy — i kosztowało to prawdziwe ' + 'zderzenie, bo zatrzymanie odjeżdżającego pociągu blokowało jedyny tor przyjazdowy, a pociąg ' + 'z tyłu wjeżdżał na niego i ulegał zniszczeniu. Pociąg oddalający się za tobą też już cię nie ' + 'zatrzymuje. Ponadto: gdy twoja plansza nadrabia ruchy innych, ekran mówi, czyj ruch ' + 'oglądasz, zamiast wskazywać tego, na kogo gra naprawdę czeka, a historia nie wyprzedza już ' + 'planszy — wiersze pojawiają się wraz z rysowaniem ruchów, a Pomiń nadal pokazuje wszystko ' + 'naraz. Nazwa na mapie Dywizji znów jest czytelna. Zmiana trasy podaje, którą kartę ' + 'przekształcono, a karta miga na mapie. Ruch wykonany jako Superintendent brzmi ' + '„Superintendent Player Tom”, i żaden wiersz nie nazywa gracza dwa razy. A gracz przy stole ' + 'może teraz pobrać swoją grę jako plik z ekranu gry — wcześniej potrafił to tylko tryb ' + 'samotny.', fr_FR: 'Inclut Station Master v0.8.0.10 — corrections issues des premières parties de test ' + 'multijoueurs. **LES PARTIES EN COURS SUR CE SERVEUR NE REPRENDRONT SOUVENT PAS APRÈS CETTE ' + 'MISE À JOUR**, car une règle sur le moment où le Superintendent doit trancher a été ' + 'corrigée, et une partie sauvegardée est rejouée selon les règles actuelles : une partie ' + 'contenant une décision que l’on ne demande plus s’arrête là. Le serveur indique à quel coup ' + 'il s’est arrêté et laisse le fichier intact — rien n’est perdu, et réinstaller la v0.8.0.9 ' + 'permet de terminer une telle partie. La correction : on faisait trancher au sujet d’un train ' + 'DERRIÈRE celui qui partait, ce qui ne concerne personne — et cela a coûté une vraie ' + 'collision, car retenir le train au départ gardait l’unique voie d’arrivée occupée et le ' + 'train derrière y arrivait et était détruit. Un train qui s’éloigne derrière vous ne vous ' + 'retient plus non plus. Également : pendant que votre plateau rattrape les coups des autres, ' + 'l’écran indique de qui est le coup que vous regardez au lieu de nommer celui que la partie ' + 'attend vraiment, et l’historique ne devance plus le plateau — les lignes apparaissent à ' + 'mesure que leurs coups sont dessinés, et Passer affiche toujours tout d’un coup. Le nom sur ' + 'la carte de la Division est de nouveau lisible. Un Réalignement indique quelle carte il a ' + 'convertie, et la carte clignote sur la carte. Un coup joué en tant que Superintendent se lit ' + '« Superintendent Player Tom », et aucune ligne ne nomme deux fois un joueur. Enfin, un ' + 'joueur assis peut désormais télécharger sa propre partie sous forme de fichier depuis ' + 'l’écran de jeu, ce que seul le solitaire permettait.', }, migrations: { /** * NOTHING TO CARRY, AND CHECKED THE SAME NARROW WAY v0.7.9.8's ENTRY WAS. * * The rule this package lives by is in the game's README: a save is a seed plus the moves * played, replayed through the CURRENT rules, so the only thing that strands an older save is a * change that makes a once-legal move illegal. So the question is never "how big was the * release" — v0.8.0 is a large one — but "did any predicate change its answer". * * Measured with `git diff v0.7.9.8..v0.8.0.1 -- src/engine/`. The WHOLE engine diff is eight * lines: * four `GameEvent` types (`trayMoved`, `carsCoupled`, `carsDropped`, `consistSorted`) gained a * `player` field, and the four places that build them pass it. `check()` is untouched, `legal.ts` * and `advance.ts` are untouched, and no predicate anywhere was edited. Games in progress resume, * and the release notes say so in all five locales rather than leaving it to be discovered. * * EVENTS ARE NOT PERSISTED, so widening four of them cannot invalidate anything on disk: a * `SavedGame` is `{ seed, config, history: Intent[], … }` and the events are derived by replaying * it. The narration TEXT of two lines changed with them ("Moved Train 3 …" where it used to read * "CREW moved …"), which a resumed game simply regenerates — the log is not stored either. * * WHAT IS NOT COVERED BY THAT ARGUMENT, and why it still does not need a migration: the wire * between this server and a browser gained a lot. `Push` now carries ordered presentation steps * and a public-board baseline, and the board deltas changed shape. None of it is on disk, and a * browser reloads onto the new page as part of the update, so there is no version skew to * migrate — the same reasoning v0.7.9.8 used for its own `Frame` changes. * * v0.8.0.1 ADDED NOTHING TO THIS ARGUMENT: `git diff v0.8.0..v0.8.0.1 -- src/engine/` is empty. * It changed `sim/pacing.ts`, `web/step-queue.ts` and `web/main.ts` — how long a step is shown * and when the queue calls itself idle — which is presentation and touches neither the rules nor * anything on disk. * * v0.8.0.2 DOES TOUCH THE ENGINE, and it is worth being exact about why that is still nothing to * migrate. `git diff v0.8.0.1..v0.8.0.2 -- src/engine/` is three added lines: `collisionsPrevDay` * declared on `GameState`, initialised to 0 in `setup.ts`, and assigned at the Day rollover in * `advance.ts`. It is a counter that nothing checks — no predicate reads it, so no once-legal move * became illegal. * * v0.8.0.3 THROUGH v0.8.0.7 ADDED NOTHING: `git diff v0.8.0.2..v0.8.0.7 -- src/engine/` is empty. * One moved the Skip button, changed what the waiting row says, and stopped the speed control * stretching the clock; one took a hostname out of comments; the last drew the Home Office deck * and lit the pile a watched move touched, which is a diff of two frames the client already * holds. None of it is a rule, and none of it is on disk. * * v0.8.0.8 IS DIFFERENT AND IS THE ONE TO READ CAREFULLY: it changes a RULE (Gitea#23). When the * Home Office deck is reshuffled, a timetabled train sitting in the SALVAGE YARD is no longer * recovered — it was played, its number is on the timetable, and it cannot be run twice. The same * card in a DEPARTMENT was discarded rather than played and still comes back, as does any Extra. * A duplicate went with it: `trainScheduled` had been pushing a synthetic `train-` beside the * real card, so four scheduled trains left eight entries in a pile of four. * * GAMES IN PROGRESS STILL RESUME, and the reason is the narrow one this package always asks * (README § Design notes): a save is a seed plus the moves played, replayed through the CURRENT * rules, so what strands one is a change that makes a once-legal move ILLEGAL. Nothing here does. * `check()` is untouched; a draw is a draw whatever lies on top of the deck. What differs is the * Salvage Yard's depth, which was double-counting, and which cards a reshuffle returns — and a * reshuffle is effectively unreachable in ordinary play: eight games driven to 4000 moves across * eight seeds produced ZERO. A game that had somehow reshuffled would replay to a different deck * order rather than refusing to replay, which is worth knowing and is not the same as breaking. * * v0.8.0.9 TOUCHES THE ENGINE FOR SPEED, AND PROVED IT CHANGED NOTHING. `git diff v0.8.0.8..v0.8.0.9 * -- src/engine/` adds a route cache scoped to one unchanged position (`withRouteCache`), splits * `applyIntent` into `prepareIntent` + `commitEvents`, trims allocation in `exploreMoves`, adds * `legalSwitchingActions`, and exports `badlyMadeUp`, `protoCard` and `extendLimitsIfNeeded` for the * bot. No predicate's answer changed: every event and intent of 32 seeded games hashed identical before * and after each step, and the game's `test/route-cache.test.ts` pins the split. Everything else is the * developer bot, whose past moves are already intents in a save. Games in progress resume. * * v0.8.0.10 IS THE FIRST BUMP THAT BREAKS RESUMES, AND IT DOES SO DELIBERATELY. It corrects WHEN §8.1 * asks the Superintendent to rule (Gitea#26): a train on a card BEHIND the one departing is nobody's * concern, and was being counted. A save is the seed and the moves replayed through the CURRENT rules, * so a game holding a `mainline.clearance` the rules no longer ask for is refused at that move with * NO_PENDING_DECISION — `tryResumeSession` reports which move, and `index.ts` logs the refusal and * leaves the file alone. Measured before shipping: 40 four-seat co-op games recorded by bots under * v0.8.0.9 and replayed under this release — 28 stop, usually 5-40% of the way in. Jesse's call * (2026-09-15): no games in progress need keeping, so this ships without a per-game switch for the old * rule, and the release notes say so in all five locales. A game worth finishing can be finished by * putting v0.8.0.9 back — the save file is untouched. * * The rest of the release is the screen and the log — who the board says it is waiting on, what the * history says and when it says it, a flash on a realigned Mainline card — plus one new read-only * route (`GET /api/save?token=…`) that hands a seated player their own save. None of it is on disk. * * A NEW STATE FIELD CANNOT STRAND A SAVE HERE, which is the property worth naming rather than * re-deriving: a `SavedGame` holds `{ seed, config, history }` and NOT a serialised `GameState`. * Resuming calls `createGame` — which fills the new field from `setup.ts` — and then replays the * intents through the current rules, so the field is populated on the way past. There is no old * shape on disk for a new field to be missing from. * * THE ONE THING THAT WOULD HAVE NEEDED CARE, had it been built the way the plan first described: * the display-step collector runs inside `submit()`, and the resume path (`fromMultiplayerSave`) * deliberately does not go through `submit()`. So replaying a saved game emits no steps and burns * no sequence numbers. A test in the game pins that, because it is a property rather than an * accident. */ up: async ({ effects }) => {}, down: IMPOSSIBLE, }, })