Ejemplo n.º 1
0
    def dijkstraEval(self, board_state, maximizer):
        h = HexBoard(board_state.shape[0])
        h.board = board_state

        red_shortestPath = self.dijkstra(hexboard=h, color=h.RED)
        blue_shortestPath = self.dijkstra(hexboard=h, color=h.BLUE)

        freeReds = self.getFreeHexes(hexboard=h, path=red_shortestPath)
        freeBlues = self.getFreeHexes(hexboard=h, path=blue_shortestPath)

        heuristic_score = 0

        if maximizer == h.RED:
            heuristic_score = freeBlues - freeReds
        else:
            heuristic_score = freeReds - freeBlues

        return heuristic_score

#    def iterativeDeepening(self, node, maximizer):
#        depth = 1
#        end_time = datetime.now() + timedelta(seconds=3)
        # For windows os
#        while datetime.now() < end_time and not msvcrt.kbhit():
#            bestScore = self.alphaBetaSearch(node, depth, -9999999, 9999999, isMaximizer=maximizer)
#            depth = depth + 1
#        return bestScore
        
        
def _update_board(board: HexBoard, l_move, is_max: bool) -> HexBoard:
    board = copy.deepcopy(
        board
    )  # I think this was the problem with the minimax core, it was using a reference instead of a deep copy
    color = board.BLUE if is_max else board.RED
    board.place(l_move, color)
    return board
def alphabeta_Id(board: HexBoard, depth: int, alpha: float, beta: float,
                 is_max: bool) -> float:
    # board.print()
    print("in alphabeta_Id000000000")
    try:
        (hit, g, ttbm) = transposition_table.lookup(board,
                                                    board.get_board_size(),
                                                    depth)
        print("in alphabeta_Id", hit, g, ttbm)
    except Exception as e:  #
        print('Exception in running lookup function: ' + str(e))
    if hit():
        return g

    if depth == 0 or board.is_game_over():
        g = dijkstra_eval(board)
        bm = ()

    legals = board.get_move_list()
    if legals:
        if is_max:
            g: float = -_INF

            for move in ttbm + legals:
                updated_board: HexBoard = _update_board(
                    board, move, is_max)  # y do we make the move first?
                gc = alphabeta_Id(updated_board, depth - 1, alpha, beta,
                                  is_max)
                if gc > g:
                    bm = updated_board
                    g = gc

                alpha = max(alpha, g)
                if beta <= alpha:
                    break

        else:  # if is_max False
            g: float = _INF

            for move in ttbm + legals:
                updated_board: HexBoard = _update_board(board, move, is_max)
                gc = alphabeta_Id(updated_board, depth - 1, alpha, beta,
                                  is_max)
                if gc < g:
                    bm = updated_board
                    g = gc

                beta = min(beta, g)
                if beta <= alpha:
                    break
        transposition_table.store(updated_board,
                                  updated_board.get_board_size(), g, depth, bm)
        return g

    else:
        print("NO MORE LEGAL MOVES LEFT")
        return dijkstra_eval(board)
def simple_dijkstra(board: HexBoard, source, is_max):

    Q = set()
    V_set = board.get_all_vertices()
    dist = {}
    dist_clone = {}  # I made a clone of dist to retain the information in dist
    prev = {}
    for v in V_set:
        dist[v] = np.inf
        dist_clone[v] = np.inf  # clone
        prev[v] = None
        Q.add(v)
    dist[source] = 0
    dist_clone[source] = dist[source]  # clone

    while len(Q) != 0:
        u = min(dist, key=dist.get)
        Q.remove(u)

        color = board.BLUE if is_max else board.RED

        ## IGNORE THE CODE BELOW, IT DOESN'T WORK PROPERLY AT THE MOMENT
        # begin reverse iteration step
        # this happens when we get to a border of the corresponding color (i.e. we connect the sides)
        # if board.border(color, u):
        #     S = []
        #     path_length = 0
        #     if prev[u] or u == source:
        #         while u:
        #             if not board.is_color(u, color):
        #                 path_length += 1
        #             S.insert(0, u)
        #             u = prev[u]
        #     print(f"S for color {color} IS: {S}")
        #     print(f"Path length when accounting for already marked hexagons: {path_length}")
        #     return path_length, S # You can also optionally return "S" if you also want to store the path
        # # end reverse iteration step

        neighbors = board.get_neighbors(u)

        for v in neighbors:
            if v in Q:  # Only check neighbours that are also in "Q"
                len_u_v = 0 if board.is_color(
                    v,
                    color) else 1  # this isn't working as intended i think...
                alt = dist[u] + len_u_v
                if alt < dist[v]:
                    dist[v] = alt
                    dist_clone[v] = dist[v]
                    prev[v] = u
        # We pop "u" from the distance dict to ensure that the keys match the ones in "Q"
        dist.pop(
            u
        )  # This is also why we need the clone, or else we'll return an empty dict

    return dist_clone, prev
