fix(render): the title card answers itself; stop promising a block that is not there #11

Merged
bosun merged 1 commit from i/win-symmetry into main 2026-07-13 13:58:04 +02:00
Owner

Herald's rulings (2a8a) — plus a bug I found by walking the campaign instead of assuming it worked.

1. The title card answers itself

The game is called BREAK OUT. The win is BROKEN OUTthe title in the past tense. The game's name becomes its own ending, and that symmetry is the payoff.

So the win banner now renders in the same gold, same size, same letter-spacing as the BREAKOUT title card, and the score is prominent (HUD-weight, bright) rather than a dim footnote — it's what the player earned across the whole campaign, and what the next guest is trying to beat.

Asserted in painted pixels, not by eye:

BREAKOUT   (title) : 7168 lit px, 87% gold, glyph band 398px
BROKEN OUT (win)   : 8088 lit px, 89% gold, glyph band 504px   <- same font/tracking band
CONTAINED  (loss)  : 7411 lit px,  0% gold                     <- still danger-red, still distinct

2. WALL BREACHED and BROKEN OUT must never collapse

Herald: "A player breaks four walls and escapes ONCE. If clearing level 2 says BROKEN OUT, the ending is spent four times before it arrives."

That's a claim about my code, so I proved it rather than inferring it from a grep — walked every level-clear across the five-level campaign against the real engine:

level | phase       | won   | BANNER SHOWN
  1   | levelclear  | false | WALL BREACHED
  2   | levelclear  | false | WALL BREACHED
  3   | levelclear  | false | WALL BREACHED
  4   | levelclear  | false | WALL BREACHED
  5   | levelclear  | false | WALL BREACHED
  5   | gameover    | true  | BROKEN OUT      <- campaign end

BROKEN OUT shown exactly ONCE : YES — only at the true campaign end

Five walls breached, escaped once. The ending is not spent early.

3. 🐛 A bug I introduced, and only found by walking it

The levelclear sub-line said "SPACE FOR BLOCK n+1". But state carries level and no level count — so the renderer cannot know whether a next block exists. On the final wall it cheerfully announced "SPACE FOR BLOCK 6", when there is no block 6.

It was a promise the renderer had no way to keep, and it is exactly the class of thing this jam kept surfacing: asserting something I hadn't checked was observable. No error, no crash — just a lie on the most important screen of the run.

Now it says what the player did"BLOCK 5 DOWN — SPACE TO CONTINUE" — which is always true, instead of what comes next, which isn't.

If a level count ever reaches state, the forward-looking line can come back honestly. That's one field in engine.js and it's Engineer's call — flagged, not assumed.

Verification

Surveyor's gate clean (100% non-blank, 0 errors, 0 4xx) · Engineer's launch probe PASS against the real engine · five-clear campaign walk PASS · typographic symmetry PASS.

Still Herald's

He wrote "the loss stays GAME OVER" while describing a card that's gold — but the live loss card is CONTAINED in danger-red (Surveyor's string, which he'd endorsed as "perfect for a LOSS — triumphant for the prison"). I think he was describing the pre-merge default he'd been playtesting, but I'm not going to guess at a creative call. CONTAINED stays until he rules; it's one token either way.

🤖 Generated with Claude Code

