import pytest from engine.game.card_database import CardDatabase from engine.game.game_state import GameState, Phase from engine.models.enums import TriggerType @pytest.fixture def db(): return CardDatabase() def test_on_live_start_interactivity(db): state = GameState() # P1 deck and hand state.initialize_game(p0_deck=[1], p1_deck=[1], p0_energy=[101], p1_energy=[101], p0_lives=[401], p1_lives=[401]) # Manually set a live card with OnLiveStart choice # PL!N-bp3-017-N Miyashita Ai has [OnLiveStart] choice: LOOK_AND_CHOOSE(1) -> Hand, Discard # Let's find a card with OnLiveStart. PL!N-bp1-118-R has [OnLiveStart] Look 3, Order Deck. # Wait, my fix for LOOK_AND_CHOOSE_ORDER (ORDER_DECK) might not be "interactive" in the sense of a choice index # if it's just a reverse (Rule 10). # But ORDER_DECK in logic.rs line 1829 is NOT interactive (it just reverses). # Let's find a REALLY interactive one. # PL!N-sd3-002-SD (DiverDiva) has [OnLiveStart] choice: LOOK_AND_CHOOSE(3) -> Hand, Discard. # Actually, let's just MOCK a card in the state if possible, or pick a known one. # We'll use a card that has LOOK_AND_CHOOSE (Effect 27). # PL!N-bp1-053-R (Mia Taylor) has [OnPlay] Look 3, Choose 1 to Hand, Rest to Discard. # Let's find an OnLiveStart with choice. # PL!N-bp3-017-N is a good candidate if BP3 is loaded. # Diagnostic: Check if we have a card with OnLiveStart + Choice found_card = None for cid, card in db.lives.items(): for ab in card.abilities: if ab.trigger == TriggerType.OnLiveStart: # Check bytecode for O_LOOK_AND_CHOOSE (41) if 41 in ab.bytecode: found_card = card break if found_card: break if not found_card: # Fallback: find any OnLiveStart and we'll just check if it triggers for cid, card in db.lives.items(): if any(ab.trigger == TriggerType.OnLiveStart for ab in card.abilities): found_card = card break assert found_card is not None, "Need a live card with OnLiveStart for test" state.players[0].live_zone[0] = found_card.card_id state.phase = Phase.LiveSet # Move to Performance state.step(db, 0) # Confirm Live Set (or Pass) -> Moves to PerformanceP1 # do_performance_phase should trigger OnLiveStart and move to Response assert state.phase == Phase.Response assert state.pending_card_id == found_card.card_id # Execute a choice (AID 550 + 0*100 + 0*10 + 0 = 550) # The AID depends on slot and ability index. # Assuming slot 0, ab 0, choice 0. state.step(db, 550) # After choice, it should return to Performance (since last_phase was PerformanceP1) # Actually, it might return to PerformanceP1. assert state.phase in [Phase.PerformanceP1, Phase.PerformanceP2] assert state.pending_ctx is None def test_on_live_success_interactivity(db): state = GameState() state.initialize_game(p0_deck=[1], p1_deck=[1], p0_energy=[101], p1_energy=[101], p0_lives=[401], p1_lives=[401]) # Find a card with OnLiveSuccess and choice found_card = None for cid, card in db.lives.items(): for ab in card.abilities: if ab.trigger == TriggerType.OnLiveSuccess and 41 in ab.bytecode: found_card = card break if found_card: break if not found_card: pytest.skip("No LiveCard with OnLiveSuccess choice found in DB") state.players[0].live_zone[0] = found_card.card_id # Ensure enough hearts for success state.players[0].heart_buffs[0] = [10] * 7 state.phase = Phase.PerformanceP1 # Advance to end of performance state.step(db, 0) # This might call do_performance_phase # After performance, it moves to LiveResult # do_live_result should move card to Success and trigger OnLiveSuccess -> Response assert state.phase == Phase.Response assert state.pending_card_id == found_card.card_id # Execute choice state.step(db, 550) # Should return to LiveResult to finalize # Wait, if finalized, it moves to Active phase of next turn. assert state.phase in [Phase.LiveResult, Phase.Active]