Exemplo n.º 1
0
    def test_feature4(self):
        # |==============|
        # |              |
        # |              |
        # |              |
        # |              |
        # |    O         |
        # |    X         |
        # |==============|
        # |0 1 2 3 4 5 6 |
        b_1_col2 = Board()
        b_1_col2.drop_piece(2, PLAYER_1)
        b_1_col2.drop_piece(2, PLAYER_2)

        self.assertEqual(heuristic_1.feature4(b_1_col2, PLAYER_1), float(120))

        # |==============|
        # |              |
        # |              |
        # |              |
        # |              |
        # |    O     X   |
        # |    X     O   |
        # |==============|
        # |0 1 2 3 4 5 6 |
        b_1_col2_1_col5 = Board()
        b_1_col2_1_col5.drop_piece(2, PLAYER_1)
        b_1_col2_1_col5.drop_piece(5, PLAYER_2)
        b_1_col2_1_col5.drop_piece(5, PLAYER_1)
        b_1_col2_1_col5.drop_piece(2, PLAYER_2)

        self.assertEqual(heuristic_1.feature4(b_1_col2_1_col5, PLAYER_1),
                         float(190))
Exemplo n.º 2
0
def generate_move_minimax(
    board: Board, player: Player, saved_state: Optional[SavedState]
) -> Tuple[PlayerAction, Optional[SavedState]]:
    """
    Generates a move for player on the current board.
    Optionally consumes and updates a saved state.
    :param board: The board state
    :param player: The player to generate a move for
    :param saved_state: (optional) Saved state
    :return: Returns the calculated move and the new saved state
    """

    # first, check if a winning move is possible. This can fix a problem where MiniMax
    # would not finish the game since all moves will have
    for move in board.actions():
        nb = board.drop_piece_copy(move)
        if nb.check_winner(player):
            return move, saved_state

    # retrieve our MiniMaxCache from saved state if possible, otherwise create the cache object
    cache = saved_state if type(
        saved_state) == MiniMaxCache2 else MiniMaxCache2()

    # calculate the MiniMax result
    minimax_result = mini_max(board,
                              alpha=-np.inf,
                              beta=np.inf,
                              depth=3,
                              max_player=player,
                              cache=cache)

    print(
        f"generate_move_minimax() returned move {minimax_result.best_move}, h={minimax_result.value}"
    )
    return minimax_result.best_move, cache
Exemplo n.º 3
0
 def look_ahead_next_move(self, game_state, move):
     piece = Piece(game_state.player_in_action, move.point)
     new_board = Board(game_state.board.board_size, game_state.board.grid)
     new_board.place_piece(piece)
     return GameState(
         new_board, self.get_player_after_move(game_state.player_in_action),
         move)
Exemplo n.º 4
0
class TestGame(unittest.TestCase):

    def setUp(self):
        self.board = Board()
        self.first_player = Player(State.white, self.board)
        self.second_player = Player(State.black, self.board)
        self.game = Game(self.board, self.first_player, self.second_player)

    def test_initialize(self):
        self.assertEqual(self.game.first_player.colour, State.white)
        self.assertEqual(self.game.second_player.colour, State.black)
        self.assertEqual(self.game.current_player_colour, State.black)

    def test_get_current_player(self):
        self.assertEqual(self.game.get_current_player(), self.second_player)

    def test_get_other_player(self):
        self.assertEqual(self.game.get_other_player(), self.first_player)

    def test_is_game_won_should_return_false(self):
        self.assertFalse(self.game.is_game_won())

    def test_is_game_won_should_return_true(self):
        for x in range(8):
            for y in range(8):
                self.board.make_white(x, y)
        self.assertTrue(self.game.is_game_won())

    def test_get_winner_should_return_none(self):
        self.assertEqual(self.game.get_winner(), None)

    def test_change_current_player(self):
        self.game.change_current_player()
        self.assertEqual(self.game.get_current_player(), self.first_player)
