Example #1
0
    def is_viable(self, agent):
        T = self.intercept_time - agent.time
        xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T * T
        vf = agent.me.velocity + agent.gravity * T

        if not agent.me.airborne:
            vf += agent.me.up * (2 * jump_speed + jump_acc * jump_max_duration)
            xf += agent.me.up * (
                jump_speed * (2 * T - jump_max_duration) + jump_acc *
                (T * jump_max_duration - 0.5 * jump_max_duration**2))

        delta_x = self.target - xf
        f = delta_x.normalize()
        phi = f.angle3D(agent.me.forward)
        turn_time = 0.7 * (2 * math.sqrt(phi / 9))

        tau1 = turn_time * cap(1 - 0.3 / phi, 0, 1)
        required_acc = (2 * delta_x.norm()) / ((T - tau1) * (T - tau1))
        ratio = required_acc / agent.boost_accel
        tau2 = T - (T - tau1) * math.sqrt(1 - cap(ratio, 0, 1))
        velocity_estimate = vf + agent.boost_accel * (tau2 - tau1) * f
        boost_estimate = (tau2 - tau1) * 30
        enough_boost = boost_estimate < 0.95 * agent.me.boost
        enough_time = abs(ratio) < 0.9
        enough_speed = velocity_estimate.normalize(True)[1] < 0.9 * max_speed

        return enough_speed and enough_boost and enough_time
Example #2
0
    def run(self, agent):
        agent.shooting = True

        if self.start_time is None:
            self.start_time = agent.time

        car_to_ball, distance = (agent.ball.location -
                                 agent.me.location).normalize(True)
        ball_to_target = (self.target - agent.ball.location).normalize()

        relative_velocity = car_to_ball.dot(agent.me.velocity -
                                            agent.ball.velocity)
        if relative_velocity != 0:
            eta = cap(distance / cap(relative_velocity, 400, 2300), 0, 1.5)
        else:
            eta = 1.5

        # If we are approaching the ball from the wrong side the car will try to only hit the very edge of the ball
        left_vector = car_to_ball.cross(Vector(z=1))
        right_vector = car_to_ball.cross(Vector(z=-1))
        target_vector = -ball_to_target.clamp(left_vector, right_vector)
        final_target = agent.ball.location + (target_vector * (distance / 2))

        # Some adjustment to the final target to ensure we don't try to dirve through any goalposts to reach it
        if abs(agent.me.location.y) > 5150:
            final_target.x = cap(final_target.x, -750, 750)

        agent.line(final_target - Vector(z=100), final_target + Vector(z=100),
                   [255, 255, 255])

        angles = defaultPD(agent,
                           agent.me.local(final_target - agent.me.location))
        defaultThrottle(
            agent, 2300 if distance > 1600 else 2300 -
            cap(1600 * abs(angles[1]), 0, 2050))
        agent.controller.boost = False if agent.me.airborne or abs(
            angles[1]) > 0.3 else agent.controller.boost
        agent.controller.handbrake = True if abs(
            angles[1]) > 2.3 else agent.controller.handbrake

        if abs(angles[1]) < 0.05 and (eta < 0.45 or distance < 150):
            agent.pop()
            agent.shooting = False
            agent.shot_weight = -1
            agent.shot_time = -1
            agent.push(flip(agent.me.local(car_to_ball)))
        elif agent.time - self.start_time > 3:
            agent.pop()
            agent.shooting = False
            agent.shot_weight = -1
            agent.shot_time = -1
Example #3
0
    def defend(self):
        if not self.me.airborne:
            if self.shooting and not self.predictions[
                    'own_goal'] and self.ball.location.y * side(
                        self.team) < self.defense_switch[self.playstyle]:
                self.clear()

            if self.is_clear():
                ball = self.ball_prediction_struct.slices[cap(
                    round(self.predictions['enemy_time_to_ball'] * 0.95) * 60,
                    0,
                    len(self.ball_prediction_struct.slices) -
                    1)].physics.location
                ball = Vector(ball.x, ball.y, ball.z)
                if self.predictions['self_from_goal'] > 2560:
                    self.backcheck()
                if self.me.boost < 72 and ball.y * side(self.team) < -1280:
                    self.goto_nearest_boost(
                        only_small=ball.y * side(self.team) > -2560)
                elif self.predictions['self_from_goal'] > 750:
                    self.backcheck()
                else:
                    face_target_routine = face_target(ball=True)
                    ball_f = face_target_routine.get_ball_target(self)
                    if ball_f.y * side(self.team) > -3840 and abs(
                            Vector(x=1).angle2D(self.me.local_location(ball_f))
                    ) >= 1 and self.me.velocity.magnitude() < 100:
                        self.push(face_target_routine)
                        return
Example #4
0
    def run(self, agent):
        ball_slice = agent.ball_prediction_struct.slices[
            agent.future_ball_location_slice].physics.location
        ball = Vector(ball_slice.x, cap(ball_slice.y, -5100, 5100))
        agent.line(ball, ball + Vector(z=185), agent.renderer.white())
        ball.y *= side(agent.team)

        if ball.y < agent.ball.location.y * side(agent.team):
            ball = Vector(agent.ball.location.x,
                          agent.ball.location.y * side(agent.team) + 640)

        target = self.get_target(agent)
        agent.line(target, target + Vector(z=642), (255, 0, 255))

        if target.flat_dist(agent.me.location) < 350:
            if agent.me.velocity.magnitude() > 100:
                self.brake.run(agent, manual=True)
            elif abs(Vector(x=1).angle2D(agent.me.local_location(ball))) > 0.5:
                agent.pop()
                agent.push(face_target(ball=True))
            else:
                agent.pop()
        else:
            self.goto.target = target
            self.goto.run(agent, manual=True)
Example #5
0
    def run(self, agent):
        if self.start_time is None:
            self.start_time = agent.time

        ball_loc = agent.ball.location.y * side(agent.team)

        if agent.time - self.start_time > 0.5 or agent.playstyle is agent.playstyles.Defensive or ball_loc > 2560:
            agent.pop()
            return

        target = Vector(y=(ball_loc + 1280) * side(agent.team))

        if agent.ball.location.x > 2560:
            target.x = 2560 if ball_loc <= 0 else 1024
        elif agent.ball.location.x < -2560:
            target.x = -2560 if ball_loc <= 0 else -1024

        self_to_target = agent.me.location.dist(target)

        if self_to_target > 250:
            self.goto.target = target
            self.goto.vector = agent.ball.location
            self.goto.run(agent, manual=True)

            if self_to_target < 500:
                agent.controller.boost = False
                agent.controller.throttle = cap(agent.controller.throttle, -0.75, 0.75)
Example #6
0
    def run(self, agent):
        target = agent.ball.location
        car_to_target = target - agent.me.location
        distance_remaining = car_to_target.flatten().magnitude()

        # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it
        if abs(agent.me.location.y) > 5150:
            target.x = cap(target.x, -750, 750)

        local_target = agent.me.local(target - agent.me.location)

        angles = defaultPD(agent, local_target)
        defaultThrottle(agent, 1400)

        agent.controller.boost = False
        agent.controller.handbrake = True if abs(
            angles[1]) > 2.3 else agent.controller.handbrake

        velocity = 1 + agent.me.velocity.magnitude()
        if distance_remaining < self.exit_distance:
            agent.pop()
            if self.exit_flip:
                agent.push(flip(local_target))
        elif abs(
                angles[1]
        ) < 0.05 and velocity > 600 and velocity < 2150 and distance_remaining / velocity > 2.0:
            agent.push(flip(local_target))
        elif abs(angles[1]) > 2.8 and velocity < 200:
            agent.push(flip(local_target, True))
        elif agent.me.airborne:
            agent.push(recovery(target))
Example #7
0
    def run(self, agent):
        target = agent.ball.location
        car_to_target = target - agent.me.location
        distance_remaining = car_to_target.flatten().magnitude()

        angle_to_target = abs(
            Vector(x=1).angle2D(agent.me.local_location(target)))
        direction = 1 if angle_to_target < 2.2 else -1
        local_target = agent.me.local_location(target)

        # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it
        if abs(agent.me.location.y) > 5120 - (agent.me.hitbox.width / 2):
            local_target.x = cap(local_target.x, -750, 750)

        angles = defaultPD(agent, local_target)
        defaultThrottle(agent, 1400)

        agent.controller.handbrake = angle_to_target > 1.54

        velocity = agent.me.local_velocity().x
        if distance_remaining < self.exit_distance:
            agent.pop()
            if self.exit_flip:
                agent.push(flip(local_target))
        elif angle_to_target < 0.05 and velocity > 600 and velocity < 1400 and distance_remaining / velocity > 3:
            agent.push(flip(local_target))
        elif angle_to_target >= 2 and distance_remaining > 1000 and velocity < 200 and distance_remaining / abs(
                velocity) > 2:
            agent.push(flip(local_target, True))
        elif agent.me.airborne:
            agent.push(recovery(local_target))
