Example #1
0
def run_hivemind(agent: MyHivemind):
    agent.debug_stack()
    if agent.kickoff_flag and all(
            len(drone.stack) < 1 for drone in agent.drones):
        if len(agent.friends + agent.drones) == 3:
            setup_3s_kickoff(agent)
        elif len(agent.friends + agent.drones) == 2:
            setup_2s_kickoff(agent)
        else:
            setup_other_kickoff(agent)
    elif not agent.kickoff_flag:
        for drone in agent.drones:
            drones = copy(agent.drones)
            drones.remove(drone)
            team = agent.friends + drones
            if len(drone.stack) < 1 or drone.action == Action.Shadowing:
                if drone.on_side and drone.closest or agent.conceding:
                    push_shot(drone, agent)
            if len(drone.stack) < 1:
                if drone.action == Action.Going:
                    if any(teammate.on_side for teammate in team):
                        drone.push(
                            GotoBoost(closest_boost(agent, drone.location)))
                        drone.action = Action.Boost
                    else:
                        drone.push(Shadow(agent.ball.location))
                        drone.action = Action.Shadowing
                elif drone.action == Action.Shadowing:
                    drone.push(Shadow(agent.ball.location))
                    drone.action = Action.Shadowing
                elif drone.action == Action.Boost:
                    drone.push(Shadow(agent.ball.location))
                    drone.action = Action.Shadowing
Example #2
0
 def run(self, drone: CarObject, agent: MyHivemind):
     # An example of pushing routines to the stack:
     agent.line(Vector3(0, 0, 50), 2000 * self.vector.flatten(), color=[255, 0, 0])
     agent.line(Vector3(0, 0, 50), 2000 * drone.forward.flatten(), color=[0, 255, 0])
     robbies_constant = (self.vector * 1.5 * 2200 - drone.velocity * 1.5) * 2 * 1.5 ** -2
     robbies_boost_constant = drone.forward.flatten().normalize().dot(robbies_constant.flatten().normalize()) > (
         0.3 if not drone.airborne else 0.1)
     drone.controller.boost = robbies_boost_constant and self.boost and not drone.supersonic
     if self.time == -1:
         elapsed = 0
         self.time = agent.time
     else:
         elapsed = agent.time - self.time
     if elapsed < self.delay:
         if elapsed < self.duration:
             drone.controller.jump = True
         else:
             drone.controller.jump = False
             self.counter += 1
         defaultPD(drone, self.preorientation)
     elif elapsed >= self.delay and self.counter < 3:
         drone.controller.jump = False
         defaultPD(drone, self.preorientation)
         self.counter += 1
     elif elapsed < self.delay + 0.05:
         drone.controller.jump = True
         defaultPD(drone, self.vector)
     else:
         drone.pop()
         drone.push(Recovery(boost=self.boost, time=agent.time))
