From 80b53e954791664096ef6efff0da163668bf144e Mon Sep 17 00:00:00 2001 From: type-two Date: Sat, 18 Jul 2026 14:11:58 +1000 Subject: [PATCH] =?UTF-8?q?Sprint=2013=20gate=201.4:=20NIGHT=205=20RULED?= =?UTF-8?q?=20=E2=80=94=20the=20garden=20is=20beyond=20saving=20BY=20DESIG?= =?UTF-8?q?N,=20and=20the=20verdict=20teaches=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - week.js night 5 carries gardenBeyondSaving: true with the measured case (bare 0.0, best buyable 27.7 vs WIN>=50 — B's game-true table, my probe agreeing) and the arc argument; nightAt defaults the flag FALSE so new nights can never inherit the excuse. Brief levels with the player up front. - verdictFor honours it on a LOSS only: no more 'the hail fell where your sail wasn't' on a night where no placement wins; a 4/4 hold is credited as the whole job, a torn sail is still named and owned. A win ignores the flag (a stale flag must never eat a real win). Asserted both ways + mutation notes. - GARDEN_DRAIN untouched, per the standing ruling; icenight hail budget also untouched — the loss is the design, so the surfaces now say so. --- web/world/js/main.js | 24 ++++++++++++++++++++++-- web/world/js/week.js | 21 ++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/web/world/js/main.js b/web/world/js/main.js index e183081..d33e73c 100644 --- a/web/world/js/main.js +++ b/web/world/js/main.js @@ -193,7 +193,7 @@ export function applyMute(sky, on) { * * @returns {{verdict: string, mode: string}} */ -export function verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped }) { +export function verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped, beyondSaving = false }) { // SPRINT12 — B's flag, actioned: "weakest link that went first" reduces on // the EFFECTIVE rating (rating × ratingHint), matching sail.js's failure // line and B's summary.weakest tie-break fix. On the bare rating a rated @@ -217,6 +217,25 @@ export function verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped }) { verdict: `THE GARDEN MADE IT. The sail didn't — the ${named} went first and took ` + `${lost.length - 1} more with it. That is what the sail was for.` }; } + // SPRINT13 gate 1.4 — A's night-5 ruling (week.js gardenBeyondSaving): on a + // night whose data says the garden cannot reach the win line at ANY price, + // every "you could have rigged better" sentence below is a lie, and the + // uncovered/rain modes are the worst liars — they blame placement on a night + // where no placement wins. This branch comes before every loss mode: the + // garden's fate was sealed at the forecast; only the STEEL's fate was the + // player's. Note it deliberately does NOT fire on a win — if a retune ever + // makes the flagged night winnable, the flag is stale and week.js says to + // delete it, not to trust this to paper over it. + if (!win && beyondSaving) { + if (lost.length >= 1) { + return { mode: 'beyond-saving', + verdict: `THE BED WAS BEYOND SAVING — no sail in the shop stops this much ice. ` + + `The ${named} letting go is the part that's on you.` }; + } + return { mode: 'beyond-saving', + verdict: 'THE BED WAS BEYOND SAVING — no sail in the shop stops this much ice. ' + + 'Yours held anyway. That was the whole job tonight, and you did it.' }; + } if (!win && lost.length >= 2) { return { mode: 'cascade', verdict: `THE SAIL LOST. The ${named} went first — and took ${lost.length - 1} more with it.` }; @@ -773,7 +792,8 @@ export async function boot(opts = {}) { */ const win = hp >= 50; const dmg = garden.damage; - const { verdict, mode } = verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped }); + const { verdict, mode } = verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped, + beyondSaving: week.job.gardenBeyondSaving }); return { hp, diff --git a/web/world/js/week.js b/web/world/js/week.js index 4d3d9d0..67007da 100644 --- a/web/world/js/week.js +++ b/web/world/js/week.js @@ -81,7 +81,23 @@ export const NIGHTS = [ storm: 'storm_02b_icenight', site: 'backyard_01', client: 'the Hendersons', addr: '14 Kurrajong St — the backyard', brief: 'Less wind than last night and more ice, which is worse for the bed and easier on the rig. ' - + 'Last night before they land.', + + 'Last night before they land. Nobody\'s pretending the seedlings ride this one out — keep ' + + 'the sail on its feet and the ice off the windows.', + // SPRINT13 gate 1.4 — A's ruling, DESIGN CANON: night 5's garden is BEYOND + // SAVING, by design, at any price. Measured game-true (B's pay table and + // A's probe, agreeing): bare bed 0.0 DEAD; best buyable garden 27.7; best + // clean 15.3 — every line in the game sits under WIN's hp >= 50, wallet or + // bank. The week's arc WANTS this: full / full / full, won-but-tattered + // (night 4, the pinned separation), then the night you cannot save — the + // icenight is where the job stops being about the bed and becomes about + // your steel (the line that would hold it needs $105 the shop caps at + // 3.20 kN shackles against 3.22/3.25 peaks — C's few-hundredths whisker, + // kept on purpose). This flag exists so surfaces TEACH the loss instead of + // implying a better rig existed: verdictFor reads it (main.js) and stops + // blaming placement; the brief above levels with the player before they + // spend a dollar. If a retune ever makes night 5 winnable, delete this + // flag in the same commit or the verdict lies in the other direction. + gardenBeyondSaving: true, }, ]; @@ -106,6 +122,9 @@ export function nightAt(i) { addr: base.addr ?? null, brief: base.brief ?? null, pay: base.pay ?? {}, + // False by default on purpose: a night is presumed savable unless its data + // says otherwise, so a new night can never inherit the icenight's excuse. + gardenBeyondSaving: base.gardenBeyondSaving ?? false, }; }