Example #8
0
def get_slices(agent, cap_):
    # Get the struct
    struct = agent.ball_prediction_struct

    # Make sure it isn't empty
    if struct is None:
        return

    start_slice = 6
    end_slices = None

    # If we're shooting, crop the struct
    if agent.shooting and agent.stack[0].__class__.__name__ != "short_shot":
        # Get the time remaining
        time_remaining = agent.stack[0].intercept_time - agent.time
        if time_remaining < 0.5 and time_remaining >= 0:
            return

        # if the shot is done but it's working on it's 'follow through', then ignore this stuff
        if time_remaining > 0:
            # Convert the time remaining into number of slices, and take off the minimum gain accepted from the time
            min_gain = 0.05
            end_slice = round(min(time_remaining - min_gain, cap_) * 60)

    if end_slices is None:
        # Cap the slices
        end_slice = round(cap_ * 60)

    # We can't end a slice index that's lower than the start index
    if end_slice <= start_slice:
        return

    # for every second worth of slices that we have to search, skip 1 more slice (for performance reasons) - min 1 and max 3
    skip = cap(end_slice - start_slice / 60, 1, 3)
    return struct.slices[start_slice:end_slice:skip]
Example #9
0
    def get_intercept(self, agent):
        struct = agent.predictions['ball_struct']
        intercepts = []

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

            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

            last_ball_location = Vector(struct.slices[i-2].physics.location.x, struct.slices[i-2].physics.location.y, struct.slices[i-2].physics.location.z)
            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 time_remaining < 0 or ball_location.z > 120 or ball_location.flat_dist(agent.friend_goal.location) > last_ball_location.flat_dist(agent.friend_goal.location):
                continue

            car_to_ball = ball_location - agent.me.location
            direction, distance = car_to_ball.normalize(True)

            forward_angle = direction.angle(agent.me.forward)
            backward_angle = math.pi - forward_angle

            forward_time = time_remaining - (forward_angle * 0.318)
            backward_time = time_remaining - (backward_angle * 0.418)

            forward_flag = forward_time > 0 and (distance / forward_time) < 1800
            backward_flag = distance < 1500 and backward_time > 0 and (distance / backward_time) < 1200

            if forward_flag or backward_flag:
                intercepts.append((
                    ball_location,
                    intercept_time,
                    1 if forward_flag else -1
                ))

        if len(intercepts) == 0:
            return None, None, None

        intercepts = list(filter(lambda i: i[1] - agent.time < 3, intercepts))

        intercepts.sort(key=lambda i: agent.me.location.dist(i[0]))

        final = (None, None, None)
        last_speed = math.inf

        for intercept in intercepts:
            speed = agent.me.location.dist(intercept[0]) / ((intercept[1] / agent.time) * (3/5))
            if abs(speed - 1100) < abs(last_speed - 1100):
                final = intercept
                last_speed = speed

        return final
Example #10
0
 def run(agent, manual=False):
     # current forward velocity
     speed = agent.me.local_velocity().x
     if abs(speed) > 10:
         # apply our throttle in the opposite direction
         # Once we're below a velocity of 50uu's, start to ease the throttle
         agent.controller.throttle = cap(speed / -50, -1, 1)
     elif not manual:
         agent.pop()
Example #11
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
Example #12
0
def find_any_jump_shot(agent, cap_=3):
    struct = agent.predictions['ball_struct']

    if struct is None:
        return

    i = 5
    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 ball_location.z > 350:
            continue

        car_to_ball = ball_location - agent.me.location
        direction, distance = car_to_ball.normalize(True)

        forward_angle = direction.angle(agent.me.forward)
        backward_angle = math.pi - forward_angle

        forward_time = time_remaining - (forward_angle * 0.318)
        backward_time = time_remaining - (backward_angle * 0.418)

        forward_flag = forward_time > 0 and (
            distance * 1.05 /
            forward_time) < (2275 if agent.me.boost > distance / 100 else 1400)
        backward_flag = distance < 1500 and backward_time > 0 and (
            distance * 1.05 / backward_time) < 1200

        # our current direction IS our best shot vector, as we just want to get to the ball as fast as possible
        if (forward_flag or backward_flag) and is_fast_shot(
                agent.me.location, ball_location, intercept_time, agent.time,
                cap_):
            slope = find_slope(direction, car_to_ball)
            if forward_flag and ball_location.z <= 275 and slope > 0:
                return jump_shot(ball_location, intercept_time, direction)
            elif backward_flag and ball_location.z <= 250 and slope > 1.5:
                return jump_shot(ball_location, intercept_time, direction, -1)
Example #13
0
    def run(self, agent):
        if not agent.shooting:
            agent.shooting = True

        if self.start_time is None:
            self.start_time = agent.time

        car_to_ball, distance = (agent.ball.location -
                                 agent.me.location).normalize(True)
        ball_to_target = (self.target - agent.ball.location).normalize()
        angle_to_target = abs(Vector(x=1).angle2D(agent.me.local(car_to_ball)))

        relative_velocity = car_to_ball.dot(agent.me.velocity -
                                            agent.ball.velocity)
        eta = cap(distance / cap(relative_velocity, 400, 1400), 0,
                  1.5) if relative_velocity != 0 else 1.5

        # If we are approaching the ball from the wrong side the car will try to only hit the very edge of the ball
        left_vector = car_to_ball.cross(Vector(z=1))
        right_vector = car_to_ball.cross(Vector(z=-1))
        target_vector = -ball_to_target.clamp2D(left_vector, right_vector)
        final_target = agent.ball.location + (target_vector * (distance / 2))

        # Some adjustment to the final target to ensure we don't try to drive through any goalposts to reach it
        if abs(agent.me.location.y) > 5130:
            final_target.x = cap(final_target.x, -750, 750)

        agent.line(final_target - Vector(z=100), final_target + Vector(z=100),
                   (255, 255, 255))

        angles = defaultPD(agent, agent.me.local_location(final_target))
        defaultThrottle(agent, 1400)

        agent.controller.handbrake = angle_to_target > 1.54

        if abs(angles[1]) < 0.05 and (eta < 0.45 or distance < 150):
            agent.pop()
            agent.shooting = False
            agent.push(flip(agent.me.local(car_to_ball)))
        elif agent.time - self.start_time > 0.24:  # This will run for 3 ticks, then pop
            agent.pop()
            agent.shooting = False
Example #14
0
    def run(self, agent):
        if self.start_time is None:
            self.start_time = agent.time

        car_to_boost = self.boost.location - agent.me.location
        distance_remaining = car_to_boost.flatten().magnitude()

        agent.line(self.boost.location - Vector(z=500),
                   self.boost.location + Vector(z=500), [0, 255, 0])

        if self.target is not None:
            vector = (self.target - self.boost.location).normalize()
            side_of_vector = sign(vector.cross(Vector(z=1)).dot(car_to_boost))
            car_to_boost_perp = car_to_boost.cross(
                Vector(z=side_of_vector)).normalize()
            adjustment = car_to_boost.angle(vector) * distance_remaining / 3.14
            final_target = self.boost.location + (car_to_boost_perp *
                                                  adjustment)
            car_to_target = (self.target - agent.me.location).magnitude()
        else:
            adjustment = 9999
            car_to_target = 0
            final_target = self.boost.location

        # Some adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it
        if abs(agent.me.location.y) > 5150:
            final_target.x = cap(final_target.x, -750, 750)

        local_target = agent.me.local(final_target - agent.me.location)

        angles = defaultPD(agent, local_target)
        defaultThrottle(agent, 2300)

        agent.controller.boost = self.boost.large if abs(
            angles[1]) < 0.3 else False
        agent.controller.handbrake = True if abs(
            angles[1]) > 2.3 else agent.controller.handbrake

        velocity = 1 + agent.me.velocity.magnitude()
        if not self.boost.active or agent.me.boost >= 99.0 or distance_remaining < 350:
            agent.pop()
        elif agent.me.airborne:
            agent.push(recovery(self.target))
        elif abs(angles[1]) < 0.05 and velocity > 600 and velocity < 2150 and (
                distance_remaining / velocity > 2.0 or
            (adjustment < 90 and car_to_target / velocity > 2.0)):
            agent.push(flip(local_target))
        elif agent.time - self.start_time > 6 and not agent.stack[
                -1].__class__.__name__ == "flip":
            agent.pop()
