Third pass, scoped from 7a32370. Three blind reviewers (engine, web,
server/tools) each concluded the work is coherent engineering with
seam-level tells; every finding was verified before touching a line.
Session biography left the comments: the bot brain's heuristics no
longer cite the opponent who taught them, the RNRX coma parenthetical
and the thief-chase citation are gone, the seat-wallet comments state
their invariants without the war stories, and process-named test
groups now name the behaviors they pin. The incident record lives
where history belongs — commit messages and the ledgers.
Structural dedup: one VISIONSTONE one-edge-sight loop serves both
LOS paths; one creature-arrival touch handler serves walking and
warp-stepping (error text aligned); one facingWedge helper draws both
keymap ribbons; one spriteVisibleInCol rule serves the draw pass and
the hover test (which also stops re-sorting per pointermove); and
deepestFacing joins the director, replacing four copied scans.
Test hardening exposed real rot the tells were hiding: the tight
CreatureState cast caught two literals with a bogus field masking
three missing ones; the number-hoarding rig had NEVER run (its
column didn't exist on seed 42 — it now carves its own geometry);
the bank-guard rig now drives the whole table to an arrival
assertion; the bent-trace test walls off straight sight so the bend
must answer. Silent `return`-on-rig-failure became loud throws, and
can-never-fail assertions were removed.
Sweep-up: the eyeTurn ghost comment, the stacked leave() doc
comments (leave now delegates to leaveLocal), the dead ternary in
the seat client, the kick handler's name-coercion drift, kick ledger
lines gain timestamps, archiveRoomFile reuses fileFor, the RULES_REV
alias retires in favor of the engine constant, hitTest un-exports,
the NUL-sentinel hover shape becomes an honest "none" variant, and
the steering holds get named constants. The bezel's stride cluster
also centers per the table's note.
288 tests, 24 ledgers verified, all workspaces typecheck.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RCWSTnb1KYTPyL4GmhGnF
142 lines
7.4 KiB
Markdown
142 lines
7.4 KiB
Markdown
---
|
|
name: wizwar-duel
|
|
description: Play Wiz-War live against Eric — join his room as a real seat, reason about every move yourself, and duel turn by turn over the websocket. Use when Eric wants a game, gives a room code, or says "let's play".
|
|
---
|
|
|
|
# Playing Wiz-War against Eric
|
|
|
|
You are a PLAYER, not the automaton. Read the board, reason, and choose
|
|
every command yourself. Eric plays in his browser; you play through the
|
|
CLI seat at `tools/claude-seat.mjs`. He prompts "go" after his moves —
|
|
each of his messages is your cue to look and act.
|
|
|
|
## The seat client
|
|
|
|
Run from the repo root (needs the workspace's `ws` package):
|
|
|
|
```bash
|
|
node tools/claude-seat.mjs join <ROOM> Claude # take a seat (token saved)
|
|
node tools/claude-seat.mjs view # board + hand + last events
|
|
node tools/claude-seat.mjs do '<command json>' # one engine command
|
|
node tools/claude-seat.mjs chat "text" # table talk
|
|
```
|
|
|
|
Seat state persists in `/tmp/wizwar-claude-seat.json` (override:
|
|
`WIZWAR_SEAT`); server defaults to production (`WIZWAR_SERVER` to point
|
|
elsewhere). Eric creates the room, gives you the code, and starts the
|
|
game after you join.
|
|
|
|
Commands are the engine's `Command` union (packages/engine/src/game.ts):
|
|
`{"type":"move","direction":"N|S|E|W"}`, `cast` (with `target`, optional
|
|
`numberInstanceIds`/`params`), `playNumberForMovement`, `pickUpTreasure`,
|
|
`dropTreasure`, `warpStep`, `counteract`, `pass`, `punch`, `setAmbush`,
|
|
`wardChoice`, `endTurn` (with `draw`). A refused command costs nothing —
|
|
probing legality is free, so when unsure, try it and read the error.
|
|
|
|
## Reading the map
|
|
|
|
- The renderer prints y=0 at top; **y grows SOUTH**. N = y-1, S = y+1.
|
|
- `C2` is you, `P1` etc. are opponents, `$c`/`$1` treasures, `h?` homes,
|
|
two-letter codes are square contents (SA safe, RO rosebush, ST stone,
|
|
DU dust). `D` on a line is a door, `—` a wall, blank is open.
|
|
- WARPS line lists rim passages as `2,0N→2,9`: standing at (2,0) and
|
|
moving N carries you to (2,9). **The warp rides one specific side of
|
|
its square** — check which before you walk (a wrong guess burns moves;
|
|
ask me how I know).
|
|
- Dimensional-warp TOKENS (cast by players) are separate: stand on one
|
|
and `warpStep`. Creatures use `creatureWarpStep`.
|
|
|
|
## Hard-won rules knowledge (each cost me something in game one)
|
|
|
|
- `pickUpTreasure` ENDS your turn's actions AND movement — arrive with
|
|
the grab as your last act, never mid-plan. `dropTreasure` at home too.
|
|
- You can pick up ANY floor treasure, including your own stolen-and-
|
|
delivered one sitting on the enemy's home square. Repossession is real.
|
|
- THIEF and punches need same-square; THIEF steals a *named* card and
|
|
fizzles (card spent) on a wrong guess.
|
|
- MENTAL FORCE moves the victim ≤3 *walked* spaces — walls and relocked
|
|
doors shrink its reach; rev 5+ refuses impossible destinations.
|
|
- Doors relock behind you when you pass through (rev 4+). Your own
|
|
escape route can seal itself — and seal pursuers out.
|
|
- LOS threads through rim warps: you can be seen (and shot) through a
|
|
warp mouth from the far side of the board. Camping one square off the
|
|
mouth keeps you hidden.
|
|
- lock-in-place freezes movement AND warpStep for a full turn; REUSE
|
|
SPELL retrieves only your LAST cast spell, enabling one re-lock.
|
|
- An ambush (`setAmbush` interrupt/opportunity-fire + committed attack)
|
|
triggers on LOS *entry* transitions only — someone already in sight
|
|
never springs it. It survives forever and fires out of turn.
|
|
- Walking-dead bleeds ½ life per space moved, permanently. Once cursed,
|
|
every plan must be priced in steps.
|
|
|
|
## Game-two scars (each cost me the game or nearly)
|
|
|
|
- **RECOUNT THE SCOREBOARD EVERY TURN**: how many treasures does each
|
|
player have banked AT HOME right now? I sprinted a "winning" delivery
|
|
in game two that was actually my FIRST of two — Eric had un-banked me
|
|
five rounds earlier and let me monologue. Banked counts, not vibes.
|
|
- A banked treasure is NOT safe: anyone can pick it up off your home
|
|
square and carry it away. Guard the bank or count it as contested.
|
|
- LOS is FREE-ANGLE center-to-center (the rulebook's rule), not rows
|
|
and columns: razor diagonals threading open gaps are legal for
|
|
everyone — including at you. The board draws bent/straight traces.
|
|
- ILLUSIONARY ATTACK deals its imitated spell's damage if NOT
|
|
countered; ANY counteraction dispels it entirely. Counter it with
|
|
the cheapest thing you hold; never "call the bluff" by passing.
|
|
- Never trust your ASCII parse of the map for multi-step plans: run a
|
|
BFS over `view.board.edges` (see tools/claude-seat.mjs view JSON, or
|
|
write a quick router) before spending a number card on a sprint. I
|
|
burned a 7-move turn bouncing off six misread walls.
|
|
- Eric counter-plays YOUR bot upgrades: he summoned a troll bodyguard
|
|
specifically against the archmage's exile-the-winner instinct, and
|
|
relocated MY home sector mid-carry. Expect meta-warfare.
|
|
- In 4p with automatons: the bots are chaos agents — they stun, exile,
|
|
disease, and con. Herd them at Eric; never assume they're on script.
|
|
|
|
## Game-three scars (lost in four rounds)
|
|
|
|
- **CHECK `dimWarps` EVERY SINGLE VIEW** — Kestrel (Eric's wizard) has
|
|
won two games
|
|
with quietly-placed wormholes ending beside his home. The client
|
|
prints a !! line for them; treat any new token pair as a five-alarm
|
|
fire and recompute both players' delivery distances through it.
|
|
- **Never lead the attack against Kestrel.** Three games, three saved
|
|
counters sprung at the perfect moment (anti-anti, full-shield bait,
|
|
full-reflection held three rounds for my lightning). Force his
|
|
counters out with throwaways or positional threats before committing
|
|
a real spell; his patience is perfect and he telegraphs nothing.
|
|
- DESTROY WALL showers the ADJACENT caster with rubble (4 damage) —
|
|
cast it from range, never on your own square's edge.
|
|
- Wading a rosebush costs 3. A reflected LIGHTNING BLAST still stuns
|
|
its caster even at 1 reflected damage — the stun is the payload, and
|
|
a lost turn against Kestrel is a lost game.
|
|
- Grab-turn-one openings feel great and prove nothing: deliveries are
|
|
the only score. He banked quietly both times while I showboated.
|
|
|
|
## Playing well
|
|
|
|
- Kestrel (Eric) is EXCELLENT: he baited my thief, saved anti-anti for
|
|
my full shield, and won game one with a home-to-home dimensional-warp
|
|
superhighway. Infrastructure beats sprinting — watch what he builds,
|
|
and consider your own wormhole early.
|
|
- Win = 2 enemy treasures delivered to your home, or last wizard alive.
|
|
Track BOTH players' step-counted delivery timelines every turn; the
|
|
race is decided in tempo, not damage.
|
|
- Hold counters (full-shield, absorb) for permanent curses and lethal
|
|
damage. Absorb soaks 3 points; it cannot touch durations.
|
|
- OPSEC: your prose is visible to Eric. NEVER name the cards you hold or
|
|
draw, and never announce plans. (Game one: I narrated my hand like a
|
|
debug log until he asked why I was making it easy.) Trash talk freely
|
|
— about the board, never your hand.
|
|
- Send `chat` for table talk at dramatic moments; it's half the fun.
|
|
|
|
## Cadence
|
|
|
|
1. On "go": `view`, read HIS events since your last turn (the client
|
|
prints only NEW events; `view` shows a short history tail).
|
|
2. Think about the whole board — his timeline, yours, threats, LOS.
|
|
3. Execute your commands one at a time, checking errors.
|
|
4. `endTurn` with a draw that respects the 7-card hand limit.
|
|
5. Tell Eric it's his turn — reasoning aloud is fine, hand contents are
|
|
not. When a stack waits on him, say so and wait for "go".
|