def _update_board(board: HexBoard, l_move, is_max: bool) -> HexBoard:
    """
    Makes a deep copy of the board and updates the board state on that copy.
    This makes it so that we don't need to use an undo move function.
    The reason for using deepcopy is because python passes objects by reference
    if you use the "=" operator
    """
    board = copy.deepcopy(
        board
    )  # I think this was the problem with the minimax core, it was using a reference instead of a deep copy
    color = board.BLUE if is_max else board.RED
    board.place(l_move, color)
    return board
def alphabeta(board: HexBoard, depth: int, alpha: float, beta: float,
              is_max: bool) -> float:
    # board.print()
    if depth == 0 or board.is_game_over():
        return dijkstra_eval(board)

    legals = board.get_move_list()
    if legals:

        if is_max:
            g: float = -_INF

            for move in legals:
                updated_board: HexBoard = _update_board(board, move, is_max)
                g = max(
                    g,
                    alphabeta(updated_board,
                              depth - 1,
                              alpha,
                              beta,
                              is_max=False))

                alpha = max(alpha, g)
                if beta <= alpha:
                    break

        else:
            g: float = _INF

            for move in legals:
                updated_board: HexBoard = _update_board(board, move, is_max)
                g = min(
                    g,
                    alphabeta(updated_board,
                              depth - 1,
                              alpha,
                              beta,
                              is_max=True))

                beta = min(beta, g)
                if beta <= alpha:
                    break

        return g

    else:
        print("NO MORE LEGAL MOVES LEFT")
        return dijkstra_eval(board)
def alphabeta_move(board: HexBoard, depth: int, is_max: bool, show_AI=False):
    """
    Set is_max to True for BLUE player, and False for RED player.
    You can set the depth to whatever you want really, just don't go too deep it'll take forever.
    Set show_AI to True if you want to see it's scoring process
    """
    legal_moves = board.get_move_list()
    best_score = -np.inf
    best_move = None
    for move in legal_moves:
        sim_board = _update_board(board, move, is_max)
        if sim_board.check_win(
                sim_board.BLUE if is_max else sim_board.RED
        ):  # KILLER MOVE: If we find a move in the simulation that wins, make that move no matter what
            if show_AI: print(f"KILLER MOVE FOUND: {move}")
            best_move = move
            best_score = np.inf
            break
        score = alphabeta(
            sim_board, depth=depth, alpha=-np.inf, beta=np.inf, is_max=is_max
        )  # For some reason performs better if you use is_max=False
        if show_AI: print(f"CURRENT SCORE: {score} for MOVE: {move}")
        if score > best_score:
            best_score = score
            best_move = move
    if show_AI: print(f"BEST MOVE: {best_move} with BEST SCORE: {best_score}")
    return best_move