Example #15
0
def get_slices(agent, cap_, weight=None, start_slice=12):
    # Get the struct
    struct = agent.ball_prediction_struct
    min_time_to_ball = agent.predictions['self_min_time_to_ball'] - (1 / 15)

    # Make sure it isn't empty
    if struct is None or min_time_to_ball > cap_:
        return

    if start_slice / 60 < min_time_to_ball:
        start_slice = round(min_time_to_ball * 60) - 1

    ball_y = agent.ball.location.y * side(agent.team)
    foes = len(
        tuple(foe for foe in agent.foes
              if not foe.demolished and foe.location.y *
              side(agent.team) < ball_y + 75))
    if not agent.predictions[
            'goal'] and agent.ball_to_goal > 2560 and agent.ball.location.dist(
                agent.foe_goal.location) > 900 and foes > 0:
        factor = 1.2 - 0.04 * foes
        cap_ = min(agent.predictions['enemy_time_to_ball'] * factor, cap_)

    end_slices = None

    # If we're shooting, crop the struct
    if agent.shooting and agent.shot_weight != -1:
        # Get the time remaining
        time_remaining = agent.stack[0].intercept_time - agent.time
        if time_remaining < 0.5 and time_remaining >= 0:
            return

        # if the shot is done but it's working on it's 'follow through', then ignore this stuff
        if time_remaining > 0:
            # Convert the time remaining into number of slices, and take off the minimum gain accepted from the time
            min_gain = 0.05 if weight is None or weight is agent.shot_weight else -(
                agent.max_shot_weight - agent.shot_weight + 1)
            end_slice = round(min(time_remaining - min_gain, cap_) * 60)

    if end_slices is None:
        # Cap the slices
        end_slice = round(cap_ * 60)

    # We can't end a slice index that's lower than the start index
    if end_slice <= start_slice:
        return

    # for every second worth of slices that we have to search, skip 1 more slice (for performance reasons) - min 1 and max 3
    skip = cap(end_slice - start_slice / 60, 1, 3)
    return struct.slices[start_slice:end_slice:skip]
Example #16
0
    def run(self, agent, manual=False):
        car_to_target = self.target - agent.me.location
        distance_remaining = car_to_target.flatten().magnitude()

        agent.dbg_2d(distance_remaining)
        agent.line(self.target - Vector(z=500), self.target + Vector(z=500), [255, 0, 255])

        if (not self.brake and distance_remaining < 350) or (self.brake and distance_remaining < (agent.me.local(agent.me.velocity).x ** 2 * -1) / (2 * brake_accel.x)):
            if not manual:
                agent.pop()

            if self.brake:
                agent.push(brake())
            return

        if self.vector != None:
            # See commends for adjustment in jump_shot or aerial for explanation
            side_of_vector = sign(self.vector.cross(Vector(z=1)).dot(car_to_target))
            car_to_target_perp = car_to_target.cross(Vector(z=side_of_vector)).normalize()
            adjustment = car_to_target.angle(self.vector) * distance_remaining / 3.14
            final_target = self.target + (car_to_target_perp * adjustment)
        else:
            final_target = self.target

        # Some adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it
        if abs(agent.me.location.y) > 5150:
            final_target.x = cap(final_target.x, -750, 750)

        local_target = agent.me.local(final_target - agent.me.location)

        angles = defaultPD(agent, local_target, self.direction)
        defaultThrottle(agent, 2300, self.direction)

        if len(agent.friends) > 0 and agent.me.local(agent.me.velocity).x < 250 and agent.controller.throttle > 0.75 and min(agent.me.location.flat_dist(car.location) for car in agent.friends) < 251:
            agent.push(flip(Vector(y=250)))
            return

        if agent.me.boost < 30 or (agent.playstyle is agent.playstyles.Defensive and agent.predictions['self_from_goal'] < 4000):
            agent.controller.boost = False
        agent.controller.handbrake = True if abs(angles[1]) >= 2.3 or (agent.me.local(agent.me.velocity).x >= 1400 and abs(angles[1]) > 1.5) else agent.controller.handbrake

        velocity = 1+agent.me.velocity.magnitude()
        if abs(angles[1]) < 0.05 and velocity > 600 and velocity < 2150 and distance_remaining / velocity > 2:
            agent.push(flip(local_target))
        elif abs(angles[1]) > 2.8 and velocity < 200 and distance_remaining / velocity > 2:
            agent.push(flip(local_target, True))
        elif agent.me.airborne:
            agent.push(recovery(self.target))
Example #17
0
    def run(self, agent):
        agent.shooting = True
        agent.shot_weight = agent.max_shot_weight - 1
        if self.ball_location is None or not shot_valid(agent, self, threshold=75):
            self.ball_location, self.intercept_time, self.direction = self.get_intercept(agent)

            if self.ball_location is None:
                agent.shooting = False
                agent.shot_weight = -1
                agent.pop()
                return

        agent.shot_time = self.intercept_time
        t = self.intercept_time - agent.time

        # if we ran out of time, just pop
        # this can be because we were successful or not - we can't tell
        if t < -0.3:
            agent.shooting = False
            agent.shot_weight = -1
            agent.pop()
            return

        if self.brake:
            if agent.ball.location.dist(agent.me.location) < 250 and agent.ball.location.y * side(agent.team) + 10 < agent.me.location.y and agent.ball.location.z < 190:
                agent.pop()
                agent.flip(agent.me.local(agent.ball.location))
        else:
            # current velocity
            u = agent.me.local(agent.me.velocity).x
            a = brake_accel.x
            # calculate how much distance we need to slow down
            x = (u ** 2 * -1) / (2 * a)

            if self.ball_location.dist(agent.me.location) <= x:
                self.brake = True
                agent.push(brake())
                return

            agent.line(self.ball_location.flatten(), self.ball_location.flatten() + Vector(z=250), color=[255, 0, 255])
            angles = defaultPD(agent, agent.me.local(self.ball_location - agent.me.location), self.direction)
            # We want to get there before the ball does, so take the time we have and get 3 fifths of it
            required_speed = cap(agent.me.location.dist(self.ball_location) / ((self.intercept_time - agent.time) * (3/5)), 600, 2275)
            defaultThrottle(agent, required_speed, self.direction)

            agent.controller.boost = False if abs(angles[1]) > 0.3 else agent.controller.boost
            agent.controller.handbrake = True if abs(angles[1]) >= 2.3 or (agent.me.local(agent.me.velocity).x >= 1400 and abs(angles[1]) > 1.5) and self.direction == 1 else False
Example #18
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
Example #19
0
def get_slices(agent, cap_, weight=0, start_slice=6):
    # Get the struct
    struct = agent.ball_prediction_struct
    min_time_to_ball = max(agent.me.minimum_time_to_ball / 3 * 2, 0)

    # Make sure it isn't empty
    if struct is None or min_time_to_ball > cap_:
        return

    if start_slice / 60 < min_time_to_ball:
        start_slice = round(min_time_to_ball * 60) - 1

    end_slices = None

    # If we're shooting, crop the struct
    if agent.shooting:
    	shot_weight = agent.stack[0].weight
    	if shot_weight != -1:
	        # Get the time remaining
	        time_remaining = agent.stack[0].intercept_time - agent.time
	        if 0 < time_remaining < 0.5:
	            return

	        # if the shot is done but it's working on it's 'follow through', then ignore this stuff
	        if time_remaining > 0:
	            # Convert the time remaining into number of slices, and take off the minimum gain accepted from the time
	            min_gain = 0.2 if weight is None or weight is shot_weight else (-1 * (agent.max_shot_weight - shot_weight + 1))
	            end_slice = round(min(time_remaining - min_gain, cap_) * 60)

    if end_slices is None:
        # Cap the slices
        end_slice = round(cap_ * 60)

    # We can't end a slice index that's lower than the start index
    if end_slice <= start_slice:
        return

    # for every second worth of slices that we have to search, skip 1 more slice (for performance reasons) - min 1 and max 3
    skip = cap(end_slice - start_slice / 60, 1, 3)
    return struct.slices[start_slice:end_slice:skip]
Example #20
0
    def run(self, agent):
        if self.ball:
            target = (agent.ball.location - agent.me.location).flatten()
        else:
            target = agent.me.velocity.flatten() if self.target is None else (
                self.target - agent.me.location).flatten()

        if agent.gravity.z < -550 and agent.gravity.z > -750:
            if self.counter == 0 and abs(Vector(x=1).angle(target)) <= 0.05:
                agent.pop()
                return

            if self.counter < 3:
                self.counter += 1

            target = agent.me.local(target)
            if self.counter < 3:
                agent.controller.jump = True
            elif agent.me.airborne and abs(Vector(x=1).angle(target)) > 0.05:
                defaultPD(agent, target)
            else:
                agent.pop()
        else:
            target = agent.me.local(target)
            angle_to_target = abs(Vector(x=1).angle2D(target))
            if angle_to_target > 0.1:
                if self.start_loc is None:
                    self.start_loc = agent.me.location

                direction = -1 if angle_to_target < 1.57 else 1

                agent.controller.steer = cap(target.y / 100, -1, 1) * direction
                agent.controller.throttle = 0.5 * direction
                agent.controller.handbrake = True
            else:
                agent.pop()
                if self.start_loc is not None:
                    agent.push(goto(self.start_loc, target, True))
