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 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 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