Ejemplo n.º 8
0
    def Expand(self, node, game_state):
        """
        Function: Adds a random child to node,
                  Updates game_state and node's untriedMoves
        Returns : The created child
        """
        untriedMoves = node.untriedMoves
        m = choice(untriedMoves)
        # node's untriedMoves updated here
        node.untriedMoves.remove(m)
        # game_state updated here
        game_state = HexBoard.makeMove(m, game_state)

        # Check the child, if it is already appended return it otherwise create that child
        child = node.getChild(game_state)
        if child is not None:
            return child

        child_type = 'MIN'
        if node.type == 'MIN':
            child_type = 'MAX'

        child = Node(node_type=child_type,
                     board_state=game_state.board,
                     parent=node)

        # node's children updated here
        node.children.append(child)

        return child
Ejemplo n.º 9
0
    def dijkstraEval(self, board_state, maximizer):
        h = HexBoard(board_state.shape[0])
        h.board = board_state

        red_shortestPath = self.dijkstra(hexboard=h, color=h.RED)
        blue_shortestPath = self.dijkstra(hexboard=h, color=h.BLUE)

        freeReds = self.getFreeHexes(hexboard=h, path=red_shortestPath)
        freeBlues = self.getFreeHexes(hexboard=h, path=blue_shortestPath)

        if maximizer == h.RED:
            heuristic_score = freeBlues - freeReds
        else:
            heuristic_score = freeReds - freeBlues

        return heuristic_score
def simple_dijkstra(board: HexBoard, source, is_max):

    Q = set()
    V_set = board.get_all_vertices()
    dist = {}
    dist_clone = {}  # I made a clone of dist to retain the information in dist
    prev = {}
    for v in V_set:
        dist[v] = np.inf
        dist_clone[v] = np.inf  # clone
        prev[v] = None
        Q.add(v)
    dist[source] = 0
    dist_clone[source] = dist[source]  # clone

    while len(Q) != 0:
        u = min(dist, key=dist.get)
        Q.remove(u)

        color = board.BLUE if is_max else board.RED

        neighbors = board.get_neighbors(u)

        for v in neighbors:
            if v in Q:  # Only check neighbours that are also in "Q"
                len_u_v = -1 if board.is_color(
                    v,
                    color) else 1  # this isn't working as intended i think...
                ### BLOCK TO MAKE AI MORE AGGRESSIVE ###
                if board.border(
                        color, v
                ):  # If there is a move that reaches the border in the simulation
                    if board.check_win(color):  # And it results in a win
                        len_u_v = -2  # Make that move more valuable
                ### END OF AGGRO BLOCK ###
                alt = dist[u] + len_u_v
                if alt < dist[v]:
                    dist[v] = alt
                    dist_clone[v] = dist[v]
                    prev[v] = u
        # We pop "u" from the distance dict to ensure that the keys match the ones in "Q"
        dist.pop(
            u
        )  # This is also why we need the clone, or else we'll return an empty dict

    return dist_clone, prev
def get_shortest_path(board: HexBoard, distances, color):
    """Gets the shortest path to a border and returns the length as score"""
    borders = board.get_borders(color)
    # print(f"ALL BORDERS: {borders}")
    shortest = np.inf
    for border in borders:
        # print(f"Dist for current border {border} is: {distances[border]}")
        if distances[border] < shortest:
            shortest = distances[border]
        # print(f"Current shortest: {shortest}")
    return shortest
Ejemplo n.º 12
0
 def MCTS_Player(hyperparameters, isMaximizer):
     # First Computer's turn (MCTS)
     mcts_agent = MCTS(
         game=game, cp=hyperparameters[0],
         n=hyperparameters[1])  # initialize mcts agent
     move, params['node'] = mcts_agent.search(
         params['node'], hyperparameters[2], hyperparameters[3],
         isMaximizer)
     params['game'] = HexBoard.makeMove(move, params['game'])
     params['node'] = util.updateNode(params['node'],
                                      params['game'])
def minimax(board: HexBoard, depth: int, is_max: bool) -> float:

    if depth == 0 or board.is_game_over():
        board.print()
        return dijkstra_eval(board)

    legals = board.get_move_list()
    if legals:

        if is_max:
            g: float = -_INF

            for move in legals:
                updated_board: HexBoard = _update_board(board, move, is_max)
                g = max(g, minimax(updated_board, depth - 1, not is_max))

        else:
            g: float = _INF

            for move in legals:
                updated_board: HexBoard = _update_board(board, move, is_max)
                g = min(g, minimax(updated_board, depth - 1, not is_max))

        return g
