bc16 endcard: year-guard the shared win-condition clause, unsqueeze the card - #12
Merged
Conversation
… the year's own row
`endcardWinCondition()` hard-coded bc22's lore on a reason two years emit:
case 'more_archons':
return 'the Singularity came at round ' + last.rounds_played +
' and ' + alias + ' had more archons left';
`more_archons` is bc22's PWNED and bc16 deliberately reuses it as its first
tiebreak rung (src/battlecode/results.nim's own note on `EndReasons`), so the
endcard of a live bc16 ladder match rendered "THE SINGULARITY CAME AT ROUND
3000 AND CLAN BASIL HAD MORE ARCHONS LEFT" — a mechanic bc16 does not have
(its games run to a 3000-round limit and are decided on the four-rung ladder,
docs/RULES-BC16.md).
The clause that names how the game ran out now comes from `ENDCARD_NOUNS`, the
per-year table the same function already resolves nouns through: bc22 keeps
`limit: 'the Singularity came'`, bc16 gets `limit: 'the round limit ran out'`,
and a year without a row falls back to the plain round limit. bc16 now reads
"the round limit ran out at round 3000 and Clan Basil had more archons left";
bc22's wording is byte-for-byte what it was.
Closes the class, not the instance: `tests/test_viewer.nim` now slices
`endcardWinCondition()` into its branches and fails if a branch for an end
reason MORE THAN ONE YEAR EMITS (`more_archons`, `annihilated`, `coin_flip`,
`abandoned`, `highest_id`) contains any word belonging to one year's rule set.
With the old line restored that test fails on two checks; nothing asserted
per-year wording for a shared reason before, which is why this shipped green.
… reach
REPRODUCED, not taken on faith: `tools/ci/renderer_fixture.html` now lays the
card out with this year's own doctrine text and the bc16 war panel on it, and
at 360/720/1280 px, in the page's own CSS, the unfixed card gives
`#ec-headline` 5px, 13px and 14px for a 20px, 21px and 32px line. The band is
`overflow: hidden`, so what it draws is a horizontal slice of its own capitals
— exactly what
runs/2026-09-09-battlecode-2016/viewer-check/viewer-smoke.png shows for
"CLAN BASIL — DAVEEY-1".
The cause is at the card, not the headline: `#endcard` is a column flex box
and a flex item shrinks below its content by default, so a card whose bands
outgrow the board region was squeezed band by band instead of scrolling. That
also kept `#endcard`'s scrollHeight equal to its clientHeight, so the FIX 2
overflow gate in `viewer_smoke.mjs` was green on a card that was clipping.
#endcard.on > * { flex: none; }
Every band now keeps its natural height and the card scrolls, which is what
`overflow-y: auto` was put there for. Because a centred column flex box that
is also the scroll container strands its overflow ABOVE the scrollport — the
trap `.ec-teams.br` already documents one level down — `#endcard` also gains
`justify-content: safe center` after its `justify-content: center`: centred
while the content fits, top-anchored and fully scrollable when it does not.
Measured without it, the headline sat 23px (1280) to 234px (360) above the
scrollport, unreachable.
The gate is the fixture, not a grep: with the two declarations removed it
exits 1 on all three widths ("the endcard headline is squeezed into 5px of
its own 20px line"), and 0 with them. `tests/test_viewer.nim` pins the shape
of both the rules and the fixture check. The existing assertion that #endcard
is the last child of #chrome is re-expressed against the populated markup —
same claim, plus the content.
REPRODUCED at 360/720/1280 px in the page's own CSS, with both seats at
bc16's widest sheet: `#endcard .ec-teams` capped itself at 52 % of the card
and hid 610px of 872px (360), 440px of 835px (720) and 295px of 579px (1280)
of the two doctrine panels — cut mid-word, no ellipsis, inside a scroll box
with no dismiss control. That is the live endcard's "...activates a" /
"...routes its" (viewer-check/viewer-smoke.png). Phase 30's item 15: ellipsis
is a label's choice and a sentence's defect; if a remark is being cut, the box
is too small.
The 52 % cap is sized for the BR field list, where a row is a name and three
numbers. The doctrine variant is one team's whole doctrine in plain words, so
it is scoped out of the cap and given the width the frame has to spare:
#endcard .ec-teams:not(.br) { max-height: none; }
#endcard .ec-teams:not(.br) .ec-team {
width: auto; flex: 1 1 calc(215 * var(--u));
max-width: calc(430 * var(--u));
}
`width: auto` is load-bearing — the card is centred, so `.ec-teams` is
shrink-to-fit and a panel still carrying the base rule's fixed 215u
contributes exactly that to the row, which could then never grow (measured:
the row stayed 452px wide inside a 1240px frame until the width was released).
At 430u a panel takes 275px instead of 579px at 1280 and the whole card needs
682px of a 586px scrollport rather than 986px. `.ec-teams.br` keeps its own
62 % cap and is untouched.
Gate: the renderer fixture now fails if `#ec-teams` scrolls inside the card,
and checks both seats' endcard text is still at full length before measuring.
With these two rules removed it exits 1 on the FIRST year row it lays out
("bc26 @ 360px: the endcard doctrine panels are cut off: 116px of 378px
hidden inside a box on the card"), so this closes the defect for all eight
years, not just bc16.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three endcard defects found by reading the rendered endcard of a real bc16
ladder match (
runs/2026-09-09-battlecode-2016/viewer-check/viewer-smoke.pngin coworld-builder). One commit per finding.
E1 — bc22's lore leaked into every year's
more_archonsendcard.endcardWinCondition()hard-coded "the Singularity came at round N" on an endreason bc22 and bc16 both emit, so a live bc16 match rendered "THE SINGULARITY
CAME AT ROUND 3000 AND CLAN BASIL HAD MORE ARCHONS LEFT" for a mechanic bc16
does not have. The clause now comes from
ENDCARD_NOUNS, the per-year tablethe function already resolves nouns through.
tests/test_viewer.nimnow slicesthe function into branches and fails on any one-year word inside a branch for
a reason more than one year emits.
E2 — the endcard headline drew a slice of its own capitals.
#endcardis acolumn flex box, so a card taller than the board region squeezed every band
instead of scrolling: 5px/13px/14px for a 20px/21px/32px line at
360/720/1280.
#endcard.on > * { flex: none; }plusjustify-content: safe center(the top of a centred, overflowing scroll container is otherwisebeyond reach).
E3 — both doctrine panels hard-clipped their sentences mid-word.
.ec-teams' 52 % cap is sized for the BR field list; on the two-paneldoctrine variant it hid 295–610px of the text with no ellipsis and no dismiss
control. The panels are now laid out whole and take the width the frame has to
spare (up to 430u each);
.ec-teams.brkeeps its own cap.E2 and E3 were verified by measurement before they were fixed, and are gated
by
tools/ci/renderer_fixture.html, which now raises a POPULATED endcard atall three widths for all eight years. With the CSS reverted the fixture exits
1 with the exact numbers above; with it, 0.