import numpy as np import pytest from engine.game.enums import Phase from engine.game.game_state import initialize_game class TestVerificationBatch16: @pytest.fixture def game_state(self): gs = initialize_game(use_real_data=True) if not gs.member_db: pytest.skip("Card data not loaded") gs.active_player.tapped_energy = np.zeros(20, dtype=bool) return gs def get_card_id(self, gs, card_no): for cid, card in gs.member_db.items(): if card.card_no == card_no: return cid for cid, card in gs.live_db.items(): if card.card_no == card_no: return cid pytest.fail(f"Card {card_no} not found") def _test_energy_deck_rest(self, game_state, card_no): """ Generic test for "On Play: Place 1 Energy from Energy Deck (Rest)". Text: 自分のエネルギーデッキから、エネルギーカードを1枚ウェイト状態で置く Cost: Discard 1 Hand (Type 3) """ gs = game_state card_id = self.get_card_id(gs, card_no) p1 = gs.players[0] fodder_id = self.get_card_id(gs, "PL!-sd1-001-SD") p1.hand = [card_id, fodder_id] p1.energy_deck = [888, 888] p1.energy_zone = [] gs.current_player = 0 gs.phase = Phase.MAIN gs._execute_action(1) # Play assert gs.pending_choices, "Expected pending choice (Cost)" choice_type, params = gs.pending_choices[0] if choice_type == "TARGET_HAND" and params.get("reason") == "cost": gs._handle_choice(500) else: pytest.fail(f"Expected Discard Cost, got {choice_type}") while gs.pending_effects: gs._resolve_pending_effect(0) assert len(p1.energy_zone) == 1 assert p1.tapped_energy[0] == True, "Placed energy should be rested" def _test_conditional_draw(self, game_state, card_no): """ Generic test for "On Play: If 7+ Energy, Draw 1". Text: 自分のエネルギーが7枚以上ある場合、カードを1枚引く """ gs = game_state card_id = self.get_card_id(gs, card_no) p1 = gs.players[0] p1.hand = [card_id] p1.main_deck = [888] * 5 # Setup Energy = 7 p1.energy_zone = [888] * 7 p1.tapped_energy = np.zeros(20, dtype=bool) initial_hand = 1 gs.current_player = 0 gs.phase = Phase.MAIN gs._execute_action(1) # Play if gs.triggered_abilities: pid, ab, ctx = gs.triggered_abilities.pop(0) gs._play_automatic_ability(pid, ab, ctx) # Hand: 1 (start) - 1 (play) + 1 (draw) = 1 assert len(p1.hand) == 1, "Should have drawn 1 card" # Negative Test: 6 Energy gs._reset() p1 = gs.players[0] p1.hand = [card_id] p1.energy_zone = [888] * 6 p1.main_deck = [888] * 5 gs.current_player = 0 gs.phase = Phase.MAIN gs._execute_action(1) # Play if gs.triggered_abilities: # Should check condition and fail effect or not trigger? # Logic usually puts it in triggers, then check_condition runs. pid, ab, ctx = gs.triggered_abilities.pop(0) gs._play_automatic_ability(pid, ab, ctx) # Hand: 1 (start) - 1 (play) = 0 assert len(p1.hand) == 0, "Should NOT have drawn" def _test_active_all(self, game_state, card_no): """ Generic test for "On Play: Active all members". """ gs = game_state card_id = self.get_card_id(gs, card_no) p1 = gs.players[0] p1.hand = [card_id] # Setup tapped members dummy_id = card_id p1.stage[1] = dummy_id p1.stage[2] = dummy_id p1.tapped_members[1] = True p1.tapped_members[2] = True gs.current_player = 0 gs.phase = Phase.MAIN gs._execute_action(1) # Play if gs.triggered_abilities: pid, ab, ctx = gs.triggered_abilities.pop(0) gs._play_automatic_ability(pid, ab, ctx) while gs.pending_effects: gs._resolve_pending_effect(0) assert not p1.tapped_members[1] assert not p1.tapped_members[2] def test_plsp_sd1_014_sd_liella_energy(self, game_state): self._test_energy_deck_rest(game_state, "PL!SP-sd1-014-SD") def test_plsp_sd1_016_sd_liella_energy(self, game_state): self._test_energy_deck_rest(game_state, "PL!SP-sd1-016-SD") def test_plsp_pr_003_pr_liella_draw(self, game_state): self._test_conditional_draw(game_state, "PL!SP-PR-003-PR") def test_plsp_pr_007_pr_liella_draw(self, game_state): self._test_conditional_draw(game_state, "PL!SP-PR-007-PR") def test_plsp_pr_010_pr_liella_draw(self, game_state): self._test_conditional_draw(game_state, "PL!SP-PR-010-PR") def test_pl_bp3_005_p_active_all(self, game_state): self._test_active_all(game_state, "PL!-bp3-005-P") def test_pl_bp3_005_r_active_all(self, game_state): self._test_active_all(game_state, "PL!-bp3-005-R") def test_pl_sd1_019_sd_start_dash(self, game_state): """ Card: PL!-sd1-019-SD (Start Dash!!) Text: [Live Success] Look 3 from deck top. Place any number on top in any order, rest to WR. """ gs = game_state card_id = self.get_card_id(gs, "PL!-sd1-019-SD") p1 = gs.players[0] # Setup Live Success # Need to simulate Live Success Trigger # This is complex. We can inject the trigger manually. # Mock Deck p1.main_deck = [901, 902, 903, 904, 905] # Inject Trigger # TriggerType.ON_LIVE_SUCCESS (3) # We need the ability object card = gs.live_db[card_id] ability = card.abilities[0] # Assuming first ability gs.triggered_abilities.append((0, ability, {})) # Execute pid, ab, ctx = gs.triggered_abilities.pop(0) gs._play_automatic_ability(pid, ab, ctx) # Effect: Look 3 assert gs.pending_choices, "Expected Look 3 Choice" choice_type, params = gs.pending_choices[0] # Verify params # Should involve reordering/placing on top? # Text: "好きな枚数を好きな順番でデッキの上に置き" (Place any number in any order on top) # Implementation might be ORDER_DECK or similar? # Or Look -> Select to Top -> Discard Rest. # Based on logs/bytecode: EffectType 4 (LOOK_DECK) -> EffectType 27 (LOOK_AND_CHOOSE) -> EffectType 18 (MOVE_TO_DECK)? # Implementation details vary. # If it's a standard choice: # Assuming we can choose cards to keep on top. # Just verifying we got the choice is a good smoke test for now. assert choice_type in ["SELECT_FROM_LIST", "ORDER_DECK", "Look"] def test_pl_bp3_015_n_vanilla(self, game_state): gs = game_state card_id = self.get_card_id(gs, "PL!-bp3-015-N") card = gs.member_db.get(card_id) assert not card.abilities def test_pl_bp3_016_n_vanilla(self, game_state): gs = game_state card_id = self.get_card_id(gs, "PL!-bp3-016-N") card = gs.member_db.get(card_id) assert not card.abilities