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, }; }