from engine.game.enums import Phase from engine.game.game_state import GameState from engine.models.card import LiveCard, MemberCard def test_play_member_to_live_zone(): """Test playing a Member card to Live Zone (Rule 8.2.2)""" # Initialize DB to avoid empty DB issues from engine.models.card import MemberCard GameState.member_db[1] = MemberCard( card_id=1, card_no="M1", name="Test", cost=1, blades=1, hearts=[1] * 7, blade_hearts=[0] * 7 ) game = GameState() # Setup: Phase to LIVE_SET game.phase = Phase.LIVE_SET p = game.players[game.current_player] # Ensure hand has a Member card if not p.hand: p.hand.append(1) # Add dummy card # Ensure deck has cards for drawing p.main_deck = [200, 201] initial_hand_size = len(p.hand) initial_deck_size = len(p.main_deck) card_to_play = p.hand[0] # Debug legality legal_mask = game.get_legal_actions() print(f"Action 400 Legal: {legal_mask[400]}") if not legal_mask[400]: print("Legal actions indices:", [i for i, v in enumerate(legal_mask) if v]) # Action: Play first card (Action 400) # Action 400 corresponds to index 0 of hand game = game.step(400) p = game.players[game.current_player] # Assertions # 1. Card should be in Live Zone assert card_to_play in p.live_zone, f"Card {card_to_play} not in live zone {p.live_zone}" assert len(p.live_zone) == 1 # 2. Hand size should DECREASE by 1 (Play 1, Draw deferred) # The draw happens at END of LIVE_SET (Action 0) assert len(p.hand) == initial_hand_size - 1, f"Hand size {len(p.hand)} != {initial_hand_size - 1}" # Deck should be same until draw assert len(p.main_deck) == initial_deck_size def test_live_zone_cleanup(): """Test cleanup of non-Live cards at start of Performance (Rule 8.3.4)""" game = GameState() p = game.active_player # Setup: Inject 1 Member (ID < 100) and 1 Live (ID > 100) member_id = 99 live_id = 101 # Mock DB presence # Add required fields for MemberCard GameState.member_db[member_id] = MemberCard( card_id=member_id, card_no="M1", name="M", cost=1, blades=1, hearts=[1, 0, 0, 0, 0, 0, 0], blade_hearts=[1, 0, 0, 0, 0, 0, 0], ) # Ensure live_id is in live_db so it isn't cleaned up GameState.live_db[live_id] = LiveCard(card_id=live_id, card_no="L1", name="L", score=1, required_hearts=[0] * 7) p.live_zone = [member_id, live_id] p.live_zone_revealed = [False, False] p.main_deck = [200] # Force Phase to PERFORMANCE_P1 (or whichever matches active player) # PhaseMixin._do_performance checks current player game.phase = Phase.PERFORMANCE_P1 if game.current_player == 0 else Phase.PERFORMANCE_P2 # We need to trigger the performance start logic. # calling step(0) (Pass) generally triggers processing if we are in that phase p_idx = game.active_player.player_id game = game.step(0) p = game.players[p_idx] # Keep checking the same player # Check Cleanup # Member ID should be gone (moved to discard) # Live ID should remain (or be processed/failed, but initially it stays for check) # Note: _do_performance might discard Live card if logic runs and fails immediately # But specifically, the member card is discarded due to "Not being a Live Card" # whereas the Live card is discarded due to "Failure" later. # To differentiate, we can check logs or step through. # But result-wise: Member card MUST be in discard. assert member_id not in p.live_zone assert member_id in p.discard # If requirements fail (which they will with 0 hearts on stage), live_id also goes to discard # But let's verification focus on the Member ID being handled.