The pieces finally meet: procgen dungeons + the baked EoB atlas pipeline + the Vigor combat engine become one game. Three fixed pre-baked floors (seeds 7 → 69 → 59, 208 frames), monsters/loot/encounters rerolled per run and composited over the empty scenes; the Ember Sovereign waits at the bottom. - game-wasm: run state machine in Rust (manifest nav graph as dungeon truth, seeded spawning by theme/depth, embedded combat-core Encounter, vigor/fatigue persistence between fights, rest/potions/relics/flee, permadeath + victory). 8 native tests incl. a whole-run bot and a ScriptedPlayer boss-winnability probe used for tuning. - game-web: no-framework front-end — title/death/victory screens, baked frames with screen-blend monster portraits, combat overlay (dual vigor bars, cast telegraphs, cooldown sweeps, floaters), minimap with fog, all SFX synthesized in WebAudio. - balance: floor-scaled levels with a hero's edge over trash, no packs on floor 1, boss tuned by sim sweep (~35%/55% win at skill 50/80). - campaign atlases now versioned (tools/.gitignore exception); boss portrait added to the Z-Image roster. Verified end-to-end in-browser: an autopilot beat the full game through the real UI (10 fights, 2 flees, Sovereign down), and died plenty before that. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
60 lines
2.8 KiB
Markdown
60 lines
2.8 KiB
Markdown
# REIKHELM: DESCENT
|
||
|
||
A first-person dungeon-crawler roguelike, three floors deep. Eye of the Beholder
|
||
presentation over the reikhelm procgen + AI-render pipeline, with the Vigor
|
||
combined-pool combat system as the fight engine. Pure Rust→WASM + vanilla JS —
|
||
no game engine.
|
||
|
||
## Play
|
||
|
||
```bash
|
||
wasm-pack build game-wasm --target web --out-dir ../game-web/pkg --no-typescript
|
||
python3 tools/serve.py --root game-web --port 8001
|
||
# open http://127.0.0.1:8001
|
||
```
|
||
|
||
**Explore** `W/S` step · `A/D` turn · `R` rest (hold) · `G` drink draught ·
|
||
`T` drink tonic · `Enter` take the stairs
|
||
**Combat** `1–5` abilities · `Space` toggle auto-attack · `Tab` switch target ·
|
||
`F` flee (costs ceiling, the monsters remember)
|
||
|
||
## The shape of a run
|
||
|
||
- Three fixed floors (atlas seeds **7 → 69 → 59**), pre-baked to pixel art by
|
||
`tools/bake_atlas.py`; monsters, treasure, and loot reroll **per run** from the
|
||
fate seed. The baked scenes are empty ruins by design — inhabitants are
|
||
composited at runtime.
|
||
- Your **vigor pool is health, mana, and stamina at once** (the Vigor system,
|
||
see `combat/`). Damage and effort drain the same pool; fatigue lowers its
|
||
ceiling and persists **between** fights. Resting restores fill quickly and
|
||
fatigue slowly; tonics clear fatigue; relics widen the pool for the run.
|
||
- The deepest room of floor III holds **the Ember Sovereign**. Kill him to win.
|
||
Death is permanent.
|
||
|
||
## Architecture
|
||
|
||
```
|
||
game-wasm/ the whole game state machine (Rust, natively tested)
|
||
src/manifest.rs parses the baked atlas manifests (nav graph = source of truth)
|
||
src/spawn.rs seeded monster/treasure placement + balance constants
|
||
src/run.rs explore/combat/dead/victory state machine, persistence
|
||
src/views.rs one JSON payload per interaction; combat views match combat-web
|
||
src/monster_ai.rs the shared enemy brain
|
||
game-web/ thin browser view (no framework)
|
||
game.js input → wasm call → render from returned state
|
||
audio.js all SFX synthesized in WebAudio, zero assets
|
||
config.json the combat table: combat/configs/default.json + the boss
|
||
tools/out/atlas/<seed>/ the baked campaign art (committed; _work/ is not)
|
||
```
|
||
|
||
The dungeon geometry is read from the atlas **manifest**, never regenerated —
|
||
the graph the game walks is exactly the graph the baked frames depict.
|
||
|
||
## Balancing notes
|
||
|
||
- Tuned via `cargo test -p game-wasm -- --nocapture`: a whole-run bot plays the
|
||
real campaign headlessly, and a `ScriptedPlayer` probe sweeps boss win rates
|
||
(target: ~35% at skill 50, ~55% at skill 80, with potions/flee on top).
|
||
- Floor 1 spawns no packs; the wraith debuts on floor 2; player gains a level
|
||
per descent so trash stays beneath a hero's edge — depth pressure comes from
|
||
kits, packs, and fatigue attrition.
|