Beispiel #1
0
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
Beispiel #2
0
    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)
Beispiel #3
0
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)
Beispiel #5
0
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()))
Beispiel #7
0
    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")