reikhelm/combat/combat-web/README.md
Parley Hatch 902a233229 feat(combat): playable browser front-end + AI monster portraits
A real-time consumer of combat-core (the front-end the spec designs for, §14):
pick a foe, manage your single Vigor pool, try not to spend your survival.

- combat-core: a HumanController (input-driven, spec §5) behind a shared intent
  cell, plus Encounter::tick_once / drain_events so a wall-clock front-end can
  drive the engine a tick at a time (§10). Trivial abilities (difficulty 0, e.g.
  auto-attack) no longer fizzle. Engine unchanged otherwise; 48 tests still green.
- combat-wasm: a wasm-bindgen Game bridge — tick-stepping, JSON world state, the
  player's ability list, and a flavorful MonsterAI that uses each monster's
  signature kit (the wraith curses your ceiling) on a coin-flip so big hits space
  into a readable duel. Own workspace member, kept out of the default host build.
- combat-web: an atmospheric battler. The signature dual Vigor bar shows fill,
  the regen-headroom ceiling, the ceiling marker, and the dark cracked fatigue
  zone in one bar — the squeeze made legible. Floating damage, cast telegraphs,
  combat log, result overlay. Verified end-to-end in a real browser.
- tools/portraits.py: stdlib text-to-image client reusing the proven LAN Z-Image
  stack (minus the depth ControlNet) to render the bestiary. 7 portraits committed.
- Added skeleton / troll / wraith monster stat blocks; bumped the duelist's
  durability so fights are readable (even-con ~30s) and active play beats every
  monster while passive auto-attacking loses the hard ones. Re-validated the sim:
  the skill gradient and anti-turtle guardrail still hold (auto ~1% → skill100 34%
  at even con). README findings updated to match.

Verified live: roster screen, win/lose, the dual bars, telegraphed casts, and a
3s active-play victory over the Skeleton Knight.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 12:46:47 -06:00

47 lines
2.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Vigor — playable combat front-end
A browser battler that drives `combat-core` (via `combat-wasm`) in real time: pick
a foe, manage your single Vigor pool, and try not to spend your survival. The
engine is authoritative and unchanged — this is just a presentation layer and a
[`HumanController`] pushing your intent between ticks.
## What's here
- `index.html` / `style.css` / `game.js` — the UI (torch-lit dark fantasy).
- `portraits/` — AI-generated monster art (Z-Image on the LAN workstation; see
`../tools/portraits.py`). Committed so the game runs offline.
- `pkg/` — the wasm-bindgen output (gitignored; rebuild with the command below).
## Build & play
```sh
# 1. Build the wasm bridge into ./pkg (cargo on PATH; from combat/)
export PATH="$HOME/.cargo/bin:$PATH"
wasm-pack build combat-wasm --dev --target web \
--out-dir ../combat-web/pkg --out-name combat_wasm
# 2. Serve combat/ as the web root (so the page AND configs/ resolve)
python3 -m http.server 8013 --directory .
# 3. Open the game
open http://127.0.0.1:8013/combat-web/
```
(Re)generate portraits — needs the LAN ComfyUI / Z-Image server up:
```sh
python3 tools/portraits.py --url http://192.168.1.26:8188 --size 768
```
## How to play
- **Click a foe** to start. The fight runs in real time (10 ticks/second).
- **Auto-attack** is on by default (toggle with the AUTO button or `space`).
- **Abilities**: click a card or press `1``5`. Each shows its **fill cost**
spending fill lowers your **capacity**, so a big hit leaves you fragile.
- Watch the **dual bar**: bright = current fill, dim = regen headroom, the gold
line is your **ceiling** (`cap`), and the dark cracked zone on the right is
**fatigue** — ceiling lost for the rest of the fight. When the ceiling collapses
to your fill, the next hit overruns you (daze → KO).
- **Second Wind** restores ceiling; **Guard** opens a brief block window. Passive
auto-attacking beats the weak foes (Dire Rat, Skeleton); the Golem, Troll, and
Wraith want real play — recover, punish when they're spent, don't over-commit.
Difficulty is a table: edit `../configs/default.json` (monster stats, ability
numbers, the con curve) to taste — the same file the sim tunes against.