Example #21
0
    def run(self, agent):
        agent.shooting = True
        raw_time_remaining = self.intercept_time - agent.time
        # Capping raw_time_remaining above 0 to prevent division problems
        time_remaining = cap(raw_time_remaining, 0.001, 10.0)
        car_to_ball = self.ball_location - agent.me.location
        # whether we are to the left or right of the shot vector
        side_of_shot = sign(
            self.shot_vector.cross(Vector(z=1)).dot(car_to_ball))

        car_to_dodge_point = self.dodge_point - agent.me.location
        car_to_dodge_perp = car_to_dodge_point.cross(
            Vector(z=side_of_shot))  # perpendicular
        distance_remaining = car_to_dodge_point.magnitude()

        speed_required = distance_remaining / time_remaining
        acceleration_required = backsolve(
            self.dodge_point, agent.me, time_remaining,
            0 if not self.jumping else agent.gravity.z)
        local_acceleration_required = agent.me.local(acceleration_required)

        # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector
        # The adjustment slowly decreases to 0 as the bot nears the time to jump
        adjustment = car_to_dodge_point.angle(
            self.shot_vector) * distance_remaining / 2.0  # size of adjustment
        # factoring in how close to jump we are
        adjustment *= (cap(self.jump_threshold -
                           (acceleration_required.z), 0, self.jump_threshold) /
                       self.jump_threshold)
        # we don't adjust the final target if we are already jumping
        final_target = self.dodge_point + (
            (car_to_dodge_perp.normalize() *
             adjustment) if not self.jumping else 0) + Vector(z=50)
        # Ensuring our target isn't too close to the sides of the field, where our car would get messed up by the radius of the curves

        # Some adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it
        if abs(agent.me.location.y) > 5150:
            final_target.x = cap(final_target.x, -750, 750)

        local_final_target = agent.me.local(final_target - agent.me.location)

        # drawing debug lines to show the dodge point and final target (which differs due to the adjustment)
        agent.line(agent.me.location, self.dodge_point, agent.renderer.white())
        agent.line(self.dodge_point - Vector(z=100),
                   self.dodge_point + Vector(z=100), agent.renderer.red())
        agent.line(final_target - Vector(z=100), final_target + Vector(z=100),
                   agent.renderer.green())

        # Calling our drive utils to get us going towards the final target
        angles = defaultPD(agent, local_final_target, self.direction)
        defaultThrottle(agent, speed_required, self.direction)

        agent.line(agent.me.location,
                   agent.me.location + (self.shot_vector * 200),
                   agent.renderer.white())

        agent.controller.boost = False if abs(
            angles[1]) > 0.3 or agent.me.airborne else agent.controller.boost
        agent.controller.handbrake = True if abs(
            angles[1]
        ) > 2.3 and self.direction == 1 else agent.controller.handbrake

        if not self.jumping:
            if raw_time_remaining <= 0 or (
                    speed_required -
                    2300) * time_remaining > 45 or not shot_valid(agent, self):
                # If we're out of time or not fast enough to be within 45 units of target at the intercept time, we pop
                agent.pop()
                agent.shooting = False
                agent.shot_weight = -1
                agent.shot_time = -1
                if agent.me.airborne:
                    agent.push(recovery())
            elif local_acceleration_required.z > self.jump_threshold and local_acceleration_required.z > local_acceleration_required.flatten(
            ).magnitude():
                # Switch into the jump when the upward acceleration required reaches our threshold, and our lateral acceleration is negligible
                self.jumping = True
        else:
            if (raw_time_remaining > 0.2 and not shot_valid(agent, self, 150)
                ) or raw_time_remaining <= -0.9 or (not agent.me.airborne
                                                    and self.counter > 0):
                agent.pop()
                agent.shooting = False
                agent.shot_weight = -1
                agent.shot_time = -1
                agent.push(recovery())
            elif self.counter == 0 and local_acceleration_required.z > 0 and raw_time_remaining > 0.083:
                # Initial jump to get airborne + we hold the jump button for extra power as required
                agent.controller.jump = True
            elif self.counter < 3:
                # make sure we aren't jumping for at least 3 frames
                agent.controller.jump = False
                self.counter += 1
            elif raw_time_remaining <= 0.1 and raw_time_remaining > -0.9:
                # dodge in the direction of the shot_vector
                agent.controller.jump = True
                if not self.dodging:
                    vector = agent.me.local(self.shot_vector)
                    self.p = abs(vector.x) * -sign(vector.x)
                    self.y = abs(vector.y) * sign(vector.y) * self.direction
                    self.dodging = True
                # simulating a deadzone so that the dodge is more natural
                agent.controller.pitch = self.p if abs(self.p) > 0.2 else 0
                agent.controller.yaw = self.y if abs(self.y) > 0.3 else 0
Example #22
0
    def run(self, agent):
        agent.shooting = True
        raw_time_remaining = self.intercept_time - agent.time
        # Capping raw_time_remaining above 0 to prevent division problems
        time_remaining = cap(raw_time_remaining, 0.001, 10.0)

        car_to_ball = self.ball_location - agent.me.location
        # whether we are to the left or right of the shot vector
        side_of_shot = sign(
            self.shot_vector.cross(Vector(z=1)).dot(car_to_ball))

        car_to_intercept = self.intercept - agent.me.location
        car_to_intercept_perp = car_to_intercept.cross(
            Vector(z=side_of_shot))  # perpendicular
        distance_remaining = car_to_intercept.flatten().magnitude()

        speed_required = distance_remaining / time_remaining
        # When still on the ground we pretend agent.gravity doesn't exist, for better or worse
        acceleration_required = backsolve(
            self.intercept, agent.me, time_remaining,
            0 if self.jump_time == 0 else agent.gravity.z)
        local_acceleration_required = agent.me.local(acceleration_required)

        # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector
        # The adjustment slowly decreases to 0 as the bot nears the time to jump
        adjustment = car_to_intercept.angle(
            self.shot_vector) * distance_remaining / 1.57  # size of adjustment
        # factoring in how close to jump we are
        adjustment *= cap(self.jump_threshold - (acceleration_required.z), 0,
                          self.jump_threshold) / self.jump_threshold
        # we don't adjust the final target if we are already jumping
        final_target = self.intercept + (
            (car_to_intercept_perp.normalize() *
             adjustment) if self.jump_time == 0 else 0)

        # Some extra adjustment to the final target to ensure it's inside the field and we don't try to dirve through any goalposts to reach it
        if abs(agent.me.location.y) > 5150:
            final_target.x = cap(final_target.x, -750, 750)

        local_final_target = agent.me.local(final_target - agent.me.location)

        # drawing debug lines to show the dodge point and final target (which differs due to the adjustment)
        agent.line(agent.me.location, self.intercept, agent.renderer.white())
        agent.line(self.intercept - Vector(z=100),
                   self.intercept + Vector(z=100), agent.renderer.red())
        agent.line(final_target - Vector(z=100), final_target + Vector(z=100),
                   agent.renderer.green())

        angles = defaultPD(agent, local_final_target)

        if self.jump_time == 0:
            defaultThrottle(agent, speed_required)
            agent.controller.boost = False if abs(
                angles[1]
            ) > 0.3 or agent.me.airborne else agent.controller.boost
            agent.controller.handbrake = True if abs(
                angles[1]) > 2.3 else agent.controller.handbrake
            if acceleration_required.z > self.jump_threshold:
                # Switch into the jump when the upward acceleration required reaches our threshold, hopefully we have aligned already...
                self.jump_time = agent.time
        else:
            time_since_jump = agent.time - self.jump_time

            # While airborne we boost if we're within 30 degrees of our local acceleration requirement
            if agent.me.airborne and local_acceleration_required.magnitude(
            ) * time_remaining > 100:
                angles = defaultPD(agent, local_acceleration_required)
                if abs(angles[0]) + abs(angles[1]) < 0.5:
                    agent.controller.boost = True
            if self.counter == 0 and (time_since_jump <= 0.2
                                      and local_acceleration_required.z > 0):
                # hold the jump button up to 0.2 seconds to get the most acceleration from the first jump
                agent.controller.jump = True
            elif time_since_jump > 0.2 and self.counter < 3:
                # Release the jump button for 3 ticks
                agent.controller.jump = False
                self.counter += 1
            elif local_acceleration_required.z > 300 and self.counter == 3:
                # the acceleration from the second jump is instant, so we only do it for 1 frame
                agent.controller.jump = True
                agent.controller.pitch = 0
                agent.controller.yaw = 0
                agent.controller.roll = 0
                self.counter += 1

        if raw_time_remaining < -0.25 or not shot_valid(agent, self):
            agent.pop()
            agent.shooting = False
            agent.shot_weight = -1
            agent.shot_time = -1
            agent.push(recovery())
