The game board now conditionally renders prize card zones based on the RulesConfig sent from the backend: - Add rules_config field to VisibleGameState in backend (visibility.py) - Add rules_config to frontend game types and game store - Update layout.ts to accept LayoutOptions with usePrizeCards and prizeCount - Update StateRenderer to conditionally create PrizeZone objects - Update Board to handle empty prize position arrays gracefully - Add game store computed properties: rulesConfig, usePrizeCards, prizeCount - Add tests for conditional prize zone rendering When use_prize_cards is false (Mantimon TCG points system), the prize zones are not rendered, saving screen space. When true (classic Pokemon TCG mode), the correct number of prize slots is rendered based on the rules config's prize count. https://claude.ai/code/session_01AAxKmpq2AGde327eX1nzUC |
||
|---|---|---|
| .. | ||
| effects | ||
| models | ||
| __init__.py | ||
| AGENTS.md | ||
| config.py | ||
| engine.py | ||
| enums.py | ||
| README.md | ||
| rng.py | ||
| rules_validator.py | ||
| turn_manager.py | ||
| visibility.py | ||
| win_conditions.py | ||
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
- /docs/ARCHITECTURE.md - System architecture
- /docs/GAME_RULES.md - Game rules
- /docs/ACTIVE_EFFECTS_DESIGN.md - Effects system design
- effects/README.md - Effects module
- models/README.md - Models module