From abec3946be10bfa79af3300b4876afefb34b0451 Mon Sep 17 00:00:00 2001 From: salmonik Date: Sat, 11 Jul 2026 01:41:50 +0200 Subject: we have plans --- docs/PLAN.md | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 docs/PLAN.md (limited to 'docs/PLAN.md') diff --git a/docs/PLAN.md b/docs/PLAN.md new file mode 100644 index 0000000..a071efe --- /dev/null +++ b/docs/PLAN.md @@ -0,0 +1,308 @@ +# Implementation Plan — Dungeon Crawler + +## Overview + +Transform the existing ray-casting maze game into a turn-based first-person dungeon crawler with infinite depth, resource management (HP / Sanity / Weakness), psychedelic horror effects, and an inventory system. + +See `CONTEXT.md` for the canonical glossary of domain terms. + +--- + +## Phase 0 — Turn-Based Game Loop + +Refactor the real-time loop into a turn-based model with smooth animations. + +### 0.1 — Game state machine +Introduce a `GameState` enum: +- `WaitingForInput` — player can press keys +- `AnimatingPlayer` — player walk/turn animation playing +- `AnimatingEnemies` — enemy movement animations playing (simultaneous, 100ms) +- `ResolvingTurn` — apply damage, weakness, sanity, pickups +- `GameOver` — fade-out and exit + +### 0.2 — Input gating +- Only accept input in `WaitingForInput`. +- On valid input → `AnimatingPlayer` (or `AnimatingEnemies` if skipping via C). +- After all animations → `ResolvingTurn` → back to `WaitingForInput`. +- C key skips turn (passes) — enemies still act. + +### 0.3 — Key bindings +| Key | Action | +|-----|--------| +| W | Move forward | +| S | Move backward | +| A | Strafe left | +| D | Strafe right | +| Q | Turn 90° left | +| E | Turn 90° right | +| Space | Attack cell ahead | +| Z | Use selected inventory item | +| X | Discard selected inventory item | +| C | Skip turn | +| 1-4 | Select inventory slot | +| Esc | Quit | + +--- + +## Phase 1 — Rooms-and-Corridors Maze Generation + +Replace the recursive-backtracker (1-tile-wide corridors) with a rooms-and-corridors generator. + +### 1.1 — Generation algorithm +1. Place random rectangular rooms (3×3 to 6×6) on the grid, non-overlapping. +2. Connect rooms with 1–2 tile wide corridors using a minimum spanning tree or BFS carving. +3. Ensure all rooms are reachable. +4. Place the player start in a room near top-left. +5. Place the exit staircase in a room far from start. +6. Maze size scales with depth (16×16 rooms → 33×33 cells at depth 1, up to 28×28 rooms → 57×57 cells at depth 13+). + +### 1.2 — Exit cell +- Exit is a passage cell with a special floor texture (tile with a hole). +- Walking onto it shows "Press Space to descend..." +- Pressing Space generates a new depth, places player in a different room facing east. + +--- + +## Phase 2 — Entity System + +Pre-place entities (enemies, hallucinations, pickups) in maze cells at generation time. + +### 2.1 — Entity types +```rust +enum Entity { + Enemy { hp: u32, max_hp: u32, damage: u32 }, + Hallucination { persistent: bool }, + Pickup(PickupType), + HallucinatedPickup(PickupType), +} +``` + +### 2.2 — Generation +- **One entity per cell** — a cell is either empty or contains one entity. +- Real enemies: 3–5 at depth 1, +2 per depth. +- Hallucinations: 1–2 per level (regardless of depth). Their *behavior* scales with sanity, not their quantity. +- Real pickups: 2–3 at depth 1, +1 per 2 depths. Mixed types (food, pill, bandage, weapon). +- Hallucinated pickups: 0–1 at depth 1, +1 per 2 depths. +- Weapons: 0–1, guaranteed at depths 2, 4, 6, etc. + +### 2.3 — Enemy stat scaling +| Depth tier | Enemy HP range | Enemy damage | +|------------|---------------|-------------| +| 1 | 1 | 1 | +| 2–3 | 2–3 | 1 | +| 4–6 | 3–5 | 1–2 | +| 7–9 | 5–8 | 2 | +| 10+ | 8+ | 2+ | + +--- + +## Phase 3 — Combat System + +### 3.1 — Attack action (Space) +- Checks the cell directly ahead (based on facing direction). +- If an enemy/hallucination is present in that cell → apply attack. +- If nothing → "You swing at the air." No effect. + +### 3.2 — Hitting an enemy +- Deal `base_damage + bonus_damage` to the enemy. +- Bonus damage: 30% chance for +1, repeat on success (infinite chain, geometric distribution). +- If enemy HP ≤ 0 → enemy dies (removed from cell). +- Enemy retaliates if still alive: deals its damage to player HP. +- Screen flash: red tint. + +### 3.3 — Hitting a hallucination +- Non-persistent hallucination: vanishes, player loses sanity. +- Persistent hallucination (sanity < ~20%): does NOT vanish; player loses sanity. May take multiple attacks to dissipate. +- Screen flash: purple tint. + +### 3.4 — Moving onto a cell with an entity +- **Real enemy:** blocked. "Something is blocking your way." Player loses their turn; enemy attacks. +- **Hallucination (non-persistent):** vanishes harmlessly — no sanity cost. +- **Persistent hallucination:** blocked. "You are frightened to death just by thinking about doing this." Turn wasted. +- **Pickup:** auto-collected into inventory. +- **Hallucinated pickup:** auto-collected into inventory (deception discovered on use). + +### 3.5 — Weapon system +- Player always has an equipped weapon (starts with fists: base damage 1). +- Picking up a weapon (`!`) auto-equips if its base damage is higher. +- If base damage ≤ current weapon, display message and discard it. +- Weapons cannot be manually discarded. +- Hallucinated weapon: nothing happens on pickup, sanity drops slightly. +- HUD displays `WPN:{base_damage}`. + +--- + +## Phase 4 — Resource System + +### 4.1 — Resources +| Resource | Start | Max | At 0 | +|----------|-------|-----|------| +| HP | 5 | 5 | Death | +| Sanity | 100 | 100 | Severe distortion, persistent hallucinations | +| Weakness | 0 | 100 | HP starts draining | + +### 4.2 — Per-turn effects +- Weakness +1 every turn (passive hunger). +- If weakness hits 100, HP drains at 1/turn. +- Heartbeat counter increments by 1 each turn. + +### 4.3 — Pickup effects +| Type | Char | Real effect | Hallucinated effect | +|------|------|------------|-------------------| +| Food | `F` | -20 weakness | No effect. Sanity -5. "It was never there..." | +| Pill | `0` | -15 weakness, +20 sanity | No effect. Sanity -5. | +| Bandage | `+` | -15 weakness, +1 HP (if HP < max) | No effect. Sanity -5. | + +### 4.4 — Healing feedback +- Screen flash: green tint on successful heal. + +--- + +## Phase 5 — Inventory System + +### 5.1 — Slots +- 4 inventory slots. +- Pickups auto-collect into the first empty slot. +- If full, message "Inventory full" — pickup stays on the ground. + +### 5.2 — Controls +- `1`–`4`: select slot. +- `Z`: use selected item (consumes a turn). +- `X`: discard selected item (does NOT consume a turn). Item disappears forever. + +### 5.3 — Hallucinated pickups in inventory +- Look identical to real pickups. +- Using one: no effect, sanity -5, message "It was never there..." +- The item is consumed (removed from inventory) on use. + +--- + +## Phase 6 — Psychedelic Horror Effects + +### 6.1 — Sanity thresholds (smooth interpolation) +| Sanity | Visual effects | Semi-physical effects | +|--------|---------------|---------------------| +| 100–80% | Clean | None | +| 79–60% | Mild color drift, wall breathing | 5% phantom wall/passage | +| 59–40% | Stronger distortion, flickering textures | 10% phantom, maze shifts 5%/turn | +| 39–20% | Heavy warping, false `@` flickers | 15% phantom, shifting 10%/turn, hallucinations patrol | +| 19–0% | Severe distortion | 20% phantom, shifting 15%/turn, persistent hallucinations | + +### 6.2 — Phantom walls (A) +- Render a wall where a passage exists. +- Player can walk through it — discovers it was fake. +- Randomly placed each frame; frequency scales with sanity threshold. + +### 6.3 — Phantom passages (B) +- Render a passage where a wall exists. +- Player tries to move forward → blocked (invisible wall). +- Disorienting but doesn't trap the player. + +### 6.4 — Shifting maze (D) +- On turn resolution, sanity-based % chance that 1–3 wall cells outside player FOV flip (wall ↔ passage). +- Constraint: never block the exit, never fully enclose the player. +- Chance: 0% at depth 1–3, 5%/turn at 59–40% sanity, 10%/turn at 39–20%, 15%/turn at 19–0%. + +### 6.5 — Hallucination behavior scaling +- Depth 1–3: hallucinations static, easy to distinguish. +- Depth 4–6 + medium sanity: hallucinations start patrolling randomly (every 3 turns). +- Depth 7+ + low sanity: hallucinations move toward player, indistinguishable from real enemies. + +### 6.6 — Screen darkness +- Two factors multiplied: + 1. **Weakness dimming:** 0% (fresh) to ~80% (max weakness). + 2. **Depth dimming:** 0% (depth 1) to 80% (depth 15+). +- At depth 10 with high weakness, vision is severely restricted. + +--- + +## Phase 7 — Enemy AI + +### 7.1 — Real enemy behavior (per turn) +1. If adjacent to player → attack (deal damage). +2. If line-of-sight to player → move one tile toward player (reduce Manhattan distance). +3. If no LOS → patrol (every 3 turns): pick random adjacent passage and move there. +4. Hallucinations at low sanity follow the same behavior. + +### 7.2 — Enemy animation +- All enemies animate simultaneously (100ms duration). +- Smooth tile-walk animation matching player's style. + +--- + +## Phase 8 — HUD + +### 8.1 — Bottom bar (Doom-style) +``` +[♥ 3/5] [♦ SAN: 72%] [⌂ Weak: 45%] ♥♥ 42 WPN:2 [F][0][ ][+] DEPTH:7 +``` +- Hearts for HP, diamond for sanity, house for weakness. +- Heartbeat counter with heart symbol. +- Weapon display. +- 4 inventory slots showing item chars (empty = blank). +- Current depth number. + +### 8.2 — Message log +- Single line above or within the HUD bar. +- Displays the most recent message for 2–3 turns, then fades. +- Messages: attack results, item usage, blocked movement, hallucination encounters. + +### 8.3 — Entity sprites (ASCII) +| Entity | Char | Color | +|--------|------|-------| +| Enemy / Hallucination | `@` | Red | +| Food | `F` | Green | +| Pill | `0` | Cyan | +| Bandage | `+` | White | +| Weapon | `!` | Yellow | +| Exit | Floor texture (hole) | — | + +Rendered as scaled pixel-font sprites in the 3D view, line-of-sight only. + +--- + +## Phase 9 — Score & Death + +### 9.1 — Score formula +``` +Score = (Kills × 100) + (Final Depth² × 50) + (Weapon Base Damage × 500) +``` +- Calculated on death. Output to terminal. +- Values subject to tuning after playtesting. + +### 9.2 — Death sequence +1. HP hits 0. +2. Screen fades to black over ~2 seconds. +3. Message: "You had become yet another legend of this dungeon." +4. Score printed to terminal. +5. Game exits. + +--- + +## Phase 10 — Screen Flashes & Feedback + +| Event | Feedback | +|-------|----------| +| Player hits enemy | Red flash | +| Player hits hallucination | Purple flash | +| Player takes damage | Red flash + camera jolt | +| Successful heal | Green flash | +| Hallucination vanishes (walk-through) | Brief warp/distortion effect | +| Enemy dies | White flash, entity removed | + +--- + +## Implementation Strategy + +Build incrementally — one feature at a time: + +1. **Phase 0** — Turn-based loop (foundation for everything) +2. **Phase 1** — Rooms-and-corridors generation +3. **Phase 2 + 3 + 4** — Entities, combat, and resources (tightly coupled) +4. **Phase 5** — Inventory +5. **Phase 8** — HUD +6. **Phase 7** — Enemy AI + animations +7. **Phase 6** — Psychedelic effects +8. **Phase 9 + 10** — Score, death, polish + +Each phase must be testable independently before moving to the next. -- cgit v1.2.3