def choose_maneuver(info: GameInfo, my_car: Car): ball = info.ball teammates = info.get_teammates(my_car) my_team = [my_car] + teammates their_goal = ground(info.their_goal.center) my_goal = ground(info.my_goal.center) # recovery if not my_car.on_ground: return Recovery(my_car) # kickoff if ball.position[0] == 0 and ball.position[1] == 0: # if I'm nearest to the ball, go for kickoff if min(my_team, key=lambda car: distance(car, ball)) is my_car: return kickoffs.choose_kickoff(info, my_car) if my_car.boost < 20: return Refuel(my_car, info) info.predict_ball() my_intercept = Intercept(my_car, info.ball_predictions) teammates_intercepts = [ Intercept(mate, info.ball_predictions) for mate in teammates ] our_intercepts = teammates_intercepts + [my_intercept] good_intercepts = [ i for i in our_intercepts if align(i.car.position, i.ball, their_goal) > 0.0 ] if good_intercepts: best_intercept = min(good_intercepts, key=lambda intercept: intercept.time) else: best_intercept = min(our_intercepts, key=lambda i: distance(i.car, my_goal)) if best_intercept is my_intercept: # if not completely out of position, go for a shot if (align(my_intercept.car.position, my_intercept.ball, their_goal) > 0 or ground_distance(my_intercept, my_goal) > 6000): return offense.any_shot(info, my_intercept.car, their_goal, my_intercept) # otherwise try to clear else: return defense.any_clear(info, my_intercept.car) # if I'm nearest to goal, stay far back if min(my_team, key=lambda car: distance(car, my_goal)) is my_car: return GeneralDefense(my_car, info, my_intercept.position, 7000) # otherwise get into position return GeneralDefense(my_car, info, my_intercept.position, 4000)
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)
def set_maneuvers(self, drones: List[Drone]): info = self.info their_goal = ground(info.their_goal.center) our_goal = ground(info.my_goal.center) if self.drone_going_for_ball is not None and self.drone_going_for_ball.maneuver is None: self.drone_going_for_ball = None if self.defending_drone is not None and self.defending_drone.maneuver is None: self.defending_drone = None # recovery for drone in drones: if drone.maneuver is None and not drone.car.on_ground: drone.maneuver = Recovery(drone.car) # decide which drone is gonna commit if self.drone_going_for_ball is None: ready_drones = [ drone for drone in drones if not drone.car.demolished and ( drone.maneuver is None or drone.maneuver.interruptible()) and drone.car.position[2] < 300 ] if not ready_drones: return info.predict_ball() our_intercepts = [ Intercept(drone.car, info.ball_predictions) for drone in ready_drones ] good_intercepts = [ i for i in our_intercepts if align(i.car.position, i.ball, their_goal) > 0.3 and ground_distance(i.car, i) > 2000 ] if good_intercepts: best_intercept = min(good_intercepts, key=lambda intercept: intercept.time) else: best_intercept = min( our_intercepts, key=lambda i: ground_distance(i.car, our_goal)) # find out which drone does the intercept belong to self.drone_going_for_ball = next( drone for drone in ready_drones if drone.car == best_intercept.car) # if not completely out of position, go for a shot if (align(best_intercept.car.position, best_intercept.ball, their_goal) > 0 or ground_distance(best_intercept, our_goal) > 6000): strike = offense.any_shot(info, best_intercept.car, their_goal, best_intercept) else: # otherwise try to clear strike = defense.any_clear(info, best_intercept.car) self.drone_going_for_ball.maneuver = strike if self.drone_going_for_ball is self.defending_drone: self.defending_drone = None # clear expired boost reservations for drone in drones: if not isinstance( drone.maneuver, PickupBoostPad) and drone in self.boost_reservations: del self.boost_reservations[drone] # drones that need boost go for boost for drone in drones: if drone.maneuver is None: if drone.car.boost < 30: self.send_drone_for_boost(drone) # pick one drone that will stay far back unemployed_drones = [ drone for drone in drones if drone.maneuver is None ] if unemployed_drones and self.defending_drone is None: self.defending_drone = min( unemployed_drones, key=lambda d: ground_distance(d.car, info.my_goal.center)) self.defending_drone.maneuver = GeneralDefense( self.defending_drone.car, info, info.ball.position, 7000) unemployed_drones.remove(self.defending_drone) for drone in unemployed_drones: drone.maneuver = GeneralDefense(drone.car, info, info.ball.position, 4000)