def step(self, dt):
        if not self.flicking:
            self.carry.step(dt)
            self.controls = self.carry.controls
            self.finished = self.carry.finished
            car = self.car
            ball = self.info.ball

            # check if it's a good idea to flick
            dir_to_target = ground_direction(car, self.target)
            if (distance(car, ball) < 150 and ground_distance(car, ball) < 100
                    and dot(car.forward(), dir_to_target) > 0.7
                    and norm(car.velocity) > clamp(
                        distance(car, self.target) / 3, 1000, 1700)
                    and dot(dir_to_target, ground_direction(car, ball)) > 0.9):
                self.flicking = True

            # flick if opponent is close
            for opponent in self.info.get_opponents():
                if (distance(opponent.position + opponent.velocity, car) < max(
                        300.0,
                        norm(opponent.velocity) * 0.5)
                        and dot(opponent.velocity,
                                direction(opponent, self.info.ball)) > 0.5):
                    if distance(car.position, self.info.ball.position) < 200:
                        self.flicking = True
                    else:
                        self.finished = True
        else:
            self.flick.target = self.info.ball.position + self.info.ball.velocity * 0.2
            self.flick.step(dt)
            self.controls = self.flick.controls
            self.finished = self.flick.finished
Exemple #2
0
 def pick_easiest_target(self, car: Car, ball: Ball,
                         targets: List[vec3]) -> vec3:
     to_goal = ground_direction(ball, self.info.their_goal.center)
     return max(targets,
                key=lambda target: dot(
                    ground_direction(car, ball) + to_goal * 0.5,
                    ground_direction(ball, target)))
Exemple #3
0
 def configure(self, intercept: Intercept):
     target_direction = ground_direction(intercept, self.target)
     strike_direction = ground_direction(intercept.ball.velocity, target_direction * 4000)
     
     self.arrive.target = intercept.position - strike_direction * 105
     self.arrive.target_direction = strike_direction
     self.arrive.arrival_time = intercept.time
    def configure(self, intercept: Intercept):
        super().configure(intercept)

        ball = intercept.ball
        target_direction = ground_direction(ball, self.target)
        hit_dir = ground_direction(
            ball.velocity, target_direction * (norm(ball.velocity) * 3 + 500))

        self.arrive.target = intercept.ground_pos - hit_dir * 165
        self.arrive.target_direction = hit_dir

        self.dodge.jump.duration = self.get_jump_duration(ball.position[2])
        self.dodge.target = intercept.ball.position
        self.arrive.additional_shift = self.get_jump_duration(
            ball.position[2]) * 1000
Exemple #5
0
    def configure(self, intercept: Intercept):
        super().configure(intercept)

        ball = intercept.ball
        target_direction = ground_direction(ball, self.target)
        hit_dir = ground_direction(ball.velocity, target_direction * 4000)

        self.arrive.target = intercept.ground_pos - hit_dir * 100
        self.arrive.target_direction = hit_dir

        additional_jump = clamp(
            (ball.position[2] - 92) / 500, 0, 1.5) * self.jump_time_multiplier
        self.dodge.jump.duration = 0.05 + additional_jump
        self.dodge.target = intercept.ball.position
        self.arrive.additional_shift = additional_jump * 500
 def configure(self, intercept: Intercept):
     super().configure(intercept)
     self.aerial.target_position = intercept.position - direction(
         intercept, self.target) * 100
     self.aerial.up = normalize(
         ground_direction(intercept, self.car) + vec3(0, 0, 0.5))
     self.aerial.arrival_time = intercept.time
