# Models Module

Pydantic models for game state, card definitions, and player actions.

---

## Files

| File | Description |
|------|-------------|
| `__init__.py` | Module exports |
| `card.py` | Card-related models |
| `game_state.py` | Game state and player state |
| `actions.py` | Player action types |

---

## Card Models (`card.py`)

### CardDefinition

Immutable template defining a card's properties. Stored in the card registry.

```python
CardDefinition(
    id="pikachu-001",
    name="Pikachu",
    card_type=CardType.POKEMON,
    stage=PokemonStage.BASIC,
    hp=60,
    pokemon_type=EnergyType.LIGHTNING,
    attacks=[
        Attack(name="Thunder Shock", damage=20, cost=[EnergyType.LIGHTNING]),
    ],
    weakness=WeaknessResistance(energy_type=EnergyType.FIGHTING, value=20),
    retreat_cost=1,
)
```

### CardInstance

A specific card in play, referencing a `CardDefinition`. Tracks runtime state.

```python
CardInstance(
    instance_id="p1-pikachu-0",      # Unique per-game
    definition_id="pikachu-001",     # References CardDefinition
    damage=30,                        # Current damage
    attached_energy=[...],            # Energy cards attached
    status_conditions=[StatusCondition.PARALYZED],
)
```

### Attack

A Pokemon's attack with cost, damage, and optional effect.

```python
Attack(
    name="Crimson Storm",
    cost=[EnergyType.FIRE, EnergyType.FIRE, EnergyType.COLORLESS],
    damage=200,
    effect_id="discard_energy",
    effect_params={"count": 2},
    effect_description="Discard 2 Energy from this Pokemon.",
)
```

### Ability

A Pokemon's special ability.

```python
Ability(
    name="Psy Shadow",
    effect_id="energy_acceleration",
    effect_params={"energy_type": "psychic", "target": "active"},
    effect_description="Attach Psychic Energy from Energy Zone to Active.",
    uses_per_turn=1,
)
```

### WeaknessResistance

Weakness or resistance to an energy type.

```python
# Additive weakness (+20)
WeaknessResistance(energy_type=EnergyType.FIRE, mode=ModifierMode.ADDITIVE, value=20)

# Multiplicative weakness (x2)
WeaknessResistance(energy_type=EnergyType.FIRE, mode=ModifierMode.MULTIPLICATIVE, value=2)

# Resistance (-30)
WeaknessResistance(energy_type=EnergyType.WATER, mode=ModifierMode.ADDITIVE, value=-30)
```

---

## Game State Models (`game_state.py`)

### GameState

Complete state of a game. Self-contained with embedded card registry.

```python
GameState(
    game_id="match-123",
    rules=RulesConfig(),
    card_registry={...},
    players={"p1": PlayerState(...), "p2": PlayerState(...)},
    current_player_id="p1",
    turn_number=3,
    phase=TurnPhase.MAIN,
)
```

**Key Methods:**
- `get_current_player()` - Current player's state
- `get_opponent(player_id)` - Opponent's state
- `get_card_definition(card_id)` - Lookup card definition
- `advance_turn()` - Move to next player's turn

### PlayerState

All zones and state for a single player.

```python
player = game.players["p1"]

# Zones (all are Zone objects)
player.deck        # Draw pile
player.hand        # Cards in hand
player.active      # Active Pokemon (0-1 cards)
player.bench       # Benched Pokemon
player.discard     # Discard pile
player.prizes      # Prize cards
player.energy_deck # Energy deck (Pocket-style)
player.energy_zone # Available energy this turn

# State tracking
player.score                       # Points scored
player.energy_attachments_this_turn
player.supporters_played_this_turn
```

**Key Methods:**
- `get_active_pokemon()` - Returns active Pokemon or None
- `get_all_pokemon_in_play()` - Active + bench
- `can_attach_energy(rules)` - Check turn limits
- `reset_turn_state()` - Clear per-turn counters

### Zone

A collection of cards (deck, hand, bench, etc.).

```python
zone = player.hand

len(zone)                    # Card count
"card-id" in zone            # Check if card present
zone.add(card)               # Add to end
zone.add_to_top(card)        # Add to top (for deck)
zone.remove("card-id")       # Remove and return card
zone.draw()                  # Remove and return from top
zone.shuffle(rng)            # Randomize order
zone.get("card-id")          # Get without removing
zone.clear()                 # Remove all cards
```

### ForcedAction

Represents a required action (e.g., "select new active after KO").

```python
ForcedAction(
    player_id="p1",
    action_type="select_active",
    reason="Your active Pokemon was knocked out",
    params={"from_zones": ["bench"]},
)
```

---

## Action Models (`actions.py`)

All actions implement a common interface with `type` discriminator field.

### Attack Actions

```python
AttackAction(attack_index=0)  # Use first attack
```

### Energy Actions

```python
AttachEnergyAction(
    energy_card_id="p1-lightning-0",
    target_pokemon_id="p1-pikachu-0",
    from_energy_zone=True,
)
```

### Pokemon Actions

```python
PlayPokemonAction(card_id="p1-bulbasaur-0", to_active=False)
EvolvePokemonAction(card_id="p1-ivysaur-0", target_pokemon_id="p1-bulbasaur-0")
```

### Trainer Actions

```python
PlayTrainerAction(card_instance_id="p1-potion-0", targets=["p1-pikachu-0"])
```

### Ability Actions

```python
UseAbilityAction(pokemon_id="p1-greninja-0", ability_index=0, targets=["p2-charmander-0"])
```

### Movement Actions

```python
RetreatAction(new_active_id="p1-squirtle-0", energy_to_discard=["p1-water-0"])
SelectActiveAction(new_active_id="p1-squirtle-0")  # After KO
```

### Turn Control

```python
PassAction()    # End turn without attacking
ResignAction()  # Forfeit the game
```

### Action Union Type

```python
Action = (
    AttackAction | AttachEnergyAction | PlayPokemonAction | 
    EvolvePokemonAction | PlayTrainerAction | UseAbilityAction |
    RetreatAction | SelectActiveAction | PassAction | ResignAction |
    SelectPrizeAction
)
```

---

## Model Relationships

```
GameState
├── card_registry: dict[str, CardDefinition]
├── players: dict[str, PlayerState]
│   └── PlayerState
│       ├── deck: Zone[CardInstance]
│       ├── hand: Zone[CardInstance]
│       ├── active: Zone[CardInstance]
│       │   └── CardInstance
│       │       ├── definition_id -> CardDefinition
│       │       ├── attached_energy: list[CardInstance]
│       │       └── evolution_stage: list[CardInstance]
│       ├── bench: Zone[CardInstance]
│       ├── discard: Zone[CardInstance]
│       └── ...
├── stadium_in_play: CardInstance | None
└── forced_actions: list[ForcedAction]
```

---

## See Also

- [../README.md](../README.md) - Core module overview
- [/docs/ARCHITECTURE.md](/docs/ARCHITECTURE.md) - System architecture
