Ejemplo n.º 1
0
def minimax_alpha_beta(moves_log,
                       state: game.GameState,
                       max_player: MinimaxPlayer,
                       max_depth=5,
                       depth=0,
                       alpha=-INF,
                       beta=INF) -> (int, int):
    winner = state.get_winner()
    if winner is not None:
        # TODO: consider depth
        score = INF - depth if winner is max_player else -INF + depth
        return NO_MOVE, score  # state.eval_state()

    moves = game.to_non_empty(state.get_moves())
    if not moves:
        return NO_MOVE, TIE_SCORE

    moves = list(moves)
    random.shuffle(moves)

    if depth >= max_depth:
        return NO_MOVE, state.eval()

    is_max_player = (depth % 2 == 0)
    best_moves = []
    best_score = None
    for move in moves:
        recursive_score = \
            minimax_alpha_beta(moves_log + [move], state.move(move), max_player, max_depth, depth + 1, alpha, beta)[1]
        if is_max_player:
            if best_score is None or recursive_score > best_score:
                best_score = recursive_score
                best_moves = [move]
                if best_score > alpha:
                    alpha = recursive_score
            elif recursive_score == best_score:
                best_moves.append(move)
        else:
            if best_score is None or recursive_score < best_score:
                best_score = recursive_score
                best_moves = [move]
                if best_score < beta:
                    beta = recursive_score
            elif recursive_score == best_score:
                best_moves.append(move)

        if alpha > beta:
            break

    # print(f'Depth {depth}/{max_depth}: [{",".join(str(i) for i in moves_log)}] | '
    #       f'As {state.get_curr_player().get_char()}, '
    #       f'my best moves are: [{",".join(str(i) for i in best_moves)}] with score: {best_score}')

    return random.choice(best_moves) if best_moves else None, best_score