Say who the game is waiting on, and move the Fedora; replay in words
Three items folded into the unshipped v0.7.9. WAITING ON (reported by Jesse from play). The status line said "nobody — the Division is running itself" while the game was stopped on the Superintendent. Frame.actor carried clock.currentActor, which is null for the whole Mainline Phase, so all three interruptions — §8.1's clearance ruling, Gitea#5's Yard Office offer, Gitea#19's Red Flag prompt — reported that nobody was holding it up. actingPlayer had the answer since the Gitea#5 refactor; the Frame threw it away. It carries actingPlayer now, plus a new `awaiting` field naming the question and the train: "waiting on Bob · a clearance ruling · Train 4". Naming the person alone is not enough when three different things can be pending. THE FEDORA (TODO #29) rides at the right-hand end of the phase row instead of a line of its own, and wraps under rather than squeezing the chips. THE DEVELOPER REPLAY (TODO #34) printed "loss — revenueFloor", the same defect Gitea#16 was filed about, still alive because nothing player-facing pointed at it. panels.ts's reasonSentence is exported and shared rather than reimplemented, fed the last recorded frame and stripped of markup. The drift test maps win/loss to won/lost so it still checks the two AGREE rather than that they are spelled alike. Also carries the previous, unsigned commit's work: the two setup screens worded the same section by section. 877 tests pass, ten new. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AdG46Ja2PEDBkpqiDazMoX
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
131538dc7c
commit
a70b7f88f3
+23
-17
@@ -2019,12 +2019,16 @@ function wireGameTypeBlock(prefix: string, root: ParentNode): WiredGameType {
|
||||
if (differing.length > 0) type = 'custom';
|
||||
else if (type === 'custom') type = base;
|
||||
for (const r of typeRadios()) r.checked = r.value === type;
|
||||
const note = field<HTMLElement>('type-note');
|
||||
note.textContent =
|
||||
type === 'custom'
|
||||
? `${gameTypeLabel('custom', preset(base).scoring)} · ${differing.length} ` +
|
||||
`${differing.length === 1 ? 'setting differs' : 'settings differ'} from ${preset(base).label}.`
|
||||
: preset(type as PresetName).blurb;
|
||||
/**
|
||||
* NO SENTENCE UNDER THE RADIOS. It restated the type just chosen — the row is already labelled
|
||||
* and already carries its own one-line description — so it was the choice read back to the
|
||||
* person who had just made it (Jesse, 2026-08-30: "It's obvious from what they selected above
|
||||
* what they're playing. There's no need to repeat it below.").
|
||||
*
|
||||
* The Custom case said something the radios do NOT — how many settings differ, and from which
|
||||
* type — and that is not lost: `form.mark` puts a hint on each row that actually differs, which
|
||||
* is where a reader can act on it rather than a count they would then have to go and find.
|
||||
*/
|
||||
}
|
||||
|
||||
function selectPreset(name: PresetName): void {
|
||||
@@ -2043,19 +2047,21 @@ function wireGameTypeBlock(prefix: string, root: ParentNode): WiredGameType {
|
||||
}
|
||||
|
||||
for (const r of typeRadios()) {
|
||||
// Nothing here can deal a multiplayer game: a `LocalSession` runs the engine in this browser and
|
||||
// a table needs a server. The lobby is the door, and the row says so rather than just refusing
|
||||
// the click (Jesse, 2026-08-23 — a disabled radio that looks enabled reads as a broken one).
|
||||
/**
|
||||
* Nothing here can deal a multiplayer game: a `LocalSession` runs the engine in this browser and
|
||||
* a table needs a server. Dimmed rather than hidden, so what this screen offers and what the
|
||||
* lobby offers read as one list (Jesse, 2026-08-23 — a disabled radio that looks enabled reads
|
||||
* as a broken one).
|
||||
*
|
||||
* NO REASON PRINTED BESIDE THEM since 2026-08-30. Each row used to gain "— use the Multiplayer
|
||||
* button; a table needs a server", which is three unreachable types each explaining the same
|
||||
* thing on a screen whose heading already says "Game type (solitaire)". Jesse: "grayed out with
|
||||
* no additional explanation. The explanation above… is sufficient." The lobby dims Solitaire the
|
||||
* same way and says nothing either, which is what lets one list serve both screens.
|
||||
*/
|
||||
if (r.value !== 'solitaire' && r.value !== 'custom') {
|
||||
r.disabled = true;
|
||||
const row = r.closest('label');
|
||||
if (row && !row.querySelector('.lb-why')) {
|
||||
row.classList.add('disabled');
|
||||
const note = document.createElement('span');
|
||||
note.className = 'lb-why';
|
||||
note.textContent = ' — use the Multiplayer button; a table needs a server';
|
||||
row.querySelector('span')?.appendChild(note);
|
||||
}
|
||||
r.closest('label')?.classList.add('disabled');
|
||||
}
|
||||
r.onchange = () => {
|
||||
if (!r.checked) return;
|
||||
|
||||
Reference in New Issue
Block a user