Exemplo n.º 5
0
class Game:
    def __init__(self, settings):
        self.board = Board(**settings['board_settings'])
        self.game_tick = 0
        self.actions = []

        self.players = []
        self.ants = []
        for i, player_settings in enumerate(settings['players_settings']):
            # Initialize players
            player = Player(player_id=i, **player_settings)
            self.players.append(player)

            # Initialize ants
            tile = self.board.random_empty_tile()
            self.ants.append(Ant(player=player, tile=tile, type="queen"))

        # Initialize food
        amt = settings['food_amount']
        num_sources = settings['food_sources']
        sprawl = settings['food_sprawl']
        tiles = self.board.flat_tiles()
        shuffle(tiles)
        for t in tiles[0:num_sources]:
            self.gen_food(t, amt, sprawl)

    def gen_food(self, tile, amt, itr):
        if itr is not 0:
            if type(tile.item) is Food:
                tile.item.quantity += amt
            elif tile.item is None:
                tile.add_item(Food(tile=tile, quantity=amt))

            nt = choice(tile.adjacent_tiles())
            self.gen_food(nt, amt, itr - 1)

    def grow_food(self):
        for t in self.board.flat_tiles():
            if t.has_item and not t.has_food():
                next
            food_tiles = [t for t in t.adjacent_tiles() if t.has_food()]
            if t.has_food():
                food_tiles += [t]
            num_food = len(food_tiles)
            sum_food = sum([t.item.quantity for t in food_tiles])
            prob = math.pow(num_food + 1, 3)
            prob = prob * (1 + (sum_food / 100))
            if random() < (prob / 100000):
                t.add_food(10)

    def advance_game(self):
        shuffle(self.ants)
        for ant in self.ants:
            action = ant.player.get_action_for_ant(ant, self.board)
            # Perform the action. If it succeeds, append it to actions
            if action.perform(self):
                # This will get big pretty fast if we don't flush it
                self.actions.append(action)
        self.grow_food()
        self.game_tick += 1
Exemplo n.º 6
0
def generate_move(net: Connect4Network, current_board: Board,
                  args: AlphaZeroArgs) -> Column:
    """
    Generates move with low randomness of given Board.
    Used for actual playing
    @param net: Neural Network Object
    @param current_board: current board state
    @param args: AlphaZeroArgs
    @return: Column index
    """
    if current_board.check_winner() or current_board.is_final():
        raise AssertionError("Game is already over.")

    # Low temperature
    t = 0.1

    # Run a UCT_search for current board
    root = UCT_search(current_board, args.num_reads_mcts, net)

    policy = get_policy(root, t)
    print(f"Policy: {policy}")

    # Determines move from policy
    move = np.random.choice(np.array([0, 1, 2, 3, 4, 5, 6]), p=policy)
    print(f"Playing col: {move}")
    return move
Exemplo n.º 7
0
def generate_move(
    board: Board, player: Player, saved_state: Optional[SavedState]
) -> Tuple[PlayerAction, Optional[SavedState]]:
    """
    Genrates move using trained model and MCTS
    @param board: connect4board
    @param saved_state:
    @return: PlayerAction
    """
    from agents.agent_alphazero.alpha_zero_args import AlphaZeroArgs
    global nn

    # translate the board
    b = board.copy()
    b.current_board[b.current_board == 0] = PLAYER_NONE

    alpha_zero_args = AlphaZeroArgs()

    if nn is None:
        nn = load_connect4network(alpha_zero_args,
                                  alpha_zero_args.playing_iteration)

    print(f"I'm AlphaZero playing as Player {b.player}")

    return PlayerAction(generate_move_mc(nn, b, alpha_zero_args)), saved_state
