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> |
||
|---|---|---|
| .. | ||
| portraits | ||
| audio.js | ||
| config.json | ||
| game.js | ||
| index.html | ||
| README.md | ||
| style.css | ||
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
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 aScriptedPlayerprobe 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.