Exemple #7
0
    def __init__(self, car: Car, info: GameInfo, face_target: vec3,
                 distance_from_target: float):
        super().__init__(car)

        self.info = info
        self.face_target = face_target

        dist = min(distance_from_target,
                   ground_distance(face_target, self.info.my_goal.center) - 50)
        target_pos = ground(face_target) + ground_direction(
            face_target, self.info.my_goal.center) * dist

        near_goal = ground_distance(car, info.my_goal.center) < 3000
        side_shift = 400 if near_goal else 2500
        points = [
            target_pos + vec3(side_shift, 0, 0),
            target_pos - vec3(side_shift, 0, 0)
        ]
        target_pos = nearest_point(face_target,
                                   points) if near_goal else farthest_point(
                                       face_target, points)
        target_pos = Arena.clamp(target_pos, 500)

        self.travel = Travel(car, target_pos)
        self.travel.finish_distance = 800 if near_goal else 1500
        self.drive = Drive(car)
        self.stop = Stop(car)

        self.start_time = car.time

        self.pad = None
    def step(self, dt):
        # update finished state even if we are not using the controls
        self.travel.step(dt)

        if self.travel.finished:
            # turn around to face the target direction
            if angle_to(self.car, self.face_target) > 0.3:
                self.drive.target_pos = self.face_target
                self.drive.target_speed = 1000
                self.drive.step(dt)
                self.controls = self.drive.controls
                self.controls.handbrake = False
            else:
                self.stop.step(dt)
                self.controls = self.stop.controls

        else:
            self.pad = None

            # collect boost pads on the way (greedy algorithm, assumes first found is best)
            if self.car.boost < 90 and self.travel.interruptible():
                to_target = ground_direction(self.car, self.travel.target)

                for pad in self.info.large_boost_pads + self.info.small_boost_pads:
                    to_pad = ground_direction(self.car, pad)

                    if (pad.is_active and
                            distance(self.car, pad) < self.BOOST_LOOK_RADIUS
                            and angle_between(to_target,
                                              to_pad) < self.BOOST_LOOK_ANGLE):
                        self.pad = pad
                        self.drive.target_pos = pad.position
                        self.drive.target_speed = 2200
                        self.drive.step(dt)
                        self.controls = self.drive.controls
                        break

            # go to the actual target
            if self.pad is None:
                self.controls = self.travel.controls

        # don't waste boost during downtime
        if self.car.boost < 100 and ground_distance(self.car,
                                                    self.travel.target) < 4000:
            self.controls.boost = False

        self.finished = self.travel.driving and self.car.time > self.start_time + self.DURATION
Exemple #9
0
    def step(self, dt):
        if self.jumping:
            self.controls = Input()
            # first jump for full 0.2 sec
            if self.timer <= 0.2:
                self.controls.jump = True
            # single tick between jumps
            elif self.timer <= 0.2 + dt * JUMP_FALSE_TICKS:
                self.controls.jump = False
            # second jump
            else:
                self.controls.jump = True
                self.jumping = False
            self.timer += dt

        else:
            self.finished = self.intercept.time < self.info.time

            if self.car.on_ground:
                # manage speed before jump
                distance_to_target = ground_distance(self.car.position,
                                                     self.intercept.position)
                if distance_to_target < MIN_DIST_BEFORE_SPEED_CONTROL:
                    target_speed = distance_to_target / self.time_for_jump
                    self.drive.target_speed = -target_speed if self._should_strike_backwards else target_speed
                    self.drive.step(dt)
                    self.controls = self.drive.controls

                else:
                    super().step(dt)

                # decide when to jump
                ground_vel = ground(self.car.velocity)
                direction_to_target = ground_direction(self.car.position,
                                                       self.intercept.position)
                alignment = dot(normalize(ground_vel), direction_to_target)
                # check alignment
                if alignment >= MIN_ALIGNMENT:
                    # check that speed is correct
                    speed_in_direction = dot(ground_vel, direction_to_target)
                    time_to_target = distance_to_target / speed_in_direction
                    if self.time_for_jump - ALLOWED_TIME_ERROR <= time_to_target <= self.time_for_jump + ALLOWED_TIME_ERROR:
                        self.jumping = True

            # after jump (when the car is in the air)
            else:
                # face the ball for some additional height
                self.reorient.target_orientation = look_at(
                    direction(self.car.position, self.info.ball),
                    vec3(0, 0, 1))
                self.reorient.step(dt)
                self.controls = self.reorient.controls
    def step(self, dt):
        if self.dodging:
            self.dodge.step(dt)
            self.controls = self.dodge.controls
        else:
            super().step(dt)
            if (self.arrive.arrival_time - self.car.time <
                    self.dodge.jump.duration + 0.13
                    and abs(self.arrive.drive.target_speed -
                            norm(self.car.velocity)) < 1000 and
                (dot(normalize(self.car.velocity),
                     ground_direction(self.car, self.arrive.target)) > 0.95
                 or norm(self.car.velocity) < 500)):
                self.dodging = True

        if self.dodge.finished:
            self.finished = True