Ejemplo n.º 14
0
    def PlayervsComputer(self):
        game = self.game
        self.clearOutput()
        game.print()

        node = Node(node_type='MIN', board_state=game.board,
                    parent=None)  # 1 - initialize node
        mcts_agent = MCTS(game=game, cp=0.8,
                          n=100)  # 3 - initialize mcts agent
        util = UTIL(infinity=np.inf,
                    maximizer=game.maximizer,
                    minimizer=game.minimizer)  # 4 - initialize util class

        while not game.isGameOver():
            if (game.turn % 2) == 0:
                move = self.getReady(game)
                game = HexBoard.makeMove(move, game)
                node = util.updateNode(node, game)
            else:
                print("Computer is thinking!!!")
                itermax = 100  # maximum iteration for search
                move, node = mcts_agent.search(node,
                                               itermax,
                                               delta=10,
                                               isMaximizer=True)
                print(f'best move: {move}')
                game = HexBoard.makeMove(move, game)
                node = util.updateNode(node, game)
            self.clearOutput()
            game.print()

            if game.isGameOver():
                if game.checkWin(game.BLUE):
                    print("!!! Blue Player Won !!!")
                elif game.checkWin(game.RED):
                    print("!!! Red Player Won !!!")
Ejemplo n.º 15
0
def initGame(b_size, starter):
    #clearOutput()
    h = HexBoard(b_size)
    if starter == h.RED:
        h.maximizer = h.BLUE
        h.minimizer = h.RED
    else:
        h.maximizer = h.RED
        h.minimizer = h.BLUE
    return h
Ejemplo n.º 16
0
 def IDTT_Player(hyperparameters, isMaximizer):
     # iterative deepening with 4 depth-Dijkstra
     boardState = params['node'].board.copy()
     try:
         move = IterativeDeepeningTranspositionTable[
             boardState.tobytes()]
     except KeyError:
         best_value = util.iterativeDeepening(
             params['node'], isMaximizer, hyperparameters[0],
             hyperparameters[1])
         move = util.getBestMove(params['node'], best_value)
         IterativeDeepeningTranspositionTable[
             boardState.tobytes()] = move
     params['game'] = HexBoard.makeMove(move, params['game'])
     params['node'] = util.updateNode(params['node'],
                                      params['game'])
def alphabeta_move_Id(board: HexBoard,
                      is_max: bool,
                      show_AI=False):  #, depth: int
    """
    Set is_max to True for BLUE player, and False for RED player.
    You can set the depth to whatever you want really, just don't go too deep it'll take forever.
    Set show_AI to True if you want to see it's scoring process
    """
    legal_moves = board.get_move_list()
    print("num of legal moves", len(legal_moves))
    best_score = -np.inf
    best_move = None
    for move in legal_moves:
        sim_board = _update_board(board, move, is_max)
        if sim_board.check_win(
                sim_board.BLUE if is_max else sim_board.RED
        ):  # KILLER MOVE: If we find a move in the simulation that wins, make that move no matter what
            if show_AI: print(f"KILLER MOVE FOUND: {move}")
            best_move = move
            best_score = np.inf
            break
        #thread = threading.Thread(target=iterative_deepening, kwargs=dict(board = sim_board,alpha=-np.inf,beta = np.inf, is_max = is_max))
        #thread.start()
        with concurrent.futures.ThreadPoolExecutor() as executor:
            future = executor.submit(iterative_deepening,
                                     sim_board,
                                     alpha=-np.inf,
                                     beta=np.inf,
                                     is_max=is_max)
            score = future.result()
            print("score ", score)
        # wait here for the result to be available before continuing
        #thread.join()
        #score = iterative_deepening(sim_board, alpha=-np.inf, beta=np.inf,
        #                 is_max=is_max)  # For some reason performs better if you use is_max=False
        if show_AI: print(f"ID CURRENT SCORE: {score} for MOVE: {move}")
        if score > best_score:
            best_score = score
            best_move = move
    if show_AI:
        print(f"BEST MOVE_ID: {best_move} with BEST SCORE: {best_score}")
    return best_move
