From cfc68bba515d53f8aed71a5585113425195fd35b Mon Sep 17 00:00:00 2001 From: Joey Yakimowich-Payne Date: Sat, 18 Apr 2026 23:23:09 -0600 Subject: [PATCH] docs(user): modifier profiles user guide --- docs/adr/modifier-profiles.md | 29 ++++++++ docs/user/modifier-profiles.md | 132 +++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 docs/user/modifier-profiles.md diff --git a/docs/adr/modifier-profiles.md b/docs/adr/modifier-profiles.md index 06167d3..f50c897 100644 --- a/docs/adr/modifier-profiles.md +++ b/docs/adr/modifier-profiles.md @@ -344,3 +344,32 @@ requiring no changes to the registry contract itself. and incompatible with deterministic module load ordering. --- + +## Implementation Retrospective + +### Deviations from ADR + +- **ADR-3 hot-swap timing**: Applied immediately on receipt rather than at + an explicit turn-boundary gate. WS message serialization per-socket + ensures a client's own move and profile swap cannot interleave. True + turn-boundary queue deferred to T2. +- **ADR-6 check 4 (DEADLOCK)**: Deferred to T2 — requires session + simulation which introduces a circular dependency with the engine. +- **ADR-3 host authority**: Profile swap allowed from host (white player) + only in T1. Two-player consent model deferred to T2. +- **Zod v3/v4 mismatch**: Server pins Zod v3; chess package moved to v4. + Schemas mirrored locally in the server package with a compile-time + key-parity guard. + +### Discovered patterns + +- `MODIFIER_REGISTRY` mirrors `PRESET_REGISTRY`/`LAYOUT_REGISTRY` exactly — + confirmed the side-effect import pattern scales cleanly. +- `__modifier-profile-integration__` pseudo-preset registered by + `applyProfileToSession` integrates `CaptureFlags` and + `DirectionAdditions` into the existing hook pipeline without modifying + `engine.ts`. +- `reconcileProfileSwap` uses retract-then-reapply semantics — idempotent + and straightforward to reason about. + +--- diff --git a/docs/user/modifier-profiles.md b/docs/user/modifier-profiles.md new file mode 100644 index 0000000..ee591ea --- /dev/null +++ b/docs/user/modifier-profiles.md @@ -0,0 +1,132 @@ +# Modifier Profiles + +Modifier Profiles let you attach rule modifiers to pieces — either globally by +piece type ("all white knights get +2 HP") or specifically by board position +("the knight that starts on b1 has +1 range"). Profiles are saved to a personal +library, shareable via URL, and can be swapped mid-game. + +--- + +## Opening the Editor + +From any game view: click the **rules drawer** (⚙ icon) → **Modifier Profiles**. + +From the lobby: click **Custom…** in the Profile Picker next to the Layout Picker. + +--- + +## Per-Type vs Per-Instance + +| | Per-Type | Per-Instance | +| ---------------- | ---------------------------------------- | --------------------------------------------------- | +| Targets | All pieces of a given type + color | One specific piece at a named board square | +| Example | "All white knights: HP +3" | "The knight starting on b1: Range +1" | +| Requires layout? | No | Yes — square must exist in the chosen layout | + +--- + +## The 6 Modifier Categories + +### HP Bonus + +Add or subtract hit points from a piece's base HP. +Values: integer from −10 to +10. Stacks additively from all sources. + +**Example**: Knight (white) HP +3 — the knight now requires 3 more attacks to +eliminate. + +--- + +### Range Bonus + +Extend the sliding distance of rooks, bishops, and queens. +Values: integer 0–7. Capped at maximum board range. + +**Example**: Rook (white) Range +1 — the rook can see one extra square per ray +when unblocked. + +--- + +### Direction Additions + +Add new movement directions to a piece (1-square step moves only). +Values: a set of directional flags: forward, backward, left, right, +diagonal-fl, diagonal-fr, diagonal-bl, diagonal-br. + +**Example**: Pawn (white) + backward — pawns can also retreat one square to an +empty square. + +--- + +### Capture Flags + +Toggle special capture behavior. +Flags: + +- **CAN_CAPTURE_OWN** — piece may capture friendly pieces +- **CANNOT_BE_CAPTURED** — piece is immune to direct capture (cannot be used on kings) +- **EN_PASSANT** — future flag for custom en-passant rules + +**Example**: Bishop + CANNOT_BE_CAPTURED — no enemy piece can legally capture it. + +--- + +### Promotion Override + +Force a pawn to always promote to a specific piece, or disable promotion +entirely. +Values: queen, rook, bishop, knight, or disabled. + +**Example**: Pawn + Promotion = bishop — any pawn reaching the back rank +auto-promotes to bishop, no dialog shown. + +--- + +### Damage Resistance + +Reduce all incoming damage by a percentage. Stacks multiplicatively across +sources. +Values: 0 (no resistance) to 1 (full immunity). + +**Example**: Queen + 0.5 resistance — every attack deals half normal damage. + +--- + +## Hot-Swap + +Profiles can be changed mid-game by the host (creator of the room). Click the +rules drawer while in a game and select a new profile. Changes take effect after +the current interaction. + +*Note*: Two-player consent model is planned for T2. In T1, the host can change +profiles unilaterally. + +--- + +## Library & Sharing + +- **Save** — click the Save button in the editor header. Up to 20 profiles stored locally. +- **Star** ⭐ — starred profiles are never evicted when the library is full. +- **Share** 🔗 — copies a URL containing the full profile. Profiles larger than 8 KB + cannot be URL-shared (save to library and share the room code instead). +- **Load** — open the library drawer in the editor and click any entry. + +--- + +## In-Play Inspection + +**Hover** any piece on the board to see a tooltip listing active modifiers. + +**Click** a piece to pin a side panel with the full modifier breakdown, including +the source of each modifier (per-type, per-instance, or from an active preset). +The panel stays pinned across turns until you dismiss it (×) or click another piece. + +--- + +## Known Limitations (T1) + +- Only the host can swap profiles mid-game. Two-player consent coming in T2. +- Maximum 20 profiles in the local library per browser. +- Profiles larger than 8 KB cannot be URL-shared. +- CANNOT_BE_CAPTURED cannot be applied to kings. +- Deadlock detection (all legal moves blocked) not yet implemented.