import type { GameState, Patron, RegularMemory } from '../data/types'; // Regulars' grudge store. Behaviour wiring (disguises, dialogue callbacks) lands // in Phase 2/3 — this is just the persistent bookkeeping, run-scoped in GameState. /** Record a denial against a stable key (cast regularId — or any patron id). */ export function recordDenialBy(state: GameState, key: string, nightIndex: number): RegularMemory { const existing = state.regulars[key]; const mem: RegularMemory = existing ?? { patronId: key, timesDenied: 0, lastSeenNight: nightIndex, grudge: 0, }; mem.timesDenied += 1; mem.lastSeenNight = nightIndex; mem.grudge = Math.min(1, mem.grudge + 0.34); // three denials = maximum grudge state.regulars[key] = mem; return mem; } export function recordDenial(state: GameState, patron: Patron, nightIndex: number): RegularMemory { const existing = state.regulars[patron.id]; const mem: RegularMemory = existing ?? { patronId: patron.id, timesDenied: 0, lastSeenNight: nightIndex, grudge: 0, }; mem.timesDenied += 1; mem.lastSeenNight = nightIndex; mem.grudge = Math.min(1, mem.grudge + 0.34); // three denials = maximum grudge state.regulars[patron.id] = mem; return mem; } export function recordSeen(state: GameState, patronId: string, nightIndex: number): void { const mem = state.regulars[patronId]; if (mem) mem.lastSeenNight = nightIndex; } /** A regular with maxed grudge comes back disguised (bad fake moustache era). */ export function shouldReturnDisguised(state: GameState, patronId: string): boolean { const mem = state.regulars[patronId]; return !!mem && mem.timesDenied >= 2; } /** Same rule, straight off a memory record (spawn-time check in the queue). */ export function disguisedFromMemory(mem: RegularMemory | undefined): boolean { return !!mem && mem.timesDenied >= 2; }