Exemple #11
0
    def render(self, draw: DrawingTool):
        self.arrive.render(draw)
        draw.color(draw.lime)
        draw.circle(self.intercept.ground_pos, Ball.radius)
        draw.point(self.intercept.ball.position)

        if self.target:
            strike_direction = ground_direction(self.intercept.ground_pos,
                                                self.target)
            draw.color(draw.cyan)
            draw.triangle(self.intercept.ground_pos + strike_direction * 150,
                          strike_direction,
                          length=100)

        if not self._has_drawn_prediction:
            self._has_drawn_prediction = True
            draw.ball_prediction(self.info.ball_predictions,
                                 self.intercept.time)
Exemple #12
0
    def __init__(self,
                 car: Car,
                 info: GameInfo,
                 face_target: vec3,
                 distance_from_target: float,
                 force_nearest=False):
        super().__init__(car)

        self.info = info
        self.face_target = face_target

        dist = min(distance_from_target,
                   ground_distance(face_target, self.info.my_goal.center) - 50)
        target_pos = ground(face_target) + ground_direction(
            face_target, self.info.my_goal.center) * dist

        near_goal = abs(car.position[1] - info.my_goal.center[1]) < 3000
        side_shift = 400 if near_goal else 1800
        points = target_pos + vec3(side_shift, 0, 0), target_pos - vec3(
            side_shift, 0, 0)
        if abs(self.car.position.x) > 3000:
            force_nearest = True
        target_pos = nearest_point(
            face_target,
            points) if near_goal or force_nearest else farthest_point(
                face_target, points)
        if abs(face_target[0]) < 1000 or ground_distance(car,
                                                         face_target) < 1000:
            target_pos = nearest_point(car.position, points)
        target_pos = Arena.clamp(target_pos, 500)

        self.travel = Travel(car, target_pos)
        self.travel.finish_distance = 800 if near_goal else 1500
        self.drive = Drive(car)
        self.stop = Stop(car)

        self.start_time = car.time

        self.pad = None
Exemple #13
0
def choose_maneuver(info: GameInfo, my_car: Car):
    ball = info.ball
    their_goal = ground(info.their_goal.center)
    my_goal = ground(info.my_goal.center)
    opponents = info.get_opponents()

    # recovery
    if not my_car.on_ground:
        return Recovery(my_car)

    # kickoff
    if ball.position[0] == 0 and ball.position[1] == 0:
        return kickoffs.choose_kickoff(info, my_car)

    info.predict_ball()

    my_intercept = Intercept(my_car, info.ball_predictions)
    their_intercepts = [
        Intercept(opponent, info.ball_predictions) for opponent in opponents
    ]
    their_intercept = min(their_intercepts, key=lambda i: i.time)
    opponent = their_intercept.car

    banned_boostpads = {
        pad
        for pad in info.large_boost_pads
        if abs(pad.position[1] -
               their_goal[1]) < abs(my_intercept.position[1] - their_goal[1])
        or abs(pad.position[0] - my_car.position[0]) > 6000
    }

    # if ball is in a dangerous position, clear it
    if (ground_distance(my_intercept, my_goal) < 3000
            and (abs(my_intercept.position[0]) < 2000
                 or abs(my_intercept.position[1]) < 4500)
            and my_car.position[2] < 300):
        if align(my_car.position, my_intercept.ball, their_goal) > 0.5:
            return offense.any_shot(info,
                                    my_intercept.car,
                                    their_goal,
                                    my_intercept,
                                    allow_dribble=True)
        return defense.any_clear(info, my_intercept.car)

    # if I'm low on boost and the ball is not near my goal, go for boost
    if my_car.boost < 10 and ground_distance(my_intercept, their_goal) > 3000:
        refuel = Refuel(my_car, info, forbidden_pads=banned_boostpads)
        if refuel.pad: return refuel

    ball_in_their_half = abs(my_intercept.position[1] - their_goal[1]) < 3000
    shadow_distance = 4000 if ball_in_their_half else 6000
    # if they can hit the ball sooner than me and they aren't out of position, wait in defense
    if (their_intercept.time < my_intercept.time
            and align(opponent.position, their_intercept.ball,
                      my_goal) > -0.1 + opponent.boost / 100
            and ground_distance(opponent, their_intercept) > 300
            and dot(opponent.velocity,
                    ground_direction(their_intercept, my_goal)) > 0):
        return GeneralDefense(my_car,
                              info,
                              my_intercept.position,
                              shadow_distance,
                              force_nearest=ball_in_their_half)

    # if not completely out of position, go for a shot
    if (align(my_car.position, my_intercept.ball, their_goal) > -0.5
            or ground_distance(my_intercept, their_goal) < 2000
            or ground_distance(opponent, their_intercept) < 300):
        if my_car.position[2] < 300:
            shot = offense.any_shot(info,
                                    my_intercept.car,
                                    their_goal,
                                    my_intercept,
                                    allow_dribble=True)
            if (not isinstance(shot, Strike)
                    or shot.intercept.time < their_intercept.time
                    or abs(shot.intercept.position[0]) < 3500):
                return shot

    if my_car.boost < 30:
        refuel = Refuel(my_car, info, forbidden_pads=banned_boostpads)
        if refuel.pad: return refuel

    # fallback
    return GeneralDefense(my_car,
                          info,
                          my_intercept.position,
                          shadow_distance,
                          force_nearest=ball_in_their_half)
