# Adventure Dice Card Game — Ruleset & Build Spec

A 1–4 player real-time, turn-based card game for iPhone and Android. This document is the authoritative reference for both rules and implementation. Hand it to Claude Code to scaffold the backend.

---

## 1. Components

### 1.1 Adventure Deck (red) — 64 cards, pure dice fuel
- 60 numbered cards: numbers 1–12 in each of 5 colors (green, red, blue, purple, orange) — one of each = 60.
- 4 "Draw Two" cards.
- This deck never scores. It exists to roll dice and to form attack combos.

### 1.2 Green Deck — monsters, abilities, actions (shuffled together)
This is the board. 5 cards are face-up in the **landscape**; the rest are the draw pile. The two dragons are seeded into the bottom 6 cards during setup.

**Monsters** — captured by beating their target for the chosen attack type. Score at end of game.

| Pts | Qty | Monster | Strike | Stomp | Scream |
|----:|----:|---------|-------:|------:|-------:|
| 1 | 4 | Spiders | 3 | 3 | 4 |
| 1 | 4 | Bats | 4 | 3 | 3 |
| 2 | 2 | Wasps | 5 | 6 | 7 |
| 2 | 2 | Ants | 7 | 4 | 6 |
| 2 | 2 | Goblins | 7 | 5 | 5 |
| 3 | 2 | Bears | 7 | 6 | 9 |
| 3 | 2 | Wolves | 6 | 7 | 9 |
| 3 | 1 | Jaguar | 8 | 6 | 8 |
| 3 | 2 | Boar | 8 | 7 | 7 |
| 4 | 1 | Troll | 9 | 11 | 9 |
| 4 | 1 | Shadow | 10 | 8 | 11 |
| 4 | 1 | Python | 11 | 8 | 10 |
| 5 | 1 | Glob | 14 | 9 | 10 |
| 5 | 1 | Ogre | 12 | 9 | 14 |
| 6 | 1 | Blue Dragon | 13 | 10 | 13 |
| 7 | 1 | Red Dragon | 15 | 11 | 12 |

**Total monsters: 28. Total points on the board: 76.**

**Abilities** — captured by beating *their* listed target (they have strike/stomp/scream numbers too). Worth **0 points**; kept as equipment.

| Ability | Effect | Strike | Stomp | Scream |
|---------|--------|-------:|------:|-------:|
| Sword | Passive **+2** to total on **strike** attacks | 10 | 6 | 7 |
| Bucket | Passive **+2** to total on **stomp** attacks | 7 | 10 | 8 |
| Ghost | Passive **+2** to total on **scream** attacks | 8 | 7 | 10 |
| Unicorn | Passive **+1** to total on **any** attack | 8 | 6 | 8 |
| Cloak | Passive **+2** to total on **any** attack | 11 | 9 | 11 |
| Reroll | One-shot: reroll a single die; new value replaces old | 7 | 5 | 7 |
| +4 | One-shot: +4 to attack total | 7 | 5 | 7 |
| Wild Card | One-shot: play as an adventure card — adds a die **and** fills any number/color in a combo | 5 | 4 | 5 |
| +1 Die | One-shot: add one extra die to the roll | 4 | 4 | 4 |

> ⚠️ **Open decision — ability quantities.** You never specified how many copies of each ability are in the green deck. Default in this spec: **1 of each** (9 ability cards total). This matches your design intent that fully stacking gear is rare/hard in multiplayer. Confirm or override.

**Action cards** — fire immediately when flipped into the landscape, then discarded and replaced.

| Action | Effect |
|--------|--------|
| Discard 1 | All players discard 1 adventure card (their choice) |
| Pass Right | All players pass 1 adventure card to the player on their right |
| Draw 2 | All players draw 2 adventure cards, dealt round-robin (alternating) |
| Reset Landscape | Remove all enhancement (ability) cards in the landscape, shuffle them back, refill |

> ⚠️ **Open decision — action quantities.** Not specified. Default: **2 of each** (8 action cards). Confirm or override.

**Default green deck size: 28 monsters + 9 abilities + 8 actions = 45 cards.**

### 1.3 Dice
A die is a custom d6 with faces **[1, 2, 2, 3, 3, 4]** (average 2.5). Number of dice rolled = number of adventure cards played + bonus dice (Wild Card, +1 Die).

---

## 2. Core Attack Rules

Minimum **2 adventure cards** per attack. **Cards played = dice rolled.** The combo determines which attack type you're using:

