import os import sys # Add project root to path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../"))) import os from engine.game.data_loader import CardDataLoader from engine.game.enums import Phase from engine.game.game_state import GameState # Mock DB loader if needed, or use real one def get_test_db(): base_path = os.path.dirname(os.path.abspath(__file__)) project_root = os.path.abspath(os.path.join(base_path, "../../../")) cards_path = os.path.join(project_root, "data/cards.json") loader = CardDataLoader(cards_path) return loader.load() def test_order_deck_logic(): m, l, e = get_test_db() # Initialize DB for GameState GameState.initialize_class_db(m, l) GameState.energy_db = e GameState._init_jit_arrays() gs = GameState() p0 = gs.players[0] # Find PL!N-bp1-002-P (Nakasuv Kasumi) # Trigger: ON_PLAY -> LOOK_AND_CHOOSE_ORDER(3) -> DECK_TOP target_card_no = "PL!N-bp1-002-P" target_card_id = -1 for cid, card in m.items(): if card.card_no == target_card_no: target_card_id = int(cid) break assert target_card_id != -1, f"Card {target_card_no} not found in DB" # Isolate card in hand, clear deck to controllable state p0.hand = [target_card_id] p0.energy_zone = [20000, 20000] # Enough energy # Fix: Ensure tapped_energy is numpy array import numpy as np p0.tapped_energy = np.zeros(100, dtype=bool) p0.tapped_energy[0] = False p0.tapped_energy[1] = False # Setup Deck: [C, B, A] -> Top is A # We want known cards to verify ordering # Let's use some dummy IDs if possible or just other members deck_cards = [1001, 1002, 1003, 1004, 1005] # Assumptions p0.deck = deck_cards[:] # Setup Phase gs.phase = Phase.MAIN gs.current_player = 0 gs.turn = 1 print("\n--- Playing Card ---\n") # Play to Center (Slot 1). Action ID: 1 + 0*3 + 1 = 2 gs.step(2) print("DEBUG RULE LOG:", gs.rule_log) # 1. Verify we paused for ORDER_DECK assert gs.phase == Phase.RESPONSE, f"Expected Response phase, got {gs.phase}" assert gs.pending_choice_type == "ORDER_DECK", f"Expected ORDER_DECK choice, got {gs.pending_choice_type}" # 2. Verify looked_cards populated looked = p0.looked_cards print(f"Looked Cards: {looked}") assert len(looked) == 3, f"Expected 3 looked cards, got {len(looked)}" # Should be the popped cards from deck. Since deck pops from end: # Deck was [..., 1003, 1004, 1005] # Pop 1: 1005, Pop 2: 1004, Pop 3: 1003 # Looked should be [1005, 1004, 1003] (or visible order) # 3. Check Legal Actions # Should offer choices 0, 1, 2 (corresponding to the 3 cards) # Action ID range: 550 + area_idx*100 + ab_idx*10 + c # area_idx = 1 (Center) # ab_idx for OnPlay usually -1 -> mapped to 0 safely in our new logic? # Let's check get_legal_actions output mask legal_mask = gs.get_legal_actions() legal_indices = [i for i, v in enumerate(legal_mask) if v] print(f"Legal Actions: {legal_indices}") # Calculate Expected IDs # area=1, ab=0 (safe_ab), c=0..2 # 550 + 100 + 0 + 0 = 650 # 550 + 100 + 0 + 1 = 651 # 550 + 100 + 0 + 2 = 652 expected_ids = [650, 651, 652] for eid in expected_ids: assert eid in legal_indices, f"Expected Action ID {eid} not found in {legal_indices}" print("\n--- Selecting First Card to Top ---\n") # Choose Index 1 (Card 1004) to put on TOP gs.step(651) # 4. Verify Card Moved # Deck should now have 1004 on top (end of list) assert p0.deck[-1] == looked[1], "Chosen card not on top of deck" # 5. Verify Loop (Still in Response, fewer cards) assert gs.phase == Phase.RESPONSE, "Should still be in Response phase for next card" assert len(p0.looked_cards) == 2, "Should have 2 cards left in looked_cards" print("\n--- Discarding Rest ---\n") # If we want to test "Done"/Discard logic, we need to know what ID triggers that. # In my implementation plan, I said "Invalid choice implies discard rest". # But get_legal_actions only gives valid choices [0, 1]. # Wait, the logic handles "Invalid choice" but UI prevents it usually. # The logic says: `if choice >= 0 && choice < looked_len: ... else: discard all` # So we need to send an action that maps to a choice >= looked_len? # Or maybe we rely on the fact that we can just pick all cards one by one. # Let's pick another card. Index 0 of REMAINING list. # Remaining: [1005, 1003] (Original 0 and 2) # We pick 1005 (Current Index 0) gs.step(650) # Same ID 650 is valid for index 0 assert p0.deck[-1] == looked[0], "Next chosen card not on top" assert len(p0.looked_cards) == 1 # Pick last card gs.step(650) assert p0.deck[-1] == looked[2], "Last card not on top" assert len(p0.looked_cards) == 0 # 6. Verify Phase Transition assert gs.phase == Phase.MAIN, "Should return to Main phase after cards depleted" print("Test Passed: O_ORDER_DECK logic verified.") if __name__ == "__main__": test_order_deck_logic()