mantimon-tcg/backend/app/core/models/enums.py
Cal Corum 32541af682 Add card/action models with stage/variant separation
- Add CardDefinition and CardInstance models for card templates and in-game state
- Add Attack, Ability, and WeaknessResistance models for Pokemon card components
- Add 11 action types as discriminated union (PlayPokemon, Evolve, Attack, etc.)
- Split PokemonStage (BASIC, STAGE_1, STAGE_2) from PokemonVariant (NORMAL, EX, GX, V, VMAX, VSTAR)
- Stage determines evolution mechanics, variant determines knockout points
- Update PrizeConfig to use variant for knockout point calculation
- VSTAR and VMAX both worth 3 points; EX, GX, V worth 2 points; NORMAL worth 1 point

Tests: 204 passing, all linting clean
2026-01-24 22:35:31 -06:00

186 lines
5.5 KiB
Python

"""Enumeration types for the Mantimon TCG game engine.
This module defines all enum types used throughout the game engine. We use StrEnum
for JSON serialization compatibility - enum values serialize as strings directly.
Note on extensibility: While these enums define the standard types, the game engine
is designed to be configurable. Custom energy types or card types could be added
via configuration for free play mode.
"""
from enum import StrEnum
class CardType(StrEnum):
"""The primary type of a card.
Every card in the game belongs to exactly one of these types, which determines
how it can be played and what rules apply to it.
"""
POKEMON = "pokemon"
TRAINER = "trainer"
ENERGY = "energy"
class PokemonStage(StrEnum):
"""The evolution stage of a Pokemon card.
Determines how the Pokemon can be played:
- BASIC: Can be played directly from hand to bench
- STAGE_1: Must evolve from a Basic Pokemon
- STAGE_2: Must evolve from a Stage 1 Pokemon
Note: This is separate from PokemonVariant (EX, V, GX, etc.) which affects
knockout points but not evolution mechanics.
"""
BASIC = "basic"
STAGE_1 = "stage_1"
STAGE_2 = "stage_2"
class PokemonVariant(StrEnum):
"""Special variant classification for Pokemon cards.
Variants affect knockout points and may have special rules, but are
orthogonal to evolution stage. A card can be a "Basic EX" or "Stage 2 GX".
- NORMAL: Standard Pokemon, worth 1 knockout point
- EX: Worth 2 knockout points
- GX: Worth 2 knockout points, has GX attack (once per game)
- V: Worth 2 knockout points
- VMAX: Evolves from V variant, worth 3 knockout points
- VSTAR: Evolves from V variant, worth 3 knockout points, has VSTAR power
"""
NORMAL = "normal"
EX = "ex"
GX = "gx"
V = "v"
VMAX = "vmax"
VSTAR = "vstar"
class EnergyType(StrEnum):
"""Energy types available in the game.
Based on modern Pokemon TCG with 10 types. Colorless is special - any energy
can satisfy colorless requirements.
Note: The engine supports all types, but specific games can restrict which
types are enabled via RulesConfig.
"""
COLORLESS = "colorless"
DARKNESS = "darkness"
DRAGON = "dragon"
FIGHTING = "fighting"
FIRE = "fire"
GRASS = "grass"
LIGHTNING = "lightning"
METAL = "metal"
PSYCHIC = "psychic"
WATER = "water"
class TrainerType(StrEnum):
"""Subtypes of Trainer cards.
Each subtype has different rules for how many can be played per turn:
- ITEM: Unlimited per turn
- SUPPORTER: One per turn
- STADIUM: One per turn, stays in play
- TOOL: Attached to Pokemon, unlimited per turn
"""
ITEM = "item"
SUPPORTER = "supporter"
STADIUM = "stadium"
TOOL = "tool"
class TurnPhase(StrEnum):
"""Phases within a player's turn.
Turn structure:
1. SETUP: Initial game setup (draw starting hand, place basics, set prizes)
2. DRAW: Draw a card from deck
3. MAIN: Play cards, attach energy, evolve, use abilities, retreat
4. ATTACK: Declare and resolve an attack (optional)
5. END: Apply end-of-turn effects, check knockouts, score points
Valid transitions:
- SETUP -> DRAW (game start, first player's turn)
- DRAW -> MAIN
- MAIN -> ATTACK or END (can skip attack)
- ATTACK -> END
- END -> DRAW (next player's turn)
"""
SETUP = "setup"
DRAW = "draw"
MAIN = "main"
ATTACK = "attack"
END = "end"
class StatusCondition(StrEnum):
"""Status conditions that can affect Pokemon in play.
Status conditions have specific effects and removal conditions:
- POISONED: 10 damage between turns; removed by evolution, retreat, or card effect
- BURNED: 20 damage between turns + flip to remove; removed on heads
- ASLEEP: Cannot attack or retreat; removed on heads flip; overrides PARALYZED/CONFUSED
- PARALYZED: Cannot attack or retreat for 1 turn; removed at end of next turn;
overrides ASLEEP/CONFUSED
- CONFUSED: Flip to attack, 30 self-damage on tails; removed by evolution/retreat;
overrides ASLEEP/PARALYZED
Note: POISONED and BURNED stack with other conditions. ASLEEP, PARALYZED, and
CONFUSED override each other (only one can be active at a time).
"""
POISONED = "poisoned"
BURNED = "burned"
ASLEEP = "asleep"
PARALYZED = "paralyzed"
CONFUSED = "confused"
class ActionType(StrEnum):
"""Types of actions a player can take during their turn.
Each action type has specific validation rules and can only be performed
during certain phases. See rules_validator.py for details.
"""
PLAY_POKEMON = "play_pokemon"
EVOLVE = "evolve"
ATTACH_ENERGY = "attach_energy"
PLAY_TRAINER = "play_trainer"
USE_ABILITY = "use_ability"
ATTACK = "attack"
RETREAT = "retreat"
PASS = "pass"
class GameEndReason(StrEnum):
"""Reasons why a game ended.
Used in GameState.end_reason to indicate how the game concluded:
- PRIZES_TAKEN: A player took all required prize points
- NO_POKEMON: A player has no Pokemon in play (active or bench)
- DECK_EMPTY: A player cannot draw a card at the start of their turn
- RESIGNATION: A player resigned from the match
- TIMEOUT: A player ran out of time (multiplayer only)
- DRAW: The game ended in a draw (tie on points at timer expiration)
"""
PRIZES_TAKEN = "prizes_taken"
NO_POKEMON = "no_pokemon"
DECK_EMPTY = "deck_empty"
RESIGNATION = "resignation"
TIMEOUT = "timeout"
DRAW = "draw"