Spaces:
Running
Running
| import type { Decision, EventDef, EventScores, FairyState, PuckMode } from "./types"; | |
| import { clamp } from "./util"; | |
| /** Personality bends the raw event scores before the decision bands see them. */ | |
| export function score(ev: EventDef, fs: FairyState): EventScores { | |
| const s = { ...ev.base }; | |
| // protectiveness raises the bar for annoyance; mischief lowers Puck's filter | |
| s.annoyance = clamp(s.annoyance + (fs.protectiveness - 50) * 0.25 - (fs.mischief - 50) * 0.15); | |
| s.interest = clamp(s.interest + (fs.curiosity - 50) * 0.2 + (fs.mischief - 50) * 0.15); | |
| s.relevance = clamp(s.relevance + (fs.protectiveness - 50) * 0.1); | |
| return s; | |
| } | |
| /** Decision bands → rungs of the interruption ladder. */ | |
| export function decide(s: EventScores): Decision { | |
| const worth = s.relevance + s.urgency + s.interest - s.annoyance; | |
| if (s.urgency >= 80 && s.relevance >= 80) return "interrupt"; | |
| if (s.relevance < 35 && s.annoyance > 60) return "ignore"; | |
| if (worth > 180) return "notify"; | |
| if (worth > 120) return "glow"; | |
| if (worth > 70) return "scroll"; | |
| return "ignore"; | |
| } | |
| /** Mode overrides applied after scoring + learned bias (mirrors applyBias). */ | |
| export function applyMode(decision: Decision, mode: PuckMode): Decision { | |
| if (mode === "silent" && (decision === "notify" || decision === "interrupt")) return "scroll"; | |
| if (mode === "goblin" && decision === "glow") return "notify"; | |
| return decision; | |
| } | |