Exemple #14
0
    def step(self, dt):
        time_left = self.aerial.arrival_time - self.car.time

        if self.aerialing:
            to_ball = direction(self.car, self.info.ball)

            # freestyling
            if self.car.position[2] > 200:
                # if time_left > 0.7:
                #     rotation = axis_to_rotation(self.car.forward() * 0.5)
                #     self.aerial.up = dot(rotation, self.car.up())
                # else:
                self.aerial.up = vec3(0, 0, -1) + xy(to_ball)

            self.aerial.target_orientation = look_at(to_ball,
                                                     vec3(0, 0, -3) + to_ball)
            self.aerial.step(dt)

            self.controls = self.aerial.controls
            self.finished = self.aerial.finished and time_left < -0.3

        else:
            super().step(dt)

            # simulate aerial from current state
            simulated_car = self.simulate_flight(self.car, self.aerial,
                                                 self._flight_path)

            speed_towards_target = dot(
                self.car.velocity,
                ground_direction(self.car, self.aerial.target_position))
            speed_needed = ground_distance(
                self.car, self.aerial.target_position) / time_left

            # too fast, slow down
            if speed_towards_target > speed_needed and angle_to(
                    self.car, self.aerial.target_position) < 0.1:
                self.controls.throttle = -1

            # if it ended up near the target, we could take off
            elif distance(
                    simulated_car,
                    self.aerial.target_position) < self.MAX_DISTANCE_ERROR:
                if angle_to(self.car,
                            self.aerial.target_position) < 0.1 or norm(
                                self.car.velocity) < 1000:

                    if self.DELAY_TAKEOFF and ground_distance(
                            self.car, self.aerial.target_position) > 1000:
                        # extrapolate current state a small amount of time
                        future_car = Car(self.car)
                        time = 0.5
                        future_car.time += time
                        displacement = future_car.velocity * time if norm(future_car.velocity) > 500\
                            else normalize(future_car.velocity) * 500 * time
                        future_car.position += displacement

                        # simulate aerial fot the extrapolated car again
                        future_simulated_car = self.simulate_flight(
                            future_car, self.aerial)

                        # if the aerial is also successful, that means we should continue driving instead of taking off
                        # this makes sure that we go for the most late possible aerials, which are the most effective
                        if distance(future_simulated_car, self.aerial.
                                    target_position) > self.MAX_DISTANCE_ERROR:
                            self.aerialing = True
                        else:
                            self.too_early = True
                    else:
                        self.aerialing = True

            else:
                # self.controls.boost = True
                self.controls.throttle = 1
Exemple #15
0
 def pick_easiest_target(car: Car, ball: Ball, targets: List[vec3]) -> vec3:
     return max(targets,
                key=lambda target: dot(ground_direction(car, ball),
                                       ground_direction(ball, target)))