legomaheggo Claude Opus 4.6 commited on
Commit
b24ad7d
Β·
1 Parent(s): 17a2f53

docs: Update architecture/UI docs and add new game mode template

Browse files

- ARCHITECTURE.md: Updated deployment section with dual remotes,
added audio caching and preference persistence to perf table
- CONTEXT_UI.md: Added Discovered Context with actual file structure,
JS audio caching architecture, asset naming conventions, auto-hold
pattern, and sidebar rules documentation
- NEW_GAME_MODE_TEMPLATE.md: Comprehensive template for defining new
game modes β€” covers rules, scoring, tiers, audio, UI patterns, and
integration checklist with a worked Peasant's Gamble example

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

docs/ARCHITECTURE.md CHANGED
@@ -250,34 +250,40 @@ To reduce perceived latency:
250
  ## 7. Deployment Architecture
251
 
252
  ```
253
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
254
- β”‚ Hugging Face Spaces β”‚
255
- β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
256
- β”‚ β”‚ Streamlit Application β”‚ β”‚
257
- β”‚ β”‚ (Free Tier) β”‚ β”‚
258
- β”‚ β”‚ - Serves UI β”‚ β”‚
259
- β”‚ β”‚ - Runs game engine β”‚ β”‚
260
- β”‚ β”‚ - Connects to Supabase β”‚ β”‚
261
- β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
262
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
263
- β”‚
264
- β”‚ HTTPS
265
- β–Ό
266
- β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
267
- β”‚ Supabase β”‚
268
- β”‚ (Free Tier) β”‚
269
- β”‚ - PostgreSQL database β”‚
270
- β”‚ - Realtime WebSocket channels β”‚
271
- β”‚ - Row Level Security β”‚
272
- β”‚ - 500MB storage limit β”‚
273
- β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
274
  ```
275
 
276
- ### Environment Variables (Hugging Face Secrets)
 
 
 
 
 
 
 
277
 
278
  ```
279
  SUPABASE_URL=https://xxx.supabase.co
280
- SUPABASE_ANON_KEY=eyJxxx...
281
  ```
282
 
283
  ---
@@ -292,6 +298,8 @@ SUPABASE_ANON_KEY=eyJxxx...
292
  | Database round-trips | Batch updates where possible |
293
  | Realtime subscription limits | One channel per lobby |
294
  | Animation performance | CSS animations over JS |
 
 
295
 
296
  ### Scaling Limits (Free Tier)
297
 
 
250
  ## 7. Deployment Architecture
251
 
252
  ```
253
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
254
+ β”‚ GitHub (source) β”‚ β”‚ Hugging Face Spaces β”‚
255
+ β”‚ origin/master β”‚ β”‚ hf/main (live app) β”‚
256
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
257
+ β”‚ git push origin master β”‚ git push hf master:main
258
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
259
+ β”‚
260
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
261
+ β”‚ Streamlit Application β”‚
262
+ β”‚ - Serves UI + game engine β”‚
263
+ β”‚ - JS-cached audio system β”‚
264
+ β”‚ - Connects to Supabase (HTTPS) β”‚
265
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
266
+ β”‚
267
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
268
+ β”‚ Supabase β”‚
269
+ β”‚ - PostgreSQL database β”‚
270
+ β”‚ - Realtime WebSocket channels β”‚
271
+ β”‚ - Row Level Security β”‚
272
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
 
273
  ```
274
 
275
+ ### Remotes
276
+
277
+ | Remote | URL | Branch |
278
+ |--------|-----|--------|
279
+ | `origin` | `https://github.com/legomaheggoz-source/DevilsDozen.git` | `master` |
280
+ | `hf` | `https://huggingface.co/spaces/legomaheggo/DevilsDozen` | push `master:main` |
281
+
282
+ ### Environment Variables (HF Spaces Secrets / `.env` locally)
283
 
284
  ```
285
  SUPABASE_URL=https://xxx.supabase.co
286
+ SUPABASE_ANON_KEY=sb_publishable_xxx...
287
  ```
288
 
289
  ---
 
298
  | Database round-trips | Batch updates where possible |
299
  | Realtime subscription limits | One channel per lobby |
300
  | Animation performance | CSS animations over JS |
