# 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// 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.