class_name Luck extends RefCounted ## Numeric Luck (charter §7). Lives in GameState; only descriptor() reaches the ## log. Deterministic given a seeded RNG (charter §10). Die/range/bands are ## TUNABLE constants — not final values. const MIN := 1 const MAX := 20 const DRIFT := 3 const BANDS := [ {"max": 4, "text": "Fortune spits on you"}, {"max": 8, "text": "The world is not on your side"}, {"max": 12, "text": "The dice are indifferent"}, {"max": 16, "text": "Luck rides with you"}, {"max": 20, "text": "The dice are kind today"}, ] static func roll_base(rng: RandomNumberGenerator, modifier: int) -> int: var total := 0 for i in 5: total += rng.randi_range(1, 20) return clampi(roundi(total / 5.0) + modifier, MIN, MAX) static func drift(current: int, base: int, delta: int) -> int: return clampi(clampi(current + delta, base - DRIFT, base + DRIFT), MIN, MAX) static func descriptor(luck: int) -> String: for band in BANDS: if luck <= band["max"]: return band["text"] return BANDS[-1]["text"]