• v0.6.0 40f07b0710

    v0.6.0 — saves survive a release, Employee Rotation is real, and the lobby

    Jesse.Markowitz released this 2026-08-22 01:45:34 +00:00 | 67 commits to main since this release

    asks what game you want

    Three queued items. The last matters most.

    A RELEASE NO LONGER DESTROYS EVERY GAME IN PROGRESS.

    Four consecutive releases killed every game on the box, one of them a
    release that changed only how the board is drawn. The reasoning behind the
    refusal was always right — a move legal under old rules may not be legal
    under new ones, and half-replaying a save is worse than refusing it. The
    TEST was wrong: it compared engineVersion for exact equality, and that
    stamp is the package version, which moves for a CSS fix.

    Whether a save still replays has an exact answer, so it is now asked
    directly. loadGame reads the file and judges nothing; tryResumeSession
    replays the intents and reports the first one the engine refuses. A save
    stamped with a version this server has never run resumes fine provided its
    moves replay — verified against a file hand-stamped 0.4.9-ancient. One that
    genuinely does not replay is still refused, but the log names the move
    rather than two version strings: "move 3 of 8 (localOps.choose) is rejected
    by the current rules with OPTION_ALREADY_CHOSEN".

    fromMultiplayerSave had to stop lying first. It has always stopped at the
    first unacceptable intent and done so in silence, which was survivable only
    because the version gate meant a doomed replay was never attempted. Now
    that the replay IS the check, it returns where it stopped and why.

    Deliberately not done: resuming a partly-replayable game at its last good
    move. That silently rewinds a game to a position nobody played to while
    every browser holding a later Frame carries on unaware. Refusing leaves the
    file intact, so putting the previous version back still recovers it.

    EMPLOYEE ROTATION IS IMPLEMENTED, SISTER TRAINS IS DELETED.

    Two of the four optional-rule flags were read by nothing at all. Employee
    Rotation is four lines in advance.ts, because the seat/player split (D9)
    exists for precisely this rule: seating is the only thing that moves, so
    Revenue, hands, the Superintendent and whose turn it is travel with the
    player, and the Office, district, grid and any trains standing in it stay
    with the chair. Inheriting the district you move into is the point of the
    rule, not a side effect. "Left" is seat + 1, matching playerLeftOf.

    Sister Trains is deleted rather than built: Q9 records that the Second
    Section card supersedes it, and that card exists, so the flag was a toggle
    for a rule the game no longer has.

    THE LOBBY ASKS WHAT GAME YOU WANT TO PLAY.

    Creating a game asked for a name, a mode and a table size; every other dial
    was hardcoded. A Game settings block now carries the same set the solitaire
    dialog does — seed, starting hand, the three revenue rates, Days, the
    combined-Revenue floor, both collision caps, the opponent-card toggle —
    plus the three surviving optional rules. Mode and table size set the
    defaults and everything stays editable. The seed is honoured, so a game can
    be reproduced or compared.

    Verified: 682 tests pass (679 + 3). The rotation tests were mutation-checked
    both ways — disabling the rotation and turning the table the wrong way each
    fail the suite. Live: a save stamped 0.4.9-ancient resumed, an injected
    illegal move was refused by name, and a create with every dial set to a
    non-default value came back out of game.json with all of them intact,
    including seed 777.

    Two of my own assertions were wrong on the way and the tests caught them:
    the Fedora legitimately passes at Stage 12 (§5) so it cannot be compared
    against its own earlier value, and dispatchUsedToday is cleared at every
    Day boundary so it cannot mark a district.

    Downloads