Example #23
0
    def run(self, agent, manual=False):
        car_to_target = self.target - agent.me.location
        distance_remaining = car_to_target.flatten().magnitude()
        angle_to_target = abs(
            Vector(x=1).angle2D(agent.me.local(car_to_target)))
        direction = 1 if angle_to_target <= 2 or (
            agent.gravity.z > -450 and distance_remaining >= 1000) else -1

        agent.dbg_2d(f"Angle to target: {angle_to_target}")
        agent.dbg_2d(f"Distance to target: {distance_remaining}")
        agent.line(self.target - Vector(z=500), self.target + Vector(z=500),
                   (255, 0, 255))

        if (not self.brake and distance_remaining < 350) or (
                self.brake and distance_remaining * 0.95 <
            (agent.me.local_velocity().x**2 * -1) / (2 * brake_accel.x)):
            if not manual:
                agent.pop()

            if self.brake:
                agent.push(brake())
            return

        final_target = self.target.copy()

        # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it
        if abs(agent.me.location.y) > 5120 - (agent.me.hitbox.length / 2):
            final_target.x = cap(final_target.x, -750, 750)

        if self.vector is not None:
            # See comments for adjustment in jump_shot for explanation
            side_of_vector = sign(
                self.vector.cross(Vector(z=1)).dot(car_to_target))
            car_to_target_perp = car_to_target.cross(
                Vector(z=side_of_vector)).normalize()
            adjustment = car_to_target.angle2D(
                self.vector) * distance_remaining / 3.14
            final_target += car_to_target_perp * adjustment

        local_target = agent.me.local_location(final_target)

        defaultPD(agent, local_target)
        target_speed = 2300 if distance_remaining > 640 else 1400
        defaultThrottle(agent, target_speed * direction)

        # this is to break rule 1's with TM8'S ONLY
        # 251 is the distance between center of the 2 longest cars in the game, with a bit extra
        if len(agent.friends) > 0 and agent.me.local_velocity(
        ).x < 50 and agent.controller.throttle == 1 and min(
                agent.me.location.flat_dist(car.location)
                for car in agent.friends) < 251:
            if self.rule1_timer == -1:
                self.rule1_timer = agent.time
            elif agent.time - self.rule1_timer > 1.5:
                agent.push(flip(Vector(y=250)))
                return
        elif self.rule1_timer != -1:
            self.rule1_timer = -1

        if distance_remaining < 320:
            agent.controller.boost = False
        agent.controller.handbrake = angle_to_target > 1.54 if direction == 1 else angle_to_target < 2.2

        velocity = agent.me.local_velocity().x
        if agent.boost_amount != 'unlimited' and angle_to_target < 0.03 and distance_remaining > 1920 and velocity > 600 and velocity < 2150 and distance_remaining / velocity > 2:
            if agent.gravity.z < -450:
                agent.push(wave_dash())
            else:
                agent.push(flip(local_target))
        elif direction == -1 and distance_remaining > 1000 and velocity < 200:
            agent.push(flip(local_target, True))
        elif agent.me.airborne:
            agent.push(recovery(self.target))