- **Strike** = a run of sequential numbers, any color. (e.g. 4-5-6)
- **Stomp** = same number, any color. (e.g. 4-4-4)
- **Scream** = same color, any number. (e.g. three oranges)

**Win = total ≥ the target** for that attack type on the card. **Lose = total < target → discard 1 adventure card of your choice.**

A **Wild Card** played into the combo counts as any number and any color, so it can complete or extend any of the three patterns, and it adds a die.

### 2.1 Resolution order within an attack
1. **Declare** target (a landscape card), play ≥2 adventure cards, and the combo defines the attack type. Wild Cards are assigned their number/color now.
2. **Pre-roll one-shots:** play `+1 Die` and/or `Wild Card` (each adds a die; Wild also fills the combo).
3. **Roll** all dice (server RNG only).
4. **Reactions** (repeatable, any order, until the player passes): use `Reroll` (replace one die's value with a fresh roll — new value stands even if worse), play `+4` (+4 to total).
5. **Apply passive equipment** automatically: sum boosts whose attack type matches (Sword→strike, Bucket→stomp, Ghost→scream) plus universal boosts (Unicorn +1, Cloak +2). Boosts stack additively.
6. **Compare** final total to target.

One-shots (`Reroll`, `+4`, `+1 Die`, `Wild Card`) are **consumed and discarded** after use. Passive boosts (Sword/Bucket/Ghost/Unicorn/Cloak) are permanent once captured.

> **Power curve (intended):** 2 cards ≈ avg roll 5; 3 ≈ 7.5; 4 ≈ 10; 5 ≈ 12.5. A fully-geared player (Cloak + Unicorn + matching gear) adds ~+5, so late game they can clear most monsters on 2 cards — at which point the real constraint is *forming a valid combo*, not the dice. By design.

> **Combo-type asymmetry (note, not a bug):** with one card per number/color, Scream (same color, 12 candidates) scales easiest, Strike (runs) is medium, Stomp (same number, only 5 copies) is hardest — a 4-stomp eats 4 of 5 copies. Monsters with low scream / high stomp targets become "scream bait." Lean into it when tuning.

---

## 3. Setup

1. Build and shuffle both decks.
2. Seed the green deck: place the **two dragons within the bottom 6 cards**, then place 5 cards face-up as the landscape. **If any action card lands in the landscape during setup, remove it, shuffle it back, and redraw** (actions do not fire during setup).
3. Deal each player **5 adventure cards**. If a player is dealt a Draw Two, they discard it and draw 2 replacements immediately (repeat until no Draw Two in the opening hand).
4. Pick a starting player.
5. If the adventure deck runs out at any point, shuffle its discard pile to reform the draw pile.

---

## 4. Turn Structure

On your turn, choose **Draw** or **Attack**.

**Draw:** draw 1 adventure card, then end turn. (Auto-resolve any Draw Two drawn — see §5.) Hand cap is 12.

**Attack:** resolve per §2 against one landscape card.
- **Win:** discard the played adventure cards; capture the landscape card (monster → hidden score pile; ability → your equipment, usable starting next turn). Refill the landscape (§5). Then end turn.
- **Lose:** discard 1 adventure card of your choice. End turn.

Captured abilities become usable **on your next turn**, not the turn you win them.

---

## 5. Landscape Refill & Auto-Resolving Cards

Whenever a landscape slot empties (a card was captured, or an action fired), draw a replacement from the green deck:
- **Monster or ability** → it stays face-up in the landscape.
- **Action card** → it fires immediately (§1.2), is discarded, and another replacement is drawn into the slot. Repeat until a non-action card fills it.

**Draw Two (adventure deck):** the instant it is drawn into a hand, it is discarded and the player draws 2 replacements. (This can chain.)

**"Draw 2" action:** all players draw 2, dealt round-robin (alternating one at a time) so a thin deck stays fair.

> ⚠️ **Open decision — hand overflow.** Hand cap is 12. If a forced draw (Draw Two chain, or "Draw 2" action) pushes a hand over 12, default rule: the player **discards down to 12 of their choice** after the draw resolves. Confirm.

---

## 6. Game Over & Scoring

The game ends when **all monsters are captured**. (Abilities/actions remaining in the deck or landscape don't matter.)

**Scoring is hidden the entire game** — no running totals, no leaderboard. At game end, reveal each player's captured-monster pile and sum points (Spiders/Bats 1 … Blue Dragon 6, Red Dragon 7). Highest total wins. Abilities score 0.

> ⚠️ **UX decision — hidden-info scope.** "Hidden until the end" can mean (a) only *totals* are hidden but you see your own captured monsters, or (b) opponents' captures are face-down too. Default: you see your own captured cards but no computed total; opponents' captures show as face-down counts; full reveal at end. Confirm.

### 6.1 Solo (1 player)
Ship as a **score-chase vs the deck**: identical rules, no opponent, beat your own high score. No AI required. (Bot opponents = optional later phase.)

---

## 7. Architecture

### 7.1 Non-negotiable: authoritative server
Hidden hands, deck order, and dice make client-side authority trivially cheatable. The **server is the only source of truth**: it shuffles, deals, rolls all dice, and validates every move (is it your turn? do you hold those cards? is the combo valid for the declared type? is the target in the landscape?). Clients are thin renderers that send intents and receive state.

State is tiny (≤64 + ~45 cards, ≤4 hands), so **broadcast full game state on every change** — no diffing needed.

### 7.2 Recommended stack (fits your existing world)
- **Backend:** ASP.NET Core 8 + **SignalR** on Azure App Service. SignalR handles the live push; a turn state machine drives play. You already run this stack daily.
- **Client:** **Flutter** (best 2D card-animation feel per unit of effort, single codebase for iOS + Android). Alternative: **Unity** if you want C# end-to-end and richer animation. Avoid MAUI — it's business-UI, not game-feel.
- **Faster MVP alternative:** Firebase (Firestore realtime + Cloud Functions for authoritative moves + Auth). Off your stack and server-authority is clunkier, but quickest to a playable build.

### 7.3 Lobby flow
Create game → server generates a short join code (e.g. 4 chars) → others join by code into a lobby → host starts → server deals and broadcasts initial state.

---

## 8. Turn State Machine

```
LOBBY
  → (host StartGame) → DEAL → PLAYER_TURN

PLAYER_TURN (active player chooses)
  ├─ DRAW → draw 1 (resolve Draw Two) → check hand cap → END_TURN
  └─ ATTACK → ATTACK_DECLARE

ATTACK_DECLARE
  validate: target in landscape, ≥2 cards held, combo valid for type
  → ATTACK_PREROLL

ATTACK_PREROLL
  optional: play +1 Die / Wild Card (add dice)
  → ROLL (server RNG)
  → ATTACK_REACT

ATTACK_REACT  (loop until player passes)
  optional: Reroll one die (replace value) / play +4
  → on pass: APPLY_PASSIVES → COMPARE

COMPARE
  ├─ total ≥ target → WIN: discard played cards, capture card,
  │                    REFILL_LANDSCAPE (resolve actions) → END_TURN
  └─ total < target  → LOSE: discard 1 chosen card → END_TURN

REFILL_LANDSCAPE
  draw replacement; if action → fire + discard + redraw; loop until non-action

END_TURN
  → check win condition (all 28 monsters captured?)
      ├─ yes → GAME_OVER (reveal scores)
      └─ no  → advance to next player → PLAYER_TURN
```

### 8.1 Client → Server commands
`CreateGame`, `JoinGame(code)`, `StartGame`, `Draw`, `BeginAttack(targetId, cardIds[], declaredType, wildAssignments[])`, `PlayPreRollOneShot(abilityId)`, `RerollDie(dieIndex)`, `PlayPlusFour()`, `PassReactions()`, `DiscardCard(cardId)` (for forced discards/overflow).

### 8.2 Server → Client events
`GameStateUpdated(fullState)`, `RollResult(dice[], runningTotal, target, passes)`, `ActionFired(actionType, affectedPlayers)`, `Error(reason)`, `GameOver(scores[])`.

### 8.3 Validation the server must enforce
- Move comes from the active player.
- Player actually holds every card referenced.
- Combo is valid for the declared attack type (with wild assignments applied).
- One-shots are owned, unused, and played in the correct phase.
- Equipment boosts auto-apply only for matching attack types.
- All randomness (shuffle, deal, dice, rerolls) is server-side; clients never roll.
- Hidden info: never send opponents' hands or score totals; gate captured-monster details per the §6.1 UX decision.

---

## 9. Open Decisions (answer before scaffolding)

1. **Ability quantities** — default 1 each (9 cards). Confirm/override.
2. **Action quantities** — default 2 each (8 cards). Confirm/override.
3. **Hand overflow** — default: discard down to 12 after a forced draw. Confirm.
4. **Hidden-info scope** — default: own captures visible (no totals), opponents face-down counts, reveal at end. Confirm.
5. **Client stack** — Flutter (recommended) vs Unity vs Firebase MVP.