Exemplo n.º 8
0
    def _simulate_random_game_for_state(self, game_state):
        random_agent_0 = RandomAgent(Connect5Game.ASSIGNED_PLAYER_ID_1,
                                     "RandomAgent0")
        random_agent_1 = RandomAgent(Connect5Game.ASSIGNED_PLAYER_ID_2,
                                     "RandomAgent1")

        bots = {}
        bots[random_agent_0.id] = random_agent_0
        bots[random_agent_1.id] = random_agent_1

        # current board status
        board = Board(game_state.board.board_size, game_state.board.grid)
        init_game_state = GameState(board, game_state.player_in_action, None)

        game = Connect5Game(init_game_state,
                            [random_agent_0.id, random_agent_1.id], 0)

        # game.working_game_state.board.print_board()

        while not game.is_over():
            move = bots[game.working_game_state.player_in_action].select_move(
                game)
            game.apply_move(move)

        winner = game.final_winner
        # game.working_game_state.board.print_board()

        if winner is None:
            return 0.0
        else:
            return 1.0 if winner == game_state.player_in_action else -1.0
Exemplo n.º 9
0
def evaluate():

    mcts_agent = MCTSAgent(Connect5Game.ASSIGNED_PLAYER_ID_1, "MCTSAgent",
                           7000, 5.0)
    human_player = HumanPlayer(Connect5Game.ASSIGNED_PLAYER_ID_2, "Human")

    board = Board(11)

    players = {}
    players[mcts_agent.id] = mcts_agent
    players[human_player.id] = human_player

    init_game_state = GameState(board, 0, None)
    game = Connect5Game(init_game_state, [mcts_agent.id, human_player.id], 0)

    while not game.is_over():
        move = players[game.working_game_state.player_in_action].select_move(
            game)
        if game.working_game_state.player_in_action == Connect5Game.ASSIGNED_PLAYER_ID_2:
            mcts_agent.mcts_tree.go_down(game, move)

        game.apply_move(move)
        print("Last move is {}".format(move.point))

        if game.working_game_state.player_in_action == Connect5Game.ASSIGNED_PLAYER_ID_1:
            game.working_game_state.board.print_board()

    game.working_game_state.board.print_board()
    # self._logger.info(game.final_winner.name)

    print(players[game.final_winner].name)
Exemplo n.º 10
0
    def _check_policy_once(self):
        device = self._devices[0]
        mcts_agent = MCTSAgent(Connect5Game.ASSIGNED_PLAYER_ID_1, "MCTSAgent",
                               self._basic_mcts_rounds_per_move, self._basic_mcts_c_puct)
        az_agent = AlphaZeroAgent(Connect5Game.ASSIGNED_PLAYER_ID_2, "AlphaZeroAgent", self._encoder, self._model,
                                  self._az_mcts_rounds_per_move, self._c_puct, self._az_mcts_temperature, device=device)

        board = Board(self._board_size)
        players = {}
        players[mcts_agent.id] = mcts_agent
        players[az_agent.id] = az_agent

        start_game_state = GameState(board, mcts_agent.id, None)

        # MCTS agent always plays first
        game = Connect5Game(start_game_state, [mcts_agent.id, az_agent.id], self._number_of_planes, is_self_play=False)

        while not game.is_over():
            move = players[game.working_game_state.player_in_action].select_move(
                game)
            if players[0].id == game.working_game_state.player_in_action:
                players[1].mcts_tree.go_down(game, move)
            else:
                players[0].mcts_tree.go_down(game, move)

            game.apply_move(move)

        winner = game.final_winner
        score = 0
        if winner == az_agent.id:
            score = 1
        print('This score is {}'.format(score))
        return score
Exemplo n.º 11
0
 def calc_hash(self, board: Board, max_player: Player):
     """
     Calculates the hash value of a given board state combined with the given maximizing player.
     Mirrored boards with the same maximizing player will have the same hash value.
     :param board: The board state
     :param max_player: The maximizing player
     :return: Returns the calculated hash
     """
     return min(hash((board, max_player)),
                hash((board.mirrored_copy(), max_player)))
