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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user