예제 #1
0
def next_move(game: Game_IJK)-> None:

    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()
    
    print(player)

    # You'll want to put in your fancy AI code here. For right now this just 
    # returns a random move.
    
    if player == '+':
       temp = 'max'
    else:
       temp = 'min'
    
    if deterministic == True:
        yield choice(game,temp,4)#random.choice(['U', 'D', 'L', 'R'])
    else:
        yield choice(game,temp,5)#random.choice(['U', 'D', 'L', 'R'])
예제 #2
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    beta = math.inf
    alpha = -1 * math.inf

    # depth
    future_step = 3

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    if player == '+':
        # succ = [game,'move']
        succ = successor(game)

        best, c = max(min_value(i, future_step, alpha, beta) for i in succ)
        yield best[1]

    else:
        yield random.choice(['U', 'L', 'D', 'R'])
예제 #3
0
def evaluate(game: Game_IJK, player) -> (int, int):
    up, low = 0, 0
    gamestate = game.state()
    if (gamestate == 'C'):
        up = float("inf")
        low = float("-inf")
        return float("inf")
    elif (gamestate == 'c'):
        return float("-inf")
    elif (gamestate == 'Tie'):
        return 0
    adjscore = 0
    board = game.getGame()
    for row in board:
        for e in row:
            if (e != ' '):
                if (e >= 'a'):
                    low += (2**(ord(e) - ord('a') + 1) - 1)
                else:
                    up += (2**(ord(e) - ord('A') + 1) - 1)
    for i in range(6):
        for j in range(6):
            if (j + 1 < 6
                    and abs(ord(board[i][j + 1]) - ord(board[i][j])) == 32):
                adjscore += (2**(ord(board[i][j + 1]) - ord('a') + 2) - 1)
            elif (i + 1 < 6
                  and abs(ord(board[i + 1][j]) - ord(board[i][j])) == 32):
                adjscore += (2**(ord(board[i + 1][j]) - ord('a') + 2) - 1)
    return up - low + (adjscore
                       if game.getCurrentPlayer() == player else -adjscore)
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
           current_player: int -> player who will make the next move either ('+') or -'-')
           deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''
    global InitialPlayer
    InitialPlayer = game.getCurrentPlayer()
    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    boards = []
    level = 0
    max_score = -math.inf
    min_score = math.inf
    final_move = ""
    if player == "+":
        boards = succesor_boards(True, game, board)
    else:
        boards = succesor_boards(False, game, board)

    for board in boards:
        alpha = -math.inf
        beta = math.inf
        score = compute_score(False, level, 3, board[1], alpha, beta, game)
        if score > max_score:
            # print(score)
            # print("Final score")
            max_score = score
            final_move = board[0]
    yield final_move
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
	   current_player: int -> player who will make the next move either ('+') or -'-')
	   deterministic: bool -> either True or False, indicating whether the game is deterministic or not
	'''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    moves = getAvailableMoves(game)
    maxUtility = -np.inf
    nextMove = -1

    for move in moves:
        child = getChild(game, move)
        utility = MinimaxAB(board=child,
                            node=player,
                            deterministic=deterministic)

        if utility >= maxUtility:
            maxUtility = utility
            nextMove = move

    yield nextMove
예제 #6
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.

    moves = ['U', 'L', 'R', 'D']
    value = []

    #start with minimax algorithm with current game state
    for i in ['U', 'L', 'R', 'D']:
        child = successor(copy.deepcopy(game), i)
        value.append(minimax(child, 3, False, float('-inf'), float('inf')))
    #get index number with highest value
    k = np.argmax(value)

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.

    #choose a move with highest minimax utility value
    yield moves[k]
예제 #7
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.
    #print('Board: ', board)
    if (player == '+'):
        current_player = 1
    else:
        current_player = -1
    #print(merge(board, current_player))
    #children(board, current_player)
    #board = [['J', 'J', ' ', ' '], [' ', ' ', ' ', ' '], [' ', ' ', ' ', ' '], ['i', ' ', ' ', ' ']]
    if (deterministic == True):
        score, move = Decision(board, current_player, True)
        #print('MOVE', move, score)
        return move
    else:
        score, move = Decision_nondet(board, current_player, True)
        #print('MOVE: ', move, score)
        return move
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.

    depth = 0

    alpha = -math.inf
    beta = math.inf
    mv = ''
    to_be_done = ''

    unchanged_board = board

    for m in moves:
        alpha, mv = max([alpha, mv], Min(m, game, depth, alpha, beta))
        to_be_done = mv
    return to_be_done
예제 #9
0
def next_move(game: Game_IJK)-> None:

    
    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()
    print( "Player" , player )
    yield moves_run( board , game , player )
예제 #10
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
           current_player: int -> player who will make the next move either ('+') or -'-')
           deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''
    global InitialPlayer
    InitialPlayer = game.getCurrentPlayer()
    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    boards = []
    level = 0
    max_score = -math.inf
    min_score = math.inf
    final_move = ""
    if deterministic:
        " Minimax  - alpha/beta pruning"
        if player == "+":
            boards = succesor_boards(True, game, board)
        else:
            boards = succesor_boards(False, game, board)
        for board in boards:
            alpha = -math.inf
            beta = math.inf
            score = compute_score(False, False, level, 3, board[1], alpha,
                                  beta, game, InitialPlayer, "")
            if score > max_score:
                # print(score)
                # print("Final score")
                max_score = score
                final_move = board[0]

    else:
        " Expectiminimax - alpha/beta pruning"
        moves = ['U', 'D', 'L', 'R']
        empty_tiles = get_empty_tiles(board)
        for move in moves:
            score = 0
            if player == "+":
                boards = chance_boards(True, game, board, move, empty_tiles)
            else:
                boards = chance_boards(False, game, board, move, empty_tiles)
            for board1 in boards:
                alpha = -math.inf
                beta = math.inf
                score += compute_score(False, False, level, 3, board1[1],
                                       alpha, beta, game, InitialPlayer, "")
            avg_score = score / empty_tiles
            if avg_score > max_score:
                # print(score)
                # print("Final score")
                max_score = avg_score
                final_move = move

    yield final_move
예제 #11
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.
    yield MINIMAX_Decision(game, deterministic, h=5)
예제 #12
0
def Max(move, game: Game_IJK, depth, alpha, beta):

    game = game.makeMove(move)

    depth = depth + 1
    board = game.getGame()

    if (depth == 6):
        return [utility(board), move]

    for m in moves:
        alpha, move = max([alpha, move], Min(move, game, depth, alpha, beta))
        if alpha > beta:
            return [alpha, move]
    return [alpha, move]
예제 #13
0
def next_move(game: Game_IJK) -> None:
    """board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    """

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    if deterministic == True:
        move = findOptimalMoveDet(game, board, 4, player)
    elif deterministic == False:
        move = findOptimalMoveNonDet(game, board, player)
    yield move
예제 #14
0
def next_move(game: Game_IJK)-> None:

    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just 
    # returns a random move    
    direction, child, utility = decision(game)
    yield direction
#    yield random.choice(['U', 'D', 'L', 'R'])
예제 #15
0
def max_utility(game: Game_IJK, d, alpha, beta):
    d = d + 1
    state = game.state()
    board = game.getGame()
    if state == 'K' or state == 'k' or state == 'tie' or d == 6:
        return heuristics(board)
    moves = ['U', 'D', 'L', 'R']
    best_utility = float('-inf')
    for move in moves:
        clone = game.makeMove(move)
        utility = min_utility(clone, d, -float('inf'), float('inf'))
        if utility > best_utility:
            best_move = move
            best_utility = utility
            alpha = max(alpha, best_utility)
            if beta <= alpha:
                break
    return best_utility
예제 #16
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''
    global maxdepth
    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.
    if deterministic == False:
        if countboard(board) > 8:
            maxdepth = 0
        elif countboard(board) > 5:
            maxdepth = 1
        else:
            maxdepth = 2
        if player == '+':

            start = time.time()
            best_move, _ = maximizechance(game, board)
            end = time.time()
            print(start - end)

            yield (best_move)
        if player == '-':
            best_move, _ = minimizechance(game, board)

            yield (best_move)

    if deterministic == True:
        if player == "+":
            maxdepth = 7
            best_move, _ = Max(game, board)

            yield (best_move)

        if player == "-":
            maxdepth = 7
            best_move, _ = Min(game, board)

            yield (best_move)
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    if player == '+':
        Ismax = True
    else:
        Ismax = False
    depth = 5
    if (deterministic == True):
        score, move = Mininax_AlphaBeta(board, depth, Ismax, -math.inf,
                                        math.inf, game)
        #print('MOVE', move, score)

        return move
예제 #18
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.
    if (deterministic):
        depth = 6
    else:
        depth = 0
    mins = {}
    w = copy.deepcopy(game)
    w = w.makeMove('U')
    s = copy.deepcopy(game)
    s = w.makeMove('D')
    a = copy.deepcopy(game)
    a = w.makeMove('L')
    d = copy.deepcopy(game)
    d = w.makeMove('R')
    mins['U'] = MIN_Value(w, float("-inf"), float("inf"), depth, player)
    mins['D'] = MIN_Value(s, float("-inf"), float("inf"), depth, player)
    mins['L'] = MIN_Value(a, float("-inf"), float("inf"), depth, player)
    mins['R'] = MIN_Value(d, float("-inf"), float("inf"), depth, player)
    move = max(mins, key=lambda k: mins[k])
    for i in range(6):
        for j in range(6):
            if (j + 1 < 6
                    and abs(ord(board[i][j + 1]) - ord(board[i][j])) == 32):
                move = 'R'
            elif (i + 1 < 6
                  and abs(ord(board[i + 1][j]) - ord(board[i][j])) == 32):
                move = 'D'
    yield move
예제 #19
0
def next_move(game: Game_IJK):
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''
    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # You'll want to put in your fancy AI code here. For right now this just
    # returns a random move.

    moves = ['U', 'D', 'L', 'R']
    best_move = moves[0]
    best_utility = float('-inf')
    for move in moves:
        clone = game.makeMove(move)
        utility = min_utility(clone, 0, -float('inf'), float('inf'))
        if utility > best_utility:
            best_utility = utility
            best_move = move
    yield best_move
예제 #20
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    # Create an object of the class Node
    node = Node(copy.deepcopy(board), player, '')
    start = time.time()
    if deterministic:
        # if deterministic, then call minimax with alpha beta pruning
        result = minimax_alpha_beta(node, 9, player, NINF, PINF, deterministic,
                                    start)
    else:
        # if non-deterministic then call normal minimax as expectation is involved
        result = minimax(node, 6, player, deterministic, start)
    print(time.time() - start)
    print(result)
    return result[0]
예제 #21
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()
    player = game.getCurrentPlayer()
    deterministic = game.getDeterministic()

    global current_index

    if deterministic:
        fringe = [board]
        count = 1

        while len(fringe) >= 0 and count <= 85:

            board = fringe.pop(0)
            fringe += find_successors(board, player, deterministic)
            count += 1

        list_mini_max = []
        for i in fringe:
            list_mini_max.append(heuristic(i, player))

        temp, temp1 = minimax(0, 0, True, list_mini_max, -1000, 1000)

        temp_dict = {0: 'L', 1: 'R', 2: 'U', 3: 'D'}
        yield temp_dict[temp1]

    else:
        # Tuple structure : Board, max=1/min=0/chance=-1, depth, Heuristic, parent, current node index, parent node index
        fringe = [(board, 1, 1, 0, "root", 0, 0)]
        fringe1 = [(board, 1, 1, 0, "root", 0, 0)]
        tree_depth = 4
        empty_tiles = 1
        board = fringe.pop(0)
        succ = []
        current_index = 1
        succ += find_successors1(board[0], player, board[2], deterministic,
                                 tree_depth, board[5])

        for i in succ:
            fringe1.append(i)
            fringe.append(i)
            current_index += 1

        chance_flag = 0
        while len(fringe) > 0:
            fringe_temp = []
            board = fringe.pop(0)

            if board[2] < tree_depth:
                if board[1] in [1, 0]:
                    fringe_temp = [
                        chance_nodes for chance_nodes in find_chance(
                            board[0], board[1], board[2], board[5])
                    ]
                    fringe += fringe_temp
                    fringe1 += fringe_temp
                    chance_flag = board[1]

                else:
                    fringe_temp += find_successors1(board[0], chance_flag,
                                                    board[2], deterministic,
                                                    tree_depth, board[5])
                    fringe += fringe_temp
                    fringe1 += fringe_temp
            else:
                break

        count = expectiminimax(fringe1)
        dict = {0: 'L', 1: 'R', 2: 'U', 3: 'D'}

        yield dict[count]
예제 #22
0
def next_move(game: Game_IJK) -> None:
    '''board: list of list of strings -> current state of the game
       current_player: int -> player who will make the next move either ('+') or -'-')
       deterministic: bool -> either True or False, indicating whether the game is deterministic or not
    '''

    board = game.getGame()

    MAX = float('inf')
    MIN = float('-inf')

    def calculate_empty_tiles(state):
        bonus = 0
        for i in range(6):

            for j in range(6):
                if state[i][j] == 0:
                    bonus = bonus + 1
        return bonus

    def weighted_tiles(state):
        board_score = [
            6 * 35, 6 * 34, 6 * 33, 6 * 32, 6 * 31, 6 * 30, 6 * 24, 6 * 25,
            6 * 26, 6 * 27, 6 * 28, 6 * 29, 6 * 23, 6 * 22, 6 * 21, 6 * 20,
            6 * 19, 6 * 18, 6 * 12, 6 * 13, 6 * 14, 6 * 15, 6 * 16, 6 * 17,
            6 * 11, 6 * 10, 6 * 9, 6 * 8, 6 * 7, 6 * 6, 6 * 0, 6 * 1, 6 * 2,
            6 * 3, 6 * 4, 6 * 5
        ]

        bonus = 0
        for i in range(36):
            current_element = ord(state[i])
            bonus = bonus + int(current_element) * int(board_score[i])

        return bonus

    def convert_to_number(state):
        for i in range(0, 6):
            for j in range(0, 6):
                if state[i][j] == "A" or state[i][j] == "a":
                    state[i][j] = 1
                elif state[i][j] == "B" or state[i][j] == "b":
                    state[i][j] = 2
                elif state[i][j] == "C" or state[i][j] == "c":
                    state[i][j] = 3
                elif state[i][j] == "D" or state[i][j] == "d":
                    state[i][j] = 4
                elif state[i][j] == "E" or state[i][j] == "e":
                    state[i][j] = 5
                elif state[i][j] == "F" or state[i][j] == "f":
                    state[i][j] = 6
                elif state[i][j] == "G" or state[i][j] == "g":
                    state[i][j] = 7
                elif state[i][j] == "H" or state[i][j] == "h":
                    state[i][j] = 8
                elif state[i][j] == "I" or state[i][j] == "i":
                    state[i][j] = 9
                elif state[i][j] == "J" or state[i][j] == "j":
                    state[i][j] = 10
                elif state[i][j] == "K" or state[i][j] == "k":
                    state[i][j] = 11
                else:
                    state[i][j] = 0
        return state

    def calculate_monotonicity(state):
        bonus = 0
        for i in range(6):
            row = state[i]
            for j in range(6):
                x = row[j]
                # now check left and right side of the element
                # call function to check the position of first non-zero number in right direction
                if state[i][j] != 0 and j != 5:
                    for z in range(j + 1, 6):
                        if state[i][z] != 0:
                            index = z
                            break
                        elif z == 5 and state[i][z] == 0:
                            index = z

                    if x <= row[index] and row[index] != 0:
                        bonus = bonus + 10
                    elif x > row[index] and row[index] != 0:
                        bonus = bonus - 15

                    if x <= state[index][j]:
                        bonus = bonus + 10
                    elif x > state[index][j]:
                        bonus = bonus - 15
                elif state[i][j] == 0:
                    bonus = bonus + 0

                if state[i][j] != 0 and i != 5:

                    for z in range(i + 1, 6):
                        if state[z][j] != 0:
                            index = z
                            break
                        elif z == 5 and state[z][j] == 0:
                            index = z
                    index = i
                    if x <= state[index][j] and state[index][j] != 0:
                        bonus = bonus + 10
                    elif x > state[index][j] and state[index][j] != 0:
                        bonus = bonus - 15

                elif state[i][j] == 0:
                    bonus = bonus + 0

        return bonus

    def flattened(listt):
        flattened_list = []
        for j in listt:
            for i in j:
                flattened_list.append(i)

        return flattened_list

    def calculate_smoothness(state):
        bonus = 0
        for i in range(6):
            row = state[i]
            for j in range(6):
                x = row[j]
                if j != 5 and (x - state[i][j + 1]) <= 1:
                    bonus = bonus + 5
                if i != 5 and (x - state[i + 1][j]) <= 1:
                    bonus = bonus + 5

        return bonus

    def gt_mov(array):
        for i in range(len(array)):
            array[i] = list(array[i])
            if i >= 0 and i < 64:
                array[i][1] = 'U'
            elif i >= 64 and i < 128:
                array[i][1] = 'D'
            elif i >= 128 and i < 192:
                array[i][1] = 'L'
            elif i >= 192 and i < 256:
                array[i][1] = 'R'

        return array

    def heuristic_containing_evrything(now, state):
        score = 0
        state = convert_to_number(state)
        score1 = calculate_empty_tiles(state) * 100
        #score2 = weighted_tiles(now)
        score3 = calculate_monotonicity(state) * 100
        score4 = calculate_smoothness(state) * 200
        score = score1 + score3 + score4
        return score

    def successors(game1):
        moves = ['U', 'D', 'L', 'R']

        successor_s = []

        for i in moves:
            successor1 = game.makeMove(i)
            successor1 = successor1.getGame()
            successor_s.append((successor1, i))
        return successor_s

    def parse_full(game1):
        for_first_depth = successors(game1)
        for_second_depth = []

        for i in for_first_depth:

            for_second_depth.append(successors(i[0]))

        for_second_depth = flattened(for_second_depth)

        for_third_depth = []

        for i in for_second_depth:

            for_third_depth.append(successors(i[0]))

        for_third_depth = flattened(for_third_depth)
        for_fourth_depth = []

        for i in for_third_depth:

            for_fourth_depth.append(successors(i[0]))

        for_fourth_depth = flattened(for_fourth_depth)

        future_successors = []
        possible_moves = []

        for i in for_fourth_depth:
            future_successors.append(i[0])
            possible_moves.append(i[1])
        scores = calculate_score(future_successors)
        final = []
        for i in range(len(scores)):
            final.append((scores[i], possible_moves[i]))
        final = gt_mov(final)
        return final

    def calculate_score(arrStates):
        scores = []
        for i in arrStates:

            x = flattened(i)
            score = heuristic_containing_evrything(x, i)
            scores.append(score)
        return scores

    def mini_max_algo(depth, Index_of_node, maximizing_player, values, alpha,
                      beta):
        if depth == 4:

            return values[Index_of_node][0], values[Index_of_node][1]
        if maximizing_player:
            best = MIN
            final_move = " "
            for i in range(0, 4):
                value, moves = mini_max_algo(depth + 1, Index_of_node * 4 + i,
                                             False, values, alpha, beta)

                if value > best:
                    best = value
                    final_move = moves
                alpha = max(alpha, best)

                if beta <= alpha:
                    break
            return (best, final_move)

        else:

            best = MAX
            final_move = " "
            for i in range(0, 4):

                value, moves = mini_max_algo(depth + 1, Index_of_node * 4 + i,
                                             True, values, alpha, beta)

                if value < best:

                    best = value

                    final_move = moves
                beta = min(beta, best)
                if beta <= alpha:
                    break
            return (best, final_move)

    final_s = parse_full(board)
    score, move = mini_max_algo(0, 0, True, final_s, MIN, MAX)

    yield move