Exemplo n.º 12
0
    def __init__(self, tty_file, id):
        log("%s.%s tty_file=%s id=%s", self.__class__, self.__init__.__name__,
            tty_file, id)

        self.id = id
        self.btp_address = BTP_ADDRESS + '-' + str(self.id)
        self.tty_file = tty_file
        self.socat_process = None
        self._btp_socket = None
        self._btp_worker = None
        self.rtt = None

        self.log_filename = "iut-mynewt-{}.log".format(id)
        self.log_file = open(self.log_filename, "w")

        self.board = Board(id, "nrf52", self.log_file)

        self._stack = Stack()
        self._event_handler = BTPEventHandler(self)
Exemplo n.º 13
0
def agent_vs_agent(generate_move_1: GenMove,
                   generate_move_2: GenMove,
                   player_1: str = "Player 1",
                   player_2: str = "Player 2",
                   args_1: tuple = (),
                   args_2: tuple = (),
                   init_1: Callable = lambda board, player: None,
                   init_2: Callable = lambda board, player: None):
    from agents.common import PLAYER1, PLAYER2, GameState
    from agents.common import initialize_game_state, pretty_print_board, apply_player_action, check_end_state

    players = (PLAYER1, PLAYER2)
    for play_first in (1, -1):
        for init, player in zip((init_1, init_2)[::play_first], players):
            init(initialize_game_state(), player)

        saved_state = {PLAYER1: None, PLAYER2: None}
        board = initialize_game_state()
        gen_moves = (generate_move_1, generate_move_2)[::play_first]
        player_names = (player_1, player_2)[::play_first]
        gen_args = (args_1, args_2)[::play_first]

        playing = True
        while playing:
            for player, player_name, gen_move, args in zip(
                    players,
                    player_names,
                    gen_moves,
                    gen_args,
            ):
                t0 = time.time()
                print(pretty_print_board(board))

                c_board = Board(board.copy(), player)

                action, saved_state[player] = gen_move(c_board, player,
                                                       saved_state[player],
                                                       *args)
                print(f"Move time: {time.time() - t0:.3f}s")

                apply_player_action(board, action, player)

                end_state = check_end_state(board, player)
                if end_state != GameState.STILL_PLAYING:
                    print(pretty_print_board(board))
                    if end_state == GameState.IS_DRAW:
                        print("Game ended in draw")
                    else:
                        print(
                            f'{player_name} won playing {"X" if player == PLAYER1 else "O"}'
                        )

                    time.sleep(4)

                    playing = False
Exemplo n.º 14
0
    def _collect_data_once_in_parallel(encoder, model, az_mcts_round_per_moves,
                                       board_size, number_of_planes, c_puct,
                                       az_mcts_temperature, device, pipe):

        agent_1 = AlphaZeroAgent(Connect5Game.ASSIGNED_PLAYER_ID_1,
                                 "AlphaZeroAgent1",
                                 encoder,
                                 model,
                                 az_mcts_round_per_moves,
                                 c_puct,
                                 az_mcts_temperature,
                                 device=device)
        agent_2 = AlphaZeroAgent(Connect5Game.ASSIGNED_PLAYER_ID_2,
                                 "AlphaZeroAgent2",
                                 encoder,
                                 model,
                                 az_mcts_round_per_moves,
                                 c_puct,
                                 az_mcts_temperature,
                                 device=device)
        agent_2.mcts_tree = agent_1.mcts_tree

        board = Board(board_size)
        players = {agent_1.id: agent_1, agent_2.id: agent_2}
        start_game_state = GameState(board,
                                     random.choice([agent_1.id, agent_2.id]),
                                     None)
        game = Connect5Game(start_game_state, [agent_1.id, agent_2.id],
                            number_of_planes,
                            is_self_play=True)

        while not game.is_over():
            move = players[
                game.working_game_state.player_in_action].select_move(game)
            game.apply_move(move)

            # game.working_game_state.board.print_board()

        # game.working_game_state.board.print_board()

        winner = game.final_winner

        if winner is not None:
            if winner == players[0].id:
                players[0].experience_collector.complete_episode(reward=1)
                players[1].experience_collector.complete_episode(reward=-1)
            if winner == players[1].id:
                players[1].experience_collector.complete_episode(reward=1)
                players[0].experience_collector.complete_episode(reward=-1)

            expericence_buffer = ExpericenceBuffer()
            expericence_buffer.combine_experience(
                [agent_1.experience_collector, agent_2.experience_collector])
            pipe.send(expericence_buffer)
            pipe.close()
