Exemple #1
0
 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) < 80
             and dot(car.forward(), dir_to_target) > 0.7
             and norm(car.velocity) > distance(car, self.target) / 3
             and norm(car.velocity) > 1300
             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(car):
             if (
                 distance(opponent.position + opponent.velocity, car) < max(300.0, norm(opponent.velocity))
                 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.step(dt)
         self.controls = self.flick.controls
         self.finished = self.flick.finished
Exemple #2
0
    def step(self, dt):
        if self.aerialing:
            self.aerial.target_orientation = look_at(
                direction(self.car, self.target), vec3(0, 0, -1))
            self.aerial.step(dt)
            self.controls = self.aerial.controls
            self.finished = self.aerial.finished

        else:
            super().step(dt)

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

            # if the car ended up too far, we're too fast and we need to slow down
            if ground_distance(self.car,
                               self.aerial.target) + 100 < ground_distance(
                                   self.car, simulated_car):
                # self.controls.throttle = -1
                pass

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

                    if self.DELAY_TAKEOFF:
                        # extrapolate current state a small amount of time
                        future_car = Car(self.car)
                        time = 0.2
                        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, write_to_flight_path=False)

                        # 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) > 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
    def step(self, dt):
        car = self.car

        if self.phase == 1:
            if norm(car.velocity) > 1400:
                self.phase = 2
                self.action = AirDodge(car, 0.05, car.position + car.velocity)

        if self.phase == 2:
            self.action.controls.boost = self.action.state_timer < 0.1

            if car.on_ground and self.action.finished:
                self.action = self.drive
                self.phase = 3

        if self.phase == 3:
            if distance(car, vec3(0, 0, 93)) < norm(car.velocity) * 0.4:
                self.phase = 4
                self.action = AirDodge(car, 0.05, self.info.ball.position)

                self.counter_fake_kickoff()

        if self.phase == 4:
            if self.action.finished:
                self.finished = True

        super().step(dt)
Exemple #4
0
    def counter_fake_kickoff(self):
        if any(
                distance(self.info.ball, opponent) < 1500
                for opponent in self.info.get_opponents(self.car)):
            return

        self.phase = "anti-fake-kickoff"
        self.action = self.drive
Exemple #5
0
def estimate_time(car: Car, target, speed, dd=1) -> float:
    dist = distance(car, target)
    if dist < 100:
        return 0
    travel = dist / speed
    turning = angle_between(car.forward() * dd, direction(car, target)) / math.pi * 2
    if turning < 1:
        turning **= 2
    acceleration = (speed * dd - dot(car.velocity, car.forward())) / 2100 * 0.2 * dd / max(car.boost / 20, 1)
    return travel + acceleration + turning * 0.7
Exemple #6
0
    def step(self, dt):
        if self.pad is None:
            self.finished = True
            return

        # slow down when we're about to pick up the boost, so we can turn faster afterwards
        if distance(self.car, self.pad) < norm(self.car.velocity) * 0.2:
            self.travel.drive.target_speed = 1400

        self.travel.step(dt)
        self.controls = self.travel.controls

        # finish when someone picks up the pad
        if not self.pad.is_active and self.pad_was_active:
            self.finished = True
        self.pad_was_active = self.pad.is_active

        # finish when we picked the boost up but the previous condition somehow wasn't true
        if self.car.boost > 99 or distance(self.car, self.pad) < 100:
            self.finished = True
Exemple #7
0
    def direct_shot(self, car: Car, target: vec3) -> Maneuver:
        dodge_shot = DodgeShot(car, self.info, target)
        ground_shot = GroundShot(car, self.info, target)

        if car.boost > 40:
            aerial_strike = AerialStrike(car, self.info, target)
            fast_aerial = FastAerialStrike(car, self.info, target)

            if min(aerial_strike.intercept.time,
                   fast_aerial.intercept.time) < dodge_shot.intercept.time:
                return min([aerial_strike, fast_aerial],
                           key=lambda strike: strike.intercept.time)

        if (dodge_shot.intercept.time < ground_shot.intercept.time - 0.1
                or ground_distance(dodge_shot.intercept, target) < 4000
                or distance(ground_shot.intercept.ball.velocity,
                            car.velocity) < 500):
            if (distance(dodge_shot.intercept.ground_pos, target) < 4000
                    and abs(dodge_shot.intercept.ground_pos[0]) < 3000):
                return CloseShot(car, self.info, target)
            return dodge_shot
        return ground_shot
