def run_game(black: AbstractPlayer, white: AbstractPlayer, logger=None, verbose=True,**kwargs) \ -> Generator[Tuple[Game, List[Tuple[Union[Space, Tuple[Space, Space]], Direction]]], None, None]: """Runs a game instance and prints the progress / current state at every turn. Args: black: An `abalone.abstract_player.AbstractPlayer` white: An `abalone.abstract_player.AbstractPlayer` **kwargs: These arguments are passed to `abalone.game.Game.__init__` Yields: A tuple of the current `abalone.game.Game` instance and the move history at the start of the game and after\ every legal turn. """ game = Game() moves_history = [] # yield game, moves_history while True: score = game.get_score() score_str = f'BLACK {score[0]} - WHITE {score[1]}' if verbose: print(score_str, '', sep='\n') game.get_plot() plt.show() winner = _get_winner(score) if winner is not None: print(f'{winner.name} won!') break try: move = black.turn( game, moves_history) if game.turn is Player.BLACK else white.turn( game, moves_history) if logger is not None: logger.log_turn(game, move) if verbose: print(_format_move(game.turn, move, len(moves_history)), end='\n\n') game.move(*move) game.switch_player() moves_history.append(move) # yield game, moves_history except IllegalMoveException as ex: print( f'{game.turn.name}\'s tried to perform an illegal move ({ex})\n' ) break except: print(f'{game.turn.name}\'s move caused an exception\n') print(format_exc()) break return game, winner, logger
def __init__(self, id, active_player=0, history=None, *args, **kwargs): self.state = Game() # update state because a new instance is created before every turn and previous state cannot be accessed if history is not None: board = deepcopy(history[-1]) for row in range(len(board)): for col in range(len(board[row])): board[row][col] = Marble[board[row][col]] self.state.board = board if active_player == 1: self.state.switch_player() super().__init__(id, active_player, history, *args, **kwargs)
def get_moves_gif(moves: List[str], fps=1) -> Path: game = Game() figures = [] dir_path = Path('videos', hashlib.md5(str(moves).encode()).hexdigest()) gif_path = Path(dir_path, 'moves.gif') if gif_path.exists(): print(f'{dir_path} already exists. Skipping') return gif_path dir_path.mkdir(parents=True, exist_ok=True) for i, move in tqdm(enumerate(moves)): game.move(*move) game.switch_player() fig = game.get_plot() plt.savefig(Path(dir_path, f'm{i}.jpg')) plt.close() frames = [] for filename in glob.glob(f'{dir_path}/*.jpg'): frames.append(imageio.imread(filename)) imageio.mimsave(gif_path.as_posix(), frames, format='GIF', duration=len(frames) // fps) return gif_path
def turn(self, game: Game, moves_history: List[Tuple[Union[Space, Tuple[Space, Space]], Direction]]) \ -> Tuple[Union[Space, Tuple[Space, Space]], Direction]: legal_moves = list(game.generate_legal_moves()) move_type = _prompt_move_type() marble1 = _prompt_marble1(move_type, legal_moves) if move_type == 'In-line': marbles = marble1 else: marbles = (marble1, _prompt_marble2(marble1, legal_moves)) return marbles, _prompt_direction(marbles, legal_moves)
class AbaloneInstance(GameInstance): GAME_NAME = "Abalone" AMOUNT_PLAYERS = 2 def __init__(self, id, active_player=0, history=None, *args, **kwargs): self.state = Game() # update state because a new instance is created before every turn and previous state cannot be accessed if history is not None: board = deepcopy(history[-1]) for row in range(len(board)): for col in range(len(board[row])): board[row][col] = Marble[board[row][col]] self.state.board = board if active_player == 1: self.state.switch_player() super().__init__(id, active_player, history, *args, **kwargs) def initialize_board(self): return _serializable_board(self.state.board) def turn(self, vars): self.state.move(*_vars_to_move_args(vars)) self.board = _serializable_board(self.state.board) def valid(self, vars): game = deepcopy(self.state) try: game.move(*_vars_to_move_args(vars)) return True except IllegalMoveException as ex: return False def won_check(self): score = self.state.get_score() if 8 not in score: return False self.won(0 if score[0] == 8 else 1) return True def next_player(self): self.state.switch_player() super().next_player()
def turn(self, game: Game, moves_history: List[Tuple[Union[Space, Tuple[Space, Space]], Direction]]) \ -> Tuple[Union[Space, Tuple[Space, Space]], Direction]: return choice(list(game.generate_legal_moves()))
def handle_available(self, game_ids=None): """ Handles the games specified in "game_ids" or all started games. # TODO auto create games if no games available Example usage: while True: api.handle_available() time.sleep(10) :param game_ids: Optional game_ids :return: None """ self.check_and_update_token() if game_ids is None: game_ids = self.get_games(own=True, game_state=GameState.STARTED) for game_id in game_ids: game_status = self.status(game_id) if self.is_my_turn(game_id, game_status=game_status): game_name = game_status['game_name'] self.log("handle_available", "Handling", game_id, game_name) if game_name == "Core": pos_x, pos_y = self.func( game_status['history'][-1]['board'], BOAIapi.get_symbol(game_status["active_player"])) self.log( "handle_available", "Moving to (" + str(pos_x) + ", " + str(pos_y) + ")") self.make_turn(game_id, [pos_x, pos_y]) elif game_name == "Abalone": # deserialize game from abalone.enums import Marble from abalone.game import Game from copy import deepcopy board = deepcopy(game_status["history"][-1]["board"]) for row in range(len(board)): for col in range(len(board[row])): board[row][col] = Marble[board[row][col]] game = Game() game.board = board if game_status["active_player"] == 1: game.switch_player() # TODO: moves_history is unsupported by API moves_history = None marbles, direction = self.func(game, moves_history) turn = {} if isinstance(marbles, tuple): turn["marble1"] = marbles[0].name turn["marble2"] = marbles[1].name marbles_str = f"({turn['marble1']}, {turn['marble2']})" move_type = "(broadside)" else: turn["marble1"] = marbles.name marbles_str = turn["marble1"] move_type = "(in-line)" turn["direction"] = direction.name self.log( "handle_available", f"Moving {marbles_str} in direction {turn['direction']} {move_type}" ) self.make_turn(game_id, turn) else: self.log("handle_available", "Handled", game_id, "(Not your turn)") self.log("handle_available", "Done handling available")