docs: fix guard condition and add reviewer feedback to nap spec

Fix inverted guard logic (napTarget < 60 triggers full sleep, not >=),
add cycleTicks derivation, clamp napTarget to 100, add test plan.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-11 02:57:54 +00:00
parent f0b8fea4f1
commit 37d5ce96d6

View File

@@ -11,28 +11,32 @@ When sleeping during daytime, treat it as a **nap**: calculate just enough energ
## Nap Target Calculation
```
cycleTicks = Math.round((100 / ENERGY_DECAY_PER_TICK) * (1 + 1 / DAY_NIGHT_RATIO))
remainingDayTicks = (SLEEP_NIGHT_START - gameTime) * cycleTicks
energyNeeded = remainingDayTicks * ENERGY_DECAY_PER_TICK * constitutionMultiplier
napTarget = ENERGY_THRESHOLD + energyNeeded + NAP_BUFFER
napTarget = clamp(ENERGY_THRESHOLD + energyNeeded + NAP_BUFFER, 0, 100)
```
- `NAP_BUFFER`: ~15 energy. NPCs arrive at nightfall around 35 energy — above the 20 emergency threshold, below the 60 voluntary night sleep threshold.
- `constitutionMultiplier`: `1 - (con - 10) * 0.03` (same formula used in needsDecaySystem).
- `cycleTicks`: derived from runtime constants (`ENERGY_DECAY_PER_TICK`, `DAY_NIGHT_RATIO`), both available via `rc` in npcBrainSystem.
- `NAP_BUFFER`: 15 energy. NPCs arrive at nightfall around 35 energy — above the 20 emergency threshold, below the 60 voluntary night sleep threshold.
- `constitutionMultiplier`: `1 - (con - 10) * 0.03` (same formula used in needsDecaySystem). Uses point-in-time CON; transient stat modifiers may shift this slightly, which is acceptable.
- `energyNeeded` represents the **post-wake awake energy budget** — how much the NPC will burn while awake between nap and nightfall.
- Note: for early-morning crashes (gameTime ~0.1-0.3), napTarget approaches 85-100 and the nap is effectively identical to full sleep. The nap diverges meaningfully for afternoon crashes.
## Wake Logic
In the sleep wake check (npcBrainSystem.ts):
1. Determine if this is a **daytime sleep** (gameTime < SLEEP_NIGHT_START).
2. Calculate nap target.
3. **Guard**: if napTarget >= SLEEP_VOLUNTARY_ENERGY_THRESHOLD (60), treat as normal full sleep (too close to nightfall for a nap to matter — avoid wake-then-immediately-re-sleep).
4. **Daytime nap**: wake immediately when energy >= napTarget (clean cutoff, no probabilistic ramp).
1. Check if it is currently daytime (gameTime < SLEEP_NIGHT_START). This check happens every tick during sleep, not just at entry.
2. If daytime: calculate nap target.
3. **Guard**: if napTarget < SLEEP_VOLUNTARY_ENERGY_THRESHOLD (60), the NPC is so close to nightfall that a nap would leave them with too little energy — they'd wake and immediately re-trigger voluntary night sleep. Skip the nap; use normal full sleep instead.
4. **Daytime nap**: if napTarget >= 60, wake immediately when energy >= napTarget (clean cutoff, no probabilistic ramp).
5. **Night or guarded**: use existing probabilistic wake (85-100 range).
## Edge Cases
- **Night arrives while napping**: switch to normal night sleep wake logic (85-100 probabilistic). The NPC was exhausted enough to sleep into night — that's fine.
- **Close to nightfall**: napTarget would be low (~25-30), which is below 60, so the guard triggers normal full sleep. No silly wake-then-re-sleep.
- **Close to nightfall**: napTarget would be low (~25-30), which is below the 60 guard threshold, so it falls through to normal full sleep. No silly wake-then-re-sleep.
- **Constitution variation**: high-CON NPCs decay slower, so shorter naps. Low-CON NPCs need more banked energy, so longer naps. Natural.
## Recovery Rate
@@ -49,6 +53,14 @@ Same as normal sleep (0.048/tick). No change. A nap is just a shorter sleep.
- `shared/src/constants.ts` — add NAP_BUFFER
- `server/src/systems/npcBrainSystem.ts` — modify sleep wake logic
## Tests
- Nap target calculation at various times of day (morning, midday, afternoon)
- Wake behavior: immediate wake at nap target (no probabilistic ramp)
- Guard condition: napTarget < 60 triggers full sleep instead of nap
- Edge case: night arrives during nap → switches to normal wake logic
- Edge case: napTarget clamped to 100 for very early crashes
## What Stays the Same
- Sleep entry conditions (emergency < 20, voluntary night < 60)