# Scoundrel Web Game Design Document
## 1. Overview
This document outlines the design for a web-based implementation of "Scoundrel," a solo dungeon crawler card game played with a standard poker deck. The application will be a static single-page application (SPA) requiring no server-side code or build steps. It will utilize **Preact** and **HTM** (Hyperscript Tagged Markup) via ES Modules to allow for modern component-based development directly in the browser.
## 2. Game Rules Summary
The game simulates a dungeon crawl. The goal is to traverse the entire dungeon (the deck) without dying.
### 2.1 Setup
- **Deck**: Standard 52-card deck.
- **modifications**: Remove all Red Face cards (J, Q, K of Hearts and Diamonds) and Red Aces.
- **Start**: Player begins with 20 HP.
### 2.2 Core Loop
1. **The Room**: A room is formed by dealing 4 cards face up.
2. **Action**: The player must resolve (interact with) at least 3 of the 4 cards to clear the room.
3. **Progression**: Once 3 cards are resolved, the remaining 1 card stays, and 3 new cards are dealt to refill the room to 4.
4. **Fleeing**: The player may choose to flee (skip) a room. The 4 cards are shuffled to the bottom of the deck. You cannot flee two rooms in a row.
### 2.3 Card Types & Interactions
- **Monsters (Spades ♠ & Clubs ♣)**:
- Damage = Card Value (2-10, J=11, Q=12, K=13, A=14).
- If unarmed: Take full damage to HP.
- If armed: Damage = (Monster Value - Weapon Value). If result is < 0, take 0 damage.
- **Weapons (Diamonds ♦)**:
- Equipping a weapon replaces the current one.
- Adds the card's value to attack power.
- **Durability**: After a weapon is used to kill a monster, it can only kill monsters *strictly weaker* than the last one killed. (e.g., if you kill a 10, the next kill must be < 10).
- **Health Potions (Hearts ♥)**:
- Heals HP equal to card value (2-10).
- Max HP is 20.
- You can only use **one** potion per turn (per room refill). Other hearts in the room are useless for healing until the room refreshes (or unless they are discarded to clear the room).
### 2.4 Win/Loss
- **Win**: The deck is empty, and the final room is cleared.
- **Lose**: HP drops to 0 or below.
## 3. Technical Architecture
### 3.1 Stack
- **HTML5**: Semantic structure.
- **CSS3**: Custom styling, CSS Grid/Flexbox for layout, CSS patterns for card backs.
- **JavaScript (ES6+)**: Logic and State management.
- **Libraries**:
- `preact`: Lightweight React alternative.
- `htm`: JSX-like syntax using tagged templates, eliminating the need for Babel/transpilation.
- *Import strategy*: ES Modules via `unpkg` or `esm.sh`.
### 3.2 File Structure
```text
/
├── index.html # Entry point, imports main.js
├── style.css # All visual styles
└── main.js # Game logic, state management, and UI components
```
### 3.3 Coding Conventions
- **Functions**: `camelCase` (e.g., `calculateDamage`)
- **Variables**: `snake_case` (e.g., `current_hp`)
- **Global Constants**: `UPPER_CASE` (e.g., `MAX_HP`)
- **Comments**: JSDoc style for complex logic.
## 4. Data Structures
### 4.1 Card Representation
```javascript
const CARD_SUITS = {
HEARTS: '♥',
DIAMONDS: '♦',
CLUBS: '♣',
SPADES: '♠'
};
// Card Object
{
suit: '♥', // One of CARD_SUITS
rank: 'K', // Display rank (2-10, J, Q, K, A)
value: 13, // Numerical value for logic
id: 'unique_id_string', // For React keys
type: 'POTION' // POTION, WEAPON, or MONSTER
}
```
### 4.2 Game State
```javascript
{
current_hp: 20,
max_hp: 20,
deck: [], // Array of Card objects
room: [], // Array of Card objects (max 4)
discard_pile: [], // Array of Card objects (cleared cards)
// Weapon State
equipped_weapon: null, // Card object or null
last_enemy_value: null, // For tracking weapon durability rule
// Turn State
cards_played_this_turn: 0, // Need 3 to advance
potion_used_this_turn: false,
can_flee: true,
// History
defeated_monsters: [] // Array of Card objects (visual appeal)
}
```
## 5. UI Design
### 5.1 Layout
The screen will be divided into three main sections:
1. **Header/Stats**: Title, Current HP bar, Deck count.
2. **The Dungeon (Center)**:
- **Room Area**: The 4 active cards laid out horizontally.
- **Weapon Slot**: Shows current weapon and its "max killable value".
- **Controls**: "Run Away" button (if applicable).
3. **History/Footer**:
- Pile of defeated monsters (stacked visually).
- Rules summary / Help toggle.
### 5.2 Card Visuals
- **Face**: White background with red (Hearts/Diamonds) or black (Clubs/Spades) text. Large unicode suit symbol in center. Corners show Rank + Suit.
- **Back**: CSS `repeating-linear-gradient` to create a cross-hatch or diagonal pattern.
## 6. Implementation Logic
### 6.1 Initialization (`initGame`)
1. Generate full deck.
2. Filter out Red Faces (J,Q,K) and Red Aces.
3. Shuffle.
4. Deal 4 cards to `room`.
### 6.2 Interactions
- **Clicking a Card**:
- *If Monster*: Calculate damage. `current_hp -= max(0, monster.value - (weapon ? weapon.value : 0))`. If weapon used, update `last_enemy_value`. Check validity (weapon durability). Move monster to `defeated_monsters`.
- *If Weapon*: Move current weapon (if any) to discard. Set new weapon. Reset `last_enemy_value` to infinity (or max).
- *If Potion*: If `!potion_used_this_turn`, `current_hp = min(20, current_hp + potion.value)`. Mark potion used. Move card to discard.
- **State Update**: Increment `cards_played_this_turn`.
- **Turn End**: If `cards_played_this_turn == 3`:
- Deal 3 new cards.
- Reset `cards_played_this_turn = 0`.
- Reset `potion_used_this_turn = false`.
- Enable `can_flee`.
## 7. Resources
- [Rules Description](https://rpdillon.net/scoundrel.html)
- [Official PDF](http://www.stfj.net/art/2011/Scoundrel.pdf)