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)
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"
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
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() neighbor_check = HexBoard(5) assert (neighbor_check.get_neighbors((0, 0)) == [(1, 0), (0, 1)]) assert (neighbor_check.get_neighbors((0, 1)) == [(1, 1), (1, 0), (0, 2), (0, 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 :-(')
def mcts_alphabeta(cp=1, N=500, method='dijkstra', depth=3, size=3, print_all=False, first=True, time_limit=5): #mcts plays with method #method='dijkstra' or 'idtt' global flag, user_color, unuse_color, INF, n_nodes, cutoff Game = HexBoard(size) A1_color = 1 A2_color = 2 root = Tree(Game, color=A2_color, parent=None, coordinate=None, my_color=A1_color) if print_all: if first == True: print('First move (blue) is mcts') print('Second move (red) is ' + method) else: print('First move (blue) is ' + method) print('Second move (red) is mcts') while not Game.is_game_over(): INF = 99999 flag = 0 n_nodes = 0 cutoff = 0 if first == True: #mcts moves first A1_move = monte_carlo_tree_search(root, cp=cp, N=N) else: #method moves first if method == 'dijkstra': A1_move = alphabeta(n=root, a=-INF, b=INF, d=depth, method=method, depth=depth, my_color=A1_color, opp_color=A2_color) elif method == 'idtt': A1_move = iterativedeepening(n=root, a=-INF, b=INF, DEPTH_stop=depth, time_limit=time_limit, my_color=A1_color, opp_color=A2_color) 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, my_color=A2_color) flag = 0 n_nodes = 0 cutoff = 0 if first == True: if method == 'idtt': A2_move = iterativedeepening(n=root, a=-INF, b=INF, DEPTH_stop=depth, time_limit=time_limit, my_color=A2_color, opp_color=A1_color) elif method == 'dijkstra': A2_move = alphabeta(n=root, a=-INF, b=INF, d=depth, method=method, depth=depth, my_color=A2_color, opp_color=A1_color) else: A2_move = monte_carlo_tree_search(root, cp=cp, N=N) Game.place(coordinates=A2_move.location, color=A2_move.color) root = Tree(Game, color=A2_color, parent=None, coordinate=A2_move.location, my_color=A1_color) 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)
def idtt_alphabeta(method='random', idtt_depth=3, depth2=3, size=3, print_all=False, first=True, time_limit=5): #idtt against alphabeta (random or dijkstra) #idtt_depth is idtt's depth; depth2 is method's deptth #first determins which moves first global flag, INF, n_nodes, cutoff Game = HexBoard(size) #firt move color=A1_color: blue A1_color = 1 #second move color=A1_color: red A2_color = 2 root = Tree(Game, color=A2_color, parent=None, coordinate=None, my_color=A1_color) if print_all: if first == True: print('First move (blue) is idtt') print('Second move (red) is ' + method) else: print('First move (blue) is ' + method) print('Second move (red) is idtt') while not Game.is_game_over(): INF = 99999 flag = 0 n_nodes = 0 cutoff = 0 if first == True: #idtt moves first A1_move = iterativedeepening(n=root, a=-INF, b=INF, DEPTH_stop=idtt_depth, time_limit=time_limit, my_color=A1_color, opp_color=A2_color) else: #method2 moves first A1_move = alphabeta(n=root, a=-INF, b=INF, d=depth2, method=method, depth=depth2, my_color=A1_color, opp_color=A2_color) Game.place(coordinates=A1_move.location, color=A1_color) if Game.is_game_over(): if print_all: Game.print() if first == True: #if idtt win, return True return Game.check_win(A1_color) else: #if idtt win, return True return Game.check_win(A2_color) else: root = Tree(Game, color=A1_color, parent=None, coordinate=A1_move.location, my_color=A2_color) n_nodes = 0 cutoff = 0 flag = 0 if first == True: A2_move = alphabeta(n=root, a=-INF, b=INF, d=depth2, method=method, depth=depth2, my_color=A2_color, opp_color=A1_color) else: A2_move = iterativedeepening(n=root, a=-INF, b=INF, DEPTH_stop=idtt_depth, time_limit=time_limit, my_color=A2_color, opp_color=A1_color) Game.place(coordinates=A2_move.location, color=A2_move.color) root = Tree(Game, color=A2_color, parent=None, coordinate=A2_move.location, my_color=A1_color) 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)
def alphabeta_randomVSdijkstra(method1='random', method2='dijkstra', depth1=3, depth2=3, size=3, print_all=False, first=True): #alphabeta: method1 and method2 can choose 'random' or 'dijkstra' #first==True: method1 moves first #first determins which moves first global flag, user_color, unuse_color, INF, n_nodes, cutoff Game = HexBoard(size) #firt move color=A1_color: blue A1_color = 1 #second move color=A1_color: red A2_color = 2 root = Tree(Game, color=A2_color, parent=None, coordinate=None, my_color=A1_color) if print_all: if first == True: print('First move (blue) is ' + method1) print('Second move (red) is ' + method2) else: print('First move (blue) is ' + method2) print('Second move (red) is ' + method1) while not Game.is_game_over(): INF = 99999 flag = 0 n_nodes = 0 cutoff = 0 if first == True: #method1 moves first A1_move = alphabeta(n=root, a=-INF, b=INF, d=depth1, method=method1, depth=depth1, my_color=A1_color, opp_color=A2_color) else: #method2 moves first A1_move = alphabeta(n=root, a=-INF, b=INF, d=depth2, method=method2, depth=depth2, my_color=A1_color, opp_color=A2_color) 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, my_color=A2_color) n_nodes = 0 cutoff = 0 flag = 0 if first == True: A2_move = alphabeta(n=root, a=-INF, b=INF, d=depth2, method=method2, depth=depth2, my_color=A2_color, opp_color=A1_color) else: A2_move = alphabeta(n=root, a=-INF, b=INF, d=depth1, method=method1, depth=depth1, my_color=A2_color, opp_color=A1_color) Game.place(coordinates=A2_move.location, color=A2_move.color) root = Tree(Game, color=A2_color, parent=None, coordinate=A2_move.location, my_color=A1_color) 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)