# 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