Ejemplo n.º 18
0
    def getBestMove(node, bestVal):
        bestChildren = []
        for child in node.children:
            if child.value == bestVal:
                bestChildren.append(child)

        if len(bestChildren) > 0:
            index = np.random.randint(0, len(bestChildren))
            bestNode = bestChildren[index]
        else:
            # print("Error, best Move couldn't find. Randomly selects the move!")
            moves = HexBoard.getMoveList(node)
            index = np.random.randint(0, len(moves))
            return moves[index]

        b_size = node.board.shape[0]

        for i in range(b_size):
            for j in range(b_size):
                if node.board[i, j] != bestNode.board[i, j]:
                    return i, j
Ejemplo n.º 19
0
    def __init__(self, node_type, board_state, parent):
        self.id = str(uuid.uuid4())  # to make it unique
        self.name = self.id[
            -3:]  # to make it simple during visualizations (for the test purposes)
        self.type = node_type  # for visualization
        self.board = board_state  # for MCTS

        untriedMoves = HexBoard.getFreeMoves(board_state)
        self.untriedMoves = untriedMoves  # for MCTS
        self.children = []  # for MCTS
        if parent is not None:
            self.parents = [parent]
            self.parent_type = parent.type  # for visualization
        else:
            self.parents = []  # for MCTS
            self.parent_type = None  # for visualization

        self.searched = False
        self.value = None
        self.visit = 0  # for MCTS UCT-Selection and finding the best move
        self.wins = np.inf  # for MCTS UCT-Selection
        self.loss = np.inf
def dijkstra_eval(board: HexBoard):
    """
    Checks the best path from every possible source (e.g. L to R for blue) and
    then returns the best evaluation score of the board based on the most
    efficient source
    """
    best_eval_score = -np.inf
    for i in range(board.get_board_size()):
        blue_source = (0, i)
        red_source = (i, 0)
        blue_dists, _ = simple_dijkstra(board, blue_source, True)
        red_dists, _ = simple_dijkstra(board, red_source, False)

        blue_score = get_shortest_path(board, blue_dists, board.BLUE)
        red_score = get_shortest_path(board, red_dists, board.RED)

        eval_score = red_score - blue_score

        if eval_score > best_eval_score:
            best_eval_score = eval_score

    return best_eval_score
Ejemplo n.º 21
0
def initGame():
    clearOutput()
    b_size = int(input("Enter the board size you want to play: "))
    h = HexBoard(b_size)
    ans = str(
        input("In order to start the game, please choose a side 'R' or 'B': ")
    ).lower()
    if ans == 'b':
        h.maximizer = h.RED
        h.minimizer = h.BLUE
    elif ans == 'r':
        h.maximizer = h.BLUE
        h.minimizer = h.RED
    else:
        print("You pressed a wrong key. Please type 'R' or 'B'.")
        print("Game is restarting!!!")
        time.sleep(2)
        h = initGame()
    return h
def main():
    board = HexBoard(2)
    num_of_cells = board.get_board_size() * board.get_board_size()
    for nc in range(int(num_of_cells / 2)):
        ## Just a small heuristic for opening strategy, you can test this if you want. But then you have to comment the move_blue below out too
        # if board.size % 2 != 0 and len(board.get_move_list()) == len(board.get_all_vertices()): # If it's the first move and the board is uneven
        #     move_blue = (board.size // 2, board.size // 2) # Always place the first move in the middle
        # else:
        # move_blue = ab.alphabeta_move(board, depth=2, is_max=True)

        move_blue = ab.alphabeta_move(board, depth=4, is_max=True)
        #move_blue = ab.alphabeta_move_Id(board, is_max=True, show_AI=True)
        board = ab._update_board(board, move_blue, is_max=True)
        board.print()
        if board.is_game_over(
        ):  # TODO: add condition for game over without no winning (board full)
            print("==== BLUE WINS ====")
            board.print()
            # break
            return "blue"
        move_red = ab.alphabeta_move(board, depth=2, is_max=True)
        #move_red = ab.alphabeta_move_Id(board, is_max=True, show_AI=True)
        board = ab._update_board(
            board, move_red, is_max=False
        )  # Using false here and true for the alphabeta is a bit confusing, but we need it to make moves for red here.
        board.print()
        if board.is_game_over(
        ):  # TODO: add condition for game over without no winning (board full)
            print("==== RED WINS ====")
            board.print()
            # break
            return "red"