Herald's rulings (2a8a) — **plus a bug I found by walking the campaign instead of assuming it worked.** ## 1. The title card answers itself The game is called **BREAK OUT**. The win is **BROKEN OUT** — *the title in the past tense*. The game's name becomes its own ending, and that symmetry is the payoff. So the win banner now renders in the **same gold, same size, same letter-spacing** as the BREAKOUT title card, and the **score is prominent** (HUD-weight, bright) rather than a dim footnote — it's what the player earned across the whole campaign, and what the next guest is trying to beat. Asserted in **painted pixels**, not by eye: ``` BREAKOUT (title) : 7168 lit px, 87% gold, glyph band 398px BROKEN OUT (win) : 8088 lit px, 89% gold, glyph band 504px <- same font/tracking band CONTAINED (loss) : 7411 lit px, 0% gold <- still danger-red, still distinct ``` ## 2. `WALL BREACHED` and `BROKEN OUT` must never collapse Herald: *"A player breaks four walls and escapes ONCE. If clearing level 2 says BROKEN OUT, the ending is spent four times before it arrives."* That's a claim about my code, so I proved it rather than inferring it from a grep — walked **every** level-clear across the five-level campaign against the real engine: ``` level | phase | won | BANNER SHOWN 1 | levelclear | false | WALL BREACHED 2 | levelclear | false | WALL BREACHED 3 | levelclear | false | WALL BREACHED 4 | levelclear | false | WALL BREACHED 5 | levelclear | false | WALL BREACHED 5 | gameover | true | BROKEN OUT <- campaign end BROKEN OUT shown exactly ONCE : YES — only at the true campaign end ``` Five walls breached, escaped once. **The ending is not spent early.** ## 3. 🐛 A bug I introduced, and only found by walking it The levelclear sub-line said **"SPACE FOR BLOCK n+1"**. But `state` carries `level` and **no level count** — so the renderer *cannot know whether a next block exists*. On the **final wall** it cheerfully announced **"SPACE FOR BLOCK 6"**, when there is no block 6. It was a promise the renderer had no way to keep, and it is exactly the class of thing this jam kept surfacing: **asserting something I hadn't checked was observable.** No error, no crash — just a lie on the most important screen of the run. Now it says what the player **did** — *"BLOCK 5 DOWN — SPACE TO CONTINUE"* — which is always true, instead of what comes next, which isn't. > If a **level count** ever reaches `state`, the forward-looking line can come back honestly. That's one field in `engine.js` and it's Engineer's call — flagged, not assumed. ## Verification Surveyor's gate clean (100% non-blank, 0 errors, 0 4xx) · Engineer's launch probe PASS against the real engine · five-clear campaign walk PASS · typographic symmetry PASS. ## Still Herald's He wrote *"the loss stays `GAME OVER`"* while describing a card that's **gold** — but the live loss card is **CONTAINED in danger-red** (Surveyor's string, which he'd endorsed as *"perfect for a LOSS — triumphant for the prison"*). I think he was describing the pre-merge default he'd been playtesting, but I'm **not going to guess at a creative call**. `CONTAINED` stays until he rules; it's one token either way. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Herald 2a8a — two rulings, plus a bug I found by walking the campaign.

1. BROKEN OUT gets the TITLE's exact weight. The game is called BREAK OUT; the
   win is BROKEN OUT — the title in the past tense, the game's name becoming its
   own ending. So it renders in the same gold, same size, same tracking as the
   BREAKOUT title card, and the score is PROMINENT (HUD-weight, bright) rather
   than a dim footnote: it's what the player earned across the whole campaign and
   what the next guest is trying to beat.
   Asserted in painted pixels, not by eye: title 87% gold, win 89% gold, same
   glyph band; CONTAINED 0% gold — still danger-red, still distinct.

2. WALL BREACHED and BROKEN OUT must never collapse. A player breaks four walls
   and escapes ONCE; if clearing level 2 said BROKEN OUT the ending would be
   spent four times before it arrived. Proved by walking all five clears against
   the real engine: 5x WALL BREACHED, BROKEN OUT exactly once, at the true end.

3. BUG I INTRODUCED, found by that walk: the levelclear sub-line said
   "SPACE FOR BLOCK n+1" — but state carries `level` and NO level COUNT, so the
   renderer cannot know whether a next block exists. On the FINAL wall it promised
   "SPACE FOR BLOCK 6" when there is no block 6. It now says what the player DID
   ("BLOCK 5 DOWN"), which is always true, instead of what comes next, which
   isn't. If a level count reaches state, the forward-looking line can come back —
   honestly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbnWrAAh3iGuPAQF53nuXG
bosun merged commit 3988c66d5a into main 2026-07-13 13:58:04 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
frankenbit/breakout!11
No description provided.