Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import traceback | |
| from typing import Callable | |
| # Ensure parent directory is in path | |
| sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) | |
| from game.game_state import GameState, Phase | |
| class StateVerifier: | |
| """Helper class to verify game state properties.""" | |
| def __init__(self, state: GameState): | |
| self.state = state | |
| def assert_phase(self, expected_phase: Phase): | |
| if self.state.phase != expected_phase: | |
| raise AssertionError(f"Expected phase {expected_phase}, but got {self.state.phase}") | |
| def assert_player_turn(self, expected_player: int): | |
| if self.state.current_player != expected_player: | |
| raise AssertionError(f"Expected player {expected_player}'s turn, but got {self.state.current_player}") | |
| def assert_hand_contains(self, player_id: int, card_id: int): | |
| if card_id not in self.state.players[player_id].hand: | |
| raise AssertionError( | |
| f"Player {player_id} hand does not contain card {card_id}. Hand: {self.state.players[player_id].hand}" | |
| ) | |
| def assert_hand_does_not_contain(self, player_id: int, card_id: int): | |
| if card_id in self.state.players[player_id].hand: | |
| raise AssertionError(f"Player {player_id} hand contains card {card_id} but shouldn't.") | |
| def assert_stage_card(self, player_id: int, position: int, card_id: int): | |
| actual = self.state.players[player_id].stage[position] | |
| if actual != card_id: | |
| raise AssertionError(f"Player {player_id} stage[{position}] expected {card_id}, got {actual}") | |
| def assert_life_at(self, player_id: int, valid_hp: int): | |
| # This is a bit complex as HP is derived from live zone, but for now we check length of lives | |
| lives = len(self.state.players[player_id].live_zone) | |
| if lives != valid_hp: | |
| raise AssertionError(f"Player {player_id} expected {valid_hp} lives, got {lives}") | |
| class ActionSequence: | |
| """Defines and executes a sequence of actions.""" | |
| def __init__(self, state: GameState = None): | |
| self.state = state if state else GameState() | |
| self.verifier = StateVerifier(self.state) | |
| self.history = [] | |
| def setup_inject(self, player_id: int, card_id: int, zone: str, position: int = -1): | |
| """Inject a card before the sequence starts properly.""" | |
| print(f"[SETUP] Inject P{player_id} {card_id} -> {zone}@{position}") | |
| self.state.inject_card(player_id, card_id, zone, position) | |
| def action_step(self, action_id: int, comment: str = ""): | |
| """Execute a single game action.""" | |
| print(f"[ACTION] {comment} (ID: {action_id})") | |
| # Validate legality | |
| legal_actions = self.state.get_legal_actions() | |
| if not legal_actions[action_id]: | |
| raise AssertionError(f"Action {action_id} is improperly illegal in phase {self.state.phase}") | |
| self.state = self.state.step(action_id) | |
| self.verifier.state = self.state # Update verifier ref | |
| self.history.append((action_id, comment)) | |
| def action_auto(self, max_steps: int = 10): | |
| """Advance through automatic phases.""" | |
| print(f"[AUTO] Advancing up to {max_steps} steps...") | |
| steps = 0 | |
| from game.game_state import Phase # Local import to avoid circular dependency issues if any | |
| while steps < max_steps and not self.state.is_terminal(): | |
| if self.state.phase in (Phase.ACTIVE, Phase.ENERGY, Phase.DRAW, Phase.PERFORMANCE_P1, Phase.PERFORMANCE_P2): | |
| self.state = self.state.step(0) | |
| self.verifier.state = self.state | |
| steps += 1 | |
| continue | |
| break | |
| print(f"[AUTO] Done after {steps} steps. Phase: {self.state.phase}") | |
| def verify(self, check_func: Callable[[StateVerifier], None]): | |
| """Run a custom verification function.""" | |
| print("[VERIFY] Running checks...") | |
| check_func(self.verifier) | |
| print("[VERIFY] Passed.") | |
| def run_wrapper(self, func): | |
| """Run a function and handle errors nicely.""" | |
| try: | |
| func() | |
| print("\n✅ Sequence Completed Successfully") | |
| except AssertionError as e: | |
| print(f"\n❌ Verification Failed: {e}") | |
| traceback.print_exc() | |
| sys.exit(1) | |
| except Exception as e: | |
| print(f"\n💥 Runtime Error: {e}") | |
| traceback.print_exc() | |
| sys.exit(1) | |