Exemplo n.º 15
0
def feature1(board: Board, player: Player) -> float:
    """
    Feature 1 checks for four connected stones (win).

    :param board: The board to check against
    :param player: The player to check for
    :return: The heuristic for feature 1
    """
    if board.check_winner(player):
        return np.inf
    else:
        return float(0)
Exemplo n.º 16
0
def select_move(bot_name):

    bot_agent = AlphaZeroAgent(Connect5Game.ASSIGNED_PLAYER_ID_2,
                               "Agent_New",
                               encoder,
                               model_new,
                               az_mcts_round_per_moves,
                               c_puct,
                               az_mcts_temperature,
                               device=device)
    human_agent = HumanPlayer(Connect5Game.ASSIGNED_PLAYER_ID_1,
                              "HumanPlayerX")

    board = Board(board_size)
    players = {}
    players[bot_agent.id] = bot_agent
    players[human_agent.id] = human_agent

    start_game_state = GameState(board, human_agent.id, None)

    game = Connect5Game(start_game_state, [bot_agent.id, human_agent.id],
                        number_of_planes, False)

    historic_jboard_positions = [
        point_from_coords([move][0]) for move in (request.json)['moves']
    ]
    historic_moves = [
        Move(Point(historic_jboard_position.row, historic_jboard_position.col))
        for historic_jboard_position in historic_jboard_positions
    ]
    over = False
    bot_move_str = ''

    for move in historic_moves:
        game.apply_move(move)

    if game.is_over():
        over = True
    else:
        bot_move = bot_agent.select_move(game)
        game.apply_move(bot_move)
        game.working_game_state.board.print_board()
        jboard_postion = Point(bot_move.point.row, bot_move.point.col)
        bot_move_str = coords_from_point(jboard_postion)
        over = True if game.is_over() else False

    return jsonify({
        'bot_move': bot_move_str,
        'over': over,
        'diagnostics': None
    })
Exemplo n.º 17
0
    def _collect_data_once(self):

        agent_1 = AlphaZeroAgent(Connect5Game.ASSIGNED_PLAYER_ID_1,
                                 "AlphaZeroAgent1",
                                 self._encoder,
                                 self._model,
                                 self._az_mcts_rounds_per_move,
                                 self._c_puct,
                                 self._az_mcts_temperature,
                                 device=self._devices[0])
        agent_2 = AlphaZeroAgent(Connect5Game.ASSIGNED_PLAYER_ID_2,
                                 "AlphaZeroAgent2",
                                 self._encoder,
                                 self._model,
                                 self._az_mcts_rounds_per_move,
                                 self._c_puct,
                                 self._az_mcts_temperature,
                                 device=self._devices[0])

        # Two agents use the same tree to save the memory and improve the efficency
        agent_2.mcts_tree = agent_1.mcts_tree

        board = Board(self._board_size)
        players = {agent_1.id: agent_1, agent_2.id: agent_2}
        start_game_state = GameState(board,
                                     random.choice([agent_1.id, agent_2.id]),
                                     None)
        game = Connect5Game(start_game_state, [agent_1.id, agent_2.id],
                            self._number_of_planes,
                            is_self_play=True)
        while not game.is_over():
            move = players[
                game.working_game_state.player_in_action].select_move(game)
            game.apply_move(move)

            # game.working_game_state.board.print_board()

        # game.working_game_state.board.print_board()

        winner = game.final_winner
        if winner is not None:
            if winner == players[0].id:
                players[0].experience_collector.complete_episode(reward=1)
                players[1].experience_collector.complete_episode(reward=-1)
            if winner == players[1].id:
                players[1].experience_collector.complete_episode(reward=1)
                players[0].experience_collector.complete_episode(reward=-1)

            self._experience_buffer.combine_experience(
                [agent_1.experience_collector, agent_2.experience_collector])
