Fight a whole mission with nothing drawing #44

Open
icub3d wants to merge 1 commit from 13-headless-integration-test into main
Owner

The test M1's architecture is for. A mission runs start to finish with no window, no
renderer and no playback — and the point of writing it is that it was easy, which is the
evidence the simulation/presentation split holds. The issue said so itself: if this is hard
to write, fix the split rather than the test.

What it asserts

  • A whole mission resolves with nothing drawing — no PlaybackPlugin, no UiPlugin.
    Leaving them out is what proves it, rather than a comment saying so.
  • Determinism on the entire outcome log, not the winner. Two runs that agree about who
    won and disagree about how are exactly what replay and PvP cannot survive, so the logs are
    compared element by element and the failure names the step that diverged.
  • Twice in one process. A leaked static, a resource that outlived its state, or a reused
    entity id shows up as a difference rather than as a test that got lucky about ordering.
  • The cell wins. The proving ground is beatable when the player fights it — the smallest
    possible version of "this is a game". If it ever flips, that is a balance change and
    should be a deliberate one.

The player's side is driven by the same Skirmisher the hostiles use. Not clever play —
fixed play, so anything that differs between two runs came from the game rather than from
the script.

Acceptance criteria

  • Runs with no rendering plugins and no display.
  • Determinism asserted on the whole event log.
  • Fast enough for the default run — the three tests take 0.03 s; the whole suite is
    3.4 s for 208 tests.
  • Same result twice in one process.

Found while writing it

A script that remembered only which unit it had acted for stalled the mission: a unit with
two action points needs asking twice, and its turn never ended otherwise. The guard keys on
what the unit has left to spend.

Where this leaves M1

The simulation half is done — a mission is started, fought, shown, ended and reported, and
replayed headlessly from a fixed seed. What remains in the milestone is the tablet half:
#24 touch camera, #25 blank resume, #26 insets, #27 font, #28 portrait, plus #32
anti-aliasing. Until those land, "with touch on a tablet" in the roadmap's done-when is a
claim rather than a fact, and docs/ROADMAP.md now says so.

Closes #13

🤖 Generated with Claude Code

https://claude.ai/code/session_01TA4hJHkRSU3XBxZYtMKXdh

The test M1's architecture is for. A mission runs start to finish with no window, no renderer and no playback — and the point of writing it is that it was easy, which is the evidence the simulation/presentation split holds. The issue said so itself: if this is hard to write, fix the split rather than the test. ## What it asserts - **A whole mission resolves with nothing drawing** — no `PlaybackPlugin`, no `UiPlugin`. Leaving them out is what proves it, rather than a comment saying so. - **Determinism on the entire outcome log**, not the winner. Two runs that agree about who won and disagree about how are exactly what replay and PvP cannot survive, so the logs are compared element by element and the failure names the step that diverged. - **Twice in one process.** A leaked static, a resource that outlived its state, or a reused entity id shows up as a difference rather than as a test that got lucky about ordering. - **The cell wins.** The proving ground is beatable when the player fights it — the smallest possible version of "this is a game". If it ever flips, that is a balance change and should be a deliberate one. The player's side is driven by the same `Skirmisher` the hostiles use. Not clever play — *fixed* play, so anything that differs between two runs came from the game rather than from the script. ## Acceptance criteria - [x] Runs with no rendering plugins and no display. - [x] Determinism asserted on the whole event log. - [x] Fast enough for the default run — the three tests take 0.03 s; the whole suite is **3.4 s** for 208 tests. - [x] Same result twice in one process. ## Found while writing it A script that remembered only *which* unit it had acted for stalled the mission: a unit with two action points needs asking twice, and its turn never ended otherwise. The guard keys on what the unit has left to spend. ## Where this leaves M1 The simulation half is done — a mission is started, fought, shown, ended and reported, and replayed headlessly from a fixed seed. What remains in the milestone is the tablet half: #24 touch camera, #25 blank resume, #26 insets, #27 font, #28 portrait, plus #32 anti-aliasing. Until those land, "with touch on a tablet" in the roadmap's done-when is a claim rather than a fact, and `docs/ROADMAP.md` now says so. Closes #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01TA4hJHkRSU3XBxZYtMKXdh
The test M1's architecture is for. A mission runs start to finish with no
window, no renderer and no playback — and the point of writing it is that it was
easy, which is the evidence the simulation/presentation split holds. If it had
been hard, the split would have been the thing to fix.

It drives the player's side with the same `Skirmisher` the hostiles use.
Not because that is clever play, but because it is fixed: given the same mission
it makes the same decisions, so anything that differs between two runs came from
the game rather than from the player.

Determinism is asserted on the entire stream of outcomes, not on the winner. Two
runs that agree about who won and disagree about how are precisely what replay
and PvP cannot survive, so the log is compared element by element and the test
says which step diverged.

It runs the mission twice in one process. A leaked static, a resource that
outlived its state, or a reused entity id would show up as a difference rather
than as a passing test that happens to be lucky about ordering.

And it asserts the cell wins. The proving ground is beatable when the player
fights it, which is the smallest possible version of "this is a game" — if that
ever flips, it is a balance change and should be a deliberate one.

The suite still runs in well under four seconds, so this stays in the default
`cargo test`.

One thing the writing of it found: a script that remembered only *which* unit it
had acted for stalled a mission, because a unit with two action points needs to
be asked twice and its turn never ended otherwise. The guard keys on what the
unit has left to spend.

Closes #13

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TA4hJHkRSU3XBxZYtMKXdh
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 13-headless-integration-test:13-headless-integration-test
git switch 13-headless-integration-test

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff 13-headless-integration-test
git switch 13-headless-integration-test
git rebase main
git switch main
git merge --ff-only 13-headless-integration-test
git switch 13-headless-integration-test
git rebase main
git switch main
git merge --no-ff 13-headless-integration-test
git switch main
git merge --squash 13-headless-integration-test
git switch main
git merge --ff-only 13-headless-integration-test
git switch main
git merge 13-headless-integration-test
git push origin main
Sign in to join this conversation.
No description provided.