Ejemplo n.º 23
0
import numpy as np
from hex_skeleton import HexBoard

# sanity check that wins are detected
for i in range(0, 2):
    winner = HexBoard.RED if i == 0 else HexBoard.BLUE
    loser = HexBoard.BLUE if i == 0 else HexBoard.RED
    board = HexBoard(3)
    board.place((1, 1), loser)
    board.place((2, 1), loser)
    board.place((1, 2), loser)
    board.place((2, 2), loser)
    board.place((0, 0), winner)
    board.place((1, 0), winner)
    board.place((2, 0), winner)
    board.place((0, 1), winner)
    board.place((0, 2), winner)
    assert (board.check_win(winner) == True)
    assert (board.check_win(loser) == False)
    board.print()
endable_board = HexBoard(4)
# sanity check that random play will at some point end the game
while not endable_board.game_over:
    endable_board.place((np.random.randint(0, 4), np.random.randint(0, 4)),
                        HexBoard.RED)
assert (endable_board.game_over == True)
assert (endable_board.check_win(HexBoard.RED) == True)
assert (endable_board.check_win(HexBoard.BLUE) == False)
print("Randomly filled board")
endable_board.print()
Ejemplo n.º 24
0
                    f.write(f'd = {d} g = {g} a = {a} b = {b}\n')
                    f.close()

                    board.make_empty((i, j))
                    #virtual_board.print()
                    if a >= g:
                        break
    if d == search_depth:
        f = open('movelist.txt', 'a')
        f.write(f'\n{search.d2l_conversion(best_move[0])},{best_move[1]}')
        f.close()
    return g


# Initialise the board.
board = HexBoard(BOARD_SIZE)

# Create a virtual board for the alphabeta algorithm.
virtual_board = board

# Make a text file for the moves.
f = open('movelist.txt', 'w')
f.write('Movelist')
f.close()