Exemple #8
0
    def __init__(self,
                 car: Car,
                 target: vec3 = vec3(0, 0, 0),
                 waste_boost=False):
        super().__init__(car)

        self.target = Arena.clamp(ground(target), 100)
        self.waste_boost = waste_boost
        self.finish_distance = 500

        self._time_on_ground = 0
        self.driving = True

        # decide whether to start driving backwards and halfflip later
        forward_estimate = estimate_time(car, self.target,
                                         estimate_max_car_speed(car))
        backwards_estimate = estimate_time(car, self.target, 1400, -1) + 0.5
        backwards = (backwards_estimate < forward_estimate
                     and (distance(car, self.target) > 3000
                          or distance(car, self.target) < 300)
                     and car.position[2] < 200)

        self.drive = Drive(car, self.target, 2300, backwards)
        self.action = self.drive
Exemple #9
0
    def best_boostpad_to_pickup(car: Car, pads: Set[Pad], pos: vec3) -> Pad:
        best_pad = None
        best_dist = math.inf

        for pad in pads:
            dist = distance(pos, pad.position)
            time_estimate = estimate_time(car, pad.position,
                                          estimate_max_car_speed(car))

            if dist < best_dist and (pad.is_active
                                     or pad.timer < time_estimate):
                best_pad = pad
                best_dist = dist

        return best_pad
    def set_kickoff_maneuvers(self, drones: List[Drone]):
        nearest_drone = min(drones, key=lambda drone: ground_distance(drone.car, self.info.ball))
        nearest_drone.maneuver = KickoffStrategy.choose_kickoff(self.info, nearest_drone.car)
        self.drone_going_for_ball = nearest_drone

        self.boost_reservations.clear()
        corner_drones = [drone for drone in drones if abs(drone.car.position[0]) > 2000]
        if len(corner_drones) > 1:
            other_corner_drone = next(drone for drone in corner_drones if drone is not nearest_drone)
            nearest_pad = min(self.info.large_boost_pads, key=lambda pad: distance(other_corner_drone.car, pad))
            other_corner_drone.maneuver = HalfFlipPickup(other_corner_drone.car, nearest_pad)
            self.boost_reservations[other_corner_drone] = nearest_pad

        for drone in drones:
            if drone is not nearest_drone and drone not in corner_drones:
                reserved_pads = {self.boost_reservations[d] for d in self.boost_reservations}
                drone.maneuver = Refuel(drone.car, self.info, self.info.my_goal.center, forbidden_pads=reserved_pads)
                self.boost_reservations[drone] = drone.maneuver.pad
Exemple #11
0
    def step(self, dt):
        ball = Ball(self.ball)
        car = self.car

        # simulate ball until it gets near the floor
        while (ball.position[2] > 120
               or ball.velocity[2] > 0) and ball.time < car.time + 10:
            ball.step(1 / 60)

        ball_local = local(car, ground(ball.position))
        target = local(car, self.target)

        shift = ground(direction(ball_local, target))
        shift[1] *= 1.8
        shift = normalize(shift)

        max_turn = clamp(norm(car.velocity) / 800, 0, 1)
        max_shift = normalize(vec3(1 - max_turn, max_turn * sign(shift[1]), 0))

        if abs(shift[1]) > abs(max_shift[1]) or shift[0] < 0:
            shift = max_shift
        shift *= clamp(car.boost, 30, 50)

        shift[1] *= clamp(norm(car.velocity) / 1000, 1, 2)

        self._shift_direction = normalize(world(car, shift) - car.position)

        target = world(car, ball_local - shift)
        speed = distance(car.position, target) / max(0.001,
                                                     ball.time - car.time)

        self.drive.target_speed = speed
        self.drive.target_pos = target

        self.drive.step(dt)
        self.controls = self.drive.controls
        self.finished = self.ball.position[2] < 100 or ground_distance(
            self.ball, self.car) > 2000
