Submodule pinned to v0.7.7 (af68aac). current.ts bumped in place at 0.7.7:0 — no new version file, no migration: the change is to how the built client is cached, not to what it does. Every packaged build until now published ?v=nogit as its cache key (the .s9pk Dockerfile copies the tree in without .git, so git rev-parse fails), and serveStatic sent no Cache-Control at all — so 0.7.5's solitaire setup screen and 0.7.6's fix to it were both installed here correctly and neither ever reached a browser. Verified on phoenix.local against what the server actually returns, not just what was packed: build tag is 0.7.7-mtf7hyxc (not nogit) and the module graph's inner imports carry the same tag; play.html is no-cache; a ?v=-tagged module is immutable for a year; an untagged one is no-cache. Migration 0.7.6:0 -> 0.7.7:0 ran empty and both games in progress (WHISTLE-4086, COAL-7370) resumed with their same intent counts. README.md records that a hard reload is NOT a sufficient check for this class of bug — confirmed in the field on 0.7.6, where only a fresh private window showed the new build. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
174 lines
12 KiB
Markdown
174 lines
12 KiB
Markdown
# Station Master
|
|
|
|
## Documentation
|
|
|
|
- [Rules and design docs](https://draco.local:53871/Jesse.Markowitz/station-master/src/branch/main/docs)
|
|
— the rulebook implications, the multiplayer design, and the game's architecture.
|
|
|
|
## What you get on StartOS
|
|
|
|
This service runs the multiplayer server: a lobby, and a table for 2 to 4 players to play a
|
|
competitive or cooperative game together from their own browsers. Everything a player needs — the
|
|
game itself, the lobby, and the connection back to this server — is served from the single web
|
|
interface below; there is nothing else to install or configure on a player's side.
|
|
|
|
## Getting set up
|
|
|
|
1. Run the **Get Join Secret** action from this service's Actions menu, and copy the value it
|
|
returns.
|
|
2. Share that secret, and this service's address, with everyone you want to play with. Anyone
|
|
holding the secret can create a new game or join one that hasn't started yet.
|
|
3. Open this service's **Multiplayer Table** interface. You'll land on the front page, which
|
|
offers three ways in: solitaire, the replay viewer, and multiplayer.
|
|
4. Click **Play multiplayer**, then **Create Game** (or **Join Game** with a game code someone
|
|
else created), and enter the join secret when asked.
|
|
|
|
## Using Station Master
|
|
|
|
### Multiplayer Table
|
|
|
|
The front page offers solitaire, the replay viewer, and multiplayer. **Play multiplayer** takes you
|
|
to the lobby: create or join a game, seat players (including filling empty seats with a bot), and
|
|
start. Once a game is underway, this same interface is where every player plays their turns and
|
|
watches the table — there is nothing else to open.
|
|
|
|
Solitaire runs entirely in your own browser and needs nothing from the server, so it works here
|
|
exactly as it does on the public Station Master site.
|
|
|
|
**What changed in 0.7.7.** Updates to this service now actually reach your browser. Until now every
|
|
release published its files under the same cache name and the server never told browsers when to
|
|
look again, so returning players kept running whatever version their browser had already stored —
|
|
the 0.7.5 solitaire setup screen and its 0.7.6 fix were both installed correctly here and neither
|
|
was ever seen. If a past update seemed to do nothing, this is why, and opening the page in a private
|
|
window was the only way to see it. That should not be necessary again.
|
|
|
|
**What changed in 0.7.6.** The **Play solitaire** door on the front page now reliably reaches
|
|
solitaire. If this browser had ever taken a seat at a multiplayer table, the door used to lose to
|
|
that game or lobby instead — a plain page load couldn't tell "I clicked Play solitaire" apart from
|
|
"I reloaded mid multiplayer game". Fixed; nothing else changed.
|
|
|
|
**What changed in 0.7.5.** Solitaire now asks before it deals. A genuinely fresh visit to the
|
|
solitaire page opens a setup screen with the full set of options — game type, starting hand, where
|
|
an Extra may start, the revenue rates, victory conditions, and the optional rules — the same
|
|
question the multiplayer lobby has asked before a game starts since 0.7.0, below. Press **Deal**
|
|
when you're ready. A saved game, a shared link that already carries a seed, or a link the setup
|
|
screen itself just produced all skip straight past it — those already answer the question rather
|
|
than needing to ask it again. Nothing about the rules changed, so **every game in progress carries
|
|
over**, both here and on the multiplayer server, without exception.
|
|
|
|
**Setting a game up (new in 0.7.0).** The lobby opens on **Join a game**: type the code you were
|
|
given and you will see the whole rule set — the opening hand, what the work pays, every way the game
|
|
can end — *before* you take a seat. Creating a game instead starts from a **game type**: Co-op,
|
|
Competitive or Cutthroat. A type just fills in the rules; every one of them is yours to change, and
|
|
changing any of them marks the game **Custom**, which keeps the scoring of the type you started
|
|
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.4.** Before anything else: **a game already in progress may not carry over.**
|
|
These are rules changes, and three of them alter what a saved game is allowed to contain, so an
|
|
old game may stop replaying. The server declines to resume one rather than breaking it — it says
|
|
which move it stopped at and leaves the save alone — so if you are mid-game and it matters, finish
|
|
it before updating or put 0.7.3 back on afterwards. A game that never runs into one of the three
|
|
carries on as normal.
|
|
|
|
**The Yard Office asks you now.** A freight train arriving in your district used to be sent into the
|
|
yard automatically, whether you wanted it there or not. Now you are asked. Three things it never
|
|
checked before it does now: it has to be able to **reach the yard in one move** — if it cannot, you
|
|
are not offered the choice, and the history tells you why rather than staying silent — and if there
|
|
are **cars standing on the way in, the train hits them**, exactly as it would anywhere else. Taking
|
|
the yard still keeps your Train Order Office free, which is the whole point of the card.
|
|
|
|
**Circus, Campaign and Military trains run loaded.** They take loaded cars from the Division Yard
|
|
while there are any, empties once there are not, and will run short rather than wait. A Circus or
|
|
Campaign train earns its point for setting up **once in each player's district** rather than once in
|
|
the whole game — so a train that tours the Division is worth more than one that parks — and only
|
|
when every car is full. Not much of a circus if the cars are empty. The Campaign train earns that
|
|
point for the first time; it never scored at all before, and it needs its candidate aboard.
|
|
|
|
**Red Flags does something else entirely.** It used to protect one stopped train out on the line.
|
|
Now you plant it on the **east or west side of your own district**, and it holds the next train
|
|
coming from that way — which is how you buy yourself a Stage to finish switching. It comes down with
|
|
the train it stops: one card, one train. You can also play it at the moment it matters. If a train
|
|
is arriving into a certain collision and you are holding the card, the game stops and asks whether
|
|
you want to flag it; say no and the collision happens.
|
|
|
|
**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.
|
|
|
|
**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
|
|
the Hilly card** now, instead of adding a Stage to every card, so slow trains in particular get
|
|
across the Division far quicker than they used to. **The deck is smaller and holds less track**,
|
|
matching the published card counts, so building a district is a slower business and the cards you
|
|
draw are worth more. And **the Division map is one row you read left to right**, west on the left and
|
|
east on the right, instead of wrapping around the screen — it no longer shows the inside of anyone's
|
|
district, which is what your own Office map is for, but every train in a district still appears on
|
|
it, with the ones holding an arrival track drawn on the rail and any crew switching drawn below it.
|
|
|
|
**Leaving, and coming back.** Anyone may leave a lobby, and the host can clear a chair, so a
|
|
mis-join or somebody who wanders off no longer blocks a table that cannot start until every seat is
|
|
taken. A **Leave game** button appears once a game is running: it keeps your seat and the table
|
|
waits for you, and the lobby lists every game this browser is in so you can rejoin it — or join a
|
|
different one without losing the first. **Forget** on that list is the one thing that cannot be
|
|
undone: the token kept in your browser is the only proof of who you are, so a forgotten game cannot
|
|
be rejoined from that browser.
|
|
|
|
### Get Join Secret
|
|
|
|
Run this whenever you need the current join secret again, or want to shut out anyone still
|
|
holding an old one. Every run replaces the secret and immediately puts the new one into effect —
|
|
players already seated in a game are unaffected, but the old secret stops working for creating or
|
|
joining games from that point on.
|
|
|
|
### Games in Progress
|
|
|
|
Shows every game on the server: who is playing, which Day and Stage they have reached, and whose
|
|
turn it is. It changes nothing, so run it whenever you are curious. It is also how you spot a game
|
|
nobody is coming back to — one whose last move was days ago, still waiting on a particular player.
|
|
|
|
### Manage Game
|
|
|
|
Pick a game, then either save a copy of it or end it.
|
|
|
|
**Export** hands you the whole game as text and leaves it running. Save that text as a `.json`
|
|
file and you can open it in the replay viewer later to watch the game back.
|
|
|
|
**End the game** deletes it and disconnects anyone still watching. This is the only way to clear
|
|
a game that will never be finished — otherwise it sits there, and comes back every time the
|
|
service restarts. It cannot be undone, so the game's save is handed back to you when it happens:
|
|
that text is the only copy left, so keep it if the game was worth watching.
|
|
|
|
> **Games in progress normally survive an update of this service.** When the update changes the
|
|
> rules of the game itself, a half-played game cannot be resumed under rules it was not played by,
|
|
> and that game is set aside rather than continued — you would see it disappear from the lobby.
|
|
> Nothing is ever deleted, so going back to the previous version makes it playable again.
|