Design Documentation: - docs/ACTIVE_EFFECTS_DESIGN.md: Comprehensive design for persistent effect system - Data model (ActiveEffect, EffectTrigger, EffectScope, StackingMode) - Core operations (register, remove, query effects) - Integration points (damage calc, energy counting, retreat, lifecycle) - Effect categories from Pokemon Pocket card research (~372 cards) - Example implementations (Serperior, Greninja, Mr. Mime, Victreebel) - Post-launch TODO for generic modifier system Module README Files: - backend/app/core/README.md: Core engine overview and key classes - backend/app/core/effects/README.md: Effects module index and quick reference - backend/app/core/models/README.md: Models module with relationship diagram Minor cleanup: - Revert Bulbasaur weakness to Fire (was test change for Lightning) - Clean up debug output in game walkthrough
196 lines
5.1 KiB
Markdown
196 lines
5.1 KiB
Markdown
# 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
|