# Core Game Engine Module

The `app.core` module contains the platform-independent game engine for Mantimon TCG. This module is designed to be **completely decoupled** from network and database concerns to enable both online multiplayer and a future offline/standalone version.

## Architecture Principle

> **The core engine should remain forkable as a standalone offline game.**

See [ARCHITECTURE.md](/docs/ARCHITECTURE.md#offline-standalone-fork) for details on this design goal.

### Import Boundaries

```python
# ALLOWED in app/core/
from app.core.models import CardDefinition, GameState
from app.core.config import RulesConfig
from app.core.rng import RandomProvider

# FORBIDDEN in app/core/
from app.services import CardService      # NO - DB dependency
from app.api.deps import get_current_user # NO - Auth dependency
from sqlalchemy import Session            # NO - DB dependency
```

---

## Submodules

| Directory/File | Description |
|----------------|-------------|
| `models/` | Pydantic models for cards, game state, actions |
| `effects/` | Effect system for abilities and attacks |
| `engine.py` | `GameEngine` - main orchestrator |
| `config.py` | `RulesConfig` and sub-configs |
| `turn_manager.py` | Turn/phase state machine |
| `rules_validator.py` | Action validation |
| `rng.py` | Random number generation |
| `visibility.py` | Hidden information filtering |
| `win_conditions.py` | Win/loss detection |
| `enums.py` | Shared enumerations |

---

## Key Classes

### GameEngine (`engine.py`)

The primary public API for all game operations.

```python
from app.core import GameEngine, RulesConfig

engine = GameEngine(rules=RulesConfig())
result = engine.create_game(
    player_ids=["p1", "p2"],
    decks={"p1": deck1, "p2": deck2},
    card_registry=registry,
)
game = result.game

# Execute actions
action_result = await engine.execute_action(game, "p1", AttackAction(attack_index=0))
```

### RulesConfig (`config.py`)

Configures all game rules - deck sizes, prize counts, per-turn limits, etc.

```python
from app.core import RulesConfig

rules = RulesConfig(
    deck=DeckConfig(min_size=60, energy_deck_enabled=False),
    prizes=PrizeConfig(count=6),
)
```

### GameState (`models/game_state.py`)

Complete state of a game in progress. Self-contained and serializable.

```python
from app.core.models import GameState

# Access player zones
player = game.players["player1"]
active = player.get_active_pokemon()
hand_size = len(player.hand)
```

### TurnManager (`turn_manager.py`)

Handles turn phases and transitions.

```python
from app.core import TurnManager

manager = TurnManager()
manager.advance_phase(game)  # DRAW -> MAIN -> ATTACK -> END
manager.advance_turn(game)   # Switch to next player
```

### RandomProvider (`rng.py`)

Protocol for random operations. Supports seeded RNG for testing.

```python
from app.core import create_rng, SeededRandom

# Production: cryptographically secure
rng = create_rng()

# Testing: deterministic
rng = SeededRandom(seed=42)
```

---

## Enumerations (`enums.py`)

| Enum | Description |
|------|-------------|
| `CardType` | `POKEMON`, `TRAINER`, `ENERGY` |
| `PokemonStage` | `BASIC`, `STAGE_1`, `STAGE_2` |
| `EnergyType` | `FIRE`, `WATER`, `GRASS`, `LIGHTNING`, etc. |
| `TrainerType` | `ITEM`, `SUPPORTER`, `STADIUM`, `TOOL` |
| `StatusCondition` | `POISONED`, `BURNED`, `ASLEEP`, `PARALYZED`, `CONFUSED` |
| `TurnPhase` | `SETUP`, `DRAW`, `MAIN`, `ATTACK`, `END` |
| `GameEndReason` | `PRIZES`, `DECK_OUT`, `NO_POKEMON`, `RESIGNATION`, etc. |
| `ModifierMode` | `ADDITIVE`, `MULTIPLICATIVE` |

---

## Action Types (`models/actions.py`)

| Action | Description |
|--------|-------------|
| `AttackAction` | Use an attack |
| `AttachEnergyAction` | Attach energy to Pokemon |
| `PlayPokemonAction` | Play Basic to bench/active |
| `EvolvePokemonAction` | Evolve a Pokemon |
| `PlayTrainerAction` | Play a Trainer card |
| `UseAbilityAction` | Use a Pokemon's ability |
| `RetreatAction` | Retreat active Pokemon |
| `SelectActiveAction` | Choose new active (after KO) |
| `PassAction` | End turn without attacking |
| `ResignAction` | Forfeit the game |

---

## Visibility System (`visibility.py`)

Filters game state to hide information opponents shouldn't see.

```python
from app.core import get_visible_state, get_spectator_state

# Player sees own hand, opponent sees card count
visible = get_visible_state(game, "player1")

# Spectator sees neither hand
spectator_view = get_spectator_state(game)
```

---

## Effects System (`effects/`)

Handles card abilities and attack effects. See [effects/README.md](./effects/README.md).

```python
from app.core.effects import resolve_effect, EffectContext

result = resolve_effect("deal_damage", ctx)
```

---

## Testing

```bash
cd backend && uv run pytest tests/core/ -v
```

All core module tests are in `tests/core/` with ~800+ tests at 97% coverage.

---

## See Also

- [/docs/ARCHITECTURE.md](/docs/ARCHITECTURE.md) - System architecture
- [/docs/GAME_RULES.md](/docs/GAME_RULES.md) - Game rules
- [/docs/ACTIVE_EFFECTS_DESIGN.md](/docs/ACTIVE_EFFECTS_DESIGN.md) - Effects system design
- [effects/README.md](./effects/README.md) - Effects module
- [models/README.md](./models/README.md) - Models module
