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 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 _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
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()
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)