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
- Add DamageCalculationResult model for transparent damage breakdown
- Implement _calculate_attack_damage with W/R modifiers (additive/multiplicative)
- Add _execute_attack_effect for future effect system integration
- Add _build_attack_message for detailed damage breakdown in messages
- Update _execute_attack to use new calculation pipeline
- Bulbasaur now properly weak to Lightning in walkthrough demo
New features:
- Weakness applies bonus damage (additive +X or multiplicative xN)
- Resistance reduces damage (minimum 0)
- State changes include weakness/resistance details for UI
- Messages show damage breakdown (e.g. 'base 10 +20 weakness')
Tests: 7 new tests covering additive/multiplicative W/R, type matching,
minimum damage floor, knockout triggers, and state change details
- Add await to engine.execute_action() calls (energy attach and attack)
- Update entry point to use asyncio.run()
- Fix game creation result handling (use game_creation.game)
- Fix AttachEnergyAction parameter name (energy_card_id)
Creates comprehensive documentation for AI agents working with app/core/:
- Architecture overview with component diagram
- Import patterns (correct enum imports from app.core.enums)
- Core patterns: game creation, action execution, effects, config
- Key classes: GameState, PlayerState, CardDefinition, CardInstance, Zone
- Testing patterns with SeededRandom for determinism
- Security rules for hidden information
- Module independence guidelines for offline fork support
- File organization and quick commands
Updates PROJECT_PLAN.json: 31/32 tasks complete.
Creates a comprehensive interactive demo that walks through:
- Card definition creation
- Rules configuration
- Deck building
- Game initialization via GameEngine
- Setup phase with Basic Pokemon placement
- Full turn cycle (draw, main, attack, end phases)
Uses colored terminal output and 'press Enter' prompts for
step-by-step exploration of the core game engine.
Architectural refactor to eliminate circular imports and establish clean
module boundaries:
- Move enums from app/core/models/enums.py to app/core/enums.py
(foundational module with zero dependencies)
- Update all imports across 30 files to use new enum location
- Set up clean export structure:
- app.core.enums: canonical source for all enums
- app.core: convenience exports for full public API
- app.core.models: exports models only (not enums)
- Add module exports to app/core/__init__.py and app/core/effects/__init__.py
- Remove circular import workarounds from game_state.py
This enables app.core.models to export GameState without circular import
issues, since enums no longer depend on the models package.
All 826 tests passing.
Relocated SYSTEM_REVIEW.md and PROJECT_PLAN_ENERGY_EVOLUTION.md from
backend/docs/legacy to project-level docs/legacy. Added docs/README.md
indexing all documentation including ARCHITECTURE.md and GAME_RULES.md.
Relocated SYSTEM_REVIEW.md and PROJECT_PLAN_ENERGY_EVOLUTION.md to
docs/legacy/ now that all issues are resolved. Added docs/README.md
with index of documentation files.
Issue #2 gap: Added 14 CardDefinition validation tests covering all
required field checks (hp, stage, pokemon_type, evolves_from, trainer_type,
energy_type) with both negative and positive test cases.
Issue #7 gap: Added 4 confusion attack engine tests covering heads/tails
outcomes, self-damage, self-KO with opponent scoring, and configurable
damage from RulesConfig.
Issue #13 documentation: Added TODO comments in engine.py and handlers.py
documenting the expected pattern for knockout detection when effect
execution is implemented. Effect handlers set knockout flags; engine
should process knockouts after all effects resolve.
825 tests passing (+17 new tests)
Effect handler exceptions now logged at ERROR level with full context:
- effect_id, source_player_id, source/target card IDs, params
- Full traceback via logger.exception()
Game still returns safe EffectResult.failure() to prevent crashes,
but debugging information is now preserved in logs.
Both deal_damage and attack_damage now check if the target is knocked out
after applying damage. If KO'd, EffectResult includes:
- details['knockout'] = True
- details['knockout_pokemon_id'] = target's instance_id
- Message includes 'knocked out!' notification
Knockout check correctly respects HP modifiers via effective_hp().
Added 9 tests covering knockout detection, HP modifier behavior,
weakness-triggered knockouts, and resistance preventing knockouts.
Added stadium_owner_id field to GameState to track who played the stadium:
- stadium_owner_id: str | None tracks the player who played the current stadium
- When a stadium is replaced, old stadium discards to OWNER's pile (not current player)
- Added stadium_owner_id to VisibleGameState for client visibility
- Updated existing test and added 2 new tests for stadium ownership
This fixes the bug where replacing an opponent's stadium would discard
to the current player's pile instead of the opponent's.
797 tests passing.
Changed forced_action from single item to FIFO queue to support
scenarios where multiple forced actions are needed simultaneously:
- forced_actions: list[ForcedAction] replaces forced_action: ForcedAction | None
- Added queue management methods:
- has_forced_action() - check if queue has pending actions
- get_current_forced_action() - get first action without removing
- add_forced_action(action) - add to end of queue
- pop_forced_action() - remove and return first action
- clear_forced_actions() - clear all pending actions
- Updated engine, turn_manager, rules_validator, and visibility filter
- Added 8 new tests for forced action queue including double knockout scenario
This fixes the bug where simultaneous knockouts (e.g., mutual poison damage)
would lose one player's select_active action due to overwriting.
795 tests passing.
Changed ability_uses_this_turn from int to dict[int, int] to track each
ability's usage independently:
- ability_uses_this_turn: dict[int, int] maps ability index to use count
- can_use_ability() now requires ability_index parameter
- Added get_ability_uses() and increment_ability_uses() helper methods
- reset_turn_state() clears the dict instead of setting to 0
This fixes the bug where using one ability could incorrectly block
another ability on the same Pokemon from being used.
789 tests passing.
Issues #2, #3, #4, #6 are still open:
- #2: CardDefinition field validation not added
- #3: end_turn() knockout processing not fixed
- #4: Win condition timing not fixed
- #6: Engine doesn't call process_knockout for status KOs
The refactor improved process_knockout() internals but didn't fix the
callers that should invoke it.
Mark issues #1, #5, #7, #8 as FIXED:
- #1: find_card_instance now includes energy_zone + attached cards
- #5: Energy stored as CardInstance objects, not just IDs
- #7: Confusion handling added to attack execution
- #8: discard_energy handler moves cards to owner's discard
Update test count to 766 and add change log section.
Major refactor to properly track attached cards and evolution history:
Model Changes (app/core/models/card.py):
- Change attached_energy from list[str] to list[CardInstance]
- Change attached_tools from list[str] to list[CardInstance]
- Add cards_underneath field for evolution stack tracking
- Update attach_energy/detach_energy to work with CardInstance
- Add attach_tool/detach_tool methods
- Add get_all_attached_cards helper
Engine Changes (app/core/engine.py):
- _execute_attach_energy: Pass full CardInstance to attach_energy
- _execute_evolve: Build evolution stack, transfer attachments, clear status
- _execute_retreat: Detached energy goes to discard pile
- Fix: Evolution now clears status conditions (Pokemon TCG standard)
Game State (app/core/models/game_state.py):
- find_card_instance now searches attached_energy, attached_tools, cards_underneath
Turn Manager (app/core/turn_manager.py):
- process_knockout: Discard all attached energy, tools, and evolution stack
Effects (app/core/effects/handlers.py):
- discard_energy: Find owner's discard pile and move detached energy there
- NEW devolve effect: Remove evolution stages with configurable destination
- Fix: Use EffectType.SPECIAL instead of non-existent EffectType.ZONE
Rules Validator (app/core/rules_validator.py):
- Update energy type checking to iterate CardInstance objects
Tests:
- Update existing tests for new CardInstance-based energy attachment
- NEW test_evolution_stack.py with 28 comprehensive tests covering:
- Evolution stack building (Basic -> Stage 1 -> Stage 2)
- Energy/tool transfer and damage carryover on evolution
- Devolve effect (single/multi stage, hand/discard destination, KO check)
- Knockout processing with all attachments going to discard
- find_card_instance for attached cards and evolution stack
All 765 tests pass.
Implements the main public API for the core game engine:
- create_game(): deck validation, shuffling, dealing hands
- execute_action(): validates and executes all 11 action types
- start_turn()/end_turn(): turn management integration
- get_visible_state(): hidden info filtering for clients
- handle_timeout(): timeout handling for turn limits
Integrates turn_manager, rules_validator, win_conditions, and
visibility filter into a cohesive orchestration layer.
22 integration tests covering game creation, action execution,
visibility filtering, and error handling.
711 tests passing (29/32 tasks complete)
SECURITY: Implement hidden information filtering to prevent cheating.
- Create VisibleGameState, VisiblePlayerState, VisibleZone models
- get_visible_state(game, player_id): filtered view for a player
- get_spectator_state(game): filtered view for spectators
Hidden Information (NEVER exposed):
- Opponent's hand contents (count only)
- All deck contents and order
- All prize card contents
- Energy deck order
Public Information (always visible):
- Active and benched Pokemon (full details)
- Discard piles (full contents)
- Energy zone (available energy)
- Scores, turn info, phase
- Stadium in play
- 44 security-critical tests verifying no information leakage
- Tests check JSON serialization for hidden card ID leaks
- Also adds test for configurable burn damage
Completes HIGH-008 and TEST-012 from PROJECT_PLAN.json
Updates security checklist: 4/5 items now verified
- Implement rules_validator.py with config-driven action validation for all 11 action types
- Implement win_conditions.py with point/prize-based, knockout, deck-out, turn limit, and timeout checks
- Add ForcedAction model to GameState for blocking actions (e.g., select new active after KO)
- Add ActiveConfig with max_active setting for future double-battle support
- Add TrainerConfig.stadium_same_name_replace option
- Add DeckConfig.starting_hand_size option
- Rename from_energy_deck to from_energy_zone for consistency
- Fix unreachable code bug in GameState.get_opponent_id()
- Add 16 coverage gap tests for edge cases (card registry corruption, forced actions, etc.)
- 584 tests passing at 97% coverage
Completes HIGH-005, HIGH-006, TEST-009, TEST-010 from PROJECT_PLAN.json
Provides a ready-to-use REPL environment with:
- Pre-configured game state with two players and active Pokemon
- Sample card definitions (Pikachu, Charmander, Bulbasaur, Potion, Energy)
- Helper functions: make_ctx(), reset_game(), show_board()
- All imports ready (effects, models, config, RNG)
Usage: cd backend && uv run python -i references/console_testing.py
Core game state models:
- Zone: Card collection with deck operations (draw, shuffle, peek, etc.)
- PlayerState: All player zones, score, and per-turn action flags
- GameState: Complete game state with card registry, turn tracking, win conditions
Test fixtures (conftest.py):
- Sample card definitions: Pokemon (Pikachu, Raichu, Charizard, EX, V, VMAX)
- Trainer cards: Item (Potion), Supporter (Professor Oak), Stadium, Tool
- Energy cards: Basic and special energy
- Pre-configured game states: empty, mid-game, near-win scenarios
- Factory fixtures for CardInstance and SeededRandom
Tests: 55 new tests for game state models (259 total passing)
Note: GameState imported directly from game_state module to avoid
circular imports with config module.
- 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
- Create core module structure with models and effects subdirectories
- Add enums module with CardType, EnergyType, TurnPhase, StatusCondition, etc.
- Add RulesConfig with Mantimon TCG defaults (40-card deck, 4 points to win)
- Add RandomProvider protocol with SeededRandom (testing) and SecureRandom (production)
- Include comprehensive tests for all modules (97 tests passing)
Defaults reflect GAME_RULES.md: Pokemon Pocket-style energy deck,
first turn can attack but not attach energy, 30-turn limit enabled.
- Initialize FastAPI backend with uv package manager
- Configure Black, Ruff, pytest, mypy in pyproject.toml
- Add health check endpoint and initial test
- Create AGENTS.md with coding guidelines for AI agents
- Add pre-commit hook to enforce linting and tests