diff --git a/fktry/src/screen/boredom.test.ts b/fktry/src/screen/boredom.test.ts index 5832f53..861e88e 100644 --- a/fktry/src/screen/boredom.test.ts +++ b/fktry/src/screen/boredom.test.ts @@ -45,3 +45,35 @@ describe('boredom decays the display, slowly', () => { expect(freshness(-10)).toBe(1); }); }); + +describe('jammed-rot: stuck work spoils faster than resting work', () => { + const IDLE = BOREDOM_GRACE_SECONDS + 60; + + it('leaves a clean idle exactly as gentle as before', () => { + // rot defaults to 0, so round 4 behaviour is untouched for a player who walked away. + expect(freshness(IDLE, 0)).toBe(freshness(IDLE)); + }); + + it('forgets faster the more of the factory is jammed', () => { + const clean = freshness(IDLE, 0); + const half = freshness(IDLE, 0.5); + const solid = freshness(IDLE, 1); + expect(half).toBeLessThan(clean); + expect(solid).toBeLessThan(half); + }); + + it('still gives a fully jammed factory a grace window', () => { + // Even total gridlock should not punish instantly — a jam you fix in a few seconds is free. + expect(freshness(10, 1)).toBe(1); + }); + + it('makes a wholly-stuck line sag in tens of seconds, not minutes', () => { + expect(freshness(90, 1)).toBeLessThan(0.5); + expect(freshness(90, 0)).toBeGreaterThan(0.8); // ...while a clean idle has barely moved + }); + + it('clamps nonsense rot values instead of inverting the curve', () => { + expect(freshness(IDLE, -5)).toBe(freshness(IDLE, 0)); + expect(freshness(IDLE, 99)).toBe(freshness(IDLE, 1)); + }); +}); diff --git a/fktry/src/screen/boredom.ts b/fktry/src/screen/boredom.ts index 9720560..da56e27 100644 --- a/fktry/src/screen/boredom.ts +++ b/fktry/src/screen/boredom.ts @@ -20,8 +20,18 @@ const clamp01 = (x: number) => Math.min(1, Math.max(0, x)); /** * How much of the ledger's corruption is still on display, 0..1. * 1 = everything you earned is showing; 0 = the sky has forgotten (the tallies have not). + * + * `rot` (round 5 jammed-rot) accelerates forgetting. A CLEAN idle — the player walked away — + * decays at the base rate. A factory JAMMED SOLID rots faster: the work isn't resting, it's + * spoiling, and the sky should say so. rot 0 = clean idle; rot 1 = everything jammed. */ -export function freshness(idleSeconds: number): number { +export function freshness(idleSeconds: number, rot = 0): number { if (!(idleSeconds > BOREDOM_GRACE_SECONDS)) return 1; // NaN-safe: unknown idle reads as fresh - return 1 - clamp01((idleSeconds - BOREDOM_GRACE_SECONDS) / BOREDOM_HORIZON_SECONDS); + // A jammed factory shortens the grace and steepens the decay. At full rot the horizon is + // roughly a third, so a wholly-stuck line visibly sags in tens of seconds, not minutes. + const r = clamp01(rot); + const grace = BOREDOM_GRACE_SECONDS * (1 - 0.5 * r); + const horizon = BOREDOM_HORIZON_SECONDS * (1 - 0.66 * r); + if (idleSeconds <= grace) return 1; + return 1 - clamp01((idleSeconds - grace) / horizon); }