예제 #1
0
def find_aerial(agent, target, cap_=4):
    struct = agent.predictions['ball_struct']

    if struct is None:
        return

    max_aerial_height = math.inf

    if len(agent.friends) == 0 and len(agent.foes) == 1:
        max_aerial_height = 643

    i = 10  # Begin by looking 0.2 seconds into the future
    while i < struct.num_slices:
        intercept_time = struct.slices[i].game_seconds
        time_remaining = intercept_time - agent.time

        if time_remaining <= 0:
            return

        ball_location = Vector(struct.slices[i].physics.location.x,
                               struct.slices[i].physics.location.y,
                               struct.slices[i].physics.location.z)

        if abs(ball_location.y) > 5212:
            break

        ball_velocity = Vector(
            struct.slices[i].physics.velocity.x,
            struct.slices[i].physics.velocity.y,
            struct.slices[i].physics.velocity.z).magnitude()

        i += 15 - cap(int(ball_velocity // 150), 0, 13)

        # we don't actually need to calculate if we can get there; it is_viable function will do that for us
        # we just need a few variables to find the best shot vector
        car_to_ball = ball_location - agent.me.location
        direction = car_to_ball.normalize()

        left, right, swapped = post_correction(ball_location, target[0],
                                               target[1])
        if not swapped:
            left_vector = (left - ball_location).normalize()
            right_vector = (right - ball_location).normalize()
            best_shot_vector = direction.clamp(left_vector, right_vector)
            # relax the in_field requirement
            # reduce cap_ from 6 to 4 (by default)
            if in_field(ball_location - (100 * best_shot_vector),
                        1) and is_fast_shot(agent.me.location, ball_location,
                                            intercept_time, agent.time, cap_):
                slope = find_slope(best_shot_vector, car_to_ball)
                ball_intercept = ball_location - 92 * best_shot_vector

                if slope > 0.5 and 275 < ball_intercept.z and ball_intercept.z < max_aerial_height:
                    aerial = Aerial(ball_intercept, intercept_time)
                    if aerial.is_viable(agent):
                        return aerial
예제 #2
0
def find_any_shot(agent, cap_=6, can_aerial=True, can_double_jump=True, can_jump=True, can_ground=True):
    if not can_aerial and not can_double_jump and not can_jump and not can_ground:
        agent.print("WARNING: All shots were disabled when find_any_shot was ran")
        return

    # Only meant for routines that require a defined intercept time/place in the future

    # Assemble data in a form that can be passed to C
    me = agent.me.get_raw(agent)

    game_info = (
        agent.boost_accel,
        agent.ball_radius
    )

    gravity = tuple(agent.gravity)

    is_on_ground = not agent.me.airborne
    can_ground = is_on_ground and can_ground
    can_jump = is_on_ground and can_jump
    can_double_jump = is_on_ground and can_double_jump
    can_aerial = (not is_on_ground or agent.time - agent.me.land_time > 0.5) and can_aerial
    any_ground = can_ground or can_jump or can_double_jump

    if not any_ground and not can_aerial:
        return

    # Here we get the slices that need to be searched - by defining a cap, we can reduce the number of slices and improve search times
    slices = get_slices(agent, cap_)

    if slices is None:
        return

    # Loop through the slices
    for ball_slice in slices:
        # Gather some data about the slice
        intercept_time = ball_slice.game_seconds
        T = intercept_time - agent.time - (1 / 120)

        if T <= 0:
            return

        ball_location = (ball_slice.physics.location.x, ball_slice.physics.location.y, ball_slice.physics.location.z)

        if abs(ball_location[1]) > 5212.75:
            return  # abandon search if ball is scored at/after this point

        ball_info = (ball_location, (ball_slice.physics.velocity.x, ball_slice.physics.velocity.y, ball_slice.physics.velocity.z))

        # Check if we can make a shot at this slice
        # This operation is very expensive, so we use C to improve run time
        shot = virxrlcu.parse_slice_for_shot(can_ground, can_jump, can_double_jump, can_aerial, T, *game_info, gravity, ball_info, me)

        if shot['found'] == 1:
            shot_type = ShotType(shot["shot_type"])
            if shot_type == ShotType.AERIAL:
                return Aerial(intercept_time, fast_aerial=shot['fast'])

            return SHOT_SWITCH[shot_type](intercept_time)
예제 #3
0
def find_any_aerial(agent, cap_=3):
    struct = agent.predictions['ball_struct']

    if struct is None:
        return

    max_aerial_height = math.inf

    if len(agent.friends) == 0 and len(agent.foes) == 1:
        max_aerial_height = 643

    i = 10  # Begin by looking 0.2 seconds into the future
    while i < struct.num_slices:
        intercept_time = struct.slices[i].game_seconds
        time_remaining = intercept_time - agent.time

        if time_remaining <= 0:
            return

        ball_location = Vector(struct.slices[i].physics.location.x,
                               struct.slices[i].physics.location.y,
                               struct.slices[i].physics.location.z)

        if abs(ball_location.y) > 5212:
            break

        ball_velocity = Vector(
            struct.slices[i].physics.velocity.x,
            struct.slices[i].physics.velocity.y,
            struct.slices[i].physics.velocity.z).magnitude()

        i += 15 - cap(int(ball_velocity // 150), 0, 13)

        if 275 > ball_location.z or ball_location.z > max_aerial_height:
            continue

        # remove the need for a target to hit the ball to
        if is_fast_shot(agent.me.location, ball_location, intercept_time,
                        agent.time, cap_):
            aerial = Aerial(ball_location, intercept_time)
            if aerial.is_viable(agent):
                return aerial
예제 #4
0
def find_any_aerial(agent, cap_=3):
    slices = get_slices(agent, cap_)

    if slices is None:
        return

    me = (agent.me.location.tuple(), agent.me.velocity.tuple(),
          agent.me.up.tuple(), agent.me.forward.tuple(),
          1 if agent.me.airborne else -1,
          agent.me.boost if agent.boost_amount != 'unlimited' else 100000)

    gravity = agent.gravity.tuple()

    max_aerial_height = 735 if len(agent.friends) == 0 and len(
        agent.foes) == 1 else math.inf
    min_aerial_height = 551 if max_aerial_height > 643 and agent.me.location.z >= 2044 - agent.me.hitbox.height * 1.1 else (
        0 if agent.boost_amount == 'unlimited' else 450)

    for ball_slice in slices:
        intercept_time = ball_slice.game_seconds
        time_remaining = intercept_time - agent.time

        if time_remaining <= 0:
            return

        ball_location = (ball_slice.physics.location.x,
                         ball_slice.physics.location.y,
                         ball_slice.physics.location.z)

        if abs(ball_location[1]) > 5212.75:
            return

        if min_aerial_height > ball_location[2] or ball_location[
                2] > max_aerial_height:
            continue

        shot = virxrlcu.parse_slice_for_aerial_shot(time_remaining,
                                                    agent.best_shot_value,
                                                    agent.boost_accel, gravity,
                                                    ball_location, me)

        if shot['found'] == 1:
            return Aerial(intercept_time, Vector(*shot['best_shot_vector']),
                          shot['fast'])
예제 #5
0
def find_any_shot(agent,
                  cap_=3,
                  can_aerial=True,
                  can_double_jump=True,
                  can_jump=True):
    if not can_aerial and not can_double_jump and not can_jump:
        agent.print("WARNING: All shots were disabled when find_shot was ran")
        return

    slices = get_slices(agent, cap_)

    if slices is None:
        return

    me = (agent.me.location.tuple(), agent.me.forward.tuple(),
          agent.me.boost if agent.boost_amount != 'unlimited' else 100000,
          agent.me.local_velocity().x)

    game_info = (agent.best_shot_value, agent.boost_accel)

    if can_aerial:
        me_a = (me[0], agent.me.velocity.tuple(), agent.me.up.tuple(), me[1],
                1 if agent.me.airborne else -1, me[2])

        gravity = agent.gravity.tuple()

        max_aerial_height = 643 if len(agent.friends) == 0 and len(
            agent.foes) == 1 else math.inf
        min_aerial_height = 551 if max_aerial_height > 643 and agent.me.location.z >= 2044 - agent.me.hitbox.height * 1.1 else (
            0 if agent.boost_amount == 'unlimited' else 450)

    for ball_slice in slices:
        intercept_time = ball_slice.game_seconds
        time_remaining = intercept_time - agent.time

        if time_remaining <= 0:
            return

        ball_location = (ball_slice.physics.location.x,
                         ball_slice.physics.location.y,
                         ball_slice.physics.location.z)

        if abs(ball_location[1]) > 5212.75:
            return

        if can_jump:
            shot = virxrlcu.parse_slice_for_jump_shot(time_remaining - 0.1,
                                                      *game_info,
                                                      ball_location, *me)

            if shot['found'] == 1:
                return jump_shot(intercept_time,
                                 Vector(*shot['best_shot_vector']))

        if can_double_jump and time_remaining >= 0.5:
            shot = virxrlcu.parse_slice_for_double_jump(
                time_remaining - 0.3, *game_info, ball_location, *me)

            if shot['found'] == 1:
                return double_jump(intercept_time,
                                   Vector(*shot['best_shot_vector']))

        if can_aerial and not (min_aerial_height > ball_location[2]
                               or ball_location[2] > max_aerial_height):
            shot = virxrlcu.parse_slice_for_aerial_shot(
                time_remaining, *game_info, gravity, ball_location, me_a)

            if shot['found'] == 1:
                return Aerial(intercept_time,
                              Vector(*shot['best_shot_vector']), shot['fast'])
예제 #6
0
def find_shot(agent,
              target,
              cap_=6,
              can_aerial=True,
              can_double_jump=True,
              can_jump=True,
              can_ground=True):
    if not can_aerial and not can_double_jump and not can_jump and not can_ground:
        agent.print("WARNING: All shots were disabled when find_shot was ran")
        return

    # Takes a tuple of (left,right) target pairs and finds routines that could hit the ball between those target pairs
    # Only meant for routines that require a defined intercept time/place in the future

    # Assemble data in a form that can be passed to C
    targets = (tuple(target[0]), tuple(target[1]))

    me = agent.me.get_raw(agent)

    game_info = (agent.boost_accel, agent.best_shot_value)

    gravity = tuple(agent.gravity)

    max_aerial_height = 1200 if len(agent.friends) == 0 and len(
        agent.foes) == 1 else math.inf
    min_aerial_height = 551 if max_aerial_height > 1200 and agent.me.location.z >= 2044 - agent.me.hitbox.height * 1.1 else (
        150 if agent.boost_amount == 'unlimited' or agent.me.airborne else 450)

    is_on_ground = not agent.me.airborne
    can_ground = is_on_ground and can_ground
    can_jump = is_on_ground and can_jump
    can_double_jump = is_on_ground and can_double_jump

    if not can_ground and not can_jump and not can_double_jump and not can_aerial:
        return

    # Here we get the slices that need to be searched - by defining a cap, we can reduce the number of slices and improve search times
    slices = get_slices(agent, cap_)

    if slices is None:
        return

    # Loop through the slices
    for ball_slice in slices:
        # Gather some data about the slice
        intercept_time = ball_slice.game_seconds
        time_remaining = intercept_time - agent.time - (1 / 120)

        if time_remaining <= 0:
            return

        ball_location = (ball_slice.physics.location.x,
                         ball_slice.physics.location.y,
                         ball_slice.physics.location.z)

        if abs(ball_location[1]) > 5212.75:
            return  # abandon search if ball is scored at/after this point

        ball_info = (ball_location, (ball_slice.physics.velocity.x,
                                     ball_slice.physics.velocity.y,
                                     ball_slice.physics.velocity.z))

        # Check if we can make a shot at this slice
        # This operation is very expensive, so we use C to improve run time
        shot = virxrlcu.parse_slice_for_shot_with_target(
            can_ground, can_jump, can_double_jump, can_aerial
            and (min_aerial_height < ball_location[2] < max_aerial_height),
            time_remaining, *game_info, gravity, ball_info, me, targets)

        if shot['found'] == 1:
            if shot['shot_type'] == 3:
                return Aerial(
                    intercept_time,
                    (Vector(*shot['targets'][0]), Vector(*shot['targets'][1])),
                    shot['fast'])

            shot_switch = [ground_shot, jump_shot, double_jump]
            return shot_switch[shot['shot_type']](
                intercept_time,
                (Vector(*shot['targets'][0]), Vector(*shot['targets'][1])))
예제 #7
0
def find_risky_hits(agent, targets, cap_=4):
    hits = {name: [] for name in targets}
    struct = agent.predictions['ball_struct']

    if struct is None:
        return hits

    i = 10  # Begin by looking 0.2 seconds into the future
    while i < struct.num_slices:
        intercept_time = struct.slices[i].game_seconds
        time_remaining = intercept_time - agent.time
        if time_remaining > 0:
            ball_location = Vector(struct.slices[i].physics.location.x,
                                   struct.slices[i].physics.location.y,
                                   struct.slices[i].physics.location.z)

            if abs(ball_location.y) > 5200:
                break

            ball_velocity = Vector(
                struct.slices[i].physics.velocity.x,
                struct.slices[i].physics.velocity.y,
                struct.slices[i].physics.velocity.z).magnitude()

            i += 15 - cap(int(ball_velocity // 150), 0, 13)

            if ball_location.z < 300:
                continue

            car_to_ball = ball_location - agent.me.location
            direction, distance = car_to_ball.normalize(True)
            # assume we are traveling towards the ball
            distance -= (agent.me.velocity.flatten().magnitude() * i / 60)
            forward_angle = direction.angle(agent.me.forward)
            forward_time = time_remaining - (forward_angle * 0.318 * 0.5
                                             )  # cut this times in half
            # remove the 5% extra distance assumption and forget about boost requirements
            if forward_time > 0 and (distance / forward_time) < 2300:
                for pair in targets:
                    left, right, swapped = post_correction(
                        ball_location, targets[pair][0], targets[pair][1])
                    if not swapped:
                        left_vector = (left - ball_location).normalize()
                        right_vector = (right - ball_location).normalize()
                        best_shot_vector = direction.clamp(
                            left_vector, right_vector)
                        # relax the in_field requirement
                        # reduce cap_ from 6 to 4 (by default)
                        if in_field(ball_location - (100 * best_shot_vector),
                                    1) and is_fast_shot(
                                        agent.me.location, ball_location,
                                        intercept_time, agent.time, cap_):
                            slope = find_slope(best_shot_vector, car_to_ball)
                            ball_intercept = ball_location - 92 * best_shot_vector

                            if slope > 1:
                                aerial = Aerial(ball_intercept, intercept_time)
                                if aerial.is_viable(agent):
                                    hits[pair].append(aerial)
                                    return hits
        else:
            return hits
    return hits
예제 #8
0
파일: tools.py 프로젝트: VirxEC/VirxEB
def find_shot(agent: VirxERLU, target, weight=0, cap_=6, can_aerial=True, can_double_jump=True, can_jump=True, can_ground=True):
    if not can_aerial and not can_double_jump and not can_jump and not can_ground:
        agent.print("WARNING: All shots were disabled when find_shot was ran")
        return

    # Takes a tuple of (left,right) target pair or (right,left) anti-target pair and finds routines that could hit the ball between those target pairs
    # Only meant for routines that require a defined intercept time/place in the future

    cap_, aerial_time_cap = get_cap(agent, cap_, True, target is agent.anti_shot)

    # Assemble data in a form that can be passed to C
    targets = (
        tuple(target[0]),
        tuple(target[1])
    )

    me = agent.me.get_raw(agent)

    game_info = (
        agent.boost_accel,
        agent.ball_radius
    )

    gravity = tuple(agent.gravity)

    max_aerial_height = 1000 if agent.num_friends == 0 and agent.num_foes == 1 else math.inf
    min_aerial_height = 551 if max_aerial_height > 1000 and agent.me.location.z >= 2044 - agent.me.hitbox.height * 1.1 and not agent.me.doublejumped else 300

    is_on_ground = not agent.me.airborne
    can_ground = is_on_ground and can_ground
    can_jump = is_on_ground and can_jump
    can_double_jump = is_on_ground and can_double_jump
    can_aerial = (not is_on_ground or agent.time - agent.me.land_time > 0.5) and can_aerial
    any_ground = can_ground or can_jump or can_double_jump

    if not any_ground and not can_aerial:
        return

    # Here we get the slices that need to be searched - by defining a cap, we can reduce the number of slices and improve search times
    slices = get_slices(agent, cap_, weight=weight)

    if slices is None:
        return

    # Loop through the slices
    for ball_slice in slices:
        # Gather some data about the slice
        intercept_time = ball_slice.game_seconds
        T = intercept_time - agent.time - (1 / 120)

        if T <= 0:
            return

        ball_location = (ball_slice.physics.location.x, ball_slice.physics.location.y, ball_slice.physics.location.z)

        if abs(ball_location[1]) > 5212.75:
            return  # abandon search if ball is scored at/after this point

        ball_info = (ball_location, (ball_slice.physics.velocity.x, ball_slice.physics.velocity.y, ball_slice.physics.velocity.z))

        # disable aerials if need be
        should_aerial = can_aerial and (min_aerial_height < ball_location[2] < max_aerial_height) and T < aerial_time_cap

        if not any_ground and not should_aerial:
            continue

        # Check if we can make a shot at this slice
        # This operation is very expensive, so we use C to improve run time
        shot = virxrlcu.parse_slice_for_shot_with_target(can_ground, can_jump, can_double_jump, should_aerial, T, *game_info, gravity, ball_info, me, targets)

        if shot['found'] == 1:
            shot_type = ShotType(shot["shot_type"])
            if shot_type == ShotType.AERIAL:
                return Aerial(intercept_time, (Vector(*shot['targets'][0]), Vector(*shot['targets'][1])), weight, shot['fast'])

            return SHOT_SWITCH[shot_type](intercept_time, (Vector(*shot['targets'][0]), Vector(*shot['targets'][1])), weight)