import json import engine_rust as lovecasim_engine import pytest @pytest.fixture def env(): # Load real data with open("data/cards_compiled.json", "r", encoding="utf-8") as f: data = json.load(f) # Nico (ID 80) # Ensure ID 80 exists if "80" not in data["member_db"]: # Fallback or error pass db = lovecasim_engine.PyCardDatabase(json.dumps(data)) state = lovecasim_engine.PyGameState(db) # P0 gets Nico (80) in hand p0_deck = [1] * 50 state.initialize_game(p0_deck, [1] * 50, [20001] * 10, [20001] * 10, [10001], [10001]) # Force hand to have 80 at index 0 state.set_hand_cards(0, [80]) # Add energy for cost (Nico cost 2) p0 = state.get_player(0) p0.energy_zone = [20001, 20001] # 2 energy p0.tapped_energy = [False, False] state.set_player(0, p0) return db, state def test_nico_color_select_interactivity(env): db, state = env # Phase Main state.phase = 4 # Play Nico (80) to Slot 0 # Action 1000 + 0*100 + 0*10 + 0 = 1000 state.step(1000) # Nico has OnPlay but checks for cost>13 member. Likely no trigger or condition fail. # Check if we are back in Main if state.phase == 10: # If it triggered OnPlay, finish it. # But we assume the conditions fail (empty board). # Actually OnPlay condition: COUNT_STAGE {MIN=1, FILTER="COST_GE_13"} # Board is empty, so condition fails. pass assert state.phase == 4, "Should be in Main phase after play" # Now Activate Ability: # Trigger: ACTIVATED # Effect: TAP_PLAYER(1) -> SELF (Cost effectively via logic?) No, effect. # Logic: EFFECT: COLOR_SELECT(1); SELECT_MODE(1); ... # Action 200 (Activate Slot 0 Ability 0) -> Nico has 2 abilities. Activated is #1 (index 1). # So Activate Slot 0 Ability 1 -> Action 200 + 0*10 + 1 = 201 state.step(201) # EXPECTATION: Should enter Response Phase for COLOR_SELECT assert state.phase == 10 print(f"Phase is {state.phase} (Response)") # Check Legal Actions: Should be choices 550+ # 550 + 0*100 + 1*10 + c => 560, 561, ... actions = state.get_legal_action_ids() assert 560 in actions # Step 1: Select Color (Choice 0 = Pink) # If bug exists: It uses 0 for Color AND Mode, then finishes. # If fixed: It consumes 0 for Color, then pauses for Mode. state.step(560) # With fix, should STILL be in Response phase (for SELECT_MODE) assert state.phase == 10, "Should remain in Response phase for second input (Select Mode)" # Step 2: Select Mode (Choice 0) state.step(560) # Now it should finish assert state.phase == 4, "Should return to Main phase after second input"