diff --git a/src/game/game.ts b/src/game/game.ts index 32d87f3..543f9f9 100644 --- a/src/game/game.ts +++ b/src/game/game.ts @@ -98,8 +98,8 @@ export class Game { private demoMode = false; /** The Inspector's Shadow: the kitchen's words go dark; you cook by eye and ear. */ private shadowMode = false; - /** Rush hour: ticket one's verdict, parked on the pass while you cook two. */ - private rushFirst: { total: number; seconds: number } | null = null; + /** Rush hour: ticket one's total, parked on the pass while you cook two. */ + private rushFirst: number | null = null; private demoSnapshot: string | null = null; private rng = new Rng(20260716); private order!: Order; @@ -206,7 +206,7 @@ export class Game { this.beginDay(); return; } - if (this.rushFirst) { + if (this.rushFirst !== null) { // Ticket two of the rush: same day, different deal, the clock restarts // but the FIRST ticket's decay is measured by ticket two's service. this.beginDay(); @@ -650,7 +650,7 @@ export class Game { const dayRng = new Rng((day * 2654435761) >>> 0); // Ticket two of a rush re-deals the same day from a twisted seed — a // different order, deterministically, so reloads still can't scum it. - const rng2 = this.rushFirst ? new Rng(((day * 2654435761) ^ 0x9e3779b9) >>> 0) : dayRng; + const rng2 = this.rushFirst !== null ? new Rng(((day * 2654435761) ^ 0x9e3779b9) >>> 0) : dayRng; const o = day <= DAYS.length ? DAYS[day - 1] @@ -1014,6 +1014,28 @@ export class Game { extras.push('The starter is lively — the crumb held. (+0.2. She did that, not you.)'); } else if (gap >= 3 && toastDay) extras.push('The jar says nothing today. It is sulking, and the crumb knows.'); } + // RUSH HOUR (endless only): the day dealt TWO tickets. The first verdict + // goes on the pass — no streak, no book, no star, nothing written — and + // the second closes the pair. The first decays for every second it sat + // while you cooked. Only the PAIR reaches the streak, the regulars' + // book, the Shadow star and the ledger: one service, one line. + if (this.rushDay(this.order.day) && !this.dailyDate) { + if (this.rushFirst === null) { + this.rushFirst = v.total; + extras.push('Ticket one, on the pass. The second is already up — NEXT. Cook.'); + this.judgeView.extraLines = extras; + this.judgeView.shareText = ''; + return; // nothing is written until the pair closes + } + const passSec = this.orderSeconds; + const decay = Math.min(1.5, (passSec / 60) * 0.5); + const aAdj = Math.max(0, Math.round((this.rushFirst - decay) * 10) / 10); + extras.push(`Ticket one sat ${Math.round(passSec)}s on the pass: ${this.rushFirst.toFixed(1)} fell to ${aAdj.toFixed(1)}.`); + v.total = Math.round(((aAdj + v.total) / 2) * 10) / 10; + v.grade = gradeOf(v.total); + extras.push('Two tickets, one verdict — the rush is scored as a pair.'); + this.rushFirst = null; + } // The streak. He notices. He hates that he notices. const prev = this.save.streak ?? 0; if (v.grade === 'S') { @@ -1046,26 +1068,6 @@ export class Game { d[this.dailyDate] = Math.max(d[this.dailyDate] ?? 0, v.total); extras.push('The Daily. Same deal for everyone today — come back tomorrow.'); } - // RUSH HOUR (endless only): the day dealt TWO tickets. The first verdict - // goes on the pass; the second closes the pair — and the first decays for - // every second it sat there while you cooked. One combined line in the book. - if (this.rushDay(this.order.day) && !this.dailyDate) { - if (!this.rushFirst) { - this.rushFirst = { total: v.total, seconds: this.orderSeconds }; - extras.push('Ticket one, on the pass. The second is already up — NEXT. Cook.'); - this.judgeView.extraLines = extras; - this.judgeView.shareText = ''; - return; // nothing is written until the pair closes - } - const passSec = this.orderSeconds; - const decay = Math.min(1.5, (passSec / 60) * 0.5); - const aAdj = Math.max(0, Math.round((this.rushFirst.total - decay) * 10) / 10); - extras.push(`Ticket one sat ${Math.round(passSec)}s on the pass: ${this.rushFirst.total.toFixed(1)} fell to ${aAdj.toFixed(1)}.`); - v.total = Math.round(((aAdj + v.total) / 2) * 10) / 10; - v.grade = gradeOf(v.total); - extras.push('Two tickets, one verdict — the rush is scored as a pair.'); - this.rushFirst = null; - } this.judgeView.extraLines = extras; this.judgeView.shareText = this.shareLine(v); this.save.total += v.total; @@ -1086,7 +1088,7 @@ export class Game { el('div', 'ticket-day', this.ticketEl, `DAY ${o.day}`); el('div', 'ticket-who', this.ticketEl, o.who); if (o.day % 10 === 0 && !this.dailyDate) el('div', 'ticket-critic', this.ticketEl, 'THE CRITIC is in today. The flaw will be the headline.'); - if (this.rushDay(o.day) && !this.dailyDate) el('div', 'ticket-critic', this.ticketEl, this.rushFirst ? 'TICKET TWO — the first is dying on the pass.' : 'RUSH HOUR — two tickets on the rail. The first will wait for the second.'); + if (this.rushDay(o.day) && !this.dailyDate) el('div', 'ticket-critic', this.ticketEl, this.rushFirst !== null ? 'TICKET TWO — the first is dying on the pass.' : 'RUSH HOUR — two tickets on the rail. The first will wait for the second.'); const demos = (window as unknown as { __t?: { demos?: Record } }).__t?.demos; if (!this.demoMode && demos && demos[o.day]) { const watch = el('button', 'btn ghost watch-btn', this.ticketEl, '▶ watch him do it');