Exemple #12
0
    def get_output(self, packet: GameTickPacket):
        self.time = packet.game_info.seconds_elapsed
        dt = self.time - self.prev_time
        if packet.game_info.is_kickoff_pause and not isinstance(self.maneuver, Kickoff):
            self.maneuver = None

        self.prev_time = self.time
        if self.ticks < 6:
            self.ticks += 1
        self.info.read_packet(packet)
        self.strategy.packet = packet
        

        #reset maneuver when another car hits the ball
        touch = packet.game_ball.latest_touch
        if ((
            touch.time_seconds > self.last_touch_time
            and touch.player_name != packet.game_cars[self.index].name
        ) or (
            touch.player_name == '' and # if latest touch info is missing
            any([distance(self.info.ball, car) < 300 for car in self.info.opponents + self.info.teammates])
        )):
            self.last_touch_time = touch.time_seconds
            if (
                self.info.my_car.on_ground
                and (not isinstance(self.maneuver, ShadowDefense) or self.maneuver.travel._driving)
            ):
                self.maneuver = None
                #self.reset_time = self.time


        # choose maneuver
        if self.maneuver is None and self.time > self.reset_time + 0.01 and self.ticks > 5:

            if self.RENDERING:
                self.draw.clear()

            self.info.predict_ball(self.PREDICTION_RATE * self.PREDITION_DURATION, 1 / self.PREDICTION_RATE)

            self.maneuver = self.strategy.choose_maneuver()
            
            name = str(type(self.maneuver).__name__)

            self.last_ball_vel = norm(self.info.ball.vel)

        
        # execute maneuver
        if self.maneuver is not None:
            self.maneuver.step(dt)

            # I have to convert from RLU Input to SimpleControllerState, because Input doesnt have 'use_item'
            self.controls.steer = self.maneuver.controls.steer
            self.controls.throttle = self.maneuver.controls.throttle
            self.controls.jump = self.maneuver.controls.jump
            self.controls.pitch = self.maneuver.controls.pitch
            self.controls.yaw = self.maneuver.controls.yaw
            self.controls.roll = self.maneuver.controls.roll
            self.controls.handbrake = self.maneuver.controls.handbrake
            self.controls.boost = self.maneuver.controls.boost

            if self.RENDERING:
                self.maneuver.render(self.draw)

            if self.maneuver.finished:
                self.maneuver = None


        if self.RENDERING:
            self.draw.execute()

        self.maybe_chat(packet)
        self.chat.step(packet)

        return self.controls
Exemple #13
0
    def maybe_chat(self, packet: GameTickPacket):
        chat = self.chat

        for team in packet.teams:
            if team.team_index == self.team:
                our_score = team.score
            else:
                their_score = team.score

        # last second goal
        if their_score > self.num_of_their_goals_reacted_to or our_score > self.num_of_our_goals_reacted_to:
            if abs(their_score - our_score) < 2 and packet.game_info.game_time_remaining < 5:
                for _ in range(6):
                    self.chat.send_random([
                        chat.Reactions_OMG,
                        chat.PostGame_Gg,
                        chat.Reactions_HolyCow,
                        chat.Reactions_NoWay,
                        chat.Reactions_Wow,
                        chat.Reactions_OMG
                    ])

        # they scored
        if their_score > self.num_of_their_goals_reacted_to:
            self.num_of_their_goals_reacted_to = their_score
            for _ in range(2):
                if self.last_ball_vel > 2000:
                    self.chat.send_random([
                        chat.Compliments_NiceShot,
                        chat.Compliments_NiceOne,
                        chat.Reactions_Wow,
                        chat.Reactions_OMG,
                        chat.Reactions_Noooo
                    ])
                else:
                    self.chat.send_random([
                        chat.Reactions_Whew,
                        chat.Apologies_Whoops,
                        chat.Apologies_Oops,
                        chat.Apologies_Cursing
                    ])

        # we scored
        if our_score > self.num_of_our_goals_reacted_to:
            self.num_of_our_goals_reacted_to = our_score

            if self.last_ball_vel > 3000:
                self.chat.send(chat.Reactions_Siiiick)

            if self.last_ball_vel < 300:
                self.chat.send(chat.Compliments_WhatASave)

        # game is over
        if packet.game_info.is_match_ended and not self.said_gg:
            self.said_gg = True

            self.chat.send(chat.PostGame_Gg)
            self.chat.send(chat.PostGame_WellPlayed)

            if our_score < their_score:
                self.chat.send(chat.PostGame_OneMoreGame)

        # all yours :D
        if self.time > self.last_time_said_all_yours + 40:
            if isinstance(self.maneuver, ShadowDefense) and distance(self.info.my_car, self.info.ball) > 6000:
                self.last_time_said_all_yours = self.time
                self.chat.send(chat.Information_AllYours)
