Rule the pyrrhic win: WIN = hp >= 50, corners priced not gated (SPRINT9 dec 1)
The garden is the client's. The sail is yours. Saving the bed with a rig that tore itself apart is the job done expensively — not a failure. DESIGN.md doesn't call a cascade a loss, it calls it "a firework you paid for", and *paid for* is the point: the aftermath already bills the broken hardware, the collateral, and a week's fee you didn't earn cleanly. Gating the win on corners bills you twice for one night and then lies about it — the same species as the verdict that used to tell a 4/4 hold they'd skimped. B and D arrived here independently with the numbers, and B checked what it does NOT break: cheap rigs still lose (4x carabiner -> hp 38), rigs that miss the bed still lose (hp 36), $80 still cannot buy immunity. C's exhaustive sweep found the only winnable $80 line on the wild night lands exactly here — hp 52, 1 lost. The pyrrhic ending gets its own verdict, and it had to be checked FIRST: `lost >= 2` was unconditionally a cascade-and-a-loss, and under the new rule it can be the best night the game has. Two asserts pin both halves — garden saved + sail destroyed is a win that still names the weakest link; the same wreck WITHOUT the garden is still a plain cascade, because the garden is the whole job. Selftest 276 pass / 0 fail (Lane A 32 -> 34). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
62005c8fd1
commit
391722970a
@ -146,7 +146,17 @@ export function verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped }) {
|
||||
const named = worst ? `${worst.hw.name} at ${worst.anchorId.toUpperCase()}` : '';
|
||||
const hailKilled = dmg.hail > dmg.rain;
|
||||
|
||||
if (lost.length >= 2) {
|
||||
// SPRINT9 decision 1. This case had to come FIRST because it did not used to
|
||||
// exist: `lost >= 2` was unconditionally a cascade-and-a-loss, and under the
|
||||
// new rule it can be the best night the game has. A sail that tore itself
|
||||
// apart while the bed came through is DESIGN.md's actual story — the firework
|
||||
// you paid for — and the aftermath's hardware bill is where that payment goes.
|
||||
if (win && lost.length >= 2) {
|
||||
return { mode: 'pyrrhic',
|
||||
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.` };
|
||||
}
|
||||
if (!win && lost.length >= 2) {
|
||||
return { mode: 'cascade',
|
||||
verdict: `THE SAIL LOST. The ${named} went first — and took ${lost.length - 1} more with it.` };
|
||||
}
|
||||
@ -533,7 +543,25 @@ export async function boot(opts = {}) {
|
||||
if (lost.length >= 2) collateral.push({ what: 'garden gnome', cost: world.gnome.collateralValue });
|
||||
const s = rigging.summary;
|
||||
const hp = garden.hp;
|
||||
const win = hp >= 50 && lost.length < 2;
|
||||
/**
|
||||
* SPRINT9 decision 1 — Lane A's ruling on the pyrrhic win. It was
|
||||
* `hp >= 50 && lost.length < 2`; the corner clause is gone.
|
||||
*
|
||||
* **The garden is the client's. The sail is yours.** Saving the bed with a
|
||||
* rig that tore itself apart is the job done expensively — not a failure.
|
||||
* DESIGN.md doesn't call a cascade a loss, it calls it "a firework you paid
|
||||
* for", and *paid for* is the whole point: the aftermath already bills you
|
||||
* for the broken hardware, the collateral, and a week's fee you didn't earn
|
||||
* cleanly. Gating the win on corners bills you twice for the same night and
|
||||
* then lies about it — which is the same species as the verdict that used to
|
||||
* tell a 4/4 hold they'd skimped.
|
||||
*
|
||||
* B and D both arrived here independently with the numbers, and B checked
|
||||
* what it does NOT break: cheap rigs still lose (4× carabiner → hp 38), rigs
|
||||
* that miss the bed still lose (hp 36), and $80 still cannot buy immunity.
|
||||
* The corners are priced, not gated.
|
||||
*/
|
||||
const win = hp >= 50;
|
||||
const dmg = garden.damage;
|
||||
const { verdict, mode } = verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped });
|
||||
|
||||
|
||||
@ -194,6 +194,35 @@ export default async function run(t) {
|
||||
`verdict should credit the corners that held: "${heldAll.verdict}"`);
|
||||
});
|
||||
|
||||
t.test('the pyrrhic win: a sail that dies saving the garden is a WIN', () => {
|
||||
// SPRINT9 decision 1, Lane A's ruling. The garden is the client's; the sail
|
||||
// is yours. This night used to score as a flat LOSS, which was the repo's
|
||||
// longest-running dead end — C measured the only $80 line on the wild night
|
||||
// and it lands here.
|
||||
const carabiner = { anchorId: 'p1', hw: { name: 'carabiner', rating: 1200, cost: 5 } };
|
||||
const shackle = { anchorId: 'p3', hw: { name: 'shackle', rating: 3200, cost: 15 } };
|
||||
const v = verdictFor({
|
||||
hp: 52, lost: [shackle, carabiner], win: true,
|
||||
dmg: { hail: 40, rain: 8 }, pondPeak: 0, pondDumped: 0,
|
||||
});
|
||||
assertEq(v.mode, 'pyrrhic', 'garden saved + sail destroyed is its own ending, not a cascade');
|
||||
assert(/GARDEN MADE IT/.test(v.verdict), `it is a win and must read as one: "${v.verdict}"`);
|
||||
assert(/carabiner at P1/.test(v.verdict), 'and still names the weakest link that went first');
|
||||
});
|
||||
|
||||
t.test('the same wreck WITHOUT the garden is still a plain cascade', () => {
|
||||
// The other half of the ruling: corners are priced, not gated — but the
|
||||
// garden is still the whole job. Lose it and two corners and you lost.
|
||||
const carabiner = { anchorId: 'p1', hw: { name: 'carabiner', rating: 1200, cost: 5 } };
|
||||
const shackle = { anchorId: 'p3', hw: { name: 'shackle', rating: 3200, cost: 15 } };
|
||||
const v = verdictFor({
|
||||
hp: 20, lost: [shackle, carabiner], win: false,
|
||||
dmg: { hail: 70, rain: 10 }, pondPeak: 0, pondDumped: 0,
|
||||
});
|
||||
assertEq(v.mode, 'cascade');
|
||||
assert(/SAIL LOST/.test(v.verdict), `no garden, no win: "${v.verdict}"`);
|
||||
});
|
||||
|
||||
t.test('verdict names the weakest link that actually let go', () => {
|
||||
// "…the shackle. I knew about the shackle." The whole point is that the
|
||||
// player recognises the corner they gambled on.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user