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