Exemplo n.º 18
0
    def __init__(self, settings):
        self.board = Board(**settings['board_settings'])
        self.game_tick = 0
        self.actions = []

        self.players = []
        self.ants = []
        for i, player_settings in enumerate(settings['players_settings']):
            # Initialize players
            player = Player(player_id=i, **player_settings)
            self.players.append(player)

            # Initialize ants
            tile = self.board.random_empty_tile()
            self.ants.append(Ant(player=player, tile=tile, type="queen"))

        # Initialize food
        amt = settings['food_amount']
        num_sources = settings['food_sources']
        sprawl = settings['food_sprawl']
        tiles = self.board.flat_tiles()
        shuffle(tiles)
        for t in tiles[0:num_sources]:
            self.gen_food(t, amt, sprawl)
Exemplo n.º 19
0
def generate_move_random(
    board: Board, player: Player, saved_state: Optional[SavedState]
) -> Tuple[PlayerAction, Optional[SavedState]]:
    """
    Generates a random move for a given board state.
    :param board: The board to generate the move for
    :param player: The player to generate a move for
    :param saved_state: The saved state (not used here)
    :return: The randomly generated move and the passed saved state
    """

    print(f"I'm the random agent. Playing as {board.player}")

    available_columns = board.actions()

    action = PlayerAction(rnd.choice(available_columns))
    print(f"Choosing to play {action}!")

    return action, saved_state
Exemplo n.º 20
0
 def test_board_is_game_over_false(self,size,initial_grid):
     board1 = Board(size);
     board1.grid = initial_grid
     self.assertFalse(board1.is_game_over())
Exemplo n.º 21
0
 def point_from_coords(cls, text):
     col_name = text[0]
     row = int(text[1])
     return Point(row, Board.get_column_indicator_index(col_name)+1)
Exemplo n.º 22
0
    def play_round(self,
                   num_reads: int) -> Tuple[Optional[str], List[np.ndarray]]:
        """
        Evaluate the trained network by playing matches between the current and the previous NN
        @param num_reads: see args
        """
        print("Starting game round...")
        # randomly choose starting player
        if np.random.uniform(0, 1) <= 0.5:
            white = self.current
            black = self.best
            w = "current"
            b = "best"
        else:
            white = self.best
            black = self.current
            w = "best"
            b = "current"

        # initializing
        current_board = Board()
        game_won = False
        dataset = []
        value = 0
        temperature = 0.1  # exploration vs exploitation factor (smaller -> more exploitation)

        while not game_won and current_board.is_playable():
            dataset.append(copy.deepcopy(current_board.encode()))
            # get Policy
            if current_board.player == PLAYER_1:
                root = UCT_search(current_board, num_reads, white)
                policy = get_policy(root, temperature)
                print("Policy: ", policy, "white = %s" % (str(w)))
            elif current_board.player == PLAYER_2:
                root = UCT_search(current_board, num_reads, black)
                policy = get_policy(root, temperature)
                print("Policy: ", policy, "black = %s" % (str(b)))
            else:
                raise AssertionError("Invalid player.")
            # Chose a Column with given policy
            col_choice = np.random.choice(np.array([0, 1, 2, 3, 4, 5, 6]),
                                          p=policy)

            current_board.drop_piece(col_choice)  # move piece
            print(current_board)
            if current_board.check_winner():  # someone wins
                if current_board.player == PLAYER_1:  # black wins
                    value = -1
                elif current_board.player == PLAYER_2:  # white wins
                    value = 1
                game_won = True
        # Append new board to the dataset encoded in one-hot-encoding manner
        dataset.append(current_board.encode())
        if value == -1:
            dataset.append(f"{b} as black wins")
            return b, dataset
        elif value == 1:
            dataset.append(f"{w} as white wins")
            return w, dataset
        else:
            dataset.append("Nobody wins")
            return None, dataset
