diff --git a/README.md b/README.md index 6142be6..4c7fc28 100644 --- a/README.md +++ b/README.md @@ -13,24 +13,28 @@ Station Master is a railroad operations board game with an authoritative multipl solitaire needs no server and is not what this package is for. This package runs that server — the browser client, the lobby, and the intent/SSE API — as a single StartOS service. -**Bundled version: 0.7.2.** Two engine bugs and two rules corrections on top of 0.7.1. Backing into -a cut through a curve's 45° leg no longer couples it back to front, and a crew pulling out through -one takes its own cut with it instead of driving away and leaving it standing (Gitea#17). The card -deck is the published counts exactly — which halves the track and removes two long-standing density -multipliers, taking the deck from 206 cards to 121 (Gitea#14). Crossing a Mainline card counts the -regions printed on it rather than the printed speed, which was only ever scenery: most trains cross -faster, slow trains much faster, and a train's Fast/Slow rating now matters on the Hilly card alone -(Gitea#3). And the Division map is drawn as a single row read left to right, so east is always to the -right (Gitea#18). +**Bundled version: 0.7.3.** Two features, both about the end of a game (Gitea#11 and #16). A game no +longer stops dead when the timetable runs out — it enters a fourth state, `awaitingExtension`, and +asks the table whether to play one more Day; agreement is unanimous in multiplayer and one refusal +ends it. The official result is frozen at the ORIGINAL `config.days` and never rewritten, so playing +on is explicitly an exhibition; a §3.4 collision breach is not extendable and does not overwrite a +recorded result. And the end of a game now renders a full results screen in place of the raw +`outcome.reason` enum the page used to print, backed by a new event tally on the game state. -**GAMES IN PROGRESS DO NOT SURVIVE THIS UPDATE**, and this is the first release of which that is -true. A saved game is a seed plus the moves played, replayed on startup — and the deck changing size -means a card id recorded under 0.7.1 refers to a different card, or to none, so a save stops -replaying at its first `card.play`. It fails safe rather than silently: `src/server/index.ts` refuses -to resume a save the rules reject, logs which move it stopped at and why, and **leaves the file -untouched**, so an operator who wants a particular game back can put 0.7.1 on and finish it. There is -no migration, because there is no data to move — the moves were made against a deck that no longer -exists, and re-dealing would invent a game nobody played. +**GAMES IN PROGRESS SURVIVE THIS UPDATE.** No card data changed and the engine changes are additive: +every intent in a 0.7.2 save is still legal, so the save replays intact and the game simply pauses on +the new question when its timetable runs out. This is worth stating plainly because the previous +release was the opposite — 0.7.2 took the deck from 206 cards to 121 and declined every game in +progress. That still applies to anyone updating from **0.7.1 or earlier**: `src/server/index.ts` +refuses to resume a save the rules reject, logs which move it stopped at, and **leaves the file +untouched**, so an operator who wants a particular game back can put the older version on and finish +it. + +**Diagnosing the new state.** A game sitting in `awaitingExtension` is waiting on its players, not +broken: it is persisted and listed as `active`, it is resumed on restart like any other live game, +and the only move the rules will accept from it is `game.extend`. If a table appears stuck at the end +of its last Day, check whether every seat has voted — `Games in Progress` will show it as active with +nobody to wait for, because a vote is not a turn. 0.7.0 remains the shape of the service: the lobby sets a game up from one of four game types (Solitaire, Co-op, Competitive, Cutthroat) plus Custom, offers the whole rule set for reading before diff --git a/instructions.md b/instructions.md index a8250f4..686864c 100644 --- a/instructions.md +++ b/instructions.md @@ -43,13 +43,37 @@ changing any of them marks the game **Custom**, which keeps the scoring of the t from. The seed, the number of players and the number of Days sit above the type and do not make a game Custom — the targets re-derive from them. -**What changed in 0.7.2.** First, the thing to know before you update: **a game already in progress -will not carry over.** The card deck has changed size, so a game saved under 0.7.1 can no longer be -replayed, and the server declines to resume one rather than breaking it — it says which move it -stopped at and leaves the save file alone. If you are mid-game and want to finish it, do that before -updating, or put 0.7.1 back on afterwards. +**What changed in 0.7.3.** **Your games in progress survive this one** — unlike the last update, +nothing about the deck or the way a game is saved has changed, so a game saved under 0.7.2 picks up +where it left off. -At the table, three things look different. **Crossing a Mainline card is quicker, and counted +**The game asks before it ends.** When the last Day on the timetable runs out, you are no longer +simply told the game is over: you are asked whether to play one more Day. Say yes and you get one +Day — not two, not the rest of the evening — and at the end of it you are asked again. In a +multiplayer game **everybody has to agree**, and one "no" ends it there and then, so nobody is kept +playing a game they have finished with. + +**Playing on cannot change who won.** The result is decided at the length you dealt the game for. If +you set up five Days and carry on to eight, the winner is still whoever was ahead at the end of Day +5, and the results screen says so — everything after that is recorded as what it is, an exhibition. +One exception: a game that ends because of **too many collisions** is over for good and is not +offered another Day, whether that happens on a scheduled Day or an extra one. A railroad that has +been declared unsafe does not carry on regardless. + +**The end of a game now tells you what happened.** In place of one line and a number there is a full +results screen: why the game ended, in plain English rather than a code; who won and by how much; +every player's Revenue side by side; the rules the game was actually dealt under, including the pay +rates and any optional rules; who did what; and what the railroad managed — trains that ran the +length of the Division and how many of them did any switching on the way, loads made up and broken, +passengers boarded and set down, cars coupled and set out, and any trains lost to a collision along +with the cars that went with them. It comes up by itself when the game ends and there is a button to +open it again, so playing on never costs you the results. + +**What changed in 0.7.2.** Before you read on: that update was the one where **a game already in +progress did not carry over**, because the card deck changed size. If you are updating from 0.7.1 or +earlier, that still applies to you. + +At the table, three things looked different. **Crossing a Mainline card is quicker, and counted differently**: the speed sign printed on the card was always just scenery, and what decides the time is the number of regions drawn on it — Plains and Double Track one, Curves and Tunnel two, Heavy Grade three unless you have Helpers or Brakeman on it. A train's **Fast/Slow rating only matters on diff --git a/startos/versions/current.ts b/startos/versions/current.ts index 761b7cb..61ae14b 100644 --- a/startos/versions/current.ts +++ b/startos/versions/current.ts @@ -6,90 +6,89 @@ export const current = VersionInfo.of({ // action. The downstream half moves only for packaging-only changes, and RESETS to `:0` when the // upstream half moves — v0.7.0 ended on `:3` only because three test packs were played before it // was released. - version: '0.7.2:0', + version: '0.7.3:0', releaseNotes: { en_US: - 'Bundles Station Master v0.7.2. IMPORTANT — GAMES IN PROGRESS DO NOT CARRY OVER: the deck has ' + - 'changed size, so a game saved under v0.7.1 no longer replays. The server refuses to resume ' + - 'one rather than breaking it, says which move it stopped at, and leaves the file untouched, so ' + - 'you can put v0.7.1 back on to finish a game you care about. Crossing a Mainline card is now ' + - 'counted in the regions printed on it rather than the speed sign, which was only ever scenery ' + - '— most trains cross faster, slow trains much faster, and a train\u2019s Fast/Slow rating now ' + - 'matters on the Hilly card alone. The card deck matches the published counts exactly, which ' + - 'means less track and fewer industries in a smaller deck. And the Division map is drawn as one ' + - 'row you read left to right, west to east, so east is always to the right.', + 'Bundles Station Master v0.7.3. Games in progress carry over: unlike v0.7.2, neither the deck nor the ' + + 'save format has changed. When the last Day on the timetable runs out, the game now asks instead of ' + + 'stopping \u2014 you may play one more Day, and at the end of that Day it asks again. In a multiplayer ' + + 'game every player has to agree, and a single refusal ends it. The result is settled at the ORIGINAL ' + + 'length and never changes: in a five-Day game played on to eight, the winner is still whoever led at ' + + 'the end of Day 5. A game that ends on too many collisions is final and is offered no extra Day. And ' + + 'the end of a game now brings up a full results screen \u2014 why it ended, in plain words rather than an ' + + "internal code; who won; every player's Revenue; the rules the game was dealt under; and what the " + + 'railroad actually did, from trains through the Division and loads made up and broken to passengers ' + + 'carried, cars switched and trains lost.', es_ES: - 'Incluye Station Master v0.7.2. IMPORTANTE: LAS PARTIDAS EN CURSO NO SE CONSERVAN. La baraja ha ' + - 'cambiado de tama\u00f1o, as\u00ed que una partida guardada con la v0.7.1 ya no se puede ' + - 'reproducir. El servidor se niega a reanudarla en vez de estropearla, indica en qu\u00e9 ' + - 'jugada se detuvo y deja el archivo intacto, de modo que puedes volver a instalar la v0.7.1 ' + - 'para terminar una partida que te importe. Cruzar una carta de L\u00ednea Principal se cuenta ' + - 'ahora por las regiones impresas en ella y no por la se\u00f1al de velocidad, que siempre fue ' + - 'decorativa: casi todos los trenes cruzan m\u00e1s r\u00e1pido, los lentos mucho m\u00e1s, y ' + - 'la clasificaci\u00f3n R\u00e1pido/Lento solo cuenta ya en la carta Ondulada. La baraja ' + - 'coincide exactamente con las cantidades publicadas: menos v\u00eda y menos industrias en una ' + - 'baraja m\u00e1s peque\u00f1a. Y el mapa de la Divisi\u00f3n se dibuja en una sola fila que ' + - 'se lee de izquierda a derecha, de oeste a este, as\u00ed que el este siempre queda a la ' + - 'derecha.', + 'Incluye Station Master v0.7.3. Las partidas en curso se conservan: a diferencia de la v0.7.2, no han ' + + 'cambiado ni la baraja ni el formato de guardado. Cuando se agota el \u00faltimo D\u00eda del horario, la ' + + 'partida ahora pregunta en vez de terminar: pod\u00e9is jugar un D\u00eda m\u00e1s, y al final de ese D\u00eda vuelve a ' + + 'preguntar. En una partida multijugador deben estar de acuerdo todos los jugadores, y una sola ' + + 'negativa la termina. El resultado se decide con la duraci\u00f3n ORIGINAL y no cambia nunca: en una ' + + 'partida de cinco D\u00edas prolongada hasta ocho, gana quien iba en cabeza al final del D\u00eda 5. Una ' + + 'partida que termina por exceso de colisiones es definitiva y no recibe ning\u00fan D\u00eda adicional. Y al ' + + 'terminar aparece una pantalla de resultados completa: por qu\u00e9 termin\u00f3, explicado con palabras y no ' + + 'con un c\u00f3digo interno; qui\u00e9n gana; los Ingresos de cada jugador; las reglas con las que se reparti\u00f3 ' + + 'la partida; y lo que hizo realmente el ferrocarril, desde los trenes que cruzaron la Divisi\u00f3n y las ' + + 'cargas formadas y deshechas hasta los pasajeros transportados, los vagones maniobrados y los trenes ' + + 'perdidos.', de_DE: - 'Enth\u00e4lt Station Master v0.7.2. WICHTIG \u2014 LAUFENDE PARTIEN GEHEN NICHT MIT: Das Deck ' + - 'hat seine Gr\u00f6\u00dfe ge\u00e4ndert, daher l\u00e4sst sich ein unter v0.7.1 ' + - 'gespeichertes Spiel nicht mehr nachspielen. Der Server verweigert die Fortsetzung, statt das ' + - 'Spiel zu besch\u00e4digen, nennt den Zug, an dem er stehen blieb, und l\u00e4sst die Datei ' + - 'unangetastet \u2014 wer eine Partie retten will, spielt sie mit v0.7.1 zu Ende. Die ' + - '\u00dcberquerung einer Streckenkarte z\u00e4hlt jetzt die darauf gedruckten Regionen statt ' + - 'des Tempo-Schilds, das immer nur Kulisse war: Die meisten Z\u00fcge sind schneller dr\u00fcben, ' + - 'langsame deutlich schneller, und die Einstufung Schnell/Langsam z\u00e4hlt nur noch auf der ' + - 'H\u00fcgelkarte. Das Kartendeck entspricht exakt den ver\u00f6ffentlichten St\u00fcckzahlen ' + - '\u2014 weniger Gleise und weniger Industrie in einem kleineren Deck. Und die Streckenkarte ' + - 'wird als EINE Reihe gezeichnet, von links nach rechts, West nach Ost, sodass Osten immer ' + - 'rechts liegt.', + 'Enth\u00e4lt Station Master v0.7.3. Laufende Partien bleiben erhalten: anders als bei v0.7.2 hat sich ' + + 'weder am Deck noch am Speicherformat etwas ge\u00e4ndert. Wenn der letzte Tag des Fahrplans abgelaufen ' + + 'ist, fragt das Spiel jetzt, statt einfach aufzuh\u00f6ren \u2014 ihr d\u00fcrft einen weiteren Tag spielen, und am ' + + 'Ende dieses Tages fragt es erneut. In einer Mehrspielerpartie m\u00fcssen alle zustimmen, eine einzige ' + + 'Ablehnung beendet sie. Das Ergebnis wird \u00fcber die URSPR\u00dcNGLICHE Spiell\u00e4nge entschieden und \u00e4ndert ' + + 'sich nie: Wer eine F\u00fcnf-Tage-Partie auf acht Tage verl\u00e4ngert, sieht immer noch den Sieger vom Ende ' + + 'des 5. Tages. Eine Partie, die an zu vielen Kollisionen endet, ist endg\u00fcltig und bekommt keinen ' + + 'weiteren Tag. Und am Ende erscheint jetzt eine vollst\u00e4ndige Ergebnisanzeige: warum die Partie ' + + 'endete, in Worten statt als interner Code; wer gewinnt; die Einnahmen jedes Spielers; die Regeln, ' + + 'mit denen ausgeteilt wurde; und was die Eisenbahn tats\u00e4chlich geleistet hat, von Z\u00fcgen durch die ' + + 'Division und gebildeten wie aufgel\u00f6sten Ladungen bis zu bef\u00f6rderten Fahrg\u00e4sten, rangierten Wagen und ' + + 'verlorenen Z\u00fcgen.', pl_PL: - 'Zawiera Station Master v0.7.2. WA\u017bNE \u2014 TRWAJ\u0104CE PARTIE NIE ZOSTAJ\u0104 ' + - 'PRZENIESIONE: talia zmieni\u0142a rozmiar, wi\u0119c gra zapisana w v0.7.1 nie da si\u0119 ' + - 'ju\u017c odtworzy\u0107. Serwer odmawia wznowienia, zamiast j\u0105 zepsu\u0107, podaje ' + - 'ruch, na kt\u00f3rym stan\u0105\u0142, i zostawia plik nietkni\u0119ty \u2014 mo\u017cna ' + - 'wr\u00f3ci\u0107 do v0.7.1 i doko\u0144czy\u0107 wa\u017cn\u0105 parti\u0119. ' + - 'Przejazd przez kart\u0119 Magistrali liczy si\u0119 teraz wed\u0142ug wydrukowanych na niej ' + - 'region\u00f3w, a nie znaku pr\u0119dko\u015bci, kt\u00f3ry zawsze by\u0142 tylko ozdob\u0105: ' + - 'wi\u0119kszo\u015b\u0107 poci\u0105g\u00f3w przeje\u017cd\u017ca szybciej, powolne du\u017co ' + - 'szybciej, a ocena Szybki/Powolny liczy si\u0119 ju\u017c tylko na karcie Pag\u00f3rkowatej. ' + - 'Talia odpowiada dok\u0142adnie opublikowanym liczbom \u2014 mniej tor\u00f3w i mniej ' + - 'przemys\u0142u w mniejszej talii. A mapa Dywizji rysowana jest jako JEDEN rz\u0105d czytany ' + - 'od lewej do prawej, z zachodu na wsch\u00f3d, wi\u0119c wsch\u00f3d zawsze jest po prawej.', + 'Zawiera Station Master v0.7.3. Trwaj\u0105ce partie zostaj\u0105 zachowane: w odr\u00f3\u017cnieniu od v0.7.2 nie ' + + 'zmieni\u0142a si\u0119 ani talia, ani format zapisu. Gdy ko\u0144czy si\u0119 ostatni Dzie\u0144 rozk\u0142adu, gra teraz pyta, ' + + 'zamiast po prostu si\u0119 sko\u0144czy\u0107: mo\u017cecie zagra\u0107 jeszcze jeden Dzie\u0144, a na jego koniec zapyta ' + + 'ponownie. W grze wieloosobowej musz\u0105 zgodzi\u0107 si\u0119 wszyscy, a jedna odmowa ko\u0144czy parti\u0119. Wynik ' + + 'rozstrzyga si\u0119 na PIERWOTNEJ d\u0142ugo\u015bci gry i nigdy si\u0119 nie zmienia: w pi\u0119ciodniowej partii ' + + 'przed\u0142u\u017conej do o\u015bmiu Dni wygrywa ten, kto prowadzi\u0142 na koniec Dnia 5. Partia zako\u0144czona zbyt ' + + 'wieloma kolizjami jest ostateczna i nie dostaje kolejnego Dnia. A na ko\u0144cu pojawia si\u0119 pe\u0142ny ekran ' + + 'wynik\u00f3w: dlaczego partia si\u0119 sko\u0144czy\u0142a \u2014 s\u0142owami, nie wewn\u0119trznym kodem; kto wygrywa; Przych\u00f3d ' + + 'ka\u017cdego gracza; zasady, wed\u0142ug kt\u00f3rych rozdano gr\u0119; i co kolej naprawd\u0119 zrobi\u0142a, od poci\u0105g\u00f3w przez ' + + 'Dywizj\u0119 i \u0142adunk\u00f3w utworzonych oraz rozformowanych po przewiezionych pasa\u017cer\u00f3w, przetoczone wagony i ' + + 'stracone poci\u0105gi.', fr_FR: - 'Inclut Station Master v0.7.2. IMPORTANT \u2014 LES PARTIES EN COURS NE SONT PAS ' + - 'CONSERV\u00c9ES : la taille du jeu de cartes a chang\u00e9, donc une partie sauvegard\u00e9e ' + - 'sous v0.7.1 ne peut plus \u00eatre rejou\u00e9e. Le serveur refuse de la reprendre au lieu de ' + - 'l\u2019ab\u00eemer, indique le coup o\u00f9 il s\u2019est arr\u00eat\u00e9 et laisse le ' + - 'fichier intact : vous pouvez r\u00e9installer la v0.7.1 pour terminer une partie qui compte. ' + - 'La travers\u00e9e d\u2019une carte de Ligne Principale se compte d\u00e9sormais en r\u00e9gions ' + - 'imprim\u00e9es sur la carte plut\u00f4t qu\u2019au panneau de vitesse, qui n\u2019a jamais ' + - '\u00e9t\u00e9 que du d\u00e9cor : la plupart des trains traversent plus vite, les lents ' + - 'beaucoup plus vite, et la cote Rapide/Lent ne compte plus que sur la carte Vallonn\u00e9e. Le ' + - 'jeu de cartes correspond exactement aux quantit\u00e9s publi\u00e9es \u2014 moins de voie et ' + - 'moins d\u2019industries dans un jeu plus petit. Et la carte de la Division est dessin\u00e9e ' + - 'sur UNE seule rang\u00e9e qui se lit de gauche \u00e0 droite, d\u2019ouest en est : l\u2019est ' + - 'est donc toujours \u00e0 droite.', + 'Inclut Station Master v0.7.3. Les parties en cours sont conserv\u00e9es : contrairement \u00e0 la v0.7.2, ni ' + + 'le jeu de cartes ni le format de sauvegarde n\u2019ont chang\u00e9. Quand le dernier Jour de l\u2019horaire est ' + + '\u00e9coul\u00e9, la partie pose d\u00e9sormais la question au lieu de s\u2019arr\u00eater : vous pouvez jouer un Jour de ' + + 'plus, et \u00e0 la fin de ce Jour elle repose la question. En multijoueur, tous les joueurs doivent \u00eatre ' + + 'd\u2019accord, et un seul refus y met fin. Le r\u00e9sultat est \u00e9tabli sur la dur\u00e9e INITIALE et ne change ' + + 'jamais : dans une partie de cinq Jours prolong\u00e9e jusqu\u2019\u00e0 huit, le vainqueur reste celui qui menait \u00e0 ' + + 'la fin du Jour 5. Une partie qui se termine sur trop de collisions est d\u00e9finitive et ne se voit ' + + 'proposer aucun Jour suppl\u00e9mentaire. Et la fin d\u2019une partie affiche maintenant un \u00e9cran de r\u00e9sultats ' + + 'complet : pourquoi elle s\u2019est termin\u00e9e, en toutes lettres plut\u00f4t qu\u2019en code interne ; qui gagne ; ' + + 'les Recettes de chaque joueur ; les r\u00e8gles avec lesquelles la partie a \u00e9t\u00e9 distribu\u00e9e ; et ce que le ' + + 'chemin de fer a r\u00e9ellement fait, des trains ayant travers\u00e9 la Division et des chargements form\u00e9s et ' + + 'd\u00e9faits aux voyageurs transport\u00e9s, wagons man\u0153uvr\u00e9s et trains perdus.', }, migrations: { /** - * STILL NOTHING TO CARRY, AND THIS TIME THAT IS NOT THE WHOLE STORY. + * NOTHING TO CARRY, AND THIS TIME NOTHING IS LOST EITHER. * * A migration moves DATA a previous version wrote. There is none to move: the package keeps its * saved games as a seed plus the moves played, and nothing about their shape has changed. * - * WHAT HAS CHANGED IS WHETHER THEY STILL MEAN ANYTHING. v0.7.2 takes the deck from 206 cards to - * 121 (Gitea#14), so a card id recorded under v0.7.1 refers to a different card or to no card at - * all, and a saved game stops replaying at its first `card.play`. That cannot be migrated: the - * moves were made against a deck that no longer exists, and re-dealing would invent a game - * nobody played. + * THE DIFFERENCE FROM v0.7.2, which is the thing worth writing down. That release emptied this + * same function for a much worse reason — the deck went from 206 cards to 121, so a card id + * recorded under v0.7.1 meant a different card or none, and every game in progress was declined + * on startup. v0.7.3 changes no card data and adds only new moves, so a v0.7.2 save replays + * intact: every intent in it is still legal, and the game simply pauses on the new + * "play one more Day?" question when its timetable runs out instead of finishing outright. * - * IT FAILS SAFE, and that is why this is empty rather than a `down: IMPOSSIBLE` argument for - * holding the release. `src/server/index.ts` replays each save on startup and REFUSES to resume - * one the rules reject, naming the move it stopped at and leaving the file untouched — so a - * game in progress is declined, never silently corrupted, and an operator who wants it back can - * put v0.7.1 on and finish it. The release notes say so first, before anything else. + * Proven rather than assumed: the upstream suite replays the three recorded games in + * `public/replays`, all made under an older ruleset, and asserts every intent still applies + * (`test/harness.test.ts`). The release notes lead with it, since the last release's notes had + * to lead with the opposite. */ up: async ({ effects }) => {}, down: IMPOSSIBLE, diff --git a/station-master b/station-master index 2ab25e3..45580d8 160000 --- a/station-master +++ b/station-master @@ -1 +1 @@ -Subproject commit 2ab25e320c8575b1a233def40dd26f833b119fca +Subproject commit 45580d8b61bb74917f7df1339c1d7528af3c5277