mantimon-tcg/backend/app/core
Cal Corum 1123d61067 Extend core card models with rarity tiers and card subtypes
Add CardRarityTier enum for pull rate calculations (common through
crown_rare). Add CardSubtype enum for Pokemon classifications (basic,
stage1, stage2, ex, etc.). Update CardDefinition model with new fields
for subtypes and rarity display.
2026-01-31 15:43:07 -06:00
..
effects Add engine validation script with attack_coin_status effect handler 2026-01-28 00:15:12 -06:00
models Extend core card models with rarity tiers and card subtypes 2026-01-31 15:43:07 -06:00
__init__.py Move enums to app/core/enums.py and set up clean module exports 2026-01-26 14:45:26 -06:00
AGENTS.md Add core module AGENTS.md documentation (DOCS-001) 2026-01-26 14:50:52 -06:00
config.py Extend core card models with rarity tiers and card subtypes 2026-01-31 15:43:07 -06:00
engine.py Add weakness/resistance support to attack damage calculation 2026-01-26 16:04:41 -06:00
enums.py Extend core card models with rarity tiers and card subtypes 2026-01-31 15:43:07 -06:00
README.md Add Active Effects system design and module README files 2026-01-26 22:39:02 -06:00
rng.py Add game engine foundation: enums, config, and RNG modules 2026-01-24 22:14:45 -06:00
rules_validator.py Move enums to app/core/enums.py and set up clean module exports 2026-01-26 14:45:26 -06:00
turn_manager.py Implement GameService.execute_action enhancements (GS-003) 2026-01-29 15:15:34 -06:00
visibility.py Move enums to app/core/enums.py and set up clean module exports 2026-01-26 14:45:26 -06:00
win_conditions.py Move enums to app/core/enums.py and set up clean module exports 2026-01-26 14:45:26 -06:00

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 for details on this design goal.

Import Boundaries

# 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.

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.

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.

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.

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.

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.

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.

from app.core.effects import resolve_effect, EffectContext

result = resolve_effect("deal_damage", ctx)

Testing

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

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


See Also