301
+ | Audio data re-send on rerun | JS Audio caching in `window.parent` β€” base64 sent once, then tiny control commands |
302
+ | Widget prefs lost on `st.rerun()` | Non-widget session state keys (`_sfx_pref`, `_music_pref`, etc.) |
303
 
304
  ### Scaling Limits (Free Tier)
305
 
docs/CONTEXT_UI.md CHANGED
@@ -328,6 +328,61 @@ streamlit run src/ui/app.py
328
 
329
  ## Discovered Context
330
 
331
- > This section is updated during implementation. Check here before starting work.
332
 
333
- [Empty until implementation begins]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
 
329
  ## Discovered Context
330
 
331
+ > Updated Feb 2026 after full implementation and playtesting.
332
 
333
+ ### Actual File Structure
334
+
335
+ Pages live under `src/ui/views/` (not `src/ui/pages/`). Sound system is in `src/ui/themes/sounds.py`.
336
+
337
+ | File | Purpose |
338
+ |------|---------|
339
+ | `src/ui/app.py` | Entrypoint β€” routing, sidebar rules, sound system init |
340
+ | `src/ui/themes/sounds.py` | JS-cached audio system (SFX + music) |
341
+ | `src/ui/themes/animations.py` | CSS/HTML animation helpers |
342
+ | `src/ui/themes/medieval.css` | Full medieval theme CSS |
343
+ | `src/ui/components/dice_tray.py` | Dice display with hold/reroll buttons |
344
+ | `src/ui/components/scoreboard.py` | Player scores panel |
345
+ | `src/ui/components/turn_controls.py` | Roll / Bank / End Turn buttons |
346
+ | `src/ui/components/lobby.py` | Create / Join / Waiting room |
347
+ | `src/ui/views/home.py` | Home + lobby waiting page |
348
+ | `src/ui/views/game.py` | Main game loop with polling |
349
+ | `src/ui/views/results.py` | Victory screen + standings |
350
+
351
+ ### Audio System Architecture
352
+
353
+ The original approach injected base64 `<audio>` elements via `st.markdown` on every rerun, sending 5-8 MB per cycle. This was replaced with a JS-caching strategy:
354
+
355
+ 1. **First load per track**: base64 data sent via `st.components.v1.html(height=0)`, cached as `window.parent._dd_audio` JS Audio objects using **parent window's Audio constructor** (`new p.Audio(...)`) so objects survive iframe replacement.
356
+ 2. **Subsequent reruns**: Only tiny control commands (<1 KB) β€” play, pause, volume.
357
+ 3. **SFX**: Lazy-loaded on first trigger, cached as data URI strings in `window.parent._dd_audio.sfx`.
358
+ 4. **Preferences**: Stored in non-widget session state keys (`_sfx_pref`, `_music_pref`, `_sfx_volume`, `_music_volume`) that survive Streamlit's widget lifecycle cleanup during `st.rerun()`.
359
+
360
+ ### Audio Asset Naming Convention
361
+
362
+ | Type | Key | Filename | Size |
363
+ |------|-----|----------|------|
364
+ | SFX | `dice_roll` | `dice_roll.mp3` | 45 KB |
365
+ | SFX | `bust` | `bust.mp3` | 64 KB |
366
+ | SFX | `bank` | `bank.mp3` | 46 KB |
367
+ | SFX | `hot_dice` | `hot_dice.mp3` | 58 KB |
368
+ | SFX | `victory` | `victory.mp3` | 327 KB |
369
+ | SFX | `tier_advance` | `tier_advance.mp3` | 59 KB |
370
+ | Music | `menu` | `menu_theme.mp3` | 4.3 MB |
371
+ | Music | `peasants_gamble` | `d6_theme.mp3` | 6.5 MB |
372
+ | Music | `alchemists_ascent` | `d20_theme.mp3` | 4.9 MB |
373
+
374
+ To add new audio: add the file to `assets/sounds/`, add to `_SFX_FILES` or `_MUSIC_FILES` dict in `sounds.py`, and update `.gitattributes` LFS tracking if needed.
375
+
376
+ ### Auto-Hold Scoring Dice
377
+
378
+ After rolling (D6 and D20 Tier 1), all scoring dice default to "Held". Players uncheck to release. This inverts the original opt-in pattern to opt-out. D20 Tier 2 reroll and Tier 3 auto-apply are unchanged. Implementation is in `_handle_roll()` in `game.py`.
379
+
380
+ ### Sidebar Game Rules
381
+
382
+ When `page == "game"`, rules for the active game mode are rendered below audio controls in the sidebar. Rules text is defined as module-level constants `_D6_RULES` and `_D20_RULES` in `app.py`.
383
+
384
+ ### Run Command
385
+
386
+ ```bash
387
+ python -m streamlit run src/ui/app.py
388
+ ```
docs/NEW_GAME_MODE_TEMPLATE.md ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # New Game Mode Template
2
+
3
+ Use this template to define a new game mode for Devil's Dozen. Fill out each section, then open Claude Code and say:
4
+
5
+ > "I want to add a new game mode to Devil's Dozen. Here is the completed template: [paste or reference this file]."
6
+
7
+ Claude will use this template along with the existing `CONTEXT_*.md` docs to build the engine, wire up the UI, and add audio support.
8
+
9
+ ---
10
+
11
+ ## 1. Mode Identity
12
+
13
+ | Field | Value |
14
+ |-------|-------|
15
+ | **Display Name** | _(e.g., "Pirate's Plunder")_ |
16
+ | **Internal Key** | _(e.g., `pirates_plunder` β€” lowercase, underscores, used in code + DB)_ |
17
+ | **Dice Type** | _(e.g., D6 / D10 / D12 / D20 / mixed)_ |
18
+ | **Number of Dice** | _(e.g., 5)_ |
19
+ | **Min Players** | _(e.g., 2)_ |
20
+ | **Max Players** | _(e.g., 4)_ |
21
+ | **Target Score / Win Condition** | _(e.g., "First to 5,000 points" or "Survive 10 rounds")_ |
22
+ | **Configurable Win Conditions?** | _(e.g., "Yes β€” 3000 / 5000 / 10000" or "No β€” fixed at 250")_ |
23
+
24
+ ---
25
+
26
+ ## 2. Turn Structure
27
+
28
+ Describe what happens on a single player's turn from start to finish.
29
+
30
+ ```
31
+ Example (Peasant's Gamble):
32
+ 1. Player rolls all 6 D6 dice
33
+ 2. Must hold at least one scoring die
34
+ 3. Can choose to roll remaining dice or bank
35
+ 4. If no scoring dice on a roll β†’ BUST (lose all unbanked turn points)
36
+ 5. If all dice score β†’ HOT DICE (roll all 6 fresh, keep accumulated points)
37
+ 6. Bank ends the turn and adds turn score to total
38
+ ```
39
+
40
+ **Your turn structure:**
41
+ ```
42
+ 1. ...
43
+ 2. ...
44
+ 3. ...
45
+ ```
46
+
47
+ ---
48
+
49
+ ## 3. Scoring Rules
50
+
51
+ ### 3.1 Basic Scoring
52
+
53
+ List every scoring combination, its point value, and which dice participate.
54
+
55
+ | Combo | Points | Example |
56
+ |-------|--------|---------|
57
+ | _(e.g., Single 1)_ | _(e.g., 100)_ | _(e.g., rolling a 1 among other dice)_ |
58
+ | _(e.g., Three of a kind)_ | _(e.g., face value x 100)_ | _(e.g., three 4s = 400)_ |
59
+
60
+ ### 3.2 Special Combos (if any)
61
+
62
+ | Combo | Points | Notes |
63
+ |-------|--------|-------|
64
+ | _(e.g., Straight 1-6)_ | _(e.g., 1500)_ | _(e.g., must be all 6 dice)_ |
65
+
66
+ ### 3.3 Bust Condition
67
+
68
+ When does the player bust? _(e.g., "No scoring dice on a roll" / "Rolling a 1" / "Never busts")_
69
+
70
+ ### 3.4 Hot Dice / Re-roll Condition (if any)
71
+
72
+ When does the player get to re-roll all dice fresh? _(e.g., "All dice are scoring" / "Not applicable")_
73
+
74
+ ---
75
+
76
+ ## 4. Tiers / Phases (if applicable)
77
+
78
+ Does the game have tiers, phases, or stages that change the rules as the player progresses?
79
+
80
+ If **no tiers**: Write "Single phase β€” rules are constant throughout."
81
+
82
+ If **yes**:
83
+
84
+ | Tier | Name | Score Range | Dice Count | Rule Changes |
85
+ |------|------|-------------|------------|-------------|
86
+ | 1 | _(e.g., Red)_ | _(e.g., 0-100)_ | _(e.g., 8)_ | _(e.g., Standard scoring)_ |
87
+ | 2 | _(e.g., Green)_ | _(e.g., 101-200)_ | _(e.g., 3)_ | _(e.g., Score x5, per-die reroll)_ |
88
+
89
+ ---
90
+
91
+ ## 5. Special Mechanics
92
+
93
+ Describe any unique mechanics not covered above:
94
+
95
+ - _(e.g., "Kingmaker: Rolling a 20 in Tier 3 gives 20 points to last-place player")_
96
+ - _(e.g., "Steal: Rolling triples lets you steal 50 points from another player")_
97
+ - _(e.g., "Curse: Rolling snake eyes resets your score to zero")_
98
+
99
+ If none: Write "No special mechanics."
100
+
101
+ ---
102
+
103
+ ## 6. Player-Facing Rules Summary
104
+
105
+ Write a concise version of the rules as you'd want players to see it in the sidebar during gameplay. Use markdown. Aim for <=20 lines. This will be displayed directly in the app.
106
+
107
+ ```markdown
108
+ **Goal:** ...
109
+
110
+ **Rolling:**
111
+ - ...
112
+ - ...
113
+
114
+ **Scoring:**
115
+ | Combo | Points |
116
+ |---|---|
117
+ | ... | ... |
118
+ ```
119
+
120
+ ---
121
+
122
+ ## 7. Audio
123
+
124
+ ### 7.1 Background Music
125
+
126
+ Provide or describe the background music track for this mode.
127
+
128
+ | Field | Value |
129
+ |-------|-------|
130
+ | **Filename** | _(e.g., `pirates_theme.mp3` β€” place in `assets/sounds/`)_ |
131
+ | **Music dict key** | _(must match the internal key from Section 1, e.g., `pirates_plunder`)_ |
132
+ | **Vibe / Description** | _(e.g., "Upbeat tavern shanty with fiddle and accordion")_ |
133
+ | **Provided?** | _(Yes β€” file attached / No β€” generate or find one)_ |
134
+
135
+ ### 7.2 New Sound Effects (if any)
136
+
137
+ List any NEW SFX this mode needs beyond the existing set. Existing SFX that can be reused:
138
+
139
+ | Existing SFX | Trigger |
140
+ |---|---|
141
+ | `dice_roll` | On any dice roll |
142
+ | `bust` | On bust |
143
+ | `bank` | On banking score |
144
+ | `hot_dice` | On hot dice / re-roll all |
145
+ | `victory` | On game win |
146
+ | `tier_advance` | On tier/phase change |
147
+
148
+ **New SFX needed:**
149
+
150
+ | SFX Name | Filename | Trigger | Description |
151
+ |----------|----------|---------|-------------|
152
+ | _(e.g., `steal`)_ | _(e.g., `steal.mp3`)_ | _(e.g., "When player steals points")_ | _(e.g., "Coin clinking sound")_ |
153
+
154
+ If none: Write "No new SFX β€” reusing existing set."
155
+
156
+ ---
157
+
158
+ ## 8. UI Considerations
159
+
160
+ ### 8.1 Dice Display
161
+
162
+ How should the dice look? _(e.g., "Same as D6 but with pirate skull on 1" / "Standard D20 with tier colors" / "Custom D10 faces")_
163
+
164
+ ### 8.2 Hold / Interaction Pattern
165
+
166
+ Which pattern should this mode use?
167
+
168
+ - [ ] **Auto-hold scoring** (like current D6/D20 Tier 1) β€” scoring dice default to held, player unchecks to release
169
+ - [ ] **Per-die reroll** (like D20 Tier 2) β€” each die has a Reroll button
170
+ - [ ] **Auto-apply** (like D20 Tier 3) β€” roll result is applied automatically, no player choice
171
+ - [ ] **Other** β€” describe: _____________
172
+
173
+ ### 8.3 Special UI Elements
174
+
175
+ Any special animations, indicators, or displays needed?
176
+
177
+ - _(e.g., "Show a 'steal target' selector when triples are rolled")_
178
+ - _(e.g., "Tier indicator like Alchemist's Ascent")_
179
+ - _(e.g., "Round counter at the top")_
180
+
181
+ If none: Write "Standard UI β€” no special elements."
182
+
183
+ ---
184
+
185
+ ## 9. Integration Checklist
186
+
187
+ _Claude will handle these, but this is the work involved for reference:_
188
+
189
+ ### Engine (`src/engine/`)
190
+ - [ ] New engine class (e.g., `pirates_plunder.py`) with `roll_dice()`, `calculate_score()`, bust/hot-dice logic
191
+ - [ ] Scoring result dataclass with `points`, `is_bust`, `scoring_dice_indices`, `breakdown`
192
+ - [ ] Unit tests covering all scoring combos, edge cases, bust, and hot dice
193
+
194
+ ### Database
195
+ - [ ] Add mode key to `game_mode` column allowed values
196
+ - [ ] Any new `game_state` columns? _(e.g., "round_number" / "steal_target")_
197
+
198
+ ### UI
199
+ - [ ] Add to home page mode selector
200
+ - [ ] Wire into `game.py` roll/hold/bank handlers
201
+ - [ ] Add scoring indices helper in `game.py`
202
+ - [ ] Add rules text to `app.py` (`_XX_RULES` constant + sidebar render)
203
+ - [ ] Add background music entry to `_MUSIC_FILES` in `sounds.py`
204
+ - [ ] Add any new SFX entries to `_SFX_FILES` in `sounds.py`
205
+ - [ ] Add win condition options if configurable
206
+
207
+ ### Assets
208
+ - [ ] Background music file in `assets/sounds/`
209
+ - [ ] Any new SFX files in `assets/sounds/`
210
+ - [ ] Update `.gitattributes` for LFS tracking if new MP3s added
211
+
212
+ ---
213
+
214
+ ## 10. Example: Filling This Out for Peasant's Gamble
215
+
216
+ <details>
217
+ <summary>Click to expand worked example</summary>
218
+
219
+ ### 1. Mode Identity
220
+
221
+ | Field | Value |
222
+ |-------|-------|
223
+ | **Display Name** | Peasant's Gamble |
224
+ | **Internal Key** | `peasants_gamble` |
225
+ | **Dice Type** | D6 |
226
+ | **Number of Dice** | 6 |
227
+ | **Min/Max Players** | 2–4 |
228
+ | **Target Score** | First to target score |
229
+ | **Configurable?** | Yes β€” 3,000 / 5,000 / 10,000 |
230
+
231
+ ### 2. Turn Structure
232
+
233
+ ```
234
+ 1. Roll all 6 dice
235
+ 2. Must hold at least one scoring die
236
+ 3. Roll remaining dice or bank turn score
237
+ 4. No scoring dice = BUST (lose turn score)
238
+ 5. All dice score = HOT DICE (roll all 6 fresh)
239
+ 6. Bank adds turn score to total, ends turn
240
+ ```
241
+
242
+ ### 3. Scoring Rules
243
+
244
+ | Combo | Points |
245
+ |---|---|
246
+ | Single 1 | 100 |
247
+ | Single 5 | 50 |
248
+ | Three 1s | 1,000 |
249
+ | Three 2s–6s | Face x 100 |
250
+ | Four+ of a kind | Previous tier x 2 |
251
+ | 1-2-3-4-5 | 500 |
252
+ | 2-3-4-5-6 | 750 |
253
+ | 1-2-3-4-5-6 | 1,500 |
254
+
255
+ **Bust:** No scoring dice on a roll.
256
+ **Hot Dice:** All 6 dice are scoring.
257
+
258
+ ### 4. Tiers
259
+
260
+ Single phase β€” rules are constant throughout.
261
+
262
+ ### 7. Audio
263
+
264
+ | Field | Value |
265
+ |-------|-------|
266
+ | **Filename** | `d6_theme.mp3` |
267
+ | **Music key** | `peasants_gamble` |
268
+ | **Vibe** | Medieval tavern with lute and drums |
269
+ | **Provided?** | Yes |
270
+
271
+ No new SFX β€” reusing existing set.
272
+
273
+ ### 8. UI
274
+
275
+ - Auto-hold scoring dice
276
+ - No special elements beyond standard dice tray + scoreboard
277
+
278
+ </details>