Example #3
0
    def run(self, drone: CarObject, agent: MyHivemind):
        car_to_ball, distance = (agent.ball.location - drone.location).normalize(True)
        ball_to_target = (self.target - agent.ball.location).normalize()

        relative_velocity = car_to_ball.dot(drone.velocity - agent.ball.velocity)
        if relative_velocity != 0.0:
            eta = cap(distance / cap(relative_velocity, 400, 2300), 0.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((0, 0, 1))
        right_vector = car_to_ball.cross((0, 0, -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 drive through any goalposts to reach it
        if abs(drone.location[1]) > 5150:
            final_target[0] = cap(final_target[0], -750, 750)

        agent.line(final_target - Vector3(0, 0, 100), final_target + Vector3(0, 0, 100), [255, 255, 255])

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

        if abs(angles[1]) < 0.05 and (eta < 0.45 or distance < 150):
            drone.pop()
            drone.push(Flip(drone.local(car_to_ball)))
Example #4
0
def run_1v1(agent: MyHivemind):
    agent.debug_stack()
    drone = agent.drones[0]
    if agent.kickoff_flag and len(drone.stack) < 1:
        if abs(drone.location.x) < 250:
            drone.push(CenterKickoff())
            drone.action = Action.Going
        elif abs(drone.location.x) < 1000:
            drone.push(OffCenterKickoff())
            drone.action = Action.Going
        else:
            drone.push(DiagonalKickoff())
            drone.action = Action.Going
    elif not agent.kickoff_flag:
        on_side = (drone.location - agent.friend_goal.location).magnitude() < (
            agent.ball.location - agent.friend_goal.location).magnitude()
        if len(drone.stack) < 1:
            if drone.action == Action.Going:
                if on_side and (drone.location -
                                agent.ball.location).magnitude() < 2000:
                    push_shot(drone, agent)
                if len(drone.stack) < 1:
                    drone.push(Shadow(agent.ball.location))
                    drone.action = Action.Shadowing
            elif drone.action == Action.Shadowing:
                push_shot(drone, agent)
                if len(drone.stack) < 1:
                    drone.push(Shadow(agent.ball.location))
                    drone.action = Action.Shadowing
Example #5
0
def setup_2s_kickoff(agent: MyHivemind):
    x_pos = [round(drone.location.x) for drone in agent.drones]
    x_pos.extend([round(friend.location.x) for friend in agent.friends])
    if sorted(x_pos) == [-2048, 2048]:
        for drone in agent.drones:
            if round(drone.location.x) == agent.side() * -2048:
                drone.push(KickOff())
                drone.action = Action.Going
            elif round(drone.location.x) == agent.side() * 2048:
                drone.push(Shadow())
                drone.action = Action.Shadowing
    elif sorted(x_pos) == [-256, 256]:
        for drone in agent.drones:
            if round(drone.location.x) == agent.side() * -256:
                drone.push(KickOff())
                drone.action = Action.Going
            elif round(drone.location.x) == agent.side() * 256:
                drone.push(Shadow())
                drone.action = Action.Shadowing
    elif -2048 in x_pos or 2048 in x_pos:
        for drone in agent.drones:
            if round(abs(drone.location.x)) == 2048:
                drone.push(KickOff())
                drone.action = Action.Going
            else:
                drone.push(Shadow())
                drone.action = Action.Shadowing
    elif -256 in x_pos or 256 in x_pos:
        for drone in agent.drones:
            if round(abs(drone.location.x)) == 256:
                drone.push(KickOff())
                drone.action = Action.Going
            else:
                drone.push(Shadow())
                drone.action = Action.Shadowing
Example #6
0
def run_1v1(agent: MyHivemind):
    agent.debug_stack()
    drone: CarObject = agent.drones[0]
    if agent.kickoff_flag and len(drone.stack) < 1:
        drone.push(KickOff())
        drone.action = Action.Going
    elif not agent.kickoff_flag:
        if len(drone.stack) < 1 or drone.action == Action.Shadowing:
            if drone.on_side or agent.conceding:
                shot = find_shot(drone, (agent.foe_goal.left_post, agent.foe_goal.right_post))
                if shot is not None:
                    shot = find_shot(drone, (agent.foe_goal.left_post, agent.foe_goal.right_post))
                if shot is not None:
                    drone.push(shot)
                    drone.action = Action.Going
                else:
                    my_shot = find_any_shot(drone)
                    enemy_shot = find_any_shot(agent.foes[0])
                    if my_shot is not None:
                        if enemy_shot is None:
                            drone.push(my_shot)
                            drone.action = Action.Going
                        elif my_shot.intercept_time < enemy_shot.intercept_time or agent.desperate:
                            drone.push(my_shot)
                            drone.action = Action.Going
        if len(drone.stack) < 1:
            drone.push(Shadow())
            drone.action = Action.Shadowing
Example #7
0
def setup_3s_kickoff(agent: MyHivemind):
    x_pos = [round(drone.location.x) for drone in agent.drones]
    x_pos.extend([round(friend.location.x) for friend in agent.friends])
    if sorted(x_pos) in [[-2048, -256, 2048], [-2048, 0, 2048],
                         [-2048, 256, 2048]]:
        for drone in agent.drones:
            if round(drone.location.x) == agent.side() * -2048:
                drone.push(KickOff())
                drone.action = Action.Going
            elif round(drone.location.x) == agent.side() * 2048:
                target = agent.friend_goal.location + 2 * (
                    agent.ball.location - agent.friend_goal.location) / 3
                drone.push(Goto(target))
                drone.action = Action.Cheating
            else:
                drone.push(GotoBoost(closest_boost(agent, drone.location)))
                drone.action = Action.Boost
    elif sorted(x_pos) == [-256, 0, 256]:
        for drone in agent.drones:
            if round(drone.location.x) == agent.side() * -256:
                drone.push(KickOff())
                drone.action = Action.Going
            elif round(drone.location.x) == agent.side() * 256:
                target = agent.friend_goal.location + 2 * (
                    agent.ball.location - agent.friend_goal.location) / 3
                drone.push(Goto(target))
                drone.action = Action.Cheating
            else:
                drone.push(GotoBoost(closest_boost(agent, drone.location)))
                drone.action = Action.Boost
    elif -2048 in x_pos or 2048 in x_pos:
        for drone in agent.drones:
            if round(abs(drone.location.x)) == 2048:
                drone.push(KickOff())
                drone.action = Action.Going
            elif round(drone.location.x) == agent.side() * -256:
                target = agent.friend_goal.location + 2 * (
                    agent.ball.location - agent.friend_goal.location) / 3
                drone.push(Goto(target))
                drone.action = Action.Cheating
            elif round(drone.location.x) == 0:
                drone.push(GotoBoost(closest_boost(agent, drone.location)))
                drone.action = Action.Boost
            else:
                if 0 in x_pos:
                    target = agent.friend_goal.location + 2 * (
                        agent.ball.location - agent.friend_goal.location) / 3
                    drone.push(Goto(target))
                    drone.action = Action.Cheating
                else:
                    drone.push(GotoBoost(closest_boost(agent, drone.location)))
                    drone.action = Action.Boost
Example #8
0
def shot_valid(agent: MyHivemind,
               shot: Union[AerialShot, JumpShot, Aerial],
               threshold: float = 45) -> bool:
    # Returns True if the ball is still where the shot anticipates it to be
    # First finds the two closest slices in the ball prediction to shot's intercept_time
    # threshold controls the tolerance we allow the ball to be off by
    slices = agent.get_ball_prediction_struct().slices
    soonest = 0
    latest = len(slices) - 1
    while len(slices[soonest:latest + 1]) > 2:
        midpoint = (soonest + latest) // 2
        if slices[midpoint].game_seconds > shot.intercept_time:
            latest = midpoint
        else:
            soonest = midpoint
    # preparing to interpolate between the selected slices
    dt = slices[latest].game_seconds - slices[soonest].game_seconds
    time_from_soonest = shot.intercept_time - slices[soonest].game_seconds
    slopes = (Vector3(slices[latest].physics.location) -
              Vector3(slices[soonest].physics.location)) * (1 / dt)
    # Determining exactly where the ball will be at the given shot's intercept_time
    predicted_ball_location = Vector3(
        slices[soonest].physics.location) + (slopes * time_from_soonest)
    # Comparing predicted location with where the shot expects the ball to be
    return (shot.ball_location -
            predicted_ball_location).magnitude() < threshold
Example #9
0
 def run(self, drone: CarObject, agent: MyHivemind):
     target = agent.ball.location + Vector3(0, 200 * agent.side(), 0)
     local_target = drone.local(target - drone.location)
     defaultPD(drone, local_target)
     defaultThrottle(drone, 2300)
     if local_target.magnitude() < 650:
         drone.pop()
         drone.push(Flip(drone.local(agent.foe_goal.location - drone.location)))
Example #10
0
def push_shot(drone: CarObject, agent: MyHivemind):
    left = Vector3(4200 * -agent.side(),
                   agent.ball.location.y + (1000 * -agent.side()), 0)
    right = Vector3(4200 * agent.side(),
                    agent.ball.location.y + (1000 * -agent.side()), 0)
    targets = {
        "goal": (agent.foe_goal.left_post, agent.foe_goal.right_post),
        "upfield": (left, right)
    }
    shots = find_hits(drone, agent, targets)
    if len(shots["goal"]) > 0:
        drone.clear()
        drone.push(shots["goal"][0])
        drone.action = Action.Going
    elif len(shots["upfield"]) > 0:
        drone.clear()
        drone.push(shots["upfield"][0])
        drone.action = Action.Going
Example #11
0
 def run(self, drone: CarObject, agent: MyHivemind):
     target = Vector3(0, 3116 * agent.side(), 0)
     local_target = drone.local(target - drone.location)
     defaultPD(drone, local_target)
     defaultThrottle(drone, 2300)
     if local_target.magnitude() < 400:
         drone.pop()
         drone.push(DiagonalKickoff())
         drone.push(Flip(drone.local(agent.ball.location - drone.location)))
Example #12
0
def run_hivemind(agent: MyHivemind):
    agent.debug_stack()
    if agent.kickoff_flag and all(len(drone.stack) < 1 for drone in agent.drones):
        if len(agent.friends + agent.drones) == 3:
            setup_3s_kickoff(agent)
        elif len(agent.friends + agent.drones) == 2:
            setup_2s_kickoff(agent)
        else:
            setup_other_kickoff(agent)
    elif not agent.kickoff_flag:
        for drone in agent.drones:
            drones = copy(agent.drones)
            drones.remove(drone)
            team = agent.friends + drones
            empty_stack = len(drone.stack) < 1 and drone.on_side and drone.closest
            should_go = (
                                drone.action == Action.Shadowing) and drone.on_side and drone.closest
            conceding = (agent.conceding and not any(teammate.on_side for teammate in team)) or (
                    agent.conceding and drone.on_side and drone.closest)
            cheating = drone.action == Action.Cheating
            if empty_stack or should_go or conceding or cheating:
                if empty_stack or drone.stack[0].__class__.__name__ not in ["GroundShot", "JumpShot", "DoubleJump"]:
                    shot = find_any_shot(drone)
                    if shot is not None:
                        drone.push(shot)
                        drone.action = Action.Going
            if len(drone.stack) < 1:
                if drone.action == Action.Going:
                    if any(teammate.on_side for teammate in team) and drone.boost < 66:
                        drone.push(GotoBoost(closest_boost(agent, drone.location)))
                        drone.action = Action.Boost
                    else:
                        drone.push(Shadow())
                        drone.action = Action.Shadowing
                elif drone.action == Action.Shadowing:
                    if all(teammate.on_side for teammate in team) and drone.boost < 66:
                        drone.push(GotoBoost(closest_boost(agent, drone.location)))
                        drone.action = Action.Boost
                    else:
                        drone.push(Shadow())
                        drone.action = Action.Shadowing
                elif drone.action == Action.Boost:
                    drone.push(Shadow())
                    drone.action = Action.Shadowing
Example #13
0
    def run(self, drone: CarObject, agent: MyHivemind):
        if self.boost is None:
            drone.pop()
            return
        car_to_boost = self.boost.location - drone.location
        distance_remaining = car_to_boost.flatten().magnitude()

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

        if self.target is not None:
            vector = (self.target - self.boost.location).normalize()
            side_of_vector = sign(vector.cross((0, 0, 1)).dot(car_to_boost))
            car_to_boost_perp = car_to_boost.cross((0, 0, side_of_vector)).normalize()
            adjustment = car_to_boost.angle2D(vector) * distance_remaining / 3.14
            final_target = self.boost.location + (car_to_boost_perp * adjustment)
            car_to_target = (self.target - drone.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(drone.location[1]) > 5150:
            final_target[0] = cap(final_target[0], -750, 750)

        local_target = drone.local(final_target - drone.location)

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

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

        velocity = 1 + drone.velocity.magnitude()
        if not self.boost.active or drone.boost >= 99.0 or distance_remaining < 350:
            drone.pop()
        elif drone.airborne:
            drone.push(Recovery(self.target))
        elif abs(angles[1]) < 0.05 and 600 < velocity < 2150 and (
                distance_remaining / velocity > 2.0 or (adjustment < 90 and car_to_target / velocity > 2.0)):
            drone.push(Flip(local_target))
Example #14
0
def run_1v1(agent: MyHivemind):
    agent.debug_stack()
    drone = agent.drones[0]
    if agent.kickoff_flag and len(drone.stack) < 1:
        if abs(drone.location.x) < 250:
            drone.push(CenterKickoff())
            drone.action = Action.Going
        elif abs(drone.location.x) < 1000:
            drone.push(OffCenterKickoff())
            drone.action = Action.Going
        else:
            drone.push(DiagonalKickoff())
            drone.action = Action.Going
    elif not agent.kickoff_flag:
        if len(drone.stack) < 1 or drone.action == Action.Shadowing:
            if drone.on_side or agent.conceding:
                push_shot(drone, agent)
        if len(drone.stack) < 1:
            drone.push(Shadow(agent.ball.location))
            drone.action = Action.Shadowing
Example #15
0
    def run(self, drone: CarObject, agent: MyHivemind):
        if self.target is not None:
            if self.target_local:
                local_target = self.target
            else:
                local_target = drone.local((self.target - drone.location).flatten())
        else:
            local_target = drone.local(drone.velocity.flatten())

        defaultPD(drone, local_target)
        drone.controller.throttle = 1
        t = (-drone.velocity.z - (
                drone.velocity.z ** 2 + 2 * -650 * -(max(drone.location.z - 17.01, 0.01))) ** 0.5) / -650
        if self.target is not None:
            robbies_constant = (self.target.normalize() * t * 2200 - drone.velocity * t) * 2 * t ** -2
        else:
            robbies_constant = (drone.velocity.normalize() * t * 2200 - drone.velocity * t) * 2 * t ** -2
        agent.line(drone.location, robbies_constant, color=[255, 255, 255])
        robbies_boost_constant = drone.forward.normalize().dot(robbies_constant.normalize()) > 0.5
        drone.controller.boost = robbies_boost_constant and self.boost and not drone.supersonic
        if not drone.airborne:
            drone.pop()
Example #16
0
    def run(self, drone: CarObject, agent: MyHivemind):
        target = agent.friend_goal.location + (agent.ball.location - agent.friend_goal.location) / 2
        car_to_target = target - drone.location
        distance_remaining = car_to_target.flatten().magnitude()

        agent.line(target - Vector3(0, 0, 500), target + Vector3(0, 0, 500), [255, 0, 255])

        if self.vector is not None:
            # See commends for adjustment in jump_shot or aerial for explanation
            side_of_vector = sign(self.vector.cross((0, 0, 1)).dot(car_to_target))
            car_to_target_perp = car_to_target.cross((0, 0, side_of_vector)).normalize()
            adjustment = car_to_target.angle(self.vector) * distance_remaining / 3.14
            final_target = target + (car_to_target_perp * adjustment)
        else:
            final_target = 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(drone.location[1]) > 5150:
            final_target[0] = cap(final_target[0], -750, 750)

        local_target = drone.local(final_target - drone.location)

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

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

        velocity = 1 + drone.velocity.magnitude()
        if distance_remaining < 350:
            drone.pop()
        elif abs(angles[1]) < 0.05 and 600 < velocity < 2150 and distance_remaining / velocity > 2.0:
            drone.push(Flip(local_target))
        # TODO Halfflip
        # elif abs(angles[1]) > 2.8 and velocity < 200:
        #     agent.push(flip(local_target, True))
        elif drone.airborne:
            drone.push(Recovery(target))
Example #17
0
def push_shot(drone: CarObject, agent: MyHivemind):
    left = Vector3(4200 * -agent.side(), agent.side() * 5120, 0)
    right = Vector3(4200 * agent.side(), agent.side() * 5120, 0)
    targets = {"goal": (agent.foe_goal.left_post, agent.foe_goal.right_post)}
    if not agent.conceding:
        drones = copy(agent.drones)
        drones.remove(drone)
        team = agent.friends + drones
        for teammate in team:
            a = teammate.location
            b = teammate.location + 2000 * teammate.forward
            local_a = drone.local(a)
            angle_a = math.atan2(local_a.y, local_a.x)
            if angle_a > 0:
                targets["teammate" + str(team.index(teammate))] = (b, a)
            else:
                targets["teammate" + str(team.index(teammate))] = (a, b)
    targets["upfield"] = (left, right)
    shots = find_hits(drone, agent, targets)
    if len(shots["goal"]) > 0:
        drone.clear()
        drone.push(shots["goal"][0])
        drone.action = Action.Going
    elif shots.get("teammate0") is not None and len(
            shots.get("teammate0")) > 0:
        drone.clear()
        drone.push(shots["teammate0"][0])
        drone.action = Action.Going
    elif shots.get("teammate1") is not None and len(
            shots.get("teammate1")) > 0:
        drone.clear()
        drone.push(shots["teammate1"][0])
        drone.action = Action.Going
    elif len(shots["upfield"]) > 0:
        drone.clear()
        drone.push(shots["upfield"][0])
        drone.action = Action.Going
Example #18
0
def run_test(agent: MyHivemind):
    agent.debug_stack()
    next_state = agent.test_state
    if agent.test_state == TestState.Reset:
        agent.test_time = agent.time

        b_position = RLBot3(random.uniform(-1500, 1500),
                            random.uniform(2500, 3500),
                            random.uniform(300, 500))

        b_velocity = RLBot3(random.uniform(-300,
                                           300), random.uniform(-100, 100),
                            random.uniform(900, 1000))

        ball_state = BallState(
            physics=Physics(location=b_position,
                            velocity=b_velocity,
                            rotation=Rotator(0, 0, 0),
                            angular_velocity=RLBot3(0, 0, 0)))

        # this just initializes the car and ball
        # to different starting points each time
        c_position = RLBot3(b_position.x, 0 * random.uniform(-1500, -1000), 25)

        # c_position = Vector3(200, -1000, 25)
        car_state = CarState(physics=Physics(location=c_position,
                                             velocity=RLBot3(0, 800, 0),
                                             rotation=Rotator(0, 1.6, 0),
                                             angular_velocity=RLBot3(0, 0, 0)),
                             boost_amount=100)

        agent.set_game_state(
            GameState(ball=ball_state, cars={agent.drones[0].index:
                                             car_state}))

        next_state = TestState.Wait
    elif agent.test_state == TestState.Wait:
        if agent.time - agent.test_time > 0.2:
            next_state = TestState.Init
    elif agent.test_state == TestState.Init:
        push_shot(agent.drones[0], agent)
        next_state = TestState.Running
    elif agent.test_state == TestState.Running:
        if agent.time - agent.test_time > 5:
            next_state = TestState.Reset
            agent.drones[0].clear()
    agent.test_state = next_state
Example #19
0
def find_hits(drone: CarObject, agent: MyHivemind, targets):
    # 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

    # Example Useage:
    # targets = {"goal":(opponent_left_post,opponent_right_post), "anywhere_but_my_net":(my_right_post,my_left_post)}
    # hits = find_hits(agent,targets)
    # print(hits)
    # >{"goal":[a ton of jump and aerial routines,in order from soonest to latest],
    # "anywhere_but_my_net":[more routines and stuff]}
    hits = {name: [] for name in targets}
    struct = agent.get_ball_prediction_struct()

    # Begin looking at slices 0.25s into the future
    # The number of slices
    i = 15
    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 = Vector3(struct.slices[i].physics.location)
            ball_velocity = Vector3(
                struct.slices[i].physics.velocity).magnitude()

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

            # 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)

            car_to_ball = ball_location - drone.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(drone.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.0 and (
                distance * 1.05 / forward_time) < (
                    2290 if drone.boost > distance / 100 else 1400)
            backward_flag = distance < 1500 and backward_time > 0.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 == 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 best 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
                        if in_field(ball_location - (200 * best_shot_vector),
                                    1):
                            # 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[2] <= 300 and slope > 0.0:
                                    hits[pair].append(
                                        JumpShot(ball_location, intercept_time,
                                                 best_shot_vector, slope))
                                if 300 < ball_location[
                                        2] < 600 and slope > 1.0 and (
                                            ball_location[2] -
                                            250) * 0.14 > drone.boost:
                                    hits[pair].append(
                                        AerialShot(ball_location,
                                                   intercept_time,
                                                   best_shot_vector))
                            elif backward_flag and ball_location[
                                    2] <= 280 and slope > 0.25:
                                hits[pair].append(
                                    JumpShot(ball_location, intercept_time,
                                             best_shot_vector, slope, -1))
    return hits
Example #20
0
    def run(self, drone: CarObject, agent: MyHivemind):
        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.01, 10.0)

        car_to_ball = self.ball_location - drone.location
        # whether we are to the left or right of the shot vector
        side_of_shot = sign(self.shot_vector.cross((0, 0, 1)).dot(car_to_ball))

        car_to_intercept = self.intercept - drone.location
        car_to_intercept_perp = car_to_intercept.cross((0, 0, side_of_shot))  # perpendicular
        distance_remaining = car_to_intercept.flatten().magnitude()

        speed_required = distance_remaining / time_remaining
        # When still on the ground we pretend gravity doesn't exist, for better or worse
        acceleration_required = backsolve(self.intercept, drone, time_remaining, 0 if self.jump_time == 0 else 325)
        local_acceleration_required = drone.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
        adjustment *= (cap(self.jump_threshold - (acceleration_required[2]), 0.0,
                           self.jump_threshold) / self.jump_threshold)  # factoring in how close to jump we are
        # 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 drive through any goalposts to reach it
        if abs(drone.location[1] > 5150):
            final_target[0] = cap(final_target[0], -750, 750)

        local_final_target = drone.local(final_target - drone.location)

        # drawing debug lines to show the dodge point and final target (which differs due to the adjustment)
        agent.line(drone.location, self.intercept)
        agent.line(self.intercept - Vector3(0, 0, 100), self.intercept + Vector3(0, 0, 100), [255, 0, 0])
        agent.line(final_target - Vector3(0, 0, 100), final_target + Vector3(0, 0, 100), [0, 255, 0])

        angles = defaultPD(drone, local_final_target)

        if self.jump_time == 0:
            defaultThrottle(drone, speed_required)
            drone.controller.boost = False if abs(angles[1]) > 0.3 or drone.airborne else drone.controller.boost
            drone.controller.handbrake = True if abs(angles[1]) > 2.3 else drone.controller.handbrake
            if acceleration_required[2] > 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 drone.airborne and local_acceleration_required.magnitude() * time_remaining > 100:
                angles = defaultPD(drone, local_acceleration_required)
                if abs(angles[0]) + abs(angles[1]) < 0.5:
                    drone.controller.boost = True
            if self.counter == 0 and (time_since_jump <= 0.2 and local_acceleration_required[2] > 0):
                # hold the jump button up to 0.2 seconds to get the most acceleration from the first jump
                drone.controller.jump = True
            elif time_since_jump > 0.2 and self.counter < 3:
                # Release the jump button for 3 ticks
                drone.controller.jump = False
                self.counter += 1
            elif local_acceleration_required[2] > 300 and self.counter == 3:
                # the acceleration from the second jump is instant, so we only do it for 1 frame
                drone.controller.jump = True
                drone.controller.pitch = 0
                drone.controller.yaw = 0
                drone.controller.roll = 0
                self.counter += 1

        if raw_time_remaining < -0.25 or not shot_valid(agent, self):
            drone.pop()
            drone.push(Recovery())
Example #21
0
    def run(self, drone: CarObject, agent: MyHivemind):
        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 - drone.location
        # whether we are to the left or right of the shot vector
        side_of_shot = sign(self.shot_vector.cross((0, 0, 1)).dot(car_to_ball))

        car_to_dodge_point = self.dodge_point - drone.location
        car_to_dodge_perp = car_to_dodge_point.cross((0, 0, side_of_shot))  # perpendicular
        distance_remaining = car_to_dodge_point.magnitude()

        speed_required = distance_remaining / time_remaining
        acceleration_required = backsolve(self.dodge_point, drone, time_remaining, 0 if not self.jumping else 650)
        local_acceleration_required = drone.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
        adjustment *= (cap(self.jump_threshold - (acceleration_required[2]), 0.0,
                           self.jump_threshold) / self.jump_threshold)  # factoring in how close to jump we are
        # 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) + Vector3(0, 0, 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(drone.location[1]) > 5150:
            final_target[0] = cap(final_target[0], -750, 750)

        local_final_target = drone.local(final_target - drone.location)

        # drawing debug lines to show the dodge point and final target (which differs due to the adjustment)
        agent.line(drone.location, self.dodge_point)
        agent.line(self.dodge_point - Vector3(0, 0, 100), self.dodge_point + Vector3(0, 0, 100), [255, 0, 0])
        agent.line(final_target - Vector3(0, 0, 100), final_target + Vector3(0, 0, 100), [0, 255, 0])

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

        agent.line(drone.location, drone.location + (self.shot_vector * 200), [255, 255, 255])

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

        if not self.jumping:
            if raw_time_remaining <= 0.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
                drone.pop()
                if drone.airborne:
                    drone.push(Recovery())
            elif local_acceleration_required[2] > self.jump_threshold \
                    and local_acceleration_required[2] > 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 drone.airborne and self.counter > 0):
                drone.pop()
                drone.push(Recovery())
            elif self.counter == 0 and local_acceleration_required[2] > 0.0 and raw_time_remaining > 0.083:
                # Initial jump to get airborne + we hold the jump button for extra power as required
                drone.controller.jump = True
            elif self.counter < 3:
                # make sure we aren't jumping for at least 3 frames
                drone.controller.jump = False
                self.counter += 1
            elif 0.1 >= raw_time_remaining > -0.9:
                # dodge in the direction of the shot_vector
                drone.controller.jump = True
                if not self.dodging:
                    vector = drone.local(self.shot_vector)
                    self.p = abs(vector[0]) * -sign(vector[0])
                    self.y = abs(vector[1]) * sign(vector[1]) * self.direction
                    self.dodging = True
                # simulating a deadzone so that the dodge is more natural
                drone.controller.pitch = self.p if abs(self.p) > 0.2 else 0
                drone.controller.yaw = self.y if abs(self.y) > 0.3 else 0