Exemplo n.º 23
0
 def test_board_grid_update_move_not_allowed(self,size,initial_grid, move):
     board1 = Board(size);
     board1.grid = initial_grid
     self.assertFalse(board1.update_move(move,"X"))
Exemplo n.º 24
0
 def test_board_is_winner_true(self,size,initial_grid):
     board1 = Board(size);
     board1.grid = initial_grid
     self.assertTrue(board1.is_winner(RECORD_THE_WINNER))   
Exemplo n.º 25
0
    def test_feature1(self):
        # |==============|
        # |              |
        # |              |
        # |              |
        # |              |
        # |O O O         |
        # |X X X X       |
        # |==============|
        # |0 1 2 3 4 5 6 |
        b = Board()
        b.drop_piece(0, PLAYER_1)
        b.drop_piece(0, PLAYER_2)
        b.drop_piece(1, PLAYER_1)
        b.drop_piece(1, PLAYER_2)
        b.drop_piece(2, PLAYER_1)
        b.drop_piece(2, PLAYER_2)
        b.drop_piece(3, PLAYER_1)

        self.assertTrue(b.check_winner(PLAYER_1))
        self.assertFalse(b.check_winner(PLAYER_2))

        self.assertEqual(heuristic_1.feature1(b, PLAYER_1), np.inf)
Exemplo n.º 26
0
    def test_feature2(self):
        # |==============|
        # |              |
        # |              |
        # |              |
        # |              |
        # |  O O         |
        # |  X X X O     |
        # |==============|
        # |0 1 2 3 4 5 6 |
        b_3_in_row_1_neighbour = Board()
        b_3_in_row_1_neighbour.drop_piece(1, PLAYER_1)
        b_3_in_row_1_neighbour.drop_piece(1, PLAYER_2)
        b_3_in_row_1_neighbour.drop_piece(2, PLAYER_1)
        b_3_in_row_1_neighbour.drop_piece(2, PLAYER_2)
        b_3_in_row_1_neighbour.drop_piece(3, PLAYER_1)
        b_3_in_row_1_neighbour.drop_piece(4, PLAYER_2)

        self.assertEqual(
            heuristic_1.feature2(b_3_in_row_1_neighbour, PLAYER_1),
            float(900000))

        # |==============|
        # |              |
        # |              |
        # |              |
        # |              |
        # |O   O         |
        # |X   X X O     |
        # |==============|
        # |0 1 2 3 4 5 6 |
        b_3_in_row_1_gap = Board()
        b_3_in_row_1_gap.drop_piece(0, PLAYER_1)
        b_3_in_row_1_gap.drop_piece(0, PLAYER_2)
        b_3_in_row_1_gap.drop_piece(2, PLAYER_1)
        b_3_in_row_1_gap.drop_piece(2, PLAYER_2)
        b_3_in_row_1_gap.drop_piece(3, PLAYER_1)
        b_3_in_row_1_gap.drop_piece(4, PLAYER_2)

        self.assertEqual(heuristic_1.feature2(b_3_in_row_1_gap, PLAYER_1),
                         float(900000))
Exemplo n.º 27
0
def coords_from_point(point):
    coords = '%s%d' % (Board.get_column_indicator(point.col - 1),
                       point.row - 1)
    return coords
Exemplo n.º 28
0
 def test_board_grid_update_move_match_expected(self,size,move,expected_grid):
     board1 = Board(size);
     board1.update_move(move,"X")
     self.assertEqual(board1.grid,expected_grid)
Exemplo n.º 29
0
 def setUp(self):
     self.board = Board()
     self.first_player = Player(State.white, self.board)
     self.second_player = Player(State.black, self.board)
     self.game = Game(self.board, self.first_player, self.second_player)