Exemple #14
0
    def step(self, dt):
        target = self.target_pos

        # don't try driving outside the arena
        target = Arena.clamp(target, 100)

        # smoothly escape goal
        if abs(self.car.position[1]) > Arena.size[1] - 50:
            target = Arena.clamp(target, 200)
            target[0] = abs_clamp(target[0], 700)

        if not self.drive_on_walls:
            if self.car.position[2] > 100:
                target = ground(self.car)

        local_target = local(self.car, target)

        if self.backwards:
            local_target[0] *= -1
            local_target[1] *= -1

        # steering
        phi = math.atan2(local_target[1], local_target[0])
        self.controls.steer = clamp11(2.5 * phi)

        # powersliding
        if abs(phi) > 1.5 and self.car.position[2] < 200 and ground_distance(
                self.car, target) < 2500:
            self.controls.handbrake = 1
        else:
            self.controls.handbrake = 0

        # forward velocity
        vf = dot(self.car.velocity, self.car.forward())
        if self.backwards:
            vf *= -1

        # speed controller
        if vf < self.target_speed:
            self.controls.throttle = 1.0
            if self.target_speed > 1400 and vf < 2250 and self.target_speed - vf > 50:
                self.controls.boost = 1
            else:
                self.controls.boost = 0
        else:
            if (vf - self.target_speed) > 400:  # 75
                self.controls.throttle = -1.0
            else:
                if self.car.up()[2] > 0.85:
                    self.controls.throttle = 0.0
                else:
                    self.controls.throttle = 0.01
            self.controls.boost = 0

        # backwards driving
        if self.backwards:
            self.controls.throttle *= -1
            self.controls.steer *= -1
            self.controls.boost = 0
            self.controls.handbrake = 0

        # don't boost if not facing target
        if abs(phi) > 0.3 and vf > 600:
            self.controls.boost = 0

        # finish when close
        if distance(self.car, self.target_pos) < 100:
            self.finished = True
Exemple #15
0
    def get_output(self, packet: GameTickPacket):
        self.time = packet.game_info.seconds_elapsed
        dt = self.time - self.prev_time
        if packet.game_info.is_kickoff_pause and not isinstance(
                self.maneuver, Kickoff):
            self.maneuver = None

        self.prev_time = self.time
        self.ticks += 1
        self.info.read_packet(packet, self.get_field_info())
        self.strategy.packet = packet
        if self.ticks < 10:
            return Input()

        #reset maneuver when another car hits the ball
        touch = packet.game_ball.latest_touch
        if ((touch.time_seconds > self.last_touch_time
             and touch.player_name != packet.game_cars[self.index].name) or
            (touch.player_name == '' and  # if latest touch info is missing
             any([
                 distance(self.info.ball, car) < 300
                 for car in self.info.opponents + self.info.teammates
             ]))):
            self.last_touch_time = touch.time_seconds
            if (self.info.my_car.on_ground and not self.controls.jump
                    and (not isinstance(self.maneuver, ShadowDefense)
                         or self.maneuver.travel.driving)):
                self.maneuver = None
                #self.reset_time = self.time

        if self.handle_training_matchcomms():
            self.info.predict_ball(
                self.PREDICTION_RATE * self.PREDITION_DURATION,
                1 / self.PREDICTION_RATE)
            self.maneuver = get_maneuver_by_name(self.matchcomms_message,
                                                 self.info)
            print("Training: Setting " + self.matchcomms_message)

        # choose maneuver
        if self.maneuver is None:

            if self.RENDERING:
                self.draw.clear()

            self.info.predict_ball(
                self.PREDICTION_RATE * self.PREDITION_DURATION,
                1 / self.PREDICTION_RATE)

            self.maneuver = self.strategy.choose_maneuver()

            name = str(type(self.maneuver).__name__)
            print(name)

            self.last_ball_vel = norm(self.info.ball.velocity)

        # execute maneuver
        if self.maneuver is not None:
            self.maneuver.step(dt)
            self.controls = self.maneuver.controls

            if self.RENDERING:
                self.draw.group("maneuver")
                self.maneuver.render(self.draw)

            if self.maneuver.finished:
                self.maneuver = None

        for pad in self.info.large_boost_pads:
            self.draw.string(pad.position, str(pad.is_full_boost))

        if self.RENDERING:
            self.draw.execute()

        self.maybe_chat(packet)
        self.chat.step(packet)

        return self.controls