while not board.game_over:
    search_depth = 3
    eval_val = alphabeta(virtual_board,
                         d=search_depth,
                         a=-INF,
                         b=INF,
Ejemplo n.º 25
0
    df_movelist = df_movelist.append({'x': x, 'y': y}, ignore_index=True)

    board.place((x, y), agent2)
    board.print()


# Play the game.
def play_game(board, method):
    for i in range(SIZE * SIZE):
        board_copy = copy.deepcopy(board)

        eval_val = alphabeta(board_copy, DEPTH, -INF, INF, agent1, agent2,
                             method)
        df_alphabeta.to_csv('alphabeta.txt', index=False, mode='a')
        ai_make_move(board)
        if board.check_win(agent1):
            print('A1 WINS')
            break

        pl_make_move(board)
        if board.check_win(agent2):
            print('A2 WINS')
            break


DEPTH = 3
board = HexBoard(SIZE)

play_game(board, 'Dijkstra')
Ejemplo n.º 26
0
# Agents Matchup 2: [depth = 3, policy = random] vs.  [depth = 4, policy = dijkstra]

# Agents Matchup 3: [depth = 3, policy = dijkstra] vs.  [depth = 4, policy = dijkstra]

print("[Initalized Player Matchup: Experiment 1]")
print("[---------------------------------------------------------]")
res_lst_1 = []
res_elo_1 = []
res_elo_2 = []
res_elo_1.append(player1_ratings.mu)
res_elo_2.append(player2_ratings.mu)

n_games = 25  # number of games
size = 5  # board size
board = HexBoard(size)  # init board

player_1_lst = [
    player(agent='AI', color=HexBoard.BLUE, policy="random"),
    player(agent='AI', color=HexBoard.BLUE, policy="random"),
    player(agent="AI",
           color=HexBoard.BLUE,
           policy="alphabeta",
           eval="dijkstra",
           depth=3)
]

player_2_lst = [
    player(agent="AI",
           color=HexBoard.BLUE,
           policy="alphabeta",
Ejemplo n.º 27
0
def human_compu(algor, method='random', depth=3):
    """A function that human play with computer, user can choose their prefered
    board size(3,4 recommanded), color, want to take first move"""
    global flag, INF, n_nodes, cutoff, Game, size

    print('Choose a board size:')
    size = int(input())
    Game = HexBoard(size)
    print('Choose a color: 1(BLUE) or 2(RED)')
    print('Blue: from left to right; Red: from top to bottom')
    opp_color = int(input())
    my_color = Game.get_opposite_color(opp_color)
    print('Do you want to start first? Yes(y) or No(n)')
    first = input()
    print('Game start!')
    # human first move do or not
    if first == 'y' or first == 'Yes':
        Game.print()
        x, y = xy_read(Game)
        Game.place(coordinates=(x, y), color=opp_color)
        Game.print()
        root = Tree(Game,
                    color=opp_color,
                    parent=None,
                    coordinate=(x, y),
                    my_color=my_color)

    else:
        first_color = my_color
        last_color = opp_color
        root = Tree(Game,
                    color=opp_color,
                    parent=None,
                    coordinate=None,
                    my_color=my_color)

    INF = 99999  # sufficient large number

    # human and computer play the game until one of them win
    while not Game.is_game_over():
        if algor == 'alphabeta':
            # varibales intialization
            n_nodes = 0
            cutoff = 0
            flag = 0
            my_move = alphabeta(n=root,
                                a=-INF,
                                b=INF,
                                d=depth,
                                method=method,
                                depth=depth,
                                my_color=my_color,
                                opp_color=opp_color)
            print('n_nodes=', n_nodes, '\n cutoff=', cutoff)

        elif algor == 'idtt':
            flag = 0
            transpositiontable = []
            n_nodes = 0
            cutoff = 0
            my_move = iterativedeepening(n=root,
                                         a=-INF,
                                         b=INF,
                                         DEPTH_stop=5,
                                         time_limit=5,
                                         my_color=my_color,
                                         opp_color=opp_color)
            print('n_nodes=', n_nodes, '\n cutoff=', cutoff)

        elif algor == "mcts":
            my_move = monte_carlo_tree_search(root, cp=1, N=1000)

        # retunred variable "my_move" is a node and contains info about computer's next step
        Game.place(coordinates=my_move.location, color=my_move.color)
        Game.print()

        if Game.is_game_over():
            break
        else:
            # read human's next move
            x, y = xy_read(Game)
            Game.place(coordinates=(x, y), color=opp_color)
            Game.print()
            root = Tree(Game,
                        color=opp_color,
                        parent=None,
                        coordinate=(x, y),
                        my_color=my_color)

    if Game.check_win(opp_color):
        print('Game over! You win :-)')
    else:
        print('Game over! You lose :-(')
Ejemplo n.º 28
0
def mcts_mcts(cp1, N1, cp2, N2, size, print_all=False, first=True):
    #mcts plays with mcts
    Game = HexBoard(size)
    A1_color = 1
    A2_color = 2
    root = Tree(Game, color=A2_color, parent=None, coordinate=None)
    if print_all:
        if first == True:
            print('First move (blue) is mcts')
            print('Second move (red) is mcts')
        else:
            print('First move (blue) is mcts')
            print('Second move (red) is mcts')

    while not Game.is_game_over():
        if first == True:
            #mcts moves first
            A1_move = monte_carlo_tree_search(root, cp=cp1, N=N1)
        else:
            A1_move = monte_carlo_tree_search(root, cp=cp2, N=N2)
        Game.place(coordinates=A1_move.location, color=A1_color)
        if Game.is_game_over():
            if print_all:
                Game.print()
            if first == True:
                #if method1 win, return True
                return Game.check_win(A1_color)
            else:
                #if method1 win, return True
                return Game.check_win(A2_color)
        else:
            root = Tree(Game,
                        color=A1_color,
                        parent=None,
                        coordinate=A1_move.location)
            if first == True:
                A2_move = monte_carlo_tree_search(root, cp=cp2, N=N2)
            else:
                A2_move = monte_carlo_tree_search(root, cp=cp1, N=N1)
            Game.place(coordinates=A2_move.location, color=A2_move.color)
            root = Tree(Game,
                        color=A2_color,
                        parent=None,
                        coordinate=A2_move.location)
    if print_all:
        Game.print()

    if first == True:
        #if method1 win or not
        return Game.check_win(A1_color)
    else:
        return Game.check_win(A2_color)
Ejemplo n.º 29
0
    def alphaBetaSearchDijkstra(self, node, depth, alpha, beta, isMaximizer):
        node['searched'] = True

        if depth == 0 or node['type'] == 'LEAF':
            # if depth == 0, then it is already a leaf node
            node['type'] = 'LEAF'
            #node['value'] = self.dummyEval()
            # calculate the value
            if isMaximizer:
                node['value'] = self.dijkstraEval(node['board'], 1)
            else:
                node['value'] = self.dijkstraEval(node['board'], 2)
            return node['value']

        # If we already get this nodes children then this section we be skipped
        if len(node['children']) <= 0:
            # get children of this node
            children = []
            moves = HexBoard.getMoveList(node)

            # If there is no possible move then this is a leaf node
            if len(moves) == 0:
                # Node type is changing!!!!
                node['type'] = 'LEAF'
                if isMaximizer:
                    node['value'] = self.dijkstraEval(node['board'], 1)
                else:
                    node['value'] = self.dijkstraEval(node['board'], 2)
                return node['value']
            else:
                for move in moves:
                    b = node['board'].copy()
                    if isMaximizer:
                        b[move] = self.MAXIMIZER
                    else:
                        b[move] = self.MINIMIZER
                    child_id = str(uuid.uuid4())
                    node_type = 'MIN'
                    if node['type'] == 'MIN':
                        node_type = 'MAX'

                    child = {
                        'id': child_id,
                        'type': node_type,
                        'children': [],
                        'parent_type': node['type'],
                        'searched': False,
                        'board': b,
                        'value': None,
                        'name': child_id[-3:]
                    }
                    children.append(child)
            node['children'] = children

        if isMaximizer:
            bestVal = -self.INF
            for n in node['children']:
                bestVal = max(
                    bestVal,
                    self.alphaBetaSearchDijkstra(n, depth - 1, alpha, beta,
                                                 False))
                alpha = max(alpha, bestVal)  # Updating alpha
                if bestVal >= beta:
                    break  # beta cutoff, a>=b
        else:
            bestVal = self.INF
            for n in node['children']:
                bestVal = min(
                    bestVal,
                    self.alphaBetaSearchDijkstra(n, depth - 1, alpha, beta,
                                                 True))
                beta = min(beta, bestVal)  # Updating beta
                if alpha >= bestVal:
                    break  # alpha cutoff, a>=b

        node['value'] = bestVal

        return bestVal
from hex_skeleton import HexBoard
import copy

import numpy as np

# global vars
_board_size: int = 11
_INF: float = 99999.0

# initialize board with size n
_board = HexBoard(_board_size)


def _update_board(board: HexBoard, l_move, is_max: bool) -> HexBoard:
    board = copy.deepcopy(
        board
    )  # I think this was the problem with the minimax core, it was using a reference instead of a deep copy
    color = board.BLUE if is_max else board.RED
    board.place(l_move, color)
    return board


def dummy_eval() -> float:
    return np.random.randint(0, 10)


def simple_dijkstra(board: HexBoard, source, is_max):

    Q = set()
    V_set = board.get_all_vertices()
    dist = {}