Exemplo n.º 30
0
def mini_max(board: Board, alpha: float, beta: float, depth: int, max_player: Player, cache: MiniMaxCache2) \
        -> MiniMaxResult:
    """
    Execute the MiniMax algorithm with alpha-beta-pruning on a board.
    :param board: The board
    :param alpha: Lower boundary
    :param beta: Upper boundary
    :param depth: Maximum depth
    :param max_player: The maximizing player ID
    :param cache: The MiniMax cache to use
    :return: Returns the best possible result after traversing the tree with the given depth.
    """

    # first, let's see if we already cached this value
    cached_value = cache.get(board, max_player)
    if cached_value is not None:
        return cached_value

    # If we hit max depth or the board is in a final state, calculate and return the heuristic.
    # We cannot decide about the best move here, so leave it empty.
    if depth == 0 or board.get_state() != GameState.ONGOING:
        return MiniMaxResult(None,
                             calculate_heuristic(board, max_player).value)

    # collect a list of available moves from the board and order them according to moveOrder
    # which orders moves based on their distance to the middle column
    available_moves = board.actions()
    available_moves = [move for move in moveOrder if move in available_moves]

    # check if we are maximizing right now
    is_maximizing = (board.player == max_player)

    # store min and max value, initialize with boundaries
    max_value, min_value = alpha, beta
    # initialize the best move randomly
    best_move: Column = random.choice(available_moves)

    # enumerate all available moves. Recurse for each while respecting is_maximizing and adjusting
    # min_value and max_value accordingly.
    for move in available_moves:
        # create a board with the new state
        child_board = board.drop_piece_copy(move)

        if is_maximizing:
            min_result = mini_max(child_board, max_value, beta, depth - 1,
                                  max_player, cache)
            if min_result == np.inf:
                # we cannot perform better than +inf.
                return MiniMaxResult(move, np.inf)
            elif min_result.value > max_value:
                max_value = min_result.value
                best_move = move
                if max_value >= beta:
                    # beta pruning
                    break
        else:
            max_result = mini_max(child_board, alpha, min_value, depth - 1,
                                  max_player, cache)
            if max_result.value == -np.inf:
                # we cannot perform better than -inf.
                return MiniMaxResult(move, -np.inf)
            elif max_result.value < min_value:
                min_value = max_result.value
                best_move = move
                if min_value <= alpha:
                    # alpha pruning
                    break

    # return the best move and according heuristic
    return MiniMaxResult(best_move, max_value if is_maximizing else min_value)
Exemplo n.º 31
0
def point_from_coords(coords):
    col_name = coords[0]
    row = int(coords[1:])
    point = Point(row + 1, Board.get_column_indicator_index(col_name) + 1)
    return point
Exemplo n.º 32
0
    def test_feature3(self):
        # |==============|
        # |              |
        # |              |
        # |              |
        # |              |
        # |  O O         |
        # |  X X         |
        # |==============|
        # |0 1 2 3 4 5 6 |
        b_2_in_row_both_nbs_free = Board()
        b_2_in_row_both_nbs_free.drop_piece(1, PLAYER_1)
        b_2_in_row_both_nbs_free.drop_piece(1, PLAYER_2)
        b_2_in_row_both_nbs_free.drop_piece(2, PLAYER_1)
        b_2_in_row_both_nbs_free.drop_piece(2, PLAYER_2)

        self.assertEqual(
            heuristic_1.feature3(b_2_in_row_both_nbs_free, PLAYER_1),
            float(50000))

        # |==============|
        # |              |
        # |              |
        # |              |
        # |              |
        # |  O           |
        # |O X X         |
        # |==============|
        # |0 1 2 3 4 5 6 |
        b_2_in_row_4_free = Board()
        b_2_in_row_4_free.drop_piece(1, PLAYER_1)
        b_2_in_row_4_free.drop_piece(1, PLAYER_2)
        b_2_in_row_4_free.drop_piece(2, PLAYER_1)
        b_2_in_row_4_free.drop_piece(0, PLAYER_2)

        self.assertEqual(heuristic_1.feature3(b_2_in_row_4_free, PLAYER_1),
                         float(30000))