Exemple #16
0
    def choose_maneuver(self, car: Car):
        info = self.info
        offense = self.offense
        ball = info.ball

        teammates = info.get_teammates(car)
        opponents = info.get_opponents(car)

        their_goal = ground(info.their_goal.center)
        my_goal = ground(info.my_goal.center)

        my_hit = Intercept(car, info.ball_predictions)
        their_best_hit = self.best_intercept(opponents)
        opponent = their_best_hit.car

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

        # kickoff
        should_go = all(
            distance(mate, ball) > distance(car, ball) for mate in teammates)
        if should_go and ball.position[0] == 0 and ball.position[1] == 0:
            return KickoffStrategy.choose_kickoff(info, car)

        # don't save our own shots
        if info.about_to_score:
            if info.time_of_goal < their_best_hit.time - 2:
                return Stop(car)

        # save
        if info.about_to_be_scored_on:

            if align(car.position, my_hit.ball, their_goal) > 0.0:

                return offense.direct_shot(car, their_goal)

            return ClearIntoCorner(car, info)

        # fallback
        if align(car.position, my_hit.ball, my_goal) > 0.2:
            if (ground_distance(my_hit, my_goal) < 4000
                    and abs(car.position[1]) < abs(my_hit.position[1])):
                return ClearIntoCorner(car, info)
            return ShadowDefense(car, info, my_hit.ground_pos, 6000)

        # clear
        if (ground_distance(my_hit, my_goal) < 3500
                and abs(my_hit.position[0]) < 3000
                and ground_distance(car, my_goal) < 2500):
            if align(car.position, my_hit.ball, their_goal) > 0:
                return offense.direct_shot(car, their_goal)
            return ClearIntoCorner(car, info)

        if distance(their_best_hit, their_goal) < distance(
                their_best_hit, my_goal):
            opponents_align = -align(opponent.position, their_best_hit.ball,
                                     their_goal)
        else:
            opponents_align = align(opponent.position, their_best_hit.ball,
                                    my_goal)

        # 1v1
        if not teammates:

            # I can get to ball faster than them
            if my_hit.time < their_best_hit.time - 0.8:
                strike = offense.any_shot(car, their_goal, my_hit)

                if not isinstance(strike, Strike):
                    return strike

                if strike.intercept.time < their_best_hit.time - 0.8 \
                and (not info.about_to_score or strike.intercept.time < info.time_of_goal - 1):

                    if strike.intercept.time - car.time > 4 and car.boost < 30 \
                    and distance(strike.intercept.ground_pos, their_goal) > 3000 and distance(their_best_hit.ground_pos, my_goal) > 5000:

                        return Refuel(car, info, my_hit.ground_pos)

                    if abs(strike.intercept.ground_pos[0]
                           ) > Arena.size[0] - 800 and car.boost < 30:

                        return Refuel(car, info, my_hit.ground_pos)

                    if abs(strike.intercept.ball.position[1] -
                           their_goal[1]) > 300 or ground_distance(
                               strike.intercept, their_goal) < 900:
                        return strike

            # they are out of position
            if (opponents_align < -0.1 and
                    my_hit.time < their_best_hit.time - opponents_align * 1.5):

                strike = offense.any_shot(car, their_goal, my_hit)

                if not isinstance(strike, Strike) or strike.intercept.is_viable \
                and (not info.about_to_score or strike.intercept.time < info.time_of_goal - 0.5):

                    if (car.boost < 40 and
                        (distance(my_hit, their_goal) > 5000
                         or abs(my_hit.position[0]) > Arena.size[0] - 1500)
                            and distance(opponent, their_best_hit) > 3000):
                        return Refuel(car, info, my_hit.ground_pos)

                    if not isinstance(strike, Strike) or abs(
                            strike.intercept.ball.position[1] -
                            their_goal[1]) > 300 or ground_distance(
                                strike.intercept, their_goal) < 900:
                        return strike

            if distance(their_best_hit.ball, my_goal) > 7000 and \
                (distance(their_best_hit, opponent) > 3000 or align(opponent.position, their_best_hit.ball, my_goal) < 0) and car.boost < 30:
                return Refuel(car, info, my_hit.ground_pos)

            if car.boost < 35 and distance(their_best_hit, opponent) > 3000:
                refuel = Refuel(car, info, my_hit.ground_pos)
                if estimate_time(car, refuel.pad.position, 1400) < 1.5:
                    return refuel

            if opponents_align < 0:
                return offense.any_shot(car, their_goal, my_hit)

        # teamplay
        else:
            if car.boost < 40:
                return Refuel(car, info, my_goal)
            else:
                return offense.any_shot(car, their_goal, my_hit)

        shadow_distance = 4000 + opponents_align * 1500
        shadow_distance = max(shadow_distance, 3000)
        return ShadowDefense(car, info, their_best_hit.ground_pos,
                             shadow_distance)