Example #24
0
def find_hits(agent, targets, cap_=6):
    # find_hits takes a dict of (left,right) target pairs and finds routines that could hit the ball between those target pairs
    # find_hits is only meant for routines that require a defined intercept time/place in the future
    # find_hits should not be called more than once in a given tick, as it has the potential to use an entire tick to calculate
    hits = {name: [] for name in targets}
    struct = agent.predictions['ball_struct']

    if struct is None:
        return hits

    max_aerial_height = 400
    max_jump_hit_height = 200
    min_aerial_height = 150

    if (len(agent.foes) > 1
            and len(agent.friends) == 0) or len(agent.friends) > 2:
        max_jump_hit_height = 300
        max_aerial_height = 500

    # Begin looking at slices 0.2s into the future
    i = 10
    while i < struct.num_slices:
        # Gather some data about the slice
        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  # abandon search if ball is scored at/after this point

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

            # determine the next slice we will look at, based on ball velocity (slower ball needs fewer slices)
            i += 15 - cap(int(ball_velocity // 150), 0, 13)

            # If the ball is above what this function can handle, don't bother with any further processing and skip to the next slice
            if ball_location.z > max_aerial_height:
                continue

            car_to_ball = ball_location - agent.me.location
            # Adding a True to a vector's normalize will have it also return the magnitude of the vector
            direction, distance = car_to_ball.normalize(True)

            # How far the car must turn in order to face the ball, for forward and reverse
            forward_angle = direction.angle(agent.me.forward)
            backward_angle = math.pi - forward_angle

            # Accounting for the average time it takes to turn and face the ball
            # Backward is slightly longer as typically the car is moving forward and takes time to slow down
            forward_time = time_remaining - (forward_angle * 0.318)
            backward_time = time_remaining - (backward_angle * 0.418)

            # If the car only had to drive in a straight line, we ensure it has enough time to reach the ball (a few assumptions are made)
            forward_flag = forward_time > 0 and (
                distance * 1.05 / forward_time) < (
                    2290 if agent.me.boost > distance / 100 else 1400)
            backward_flag = distance < 1500 and backward_time > 0 and (
                distance * 1.05 / backward_time) < 1200

            # Provided everything checks out, we begin to look at the target pairs
            if forward_flag or backward_flag:
                for pair in targets:
                    # First we correct the target coordinates to account for the ball's radius
                    # If swapped is True, the shot isn't possible because the ball wouldn't fit between the targets
                    left, right, swapped = post_correction(
                        ball_location, targets[pair][0], targets[pair][1])
                    if not swapped:
                        # Now we find the easiest direction to hit the ball in order to land it between the target points
                        left_vector = (left - ball_location).normalize()
                        right_vector = (right - ball_location).normalize()
                        best_shot_vector = direction.clamp(
                            left_vector, right_vector)

                        # Check to make sure our approach is inside the field
                        # Check if our shot is fast enough. This is equal to 500uu's per 1/2 second, for a max time of `cap` (defaut 6) seconds.
                        if in_field(ball_location - (200 * best_shot_vector),
                                    1) and is_fast_shot(
                                        agent.me.location, ball_location,
                                        intercept_time, agent.time, cap_):
                            # The slope represents how close the car is to the chosen vector, higher = better
                            # A slope of 1.0 would mean the car is 45 degrees off
                            slope = find_slope(best_shot_vector, car_to_ball)
                            if forward_flag:
                                if ball_location.z > min_aerial_height and ball_location.z <= max_aerial_height and slope > 1.0 and (
                                        ball_location.z -
                                        250) * 0.14 > agent.me.boost:
                                    hits[pair].append(
                                        aerial_shot(ball_location,
                                                    intercept_time,
                                                    best_shot_vector, slope))
                                    return hits
                                if ball_location.z <= max_jump_hit_height and slope > 0:
                                    hits[pair].append(
                                        jump_shot(ball_location,
                                                  intercept_time,
                                                  best_shot_vector, slope))
                                    return hits
                            elif backward_flag and ball_location.z <= 280 and slope > 0.25:
                                hits[pair].append(
                                    jump_shot(ball_location, intercept_time,
                                              best_shot_vector, slope, -1))
                                return hits
        else:
            return hits
    return hits
Example #25
0
    def update_predictions(self):
        len_friends = len(self.friends)
        can_shoot = True

        if len(self.foes) > 0:
            foe_distances = tuple(
                self.ball.location.flat_dist(foe.location) for foe in self.foes
                if not foe.demolished)
            self_dist = self.ball.location.flat_dist(self.me.location)
            if len(foe_distances) > 0:
                if self.odd_tick == 0:
                    self.predictions['enemy_time_to_ball'] = min(
                        tuple(self.time_to_ball(foe) for foe in self.foes))

                self.predictions['closest_enemy'] = min(foe_distances)
            else:
                self.predictions['enemy_time_to_ball'] = 7
                self.predictions['closest_enemy'] = math.inf
        else:
            self.predictions['enemy_time_to_ball'] = 7
            self.predictions['closest_enemy'] = math.inf

        self.future_ball_location_slice = cap(
            round(self.predictions['enemy_time_to_ball'] * 60), 0,
            len(self.ball_prediction_struct.slices) - 1)
        self.dbg_2d(
            f"Predicted enemy time to ball: {round(self.predictions['enemy_time_to_ball'], 1)}"
        )

        self.predictions[
            'self_from_goal'] = self.friend_goal.location.flat_dist(
                self.me.location)
        self.predictions['self_to_ball'] = self.ball.location.flat_dist(
            self.me.location)

        if not self.predictions['was_down']:
            self.predictions[
                'was_down'] = self.game.friend_score - self.game.foe_score > 1

        if len_friends > 0:
            teammates = tuple(itertools.chain(self.friends, [self.me]))

            self.predictions["team_from_goal"] = sorted(
                tuple(
                    self.friend_goal.location.flat_dist(teammate.location)
                    if not teammate.demolished else math.inf
                    for teammate in teammates))
            self.predictions["team_to_ball"] = sorted(
                tuple(
                    self.ball.location.flat_dist(teammate.location)
                    if not teammate.demolished else math.inf
                    for teammate in teammates))
            if len_friends >= 2 and can_shoot:
                can_shoot = self.predictions[
                    'self_from_goal'] != self.predictions["team_from_goal"][0]

        if self.odd_tick == 0:
            self.predictions['self_min_time_to_ball'] = self.time_to_ball(
                self.me)
        self.min_intercept_slice = cap(
            round(self.predictions['self_min_time_to_ball'] * 60), 0,
            len(self.ball_prediction_struct.slices) - 1)

        if self.odd_tick % 2 == 0:
            if self.goalie:
                self.playstyle = self.playstyles.Defensive
            # elif len_friends > 0:
            #     ball_loc_y = self.ball.location.y * side(self.team)

            #     if ball_loc_y < 2560:
            #         # If we're down or up by 2 goals in 2's, then start playing more defensive
            #         self_time_to_ball = self.predictions['self_min_time_to_ball'] * 1.05
            #         team_time_to_ball = min(tuple(self.time_to_ball(teammate) for teammate in self.friends)) * 1.05
            #         if ball_loc_y < -1280 and self_time_to_ball < team_time_to_ball and self.predictions['self_from_goal'] != self.predictions["team_from_goal"][0]:
            #             self.playstyle = self.playstyles.Offensive if len_friends > 1 or (len_friends == 1 and (self.predictions['was_down'] or abs(self.game.friend_score - self.game.foe_score) <= 1)) else self.playstyles.Neutral
            #         elif self.predictions['self_from_goal'] == self.predictions["team_from_goal"][0]:
            #             self.playstyle = self.playstyles.Defensive if len_friends > 1 else self.playstyles.Neutral
            #         else:
            #             self.playstyle = self.playstyles.Neutral
            #     else:
            #         self.playstyle = self.playstyles.Defensive
            else:
                self_time_to_ball = self.predictions[
                    'self_min_time_to_ball'] * 1.05

                if self.ball.location.y * side(self.team) < 640:
                    self.playstyle = self.playstyles.Offensive if self_time_to_ball < self.predictions[
                        'enemy_time_to_ball'] else self.playstyles.Neutral
                else:
                    self.playstyle = self.playstyles.Neutral if self_time_to_ball < self.predictions[
                        'enemy_time_to_ball'] else self.playstyles.Defensive

            is_own_goal = False
            is_goal = False

            if self.ball_prediction_struct is not None:
                for ball_slice in self.ball_prediction_struct.slices[30::12]:
                    location = ball_slice.physics.location.y * side(self.team)

                    if location >= 5212.75:
                        is_own_goal = True
                        break

                    if location <= -5212.75:
                        is_goal = True
                        break

            if is_own_goal and not self.predictions['own_goal']:
                self.send_quick_chat(QuickChats.CHAT_EVERYONE,
                                     QuickChats.Compliments_NiceShot)

            if is_goal and not self.predictions['goal']:
                self.send_quick_chat(QuickChats.CHAT_EVERYONE,
                                     QuickChats.Reactions_Wow)

            self.predictions["own_goal"] = is_own_goal
            self.predictions["goal"] = is_goal

        self.dbg_2d(
            f"Minimum time to ball: {round(self.predictions['self_min_time_to_ball'], 1)}"
        )

        if not can_shoot and self.can_shoot is None:
            self.can_shoot = self.time - 2.9

        if self.can_shoot is not None and (self.time - self.can_shoot >= 3
                                           or self.predictions['own_goal']):
            self.can_shoot = None
Example #26
0
    def run(self, agent):
        # This routine is the same as jump_shot, but it's designed to hit the ball above 250uus (and below 551uus or so) without any boost
        if not agent.shooting:
            agent.shooting = True

        T = self.intercept_time - agent.time
        # Capping T above 0 to prevent division problems
        time_remaining = cap(T, 0.000001, 6)

        slice_n = round(T * 60)
        agent.dbg_2d(f"Shot slice #: {slice_n}")

        if T > 0.3 or self.ball_location is None:
            ball = agent.ball_prediction_struct.slices[
                slice_n].physics.location

            self.ball_location = Vector(ball.x, ball.y, ball.z)
            self.dodge_point = self.ball_location - (self.shot_vector *
                                                     agent.best_shot_value)

            if self.dodge_point.z > 490 or self.dodge_point.z < 380:
                agent.pop()
                return

        car_to_ball = self.ball_location - agent.me.location
        # whether we should go forwards or backwards
        angle_to_target = abs(
            Vector(x=1).angle2D(agent.me.local_location(self.dodge_point)))
        # whether we are to the left or right of the shot vector
        side_of_shot = sign(
            self.shot_vector.cross(Vector(z=1)).dot(car_to_ball))

        final_target = self.dodge_point.copy()

        # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it
        if abs(agent.me.location.y) > 5120 - (agent.me.hitbox.length / 2):
            final_target.x = cap(final_target.x, -750, 750)

        car_to_dodge_point = final_target - agent.me.location
        car_to_dodge_perp = car_to_dodge_point.cross(
            Vector(z=side_of_shot))  # perpendicular
        distance_remaining = car_to_dodge_point.flatten().magnitude()

        acceleration_required = backsolve(
            self.dodge_point, agent.me, time_remaining,
            Vector() if not self.jumping else agent.gravity)
        local_acceleration_required = agent.me.local_velocity(
            acceleration_required)
        # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector
        # The adjustment slowly decreases to 0 as the bot nears the time to jump
        adjustment = car_to_dodge_point.angle2D(
            self.shot_vector) * distance_remaining / 2  # size of adjustment
        # controls how soon car will jump based on acceleration required
        # we set this based on the time remaining
        # bigger = later, which allows more time to align with shot vector
        # smaller = sooner
        jump_threshold = cap(T * 200, 250, 584)
        # factoring in how close to jump we are
        adjustment *= (cap(jump_threshold -
                           (acceleration_required.z), 0, jump_threshold) /
                       jump_threshold)
        # we don't adjust the final target if we are already jumping
        final_target += ((car_to_dodge_perp.normalize() * adjustment)
                         if not self.jumping else 0) + Vector(z=50)

        distance_remaining = (final_target -
                              agent.me.location).flatten().magnitude()
        local_final_target = agent.me.local_location(final_target)

        # drawing debug lines to show the dodge point and final target (which differs due to the adjustment)
        agent.line(agent.me.location, self.dodge_point, agent.renderer.white())
        agent.line(self.dodge_point - Vector(z=100),
                   self.dodge_point + Vector(z=100), agent.renderer.green())

        vf = agent.me.velocity + agent.gravity * T

        distance = agent.me.local_location(
            self.dodge_point).x if agent.me.airborne else distance_remaining
        speed_required = 2300 if distance_remaining > 2560 else distance / time_remaining
        agent.dbg_2d(f"Speed required: {speed_required}")

        if not self.jumping:
            velocity = agent.me.local_velocity().x

            local_dodge_point = agent.me.local_location(
                self.dodge_point.flatten())
            local_vf = agent.me.local(vf.flatten())

            if T <= 0 or not virxrlcu.double_jump_shot_is_viable(
                    T + 0.3, agent.boost_accel,
                    agent.me.location.dist(
                        self.ball_location), self.shot_vector.tuple(),
                    agent.me.forward.tuple(), agent.me.boost if
                    agent.boost_amount != 'unlimited' else 100000, velocity):
                # If we're out of time or the ball was hit away or we just can't get enough speed, pop
                agent.pop()
                agent.shooting = False
                agent.shot_weight = -1
                agent.shot_time = -1
                if agent.me.airborne:
                    agent.push(ball_recovery())
            elif abs(local_dodge_point.y
                     ) < 92 and local_vf.x >= local_dodge_point.x:
                # Switch into the jump when the upward acceleration required reaches our threshold, and our lateral acceleration is negligible, and we're close enough to the point in time where the ball will be at the given location
                self.jumping = True
            elif agent.boost_amount != 'unlimited' and angle_to_target < 0.03 and velocity > 600 and velocity < speed_required - 500 and distance_remaining / velocity > 3:
                if agent.gravity.z < -450:
                    agent.push(wave_dash())
                else:
                    agent.push(flip(local_final_target))
            elif agent.boost_amount != 'unlimited' and angle_to_target >= 2 and distance_remaining > 1000 and velocity < 200:
                agent.push(flip(local_final_target, True))
            elif agent.me.airborne:
                agent.push(recovery(local_final_target))
            else:
                defaultPD(agent, local_final_target)
                defaultThrottle(agent, speed_required)
                agent.controller.handbrake = angle_to_target > 1.54
        else:
            # Mark the time we started jumping so we know when to dodge
            if self.jump_time == -1:
                self.jump_time = agent.time

            jump_elapsed = agent.time - self.jump_time

            tau = jump_max_duration - jump_elapsed
            xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T * T

            if jump_elapsed == 0:
                vf += agent.me.up * jump_speed
                xf += agent.me.up * jump_speed * T

            vf += agent.me.up * jump_acc * tau
            xf += agent.me.up * jump_acc * tau * (T - 0.5 * tau)

            vf += agent.me.up * jump_speed
            xf += agent.me.up * jump_speed * (T - tau)

            delta_x = self.dodge_point - xf
            direction = delta_x.normalize()

            if abs(agent.me.forward.dot(direction)) > 0.5:
                delta_v = delta_x.dot(agent.me.forward) / T
                if agent.me.boost > 0 and delta_v >= agent.boost_accel * min_boost_time:
                    agent.controller.boost = True
                else:
                    agent.controller.throttle = cap(
                        delta_v / (throttle_accel * min_boost_time), -1, 1)

            if T <= -0.4 or (not agent.me.airborne and self.counter > 0):
                agent.pop()
                agent.shooting = False
                agent.shot_weight = -1
                agent.shot_time = -1
                agent.push(ball_recovery())
            elif jump_elapsed < jump_max_duration and vf.z <= self.dodge_point.z:
                agent.controller.jump = True
            elif self.counter < 4:
                self.counter += 1

            if self.counter == 3:
                agent.controller.jump = True
            elif self.counter == 4:
                defaultPD(agent,
                          agent.me.local_location(self.dodge_point),
                          upside_down=True)

            if self.counter < 3:
                defaultPD(
                    agent,
                    agent.me.local(
                        (self.dodge_point - agent.me.location).flatten()))

        l_vf = vf + agent.me.location
        agent.line(l_vf - Vector(z=100), l_vf + Vector(z=100),
                   agent.renderer.red())
Example #27
0
    def run(self, agent):
        agent.shooting = True

        if self.time is -1:
            elapsed = 0
            self.time = agent.time
            agent.print(
                f"Enter aerial - Hit ball {round(agent.me.location.dist(self.target) * 1000) / 1000}uu's away in {round((self.intercept_time - self.time) * 1000) / 1000}s"
            )
        else:
            elapsed = agent.time - self.time

        T = self.intercept_time - agent.time
        xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T**2
        vf = agent.me.velocity + agent.gravity * T
        if self.jumping:
            if self.jump_time == -1:
                jump_elapsed = 0
                self.jump_time = agent.time
            else:
                jump_elapsed = agent.time - self.jump_time

            tau = jump_max_duration - jump_elapsed

            if jump_elapsed == 0:
                vf += agent.me.up * jump_speed
                xf += agent.me.up * jump_speed * T

            vf += agent.me.up * jump_acc * tau
            xf += agent.me.up * jump_acc * tau * (T - 0.5 * tau)

            vf += agent.me.up * jump_speed
            xf += agent.me.up * jump_speed * (T - tau)

            if jump_elapsed < jump_max_duration:
                agent.controller.jump = True
            elif elapsed >= jump_max_duration and self.counter < 3:
                agent.controller.jump = False
                self.counter += 1
            elif elapsed < 0.3:
                agent.controller.jump = True
            else:
                self.jumping = jump_elapsed <= 0.3  # jump_max_duration
        else:
            agent.controller.jump = False

        delta_x = self.target - xf
        direction = delta_x.normalize()

        agent.line(agent.me.location, self.target, agent.renderer.white())
        agent.line(self.target - Vector(z=100), self.target + Vector(z=100),
                   agent.renderer.red())
        agent.line(agent.me.location, direction, agent.renderer.green())

        if delta_x.norm() > 50:
            defaultPD(agent, agent.me.local(delta_x))
        else:
            defaultPD(agent, agent.me.local(self.target))

        if jump_max_duration <= elapsed and elapsed < 0.3 and self.counter**3:
            agent.controller.roll = agent.controller.pitch = agent.controller.yaw = agent.controller.steer = 0

        if agent.me.forward.angle3D(direction) < 0.3:
            if delta_x.norm() > 50:
                agent.controller.boost = 1
                agent.controller.throttle = 0
            else:
                agent.controller.boost = 0
                agent.controller.throttle = cap(0.5 * throttle_accel * T * T,
                                                0, 1)
        else:
            agent.controller.boost = agent.controller.throttle = 0

        still_valid = shot_valid(agent,
                                 self,
                                 threshold=250,
                                 target=self.target)

        if T <= 0 or not still_valid:
            if not still_valid:
                agent.print("Aerial is no longer valid")

            agent.pop()
            agent.shooting = False
            agent.shot_weight = -1
            agent.shot_time = -1
            agent.push(recovery(agent.friend_goal.location))
Example #28
0
    def run(self, agent):
        if not agent.shooting:
            agent.shooting = True

        T = self.intercept_time - agent.time
        # Capping T above 0 to prevent division problems
        time_remaining = cap(T, 0.000001, 6)

        slice_n = round(T * 60)
        agent.dbg_2d(f"Shot slice #: {slice_n}")

        if T > 0.3 or self.ball_location is None:
            ball = agent.ball_prediction_struct.slices[
                slice_n].physics.location

            self.ball_location = Vector(ball.x, ball.y, ball.z)
            self.dodge_point = self.ball_location - (self.shot_vector *
                                                     agent.best_shot_value)

            if self.dodge_point.z > 300:
                agent.pop()
                return

        car_to_ball = self.ball_location - agent.me.location
        # whether we should go forwards or backwards
        angle_to_target = abs(Vector(x=1).angle2D(agent.me.local(car_to_ball)))
        # whether we are to the left or right of the shot vector
        side_of_shot = sign(
            self.shot_vector.cross(Vector(z=1)).dot(car_to_ball))

        final_target = self.dodge_point.copy()

        # Some adjustment to the final target to ensure it's inside the field and we don't try to drive through any goalposts to reach it
        if abs(agent.me.location.y) > 5120 - (agent.me.hitbox.length / 2):
            final_target.x = cap(final_target.x, -750, 750)

        car_to_dodge_point = final_target - agent.me.location
        car_to_dodge_perp = car_to_dodge_point.cross(
            Vector(z=side_of_shot))  # perpendicular

        acceleration_required = backsolve(
            self.dodge_point, agent.me, time_remaining,
            Vector() if not self.jumping else agent.gravity)
        local_acceleration_required = agent.me.local(acceleration_required)
        distance_remaining = car_to_dodge_point.flatten().magnitude()
        # The adjustment causes the car to circle around the dodge point in an effort to line up with the shot vector
        # The adjustment slowly decreases to 0 as the bot nears the time to jump
        adjustment = car_to_dodge_point.angle2D(
            self.shot_vector) * distance_remaining / 2  # size of adjustment
        # controls how soon car will jump based on acceleration required
        # we set this based on the time remaining
        # bigger = later, which allows more time to align with shot vector
        # smaller = sooner
        jump_threshold = cap(T * 200, 250, 584)
        # factoring in how close to jump we are
        adjustment *= (cap(jump_threshold -
                           (acceleration_required.z), 0, jump_threshold) /
                       jump_threshold)
        # we don't adjust the final target if we are already jumping
        final_target += ((car_to_dodge_perp.normalize() * adjustment)
                         if not self.jumping else 0) + Vector(z=50)

        distance_remaining = (final_target -
                              agent.me.location).flatten().magnitude()
        direction = 1 if angle_to_target < 2.1 or (
            agent.gravity.z > -450 and distance_remaining >= 1000) else -1
        local_final_target = agent.me.local_location(final_target)

        # drawing debug lines to show the dodge point and final target (which differs due to the adjustment)
        agent.line(agent.me.location, self.dodge_point, agent.renderer.white())
        agent.line(self.dodge_point - Vector(z=100),
                   self.dodge_point + Vector(z=100), agent.renderer.green())
        agent.line(final_target - Vector(z=100), final_target + Vector(z=100),
                   agent.renderer.blue())

        vf = agent.me.velocity + agent.gravity * T
        xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T * T

        ball_l = agent.me.local_location(agent.ball.location)
        speed_required = 2300 if (
            self.ball_location.z < 92 + agent.me.hitbox.height / 2
            and abs(ball_l.y) < 46 and ball_l.x > agent.me.hitbox.length
        ) or distance_remaining > 2560 else distance_remaining * 0.975 / time_remaining
        agent.dbg_2d(f"Speed required: {speed_required}")

        if not self.jumping:
            defaultPD(agent, local_final_target)
            defaultThrottle(agent, speed_required * direction)

            agent.controller.handbrake = angle_to_target > 1.54 if direction == 1 else angle_to_target < 2.2

            local_dodge_point = agent.me.local_location(
                self.dodge_point.flatten())

            # use algebra to get the required jump time
            min_jump_time = self.dodge_point - agent.me.location
            min_jump_time -= agent.me.velocity * T
            min_jump_time -= 0.5 * agent.gravity * T * T
            min_jump_time -= agent.me.up * jump_speed * T
            min_jump_time /= jump_acc

            # This leaves us with xf = dT - 0.5d^2, so we use the quadratic formula to solve it
            min_jump_time = max(quadratic(-0.5, T, sum(min_jump_time) / 3))

            min_jump_time += 0.05

            f_vf = vf + (agent.me.up * (jump_speed + jump_acc * min_jump_time))
            local_vf = agent.me.local(f_vf.flatten())

            velocity = agent.me.local_velocity().x
            if T <= 0 or not virxrlcu.jump_shot_is_viable(
                    T + 0.3, agent.boost_accel,
                    agent.me.location.dist(
                        self.ball_location), self.shot_vector.tuple(),
                    agent.me.forward.tuple(), agent.me.boost if
                    agent.boost_amount != 'unlimited' else 100000, velocity):
                # If we're out of time or not fast enough to be within 45 units of target at the intercept time, we pop
                agent.pop()
                agent.shooting = False
                agent.shot_weight = -1
                agent.shot_time = -1
                if agent.me.airborne:
                    agent.push(recovery())
            elif self.dodge_point.z > 92 + agent.me.hitbox.height / 2 and (
                (T <= min_jump_time and self.dodge_point.z >= 175) or
                (T <= 0.3 and
                 self.dodge_point.z < 175)) and abs(local_dodge_point.y) < (
                     92 if find_slope(self.shot_vector, car_to_ball) > 2
                     or self.dodge_point.z <= 92 + agent.me.hitbox.height / 2
                     else math.ceil(92 + agent.me.hitbox.width /
                                    2)) and local_vf.x >= local_dodge_point.x:
                # Switch into the jump when the upward acceleration required reaches our threshold, and our lateral acceleration is negligible
                self.jumping = True
            elif agent.boost_amount != 'unlimited' and angle_to_target < 0.03 and velocity > 600 and velocity < speed_required - 150 and distance_remaining / velocity > 3:
                if agent.gravity.z < -450:
                    agent.push(wave_dash())
                else:
                    agent.push(flip(local_final_target))
            elif direction == -1 and velocity < 200 and distance_remaining / abs(
                    velocity) > 2:
                agent.push(flip(local_final_target, True))
            elif agent.me.airborne:
                agent.push(recovery(local_final_target))
        else:
            if self.jump_time == -1:
                self.jump_time = agent.time

            jump_elapsed = agent.time - self.jump_time

            tau = jump_max_duration - jump_elapsed

            if jump_elapsed == 0:
                vf += agent.me.up * jump_speed
                xf += agent.me.up * jump_speed * T

            vf += agent.me.up * jump_acc * tau
            xf += agent.me.up * jump_acc * tau * (T - 0.5 * tau)

            delta_x = self.dodge_point - xf
            d_direction = delta_x.normalize()

            if abs(agent.me.forward.dot(
                    d_direction)) > 0.5 and self.counter < 3:
                delta_v = delta_x.dot(agent.me.forward) / T
                if agent.me.boost > 0 and delta_v >= agent.boost_accel * min_boost_time:
                    agent.controller.boost = True
                else:
                    agent.controller.throttle = cap(
                        delta_v / (throttle_accel * min_boost_time), -1, 1)

            if T <= -0.4 or (not agent.me.airborne and self.counter >= 3):
                agent.pop()
                agent.shooting = False
                agent.shot_weight = -1
                agent.shot_time = -1
                agent.push(recovery())
                return
            else:
                if self.counter == 3 and agent.me.location.dist(
                        self.dodge_point) < (92.75 +
                                             agent.me.hitbox.length) * 1.05:
                    # Get the required pitch and yaw to flip correctly
                    vector = agent.me.local(self.shot_vector)
                    self.p = abs(vector.x) * -sign(vector.x)
                    self.y = abs(vector.y) * sign(vector.y) * direction

                    # simulating a deadzone so that the dodge is more natural
                    self.p = cap(self.p, -1, 1) if abs(self.p) > 0.1 else 0
                    self.y = cap(self.y, -1, 1) if abs(self.y) > 0.1 else 0

                    agent.controller.pitch = self.p
                    agent.controller.yaw = self.y
                    # Wait 1 more frame before dodging
                    self.counter += 1
                elif self.counter == 4:
                    # Dodge
                    agent.controller.jump = True
                    agent.controller.pitch = self.p
                    agent.controller.yaw = self.y
                else:
                    # Face the direction we're heading in, with the z of our target
                    target = agent.me.local(agent.me.velocity.flatten())
                    target.z = agent.me.local_location(self.dodge_point).z
                    defaultPD(agent, target)

                if jump_elapsed < jump_max_duration and vf.z < self.dodge_point.z:
                    # Initial jump to get airborne + we hold the jump button for extra power as required
                    agent.controller.jump = True
                elif self.counter < 3:
                    # Make sure we aren't jumping for at least 3 frames
                    self.counter += 1

        l_vf = vf + agent.me.location
        agent.line(l_vf - Vector(z=100), l_vf + Vector(z=100),
                   agent.renderer.red())
Example #29
0
    def run(self, agent):
        if not agent.shooting:
            agent.shooting = True

        if self.time == -1:
            self.time = agent.time

        elapsed = agent.time - self.time
        T = self.intercept_time - agent.time
        xf = agent.me.location + agent.me.velocity * T + 0.5 * agent.gravity * T * T
        vf = agent.me.velocity + agent.gravity * T

        slice_n = math.ceil(T * 60)
        agent.dbg_2d(f"Shot slice #: {slice_n}")

        if T > 0.1 or self.target is None:
            ball = agent.ball_prediction_struct.slices[
                slice_n].physics.location

            self.ball = Vector(ball.x, ball.y, ball.z)
            self.target = self.ball - (self.shot_vector *
                                       agent.best_shot_value * 0.8)

            if agent.me.location.z > 2044 - agent.me.hitbox.height * 1.1:
                self.ceiling = True
                self.target -= Vector(z=92)

        if not self.ceiling and (self.jumping or not agent.me.airborne):
            agent.dbg_2d("Jumping")

            if not self.jumping or not agent.me.airborne:
                self.jumping = True
                self.jump_time = agent.time
                self.counter = 0

            jump_elapsed = agent.time - self.jump_time

            tau = jump_max_duration - jump_elapsed

            if jump_elapsed == 0:
                vf += agent.me.up * jump_speed
                xf += agent.me.up * jump_speed * T

            vf += agent.me.up * jump_acc * tau
            xf += agent.me.up * jump_acc * tau * (T - 0.5 * tau)

            if self.fast_aerial:
                vf += agent.me.up * jump_speed
                xf += agent.me.up * jump_speed * (T - tau)

                if jump_elapsed < jump_max_duration:
                    agent.controller.jump = True
                elif self.counter < 6:
                    self.counter += 1

                if self.counter == 3:
                    agent.controller.jump = True
                    self.dodging = True
                elif self.counter == 6:
                    self.dodging = self.jumping = False
            elif jump_elapsed < jump_max_duration:
                agent.controller.jump = True
            else:
                self.jumping = False

        if self.ceiling:
            agent.dbg_2d(f"Ceiling shot")

        delta_x = self.target - xf
        direction = delta_x.normalize()

        agent.line(agent.me.location, self.target, agent.renderer.white())
        c_vf = vf + agent.me.location
        agent.line(c_vf - Vector(z=100), c_vf + Vector(z=100),
                   agent.renderer.blue())
        agent.line(xf - Vector(z=100), xf + Vector(z=100),
                   agent.renderer.red())
        agent.line(self.target - Vector(z=100), self.target + Vector(z=100),
                   agent.renderer.green())

        if not self.dodging:
            target = delta_x if delta_x.magnitude() > 50 else (
                self.target - agent.me.location)

            if self.jumping:
                target = target.flatten()

            target = agent.me.local(target)
            if abs(Vector(x=1).angle(target)) > 0.005:
                defaultPD(agent,
                          target,
                          upside_down=self.shot_vector.z < 0
                          and not self.jumping)

        if abs(agent.me.forward.dot(direction)) > 0.5:
            delta_v = delta_x.dot(agent.me.forward) / T
            if agent.me.boost > 0 and delta_v >= agent.boost_accel * min_boost_time:
                agent.controller.boost = True
            else:
                agent.controller.throttle = cap(
                    delta_v / (throttle_accel * min_boost_time), -1, 1)

        if T <= 0 or (not self.jumping and not agent.me.airborne) or (
                not self.jumping and T > 2 and self.fast_aerial
                and not virxrlcu.aerial_shot_is_viable(
                    T + 0.3, 144, agent.boost_accel, agent.gravity.tuple(),
                    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,
                    self.ball.tuple())):
            agent.pop()
            agent.shooting = False
            agent.shot_weight = -1
            agent.shot_time = -1
            agent.push(ball_recovery())
        elif (self.ceiling and
              self.target.dist(agent.me.location) < 92 + agent.me.hitbox.length
              and not agent.me.doublejumped
              and agent.me.location.z < agent.ball.location.z + 92
              and self.target.y * side(agent.team) > -4240) or (
                  not self.ceiling and not self.fast_aerial
                  and self.target.dist(agent.me.location) <
                  92 + agent.me.hitbox.length and not agent.me.doublejumped):
            agent.dbg_2d("Flipping")
            agent.controller.jump = True
            local_target = agent.me.local_location(self.target)
            agent.controller.pitch = abs(
                local_target.x) * -sign(local_target.x)
            agent.controller.yaw = abs(local_target.y) * sign(local_target.y)
Example #30
0
 def run(self, agent):
     self.recovery.target = agent.ball.location
     self.recovery.target.y = cap(self.recovery.target.y, -5100, 5100)
     self.recovery.run(agent)