def __init__(self, name, team, index): super().__init__(name, team, index) self.boost_pad_tracker = BoostPadTracker() self.previous_Goals = 0 self.previous_my_Goals = 0 self.previous_enemy_Goals = 0 self.DDPG = None
def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.airborne = False self.kickoff_active = True self.kickoff_position = None
def __init__(self, name, team, index): super().__init__(name, team, index) self.action: Action = kickoff self.info : GameInfo = None self.car : Car = None self.boost_pad_tracker = BoostPadTracker() self.stat : Strategy = None self.action : Action = None
def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.last_state = None self.agent = None self.env = None self.ac = None self.internals = None
def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.controller_state = SimpleControllerState() self.me = Car() self.ball = Ball() self.kickoff_flag = False self.state = st.State() self.state_message = "State"
def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.controls = SimpleControllerState() self.bot_car = None self.ball = None self.allies=[] self.foes=[] self.ball_prediction = None self.posts=((Vec3(893,-5120,0),Vec3(-893,-5120,0)),(Vec3(893,5120,0),Vec3(-893,5120,0))) self.back_corners=((Vec3(3672,-4096,0),Vec3(-3672,-4096,0)),(Vec3(3672,4096,0),Vec3(-3672,4096,0))) self.collision_posts=((Vec3(843,-5070,0),Vec3(-843,-5070,0)),(Vec3(843,5070,0),Vec3(-843,5070,0))) self.goal_corners=((Vec3(-893,-6000,0),Vec3(893,-5120,642.775)),(Vec3(-893,5120,0),Vec3(893,6000,642.775))) self.boxes=((Vec3(-1600,-6000,0),Vec3(1600,-4120,2044)),(Vec3(-1600,4120,0),Vec3(1600,6000,2044))) self.defending = False self.rotating = False self.supporting = 0 self.clearing = False self.shooting = False self.air_recovery = False self.current_strike = None
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.travel_distance = 0 self.pos = Vec3(0, 0, 0) def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) def get_output(self, packet: GameTickPacket) -> SimpleControllerState: self.boost_pad_tracker.update_boost_status(packet) if self.active_sequence is not None and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls def predict_ball(t): ball_in_future = find_slice_at_time( ball_prediction, packet.game_info.seconds_elapsed + t) if ball_in_future is not None: return ball_in_future else: return packet.game_ball def intersect_time(speed): best_spd = math.inf for i in range(1, 301): time_location = Vec3(predict_ball(i / 60).physics.location) if (time_location - car_location).length() * 60 / i <= speed: return i / 60 return 5 my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) ball_location = Vec3(packet.game_ball.physics.location) ball_location_gs = Vector3(packet.game_ball.physics.location) ball_velocity = Vec3(packet.game_ball.physics.velocity) ball_prediction = self.get_ball_prediction_struct() target_location = ball_location send_location = Vec3(0, 10240 * (0.5 - self.team), 300) if car_location.z == 0: self.pos = car_location self.renderer.draw_line_3d(self.pos, (target_location - self.pos) / (target_location - self.pos).length() * self.travel_distance, self.renderer.white()) self.renderer.draw_string_3d(self.pos, 1, 1, f'Speed: {car_velocity.length():.1f}', self.renderer.white()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) controls = SimpleControllerState() controls.steer = steer_toward_target(my_car, target_location) controls.throttle = 0 if packet.game_info.is_round_active == True: self.travel_distance += 2300 / 60 else: self.travel_distance = 0 if (self.pos - ball_location).length( ) <= self.travel_distance and ball_location.y / send_location.y <= 1: ball_velout = -ball_velocity v = -(ball_location - send_location) / ( ball_location - send_location).length() * 2300 tp = (ball_velout + v) / (ball_velout + v).length() * 2300 p = ball_location - tp / tp.length() * 100 self.travel_distance = 0 # Intentional weakness if random.random() <= 0.125: side = random.choice([1, -1]) p = ball_location + Vec3(-v.x * side, 0, v.z * side) / 2300 * 150 self.travel_distance = -11500 car_state = CarState( physics=Physics(location=Vector3(p.x, p.y, p.z), velocity=Vector3(v.x, v.y, v.z))) gs = GameState(cars={self.index: car_state}) self.set_game_state(gs) self.pos = Vec3(packet.game_cars[self.index].physics.location) elif packet.game_info.is_round_active == True and self.travel_distance >= 0: p = self.pos + (ball_location - self.pos) / ( ball_location - self.pos).length() * (self.travel_distance - 200) car_state = CarState(physics=Physics( location=Vector3(p.x, p.y, p.z), velocity=Vector3(0, 0, 0))) gs = GameState(cars={self.index: car_state}) self.set_game_state(gs) else: self.pos = Vec3(packet.game_cars[self.index].physics.location) if packet.game_info.is_round_active == False: self.send_quick_chat( team_only=False, quick_chat=QuickChatSelection.Compliments_WhatASave) return controls
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.bot_state = 0 def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """ This function will be called by the framework many times per second. This is where you can see the motion of the ball, etc. and return controls to drive your car. """ # Keep our boost pad info updated with which pads are currently active self.boost_pad_tracker.update_boost_status(packet) # This is good to keep at the beginning of get_output. It will allow you to continue # any sequences that you may have started during a previous call to get_output. if self.active_sequence is not None and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls # Gather some information about our car and the ball my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) ball_location = Vec3(packet.game_ball.physics.location) ball_velocity = Vec3(packet.game_ball.physics.velocity) # By default we will chase the ball, but target_location can be changed later target_location = ball_location ball_on_floor = target_location ball_prediction = self.get_ball_prediction_struct() # This can predict bounces, etc # dynamic time to the ball depending on the car's speed time_in_future = self.time_to_ball(car_location, car_velocity.length(), ball_location) seconds_in_future = packet.game_info.seconds_elapsed + time_in_future ball_in_future = find_slice_at_time(ball_prediction, seconds_in_future) ball_on_floor = find_matching_slice(ball_prediction, 0, lambda s: s.physics.location.z < 150 and s.game_seconds >= packet.game_info.seconds_elapsed + time_in_future, search_increment=1) time_to_floor = 0 # ball_in_future might be None if we don't have an adequate ball prediction right now, like during # replays, so check it to avoid errors. if ball_in_future is not None: target_location = Vec3(ball_in_future.physics.location) time_in_future = self.time_to_ball(car_location, car_velocity.length(), target_location) self.renderer.draw_line_3d(ball_location, target_location, self.renderer.cyan()) # gets the next time when the ball is on the floor if ball_on_floor is not None: floor_location = Vec3(ball_on_floor.physics.location) time_to_floor = ball_on_floor.game_seconds - packet.game_info.seconds_elapsed self.renderer.draw_line_3d(ball_location, floor_location, self.renderer.orange()) self.renderer.draw_rect_3d(floor_location, 8, 8, True, self.renderer.orange(), centered=True) # Draw some things to help understand what the bot is thinking self.renderer.draw_line_3d(car_location, target_location, self.renderer.white()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) orientation = Orientation(my_car.physics.rotation) relative = relative_location(car_location, orientation, ball_location) controls = SimpleControllerState() self.renderer.draw_string_2d(10, 10 + self.team * 100, 5, 5, f"{controls.throttle}", self.renderer.team_color()) # makes the car rotate to be more straight if not my_car.has_wheel_contact: # roll to land on all four wheels if orientation.roll < -0.1: controls.roll = 1 elif orientation.roll > 0.1: controls.roll = -1 # pitch to land on all four wheels if orientation.pitch < -0.1: controls.pitch = 1 elif orientation.pitch > 0.1: controls.pitch = -1 deg = math.degrees(car_location.ang_to(ball_location)) # yaw to correct angle towards ball if deg < 85: controls.yaw = 1 elif deg > 95: controls.yaw = -1 # jump if another car is close to not get stuck if self.location_to_nearest_car(car_location, my_car.team, packet).dist(car_location) < 200 and car_velocity.length() < 50: controls.jump = True self.set_kickoff_state(car_velocity, ball_location, ball_velocity) self.decide_state(controls, packet, my_car, car_location, car_velocity, ball_location, ball_velocity, target_location, ball_prediction, orientation, relative, time_in_future, time_to_floor) return controls def decide_state(self, controls, packet, my_car, car_location, car_velocity, ball_location, ball_velocity, target_location, ball_prediction, orientation, relative, time_to_target, time_to_floor): if self.bot_state == 0: self.ball_chase(controls, packet, my_car, car_velocity, car_location, target_location, ball_location, relative, time_to_target, time_to_floor, orientation) elif self.bot_state == 1: self.retreat_to_goal(controls, packet, my_car, car_location, car_velocity) elif self.bot_state == 2: self.go_towards_own_goal(controls, my_car, car_location, ball_location) elif self.bot_state == 3: self.kickoff() def set_kickoff_state(self, car_velocity, ball_location, ball_velocity): if car_velocity.length() == 0 and ball_location.x == 0 and ball_location.y == 0 and ball_velocity.length() == 0: self.bot_state = 3 def kickoff(self): self.bot_state = 0 def ball_chase(self, controls, packet, my_car, car_velocity, car_location, target_location, ball_location, relative, time_to_target, time_to_floor, orientation): """ Makes the bot chase the ball unless some conditions are valid """ # retreat to own goal if the ball is a lot closer to our goal than we are info = self.get_field_info() own_goal_vec = info.goals[self.team].location own_goal_location = Vec3(own_goal_vec) if ball_location.dist(own_goal_location) + 1000 < car_location.dist(own_goal_location) and car_location.dist(own_goal_location) > 4000: self.bot_state = 1 elif own_goal_vec.y > 5000 and car_location.y + 100 < target_location.y: # BLUE self.bot_state = 2 elif own_goal_vec.y < -5000 and car_location.y > target_location.y + 100: # ORANGE self.bot_state = 2 self.renderer.draw_string_3d(car_location, 1, 1, "\nBall chasing", self.renderer.red()) # makes the bots shoot towards the goal target_location = self.ball_towards_goal_location(target_location, own_goal_location, car_location, ball_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(car_location, target_location, self.renderer.red()) controls.steer = steer_toward_target(my_car, target_location) controls.throttle = 1.0 # You can set more controls if you want, like controls.boost. # angle to ball car_to_ball = Vec3(ball_location.x - car_location.x, ball_location.y - car_location.y, ball_location.z - car_location.z) angle = math.degrees(orientation.forward.ang_to(car_to_ball)) # boost if angle < 20 and not my_car.is_super_sonic: controls.boost = True # try to turn around quickly if angle > 160 and relative.x < -2000: self.begin_half_flip(packet) elif angle > 40: controls.handbrake = True elif 1000 < car_velocity.length() and angle < 90 and car_to_ball.length() < 400 and relative.z < 200: # We'll do a front flip if the car is moving at a certain speed. return self.begin_front_flip(packet, angle, orientation.right.length()) def drive_to_ball_bounce(self, my_car, car_location, floor_location): """ Slowly drives to where the ball will bounce """ pass def retreat_to_goal(self, controls, packet, my_car, car_location, car_velocity): """ Makes the bot retreat back to the goal and only change back to another state when it's close to the goal """ self.renderer.draw_string_3d(car_location, 1, 1, "\nRetreating to goal", self.renderer.red()) info = self.get_field_info() own_goal_vec = info.goals[self.team].location own_goal_location = Vec3(own_goal_vec) controls.steer = steer_toward_target(my_car, own_goal_location) controls.throttle = 1.0 if not my_car.is_super_sonic and car_velocity.length() > 200 and car_location.dist(own_goal_location) > 4500: controls.boost = True # change back to ball chasing if distance to goal is small self.renderer.draw_string_3d(car_location, 1, 1, f"\n\nDist to goal {car_location.dist(own_goal_location)}", self.renderer.white()) if car_location.dist(own_goal_location) < 4000: self.bot_state = 0 def go_towards_own_goal(self, controls, my_car, car_location, ball_location): """ Goes towards own goal and changes back to ball chasing when a bit away from the ball """ self.renderer.draw_string_3d(car_location, 1, 1, "\nGoing towards own goal", self.renderer.red()) info = self.get_field_info() own_goal_vec = info.goals[self.team].location own_goal_location = Vec3(own_goal_vec) controls.steer = steer_toward_target(my_car, own_goal_location) controls.throttle = 1.0 # goes back to ball chase state if far enough away from the ball if car_location.dist(ball_location) > 1000 or car_location.dist(own_goal_location) < 4000: self.bot_state = 0 def jump_shot(self, controls, car_location, ball_location): pass def ball_towards_goal_location(self, target_location, goal_location, car_location, ball_location): """ Modifies the target location so that the ball is hit a bit more towards the enemy goal """ enemy_goal_location = Vec3(0, -goal_location.y, goal_location.z) if target_location.x - enemy_goal_location.x == 0: target_location.x = 1 if goal_location.y < 0: # usually for blue side target_location.x = -1 slope = (target_location.y - enemy_goal_location.y) / (target_location.x - enemy_goal_location.x) dist = car_location.dist(target_location) if dist > 3000: correction = 1000 elif 500 < dist <= 3000: correction = 0.36 * dist - 80 else: correction = 100 x_value = 1 if target_location.x < 0: x_value = -1 new_target_location = Vec3(1, slope, 0).normalized() return target_location + x_value * correction * new_target_location def location_to_nearest_car(self, car_location, team, packet, enemy=False): """ Gets the closest enemy car to a target location """ # If enemy is true, only view nearest enemy cars nearest_distance = 999999 nearest_car = None for car in packet.game_cars: if car.team == team: continue other_car = Vec3(car.physics.location) distance_to = car_location.dist(other_car) if distance_to < nearest_distance: nearest_distance = distance_to nearest_car = other_car return nearest_car def time_to_ball(self, car_location, car_speed, ball_location): # estimates a time it takes for the bot to reach the ball for it to better predict where to go to hit the ball distance = car_location.dist(ball_location) return distance/(car_speed+100) def begin_half_flip(self, packet): self.active_sequence = Sequence([ ControlStep(duration=1.0, controls=SimpleControllerState(throttle=-1, boost=False)), ControlStep(duration=0.1, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, pitch=1)), ControlStep(duration=0.15, controls=SimpleControllerState(pitch=-1, boost=False)), ControlStep(duration=0.5, controls=SimpleControllerState(pitch=-1, boost=True, roll=1, throttle=1)), ControlStep(duration=0.5, controls=SimpleControllerState()), ]) return self.active_sequence.tick(packet) def begin_front_flip(self, packet, angle=0.0, right=1): # Do a flip. We will be committed to this for a few seconds and the bot will ignore other # logic during that time because we are setting the active_sequence. mult = 1 if right < 0: mult = -1 rad = math.radians(0) # set to 0 for now self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.1, controls=SimpleControllerState(jump=True, pitch=-math.cos(rad), yaw=mult * math.sin(rad))), ControlStep(duration=0.8, controls=SimpleControllerState()), ]) # Return the controls associated with the beginning of the sequence so we can start right away. return self.active_sequence.tick(packet)
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.action: Action = kickoff self.info : GameInfo = None self.car : Car = None self.boost_pad_tracker = BoostPadTracker() self.stat : Strategy = None self.action : Action = None def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) self.info = MyInfo(self.team, self.index) self.strat = Strategy(self.info) self.car = Car() def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """ This function will be called by the framework many times per second. This is where you can see the motion of the ball, etc. and return controls to drive your car. """ # Keep our boost pad info updated with which pads are currently active self.boost_pad_tracker.update_boost_status(packet) #self.info = self.info.read_packet(packet) self.car.updateCar(packet, self.index) self.info.read_packet(packet, self.get_ball_prediction_struct().slices) #print("in main target: {}".format(self.get_ball_prediction_struct().slices[0].physics.location)) #self.renderer.draw_line_3d(self.car.loc, target_location, self.renderer.white()) #self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) #cg = ChallengeGame(self.car, bp_struct) #print(cg.get_time_to_loc(cg.challenge_loc)) # This is good to keep at the beginning of get_output. It will allow you to continue # any sequences that you may have started during a previous call to get_output. if self.action is None: self.action = self.strat.chooseAction(self.info) controls = self.action.tick(self.info) print(controls.steer) return controls self.renderer.draw_string_3d(self.car.loc, 1, 1, f'Speed: {self.car.vel.length():.1f}', self.renderer.white()) if self.action.name: self.renderer.draw_string_3d(self.car.loc + Vec3(0, 0, 20), 1, 1, self.action.name, self.renderer.white()) if packet.game_info.is_kickoff_pause and not isinstance(self.action, kickoff): #self.logger.info(self.action) self.action = kickoff(self.car.loc) #print("Sequence is: {}".format(self.action)) #print("Sequence finished: {}".format(self.action.done)) controls = self.action.tick(self.info) return controls if self.action and not self.action.done: controls = self.action.tick(self.info) #print("action is: {}".format(self.action.name)) if controls is not None: return controls elif self.action.done: print("choosing new action") self.action = self.strat.chooseAction(self.info) controls = self.action.tick(self.info) return controls # Gather some information about our car and the ball ball_location = Vec3(packet.game_ball.physics.location) if self.car.loc.dist(ball_location) > 1500: # We're far away from the ball, let's try to lead it a little bit ball_prediction = self.get_ball_prediction_struct() # This can predict bounces, etc ball_in_future = find_slice_at_time(ball_prediction, packet.game_info.seconds_elapsed + 2) target_location = Vec3(ball_in_future.physics.location) self.renderer.draw_line_3d(ball_location, target_location, self.renderer.cyan()) else: target_location = ball_location # Draw some things to help understand what the bot is thinking #self.renderer.draw_string_2d(100, 100, 1, 1, f'Ball at: {ball_location}', self.renderer.white()) ''' if 750 < self.car.vel.length() < 800: # We'll do a front flip if the car is moving at a certain speed. return self.begin_front_flip(packet) #controls = self.action.controls controls = SimpleControllerState() controls.steer = steer_toward_target(self.car, target_location) controls.throttle = 1.0 # You can set more controls if you want, like controls.boost. ''' print("the f**k we doin here?!?!?!?") return controls def begin_front_flip(self, packet): # Send some quickchat just for fun self.send_quick_chat(team_only=False, quick_chat=QuickChatSelection.Information_IGotIt) # Do a front flip. We will be committed to this for a few seconds and the bot will ignore other # logic during that time because we are setting the action. self.action = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, pitch=-1)), ControlStep(duration=0.8, controls=SimpleControllerState()), ]) # Return the controls associated with the beginning of the sequence so we can start right away. return self.action.tick(packet) def is_kickoff(self, ball_location, ball_velocity): #self.logger.info(ball_location.flat() == kickoff_location) #self.logger.info(ball_velocity.length() == 0) return ball_location.flat() == kickoff_location and ball_velocity.length() == 0
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.airborne = False self.kickoff_active = True self.kickoff_position = None def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """ This function will be called by the framework many times per second. This is where you can see the motion of the ball, etc. and return controls to drive your car. """ # Keep our boost pad info updated with which pads are currently active self.boost_pad_tracker.update_boost_status(packet) # This is good to keep at the beginning of get_output. It will allow you to continue # any sequences that you may have started during a previous call to get_output. if self.active_sequence and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls # Gather some information about our car and the ball my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) ball_location = Vec3(packet.game_ball.physics.location) if my_car.team == 1: # Orange Team self.my_goal_right_post = Vec3(850, 5100, 320) self.my_goal_center = Vec3(0, 5100, 320) self.my_goal_left_post = Vec3(-850, 5100, 320) self.enemy_goal_right_post = Vec3(850, -5100, 320) self.enemy_goal_center = Vec3(0.0, -5100, 320) self.enemy_goal_left_post = Vec3(-850, -5100, 320) else: # Blue Team self.my_goal_right_post = Vec3(-850, -5100, 320) self.my_goal_center = Vec3(0.0, -5100, 320) self.my_goal_left_post = Vec3(850, -5100, 320) self.enemy_goal_right_post = Vec3(-850, 5100, 320) self.enemy_goal_center = Vec3(0, 5100, 320) self.enemy_goal_left_post = Vec3(850, 5100, 320) controls = SimpleControllerState() # Draw some things to help understand what the bot is thinking # self.renderer.draw_line_3d(car_location, target_location, self.renderer.white()) # self.renderer.draw_string_3d(car_location, 1, 1, f'Speed: {car_velocity.length():.1f}', self.renderer.white()) # self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) # Important flags to check / set if my_car.has_wheel_contact == True: self.airborne = False else: # try to recover here if self.airborne == False: self.send_quick_chat( team_only=False, quick_chat=QuickChatSelection.Custom_Useful_Faking) self.airborne = True if self.ball_in_kickoff_position(ball_location, packet): self.kickoff_active = True else: self.kickoff_active = False self.kickoff_position = None if self.kickoff_active and self.kickoff_position is None: self.kickoff_position = self.get_kickoff_position(car_location) # Main state checking area if self.kickoff_active and self.kickoff_position is not None: self.do_kickoff(my_car, car_location, car_velocity, ball_location, controls, packet) else: self.ball_chase(controls, my_car, car_location, car_velocity, ball_location, packet) # Other things that have been written: # self.boost_steal(controls, car_location, my_car, ball_location) # self.half_flip_sequence(packet) # self.manage_speed(packet, controls, my_car, car_velocity) return controls def get_kickoff_position(self, car_location): if car_location.flat().dist(Vec3( 2048.00, -2560.00)) < 50 or car_location.flat().dist( Vec3(-2048.00, 2560.00)) < 50: return 1 elif car_location.flat().dist(Vec3( -2048.00, -2560.00)) < 50 or car_location.flat().dist( Vec3(2048.00, 2560.00)) < 50: return 2 elif car_location.flat().dist(Vec3( 256.00, -3840.00)) < 50 or car_location.flat().dist( Vec3(-256.00, 3840.00)) < 50: return 3 elif car_location.flat().dist(Vec3( -256.00, -3840.00)) < 50 or car_location.flat().dist( Vec3(256.00, 3840.00)) < 50: return 4 else: return 5 def ball_in_kickoff_position(self, ball_location, packet): if ball_location.x == 0 \ and ball_location.y == 0 \ and packet.game_ball.physics.velocity.x == 0 \ and packet.game_ball.physics.velocity.y == 0 \ and packet.game_ball.physics.velocity.z == 0: return True else: return False def do_kickoff(self, my_car, car_location, car_velocity, ball_location, controls, packet): self.send_quick_chat( team_only=False, quick_chat=QuickChatSelection.Information_Incoming) print(f"kickoff position {self.kickoff_position}") # if self.kickoff_position == 1: # self.left_speed_flip_kickoff(packet) # elif self.kickoff_position == 2: # self.right_speed_flip_kickoff(packet) # elif self.kickoff_position == 3: # self.left_diagonal_flip_kickoff(packet, ball_location) # else: self.send_quick_chat(team_only=False, quick_chat=QuickChatSelection.Reactions_HolyCow) self.front_flip_kickoff(my_car, car_location, car_velocity, ball_location, controls, packet) def ball_chase(self, controls, my_car, car_location, car_velocity, ball_location, packet): if car_location.dist(ball_location) > 1500: # We're far away from the ball, let's try to lead it a little bit ball_prediction = self.get_ball_prediction_struct( ) # This can predict bounces, etc ball_in_future = find_slice_at_time( ball_prediction, packet.game_info.seconds_elapsed + 2) target_location = Vec3(ball_in_future.physics.location) self.renderer.draw_line_3d(ball_location, target_location, self.renderer.cyan()) else: target_location = ball_location controls.steer = steer_toward_target(my_car, ball_location) controls.throttle = 1.0 self.manage_speed(packet, controls, my_car, car_velocity) def half_flip_sequence(self, packet): self.active_sequence = Sequence([ ControlStep(duration=0.3, controls=SimpleControllerState(throttle=-1)), ControlStep(duration=0.1, controls=SimpleControllerState(throttle=-1, jump=True, pitch=1)), ControlStep(duration=0.2, controls=SimpleControllerState(throttle=-1, jump=False, pitch=1)), ControlStep(duration=0.1, controls=SimpleControllerState(jump=True, pitch=1)), ControlStep(duration=0.1, controls=SimpleControllerState(throttle=1, boost=True, pitch=-1)), ControlStep(duration=0.5, controls=SimpleControllerState(throttle=1, boost=True, pitch=-1, roll=1)), ControlStep(duration=0.2, controls=SimpleControllerState(roll=0)), ControlStep(duration=0.5, controls=SimpleControllerState(throttle=1)), ]) return self.active_sequence.tick(packet) def left_speed_flip_kickoff(self, packet): print("left speed flip") self.active_sequence = Sequence([ ControlStep(duration=.4, controls=SimpleControllerState(throttle=1, boost=1)), ControlStep(duration=.1, controls=SimpleControllerState(throttle=1, boost=1, steer=.75)), ControlStep(duration=.05, controls=SimpleControllerState(jump=True, yaw=1, boost=1)), ControlStep(duration=.05, controls=SimpleControllerState(yaw=-1, pitch=-1, boost=1)), ControlStep(duration=.05, controls=SimpleControllerState(jump=True, yaw=-1, pitch=-1)), ControlStep(duration=.5, controls=SimpleControllerState(yaw=1, pitch=1, roll=-1)), ControlStep(duration=.25, controls=SimpleControllerState(roll=-1, boost=1, yaw=1)), ControlStep(duration=.5, controls=SimpleControllerState(throttle=1, boost=1, handbrake=True)), ControlStep(duration=.5, controls=SimpleControllerState(throttle=1, boost=1)), ControlStep(duration=3, controls=SimpleControllerState(throttle=1)), ]) return self.active_sequence.tick(packet) def right_speed_flip_kickoff(self, packet): print("right speed flip") self.active_sequence = Sequence([ ControlStep(duration=.4, controls=SimpleControllerState(throttle=1, boost=True)), ControlStep(duration=.2, controls=SimpleControllerState(throttle=1, boost=True, steer=.75)), ControlStep(duration=.05, controls=SimpleControllerState(jump=True, yaw=1, boost=True)), ControlStep(duration=.05, controls=SimpleControllerState(yaw=-1, pitch=-1, boost=True)), ControlStep(duration=.05, controls=SimpleControllerState(jump=True, yaw=-1, pitch=-1)), ControlStep(duration=.5, controls=SimpleControllerState(yaw=1, pitch=1, roll=-1)), ControlStep(duration=.25, controls=SimpleControllerState(roll=-1, boost=True, yaw=1)), ControlStep(duration=.25, controls=SimpleControllerState(throttle=1, boost=True, handbrake=True)), ControlStep(duration=3, controls=SimpleControllerState(throttle=1)), ]) return self.active_sequence.tick(packet) def left_diagonal_flip_kickoff(self, packet, ball_location): print("left diagonal kickoff") self.active_sequence = Sequence([ ControlStep(duration=.2, controls=SimpleControllerState(throttle=1, boost=True)), ControlStep(duration=.3, controls=SimpleControllerState(throttle=1, boost=1, steer=1)), ControlStep(duration=.15, controls=SimpleControllerState(throttle=1, boost=1, steer=-1)), ControlStep(duration=.05, controls=SimpleControllerState(jump=True, yaw=-1, boost=True)), ControlStep(duration=.05, controls=SimpleControllerState(yaw=-1, boost=True)), ControlStep(duration=.05, controls=SimpleControllerState(jump=True, yaw=-1, boost=True)), ]) return self.active_sequence.tick(packet) def front_flip_kickoff(self, my_car, car_location, car_velocity, ball_location, controls, packet): self.send_quick_chat( team_only=False, quick_chat=QuickChatSelection.Information_Incoming) controls.steer = steer_toward_target(my_car, ball_location) controls.throttle = 1.0 controls.boost = True distance_from_ball = car_location.dist(ball_location) # tweak these settings so the first and second flips go off at the right time if 750 < car_velocity.length() < 900: self.begin_front_flip(packet) if distance_from_ball <= 1000: self.begin_front_flip(packet) def boost_steal(self, controls, car_location, my_car, ball_location): active_boosts = [ boost for boost in self.boost_pad_tracker.get_full_boosts() if boost.is_active == True ] car_x = int(car_location.x) car_y = int(car_location.y) boost_distances = [] for boost in active_boosts: boost_x = int(boost.location.x) boost_y = int(boost.location.y) distance_from_boost = abs(boost_x - car_x) + abs(boost_y - car_y) boost_distances.append(distance_from_boost) if len(active_boosts) == 0: controls.steer = steer_toward_target(my_car, ball_location) controls.throttle = 1.0 else: boost_index = boost_distances.index(min(boost_distances)) boost_location = active_boosts[boost_index].location controls.steer = steer_toward_target(my_car, boost_location) controls.throttle = 1.0 def begin_front_flip(self, packet): # Send some quickchat just for fun self.send_quick_chat(team_only=False, quick_chat=QuickChatSelection.Information_IGotIt) # Do a front flip. We will be committed to this for a few seconds and the bot will ignore other # logic during that time because we are setting the active_sequence. self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, pitch=-1)), ControlStep(duration=0.8, controls=SimpleControllerState()), ]) # Return the controls associated with the beginning of the sequence so we can start right away. return self.active_sequence.tick(packet) def manage_speed(self, packet, controls, my_car, car_velocity): if 750 < car_velocity.length() < 800: # We'll do a front flip if the car is moving at a certain speed. # Note: maybe do a diagonal / sideflip again? We should also only conditionally flip # since getting caught mid flip is bad, this would also be cool as a wavedash return self.begin_front_flip(packet) if my_car.is_super_sonic == False: controls.boost = True if my_car.boost == 100: controls.boost = True
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """ This function will be called by the framework many times per second. This is where you can see the motion of the ball, etc. and return controls to drive your car. """ # Keep our boost pad info updated with which pads are currently active self.boost_pad_tracker.update_boost_status(packet) # This is good to keep at the beginning of get_output. It will allow you to continue # any sequences that you may have started during a previous call to get_output. if self.active_sequence is not None and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls # Gather some information about our car and the ball my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) ball_location = Vec3(packet.game_ball.physics.location) # By default we will chase the ball, but target_location can be changed later target_location = ball_location if car_location.dist(ball_location) > 1500: # We're far away from the ball, let's try to lead it a little bit ball_prediction = self.get_ball_prediction_struct() # This can predict bounces, etc ball_in_future = find_slice_at_time(ball_prediction, packet.game_info.seconds_elapsed + 2) # ball_in_future might be None if we don't have an adequate ball prediction right now, like during # replays, so check it to avoid errors. if ball_in_future is not None: target_location = Vec3(ball_in_future.physics.location) self.renderer.draw_line_3d(ball_location, target_location, self.renderer.cyan()) # Draw some things to help understand what the bot is thinking self.renderer.draw_line_3d(car_location, target_location, self.renderer.white()) self.renderer.draw_string_3d(car_location, 1, 1, f'Speed: {car_velocity.length():.1f}', self.renderer.white()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) if 750 < car_velocity.length() < 800: # We'll do a front flip if the car is moving at a certain speed. return self.begin_front_flip(packet) controls = SimpleControllerState() controls.steer = steer_toward_target(my_car, target_location) controls.throttle = 1.0 # You can set more controls if you want, like controls.boost. return controls def begin_front_flip(self, packet): # Send some quickchat just for fun self.send_quick_chat(team_only=False, quick_chat=QuickChatSelection.Information_IGotIt) # Do a front flip. We will be committed to this for a few seconds and the bot will ignore other # logic during that time because we are setting the active_sequence. self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, pitch=-1)), ControlStep(duration=0.8, controls=SimpleControllerState()), ]) # Return the controls associated with the beginning of the sequence so we can start right away. return self.active_sequence.tick(packet)
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.last_state = None self.agent = None self.env = None self.ac = None self.internals = None def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) if MODEL is not None: max_time = 10 frames_per_sec = 20 max_timesteps = RLEnvironment.get_max_timesteps(max_time, frames_per_sec) self.env = Environment.create( environment=KickoffEnvironment, max_episode_timesteps=max_timesteps, max_time=max_time, message_throttle=20, frames_per_sec=frames_per_sec, input_exclude=[ InputOptions.BALL_POSITION_REL, InputOptions.BALL_DIRECTION, InputOptions.CAR_POSITION_REL, InputOptions.CAR_VELOCITY_MAG, ], output_exclude=[ OutputOptions.BOOST, OutputOptions.STEER, OutputOptions.E_BRAKE, OutputOptions.THROTTLE, OutputOptions.ROLL, ] ) directory='../learning/training/{0}'.format(MODEL) filename='agent' agent = os.path.join(directory, os.path.splitext(filename)[0] + '.json') if not os.path.isfile(agent): logging_utils.log_warn(os.getcwd(), {}) raise Exception('Model file doesn\'t exist') self.agent = Agent.load( directory=os.path.abspath(directory), environment=self.env, format='checkpoint', ) self.env.reset() def render(self, packet): # Gather some information about our car and the ball my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) ball_location = Vec3(packet.game_ball.physics.location) # By default we will chase the ball, but target_location can be changed later target_location = ball_location if car_location.dist(ball_location) > 1500: # We're far away from the ball, let's try to lead it a little bit ball_prediction = self.get_ball_prediction_struct() # This can predict bounces, etc ball_in_future = find_slice_at_time(ball_prediction, packet.game_info.seconds_elapsed + 2) # ball_in_future might be None if we don't have an adequate ball prediction right now, like during # replays, so check it to avoid errors. if ball_in_future is not None: target_location = Vec3(ball_in_future.physics.location) self.renderer.draw_line_3d(ball_location, target_location, self.renderer.cyan()) # Draw some things to help understand what the bot is thinking self.renderer.draw_line_3d(car_location, target_location, self.renderer.white()) self.renderer.draw_string_3d(car_location, 1, 1, f'Speed: {car_velocity.length():.1f}', self.renderer.white()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """ This function will be called by the framework many times per second. This is where you can see the motion of the ball, etc. and return controls to drive your car. """ # Keep our boost pad info updated with which pads are currently active self.boost_pad_tracker.update_boost_status(packet) # This is good to keep at the beginning of get_output. It will allow you to continue # any sequences that you may have started during a previous call to get_output. if self.active_sequence is not None and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls self.render(packet) my_car = packet.game_cars[self.index] my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) ball_location = Vec3(packet.game_ball.physics.location) target_location = ball_location if car_location.dist(ball_location) > 1500: ball_prediction = self.get_ball_prediction_struct() ball_in_future = find_slice_at_time(ball_prediction, packet.game_info.seconds_elapsed + 2) if ball_in_future is not None: target_location = Vec3(ball_in_future.physics.location) # Drive at ball controls = self.last_state or SimpleControllerState(throttle=1) # controls.steer = steer_toward_target(my_car, target_location) self.set_controls_from_model(packet, controls) self.last_state = controls return controls def set_controls_from_model(self, tick, controls): actions = self.get_actions(tick) if (len(actions) > 1): controls.throttle = actions[OutputOptions.THROTTLE][0] - 1 if OutputOptions.THROTTLE in actions else controls.throttle controls.pitch = actions[OutputOptions.PITCH][0] - 1 if OutputOptions.PITCH in actions else controls.pitch controls.roll = actions[OutputOptions.ROLL][0] - 1 if OutputOptions.ROLL in actions else controls.roll controls.yaw = actions[OutputOptions.STEER][0] - 1 if OutputOptions.STEER in actions else controls.yaw controls.steer = actions[OutputOptions.STEER][0] - 1 if OutputOptions.STEER in actions else controls.steer controls.boost = actions[OutputOptions.BOOST][0] if OutputOptions.BOOST in actions else controls.boost controls.jump = actions[OutputOptions.JUMP][0] if OutputOptions.JUMP in actions else controls.jump controls.handbrake = actions[OutputOptions.E_BRAKE][0] if OutputOptions.E_BRAKE in actions else controls.handbrake return controls def get_actions(self, tick): actions = {} if self.env is not None and self.env.update_throttle(tick): states = self.env.setRLState(tick) actions = self.agent.act(states) states, terminal, reward = self.env.execute(actions=actions) self.agent.observe(terminal=terminal, reward=reward) if terminal: self.env.reset() else: try: actions = self.matchcomms.incoming_broadcast.get(block=False) except Empty: pass return actions
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.boost_pad_tracker = BoostPadTracker() self.previous_Goals = 0 self.previous_my_Goals = 0 self.previous_enemy_Goals = 0 self.DDPG = None def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """ This function will be called by the framework many times per second. This is where you can see the motion of the ball, etc. and return controls to drive your car. """ # Keep our boost pad info updated with which pads are currently active self.boost_pad_tracker.update_boost_status(packet) # Gather some information about our car and the ball my_car = packet.game_cars[self.index] if self.team == 0: goal_location = np.array((0, 5213, 321.3875)) else: goal_location = np.array((0, -5213, 321.3875)) def dictToArr(d): return np.array((d.x,d.y,d.z)) field_length = 10426 max_velocity = 1000 ball_velocity = dictToArr(packet.game_ball.physics.velocity) car_location = dictToArr(my_car.physics.location) car_velocity = dictToArr(my_car.physics.velocity) ball_location = dictToArr(packet.game_ball.physics.location) car_ball = ball_location - car_location ball_goal = goal_location - ball_location my_Goals = packet.teams[self.team].score enemy_goals = packet.teams[1-self.team].score current_Goals = my_Goals+enemy_goals print("velocity: ", car_velocity, end = " ") state = np.concatenate((car_ball[:2]/field_length,ball_goal[:2]/field_length,car_velocity[:2]/max_velocity,ball_velocity[:2]/max_velocity)) if self.DDPG is None: self.DDPG = DDPG(state) reward = 0.0 #denom = np.linalg.norm(ball_goal) * np.linalg.norm(ball_velocity) #if denom != 0: reward += np.dot(ball_goal, ball_velocity) #np.arccos(np.dot(ball_goal, ball_velocity)/denom) #denom = np.linalg.norm(car_ball) * np.linalg.norm(car_velocity) #if denom != 0: reward += np.dot(car_ball, car_velocity) #100*np.arccos(np.dot(car_ball, car_velocity)/denom) #if denom != 0: #reward += 2000/np.linalg.norm(car_ball) if my_Goals != self.previous_my_Goals: reward = 1000 if enemy_goals != self.previous_enemy_Goals: reward = -1000 print("Time: ", round(packet.game_info.seconds_elapsed,2), end = " ") action = self.DDPG.step(state, reward) if current_Goals != self.previous_Goals: self.DDPG.newEpisode() self.previous_Goals = current_Goals self.previous_enemy_Goals = enemy_goals self.previous_my_Goals = my_Goals #target_location = ball_location # if car_location.dist(ball_location) > 500: # # We're far away from the ball, let's try to lead it a little bit # ball_prediction = self.get_ball_prediction_struct() # This can predict bounces, etc # ball_in_future = find_slice_at_time(ball_prediction, packet.game_info.seconds_elapsed + 1) # # ball_in_future might be None if we don't have an adequate ball prediction right now, like during # # replays, so check it to avoid errors. # if ball_in_future is not None: # target_location = Vec3(ball_in_future.physics.location) # self.renderer.draw_line_3d(ball_location, target_location, self.renderer.cyan()) # Draw some things to help understand what the bot is thinking # self.renderer.draw_line_3d(car_location, target_location, self.renderer.white()) # self.renderer.draw_string_3d(car_location, 1, 1, f'Speed: {car_velocity.length():.1f}', self.renderer.white()) # self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) controls = SimpleControllerState() controls.steer = action[0] controls.throttle = action[1] controls.boost = action[2]>0 # You can set more controls if you want, like controls.boost. return controls
def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.travel_distance = 0 self.pos = Vec3(0, 0, 0)
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() def initialize_agent(self): self.boost_pad_tracker.initialize_boosts(self.get_field_info()) settings = self.get_match_settings() self.map = settings.GameMap() if self.map == 35: self.map_size = [3581, 2966.7] elif self.map == 31: self.map_size = [5139.7, 4184.5] elif self.map == 37: self.map_size = [6912, 4096] else: self.map_size = [5120, 4096] def get_output(self, packet: GameTickPacket) -> SimpleControllerState: self.boost_pad_tracker.update_boost_status(packet) if self.active_sequence is not None and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls # Get the distance from the nearest surface (walls, floor, roof, etc.) def distance_from_surface(pos): min_dist = math.inf nearest_surface = pos if min_dist > pos.z: min_dist = pos.z nearest_surface = Vec3(pos.x, pos.y, 0) if min_dist > self.map_size[1] - abs(pos.x): min_dist = self.map_size[1] - abs(pos.x) nearest_surface = Vec3( sign(pos.x) * self.map_size[1], pos.y, pos.z) if min_dist > self.map_size[0] - abs(pos.y): min_dist = self.map_size[0] - abs(pos.y) nearest_surface = Vec3(pos.x, sign(pos.y) * self.map_size[0], pos.z) if min_dist > 99999 + (8064 - abs(pos.x) - abs(pos.y)) / math.sqrt(2): min_dist = (8064 - abs(pos.x) - abs(pos.y)) / math.sqrt(2) nearest_surface = Vec3(pos.x, sign(pos.y) * self.map_size[0], pos.z) return nearest_surface # Get the rate in which the object is moving away from the nearest surface def velocity_from_surface(pos, vel): val = pos - distance_from_surface(pos) if val.x != 0: return vel.x * sign(val.x) elif val.y != 0: return vel.y * sign(val.y) elif val.z != 0: return vel.z * sign(val.z) # Get the order within the team def distance_order(teams): nearest = 1 overall_nearest = 1 last = 0 ref = (car_location - ball_location).length( ) / (car_velocity.length() + 2300) + math.asin( (car_velocity * safe_div(car_velocity.length()) - ball_location * safe_div(ball_location.length())).length() / 2) * 3 / math.pi * 0 for i in range(len(packet.game_cars)): if (packet.game_cars[i].team != (-teams * packet.game_cars[self.index].team + (1 + teams) / 2) or teams == False ) and packet.game_cars[i].physics.location.z > 0: time_taken = ( Vec3(packet.game_cars[i].physics.location) - ball_location).length() / (Vec3(packet.game_cars[ i].physics.velocity).length() + 2300) + math.asin( (Vec3(packet.game_cars[i].physics.velocity) * safe_div( Vec3(packet.game_cars[i].physics.velocity ).length()) - ball_location * safe_div(ball_location.length())).length() / 2) * 3 / math.pi * 0 # When the car is further front than the POV if ref > time_taken: if ((Vec3(packet.game_cars[i].physics.location) + send_location).length() <= (ball_location + send_location).length() or (car_location + send_location).length() > (ball_location + send_location).length()): nearest += 1 overall_nearest += 1 last += 1 # Keep the full-time goal keeper if overall_nearest == last: nearest = overall_nearest # Prevent the division by 0 error return last, nearest # Find the best boost pads to use to refuel as fast as possible def find_best_boost_pads(): best_pad = None best_score = math.inf for i in range(len(self.get_field_info().boost_pads)): pad = self.get_field_info().boost_pads[i] if packet.game_boosts[ i].is_active == True or packet.game_boosts[i].timer <= ( Vec3(pad.location) - car_location).length() / 2300: score = (Vec3(pad.location) - car_location).length( ) * safe_div(car_velocity.length()) + math.sin( ((Vec3(pad.location) - car_location) / (Vec3(pad.location) - car_location).length() - car_velocity * safe_div(car_velocity.length()) ).length() / 2) * 3 / math.pi if pad.is_full_boost: score *= safe_div((50 - my_car.boost / 2) / 6) if score < best_score: best_score = score best_pad = pad return Vec3(best_pad.location) # Get the yaw based on position def get_yaw(x, y): a = math.acos(x / Vec3(x, y, 0).length()) if abs(a) < math.pi: return a * sign(y) else: return math.pi # Get the angle between two places def get_angle(p1, p2): d = (p1 * safe_div(p1.length()) - p2 * safe_div(p2.length())).length() angle = 2 * math.asin(d / 2) return angle # Determine when the car would intersect the ball assuming a speed def intersect_time(surface): t1 = 5 t2 = 5 best_spd = math.inf slowest = math.inf if surface == False: for i in range(1, 101): time_location = Vec3(predict_ball(i / 20).physics.location) if (time_location - car_location).length( ) * 20 / i <= car_velocity.length() and t1 == 5: t1 = i / 20 if (time_location - car_location).length() * 20 / i <= slowest: slowest = (time_location - car_location).length() * 20 / i t2 = i / 20 else: for i in range(1, 101): time_location = Vec3(predict_ball(i / 20).physics.location) if (distance_from_surface(time_location) - distance_from_surface(car_location)).length( ) * 20 / i <= car_velocity.length() and t1 == 5: t1 = i / 20 if (distance_from_surface(time_location) - distance_from_surface(car_location) ).length() * 20 / i <= slowest: slowest = (distance_from_surface(time_location) - distance_from_surface(car_location) ).length() * 20 / i t2 = i / 20 return t1, t2 # Determine when the car should jump def jump_ready(val): if val <= 300 and val > 92.75: delay = (2 * (val - 92.75) / 650)**0.5 return delay else: return 0 # Get the nearest player to the ball def nearest_player(teams, speed_offset): nearest = None best_time = math.inf last = True for i in range(len(packet.game_cars)): if (packet.game_cars[i].team != (-teams * packet.game_cars[self.index].team + (1 + teams) / 2) or teams == False) and Vec3( packet.game_cars[i].physics.location) != Vec3( 0, 0, 0): time_taken = (Vec3( packet.game_cars[i].physics.location ) - ball_location).length() / (Vec3( packet.game_cars[i].physics.velocity ).length() + speed_offset) + math.sin( (Vec3(packet.game_cars[i].physics.velocity) * safe_div( Vec3(packet.game_cars[i].physics.velocity).length( )) - ball_location * safe_div(ball_location.length())).length() / 2) * 3 / math.pi if time_taken < best_time: best_time = time_taken nearest = packet.game_cars[i] return nearest, best_time # Get the list of moments when the ball should be hit def opportunities(): li = [] prev_pos = ball_location for i in range(1, 101): time_location = predict_ball(i / 20) if time_location.z <= 300: li.append([ i / 20, (time_location - car_location).length() * 20 / i ]) prev_pos = time_location return li # ??? def plane_dist(pos, dist): if Vec3(pos.x, pos.y, 0).length() <= dist: return True elif Vec3(pos.x, 0, pos.z).length() <= dist: return True elif Vec3(0, pos.y, pos.z).length() <= dist: return True else: return False # Get the ball's position and velocity at a specific time def predict_ball(t): ball_in_future = find_slice_at_time( ball_prediction, packet.game_info.seconds_elapsed + t) if ball_in_future is not None: return ball_in_future else: return packet.game_ball # Divide numbers without division by 0 def safe_div(x): if x == 0: return math.inf else: return 1 / x # Return the direction of the value from 0 def sign(x): if x < 0: return -1 elif x > 0: return 1 else: return 0 # Return a value with limitations def clamp(x, m, M): if x < m: return m elif x > M: return M else: return x # Move the target location to straighten the ascent up walls def move_target_for_walls(pos1, pos2): up1 = distance_from_surface(pos1) up2 = distance_from_surface(pos2) new_pos = pos2 if up1.z == 0 and up2.z > 0: new_pos = Vec3(new_pos, 0, new_pos) + (up2 - pos2) * safe_div( (up2 - pos2).length()) * up2.z if up1.z > 0 and up2.z == 0 and pos1.z >= 30: if abs(up1.x) == self.map_size[1]: new_pos = Vec3(up1.x, up2.y, -abs(up2.x - up1.x)) elif abs(up1.y) == self.map_size[0]: new_pos = Vec3(up2.x, up1.y, -abs(up2.y - up1.y)) return new_pos # Actions # Use flip jumps to attack the ball def jump_attack(): dir_y = 0 dir_x = 0 if ((car_location + car_velocity / 5) - (ball_location + ball_velocity / 5)).length() <= 175: if (car_location + Vec3(car_velocity.y, -car_velocity.x, 0) * safe_div(car_velocity.length()) - ball_location).length() < (car_location - ball_location).length(): dir_x = -1 if (car_location + Vec3(-car_velocity.y, car_velocity.x, 0) * safe_div(car_velocity.length()) - ball_location).length() < (car_location - ball_location).length(): dir_x = 1 if (car_location + car_velocity / 5 - ball_location - ball_velocity / 5 ).length() <= (car_location - ball_location).length() - 50: dir_y = -1 dir_x *= sign(math.pi / 2 - get_angle(car_direction, car_velocity)) dir_y *= sign(math.pi / 2 - get_angle(car_direction, car_velocity)) override = self.flip(packet, dir_x, dir_y, not my_car.jumped) # Jump over cars to prevent collision def avoid_bump(): for i in range(len(packet.game_cars)): if i != self.index and packet.game_cars[ i].physics.location.z > 0: pos = car_location pos2 = Vec3(packet.game_cars[i].physics.location) vel = car_velocity vel2 = Vec3(packet.game_cars[i].physics.velocity) dist = (pos - pos2).length() on_course = False if dist > 40: if get_angle(pos2 - pos, vel) <= math.tan( math.sqrt(40**2 / (dist**2 - 40**2))): on_course = True else: on_course = True if on_course == True and dist <= 40 + (vel - vel2).length( ) / 2 and (vel.length() <= vel2.length() or packet.game_cars[i].team != self.team): self.jump_once(packet) # Modes def attack(): # Target target_ball = predict_ball(earliest_intersection) target_location = Vec3(target_ball.physics.location) target_location = target_location + ( target_location - send_location) / ( target_location - send_location).length() * 92.75 # Smoother wall transitions target_location = move_target_for_walls(car_location, target_location) jumping = jump_ready( (target_location - distance_from_surface(target_location)).length()) # Manage speed if velocity_from_surface( Vec3(target_ball.physics.location), Vec3(target_ball.physics.velocity)) >= 0 or (Vec3( target_ball.physics.location) - distance_from_surface( Vec3(target_ball.physics.location))).length( ) <= 300 or target_ball.physics.location.y * sign( send_location.y) <= -self.map_size[0]: controls.throttle = 1 else: controls.throttle = 0 # Boost controls.boost = abs( steer_toward_target(my_car, target_location) ) <= 0.1 and car_velocity.length() < 2300 and ( (Vec3(target_ball.physics.location) - distance_from_surface( Vec3(target_ball.physics.location))).length() <= 300 or velocity_from_surface(Vec3(target_ball.physics.location), Vec3(target_ball.physics.velocity)) >= 0) and car_index == 1 # Jump h = (Vec3(target_ball.physics.location) - distance_from_surface( Vec3(target_ball.physics.location))).length() if jump_ready( (Vec3(target_ball.physics.location) - distance_from_surface(Vec3(target_ball.physics.location)) ).length()) >= earliest_intersection and steer_toward_target( my_car, target_location) < 1: controls.pitch = 0 controls.yaw = 0 controls.roll = 0 controls.jump = True controls.boost = False else: jump_attack() # Catch the ball when in the air if abs( target_location.z - car_location.z ) <= 92.75 * 0.75 and get_angle( target_location - car_location, car_velocity ) >= math.atan( 200 * safe_div(car_velocity.length()) ) and my_car.jumped == True and my_car.double_jumped == False and False: controls.yaw = sign( (target_location - car_location - Vec3(car_velocity.y, -car_velocity.x, car_velocity.z) ).length() - (target_location - car_location - Vec3(-car_velocity.y, car_velocity.x, car_velocity.z) ).length()) controls.jump = True # Draw self.renderer.draw_line_3d(car_location, target_location, self.renderer.red()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.red(), centered=True) return target_location def standby(): # Friendly/enemey if enemy_time >= friendly_time + 0.2: nearest_ref = nearest_friendly md = "friendly" else: nearest_ref = nearest_enemy md = "enemy" # Target if md == "enemy" or True: target_location = ball_location - ( Vec3(nearest_ref.physics.location) - ball_location) / ( Vec3(nearest_ref.physics.location) - ball_location).length() * (2500 + Vec3( nearest_ref.physics.velocity).length() * 5 / 2.3) target_location = Vec3( target_location.x, ball_location.y + (target_location.y - ball_location.y) * sign(target_location.y - ball_location.y) * -sign(send_location.y), target_location.z) else: target_location = ball_location - ( Vec3(nearest_ref.physics.location) - ball_location) / ( Vec3(nearest_ref.physics.location) - ball_location).length() * (2500 + Vec3( nearest_ref.physics.velocity).length() * 5 / 2.3) target_location = target_location + ( target_location - send_location) / ( target_location - send_location).length() * 927.5 # Walls if (distance_from_surface(target_location) - target_location).length() <= 300: target_location = distance_from_surface(target_location) target_location = move_target_for_walls( car_location, target_location) else: target_location = Vec3(target_location.x, target_location.y, 0) # Draw self.renderer.draw_line_3d(car_location, target_location, self.renderer.green()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.green(), centered=True) # Manage speed controls.boost = False controls.throttle = clamp( (target_location - car_location).length() / 1000, -1, 1) return target_location def refuel(): # Target target_location = find_best_boost_pads() # Draw self.renderer.draw_line_3d(car_location, target_location, self.renderer.green()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.green(), centered=True) # Speed controls.throttle = 1 controls.boost = False return target_location def goalie(): target_location = car_location # Roll back onto the wheels if abs(car_rotation.roll) >= math.pi * 3 / 4: override = self.jump_once(packet) # Prepare for a save if sign(car_location.y) == -sign(send_location.y) and abs( car_location.y) >= abs(send_location.y): target_location = car_location - Vec3(0, send_location.y, 0) if car_velocity.length() >= 850: controls.throttle = -1 else: if Vec3(car_velocity.x, car_velocity.y, 0).length() >= 250: override = self.reverse_flip(packet) else: controls.pitch = 0 controls.roll = 0 if (not math.pi * 0.4 <= abs(car_rotation.yaw) <= math.pi * 0.6 or sign(car_rotation.yaw) == -sign(send_location.y)) and abs( car_velocity.z) <= 1: override = self.jump_once(packet) controls.yaw = clamp( steer_toward_target(my_car, send_location) - my_car.physics.angular_velocity.z, -1, 1) controls.throttle = 0 # Drive into the goal unless it's already done so else: target_location = defend() return target_location def defend(): if not in_goal: target_ball = predict_ball(earliest_intersection) target_location = Vec3(target_ball.physics.location) nearest_surface = (target_location - car_location) / ( target_location - car_location).length() * 140 nearest_surface_r = Vec3(-nearest_surface.y, nearest_surface.x, nearest_surface.z) nearest_surface_l = Vec3(nearest_surface.y, -nearest_surface.x, nearest_surface.z) if False: side = -sign((nearest_surface_l - send_location).length() - (nearest_surface_r - send_location).length()) else: side = -sign(((nearest_surface_l - ball_location) - ball_velocity).length() - ((nearest_surface_r - ball_location) - ball_velocity).length()) nearest_surface = Vec3(-nearest_surface.y * side, nearest_surface.x * side, nearest_surface.z) if abs(target_location.x + nearest_surface.x) >= self.map_size[1] or get_angle( car_location - send_location, car_location - target_location ) > math.pi / 3 * 2 or ball_location.z > 130: target_location = -send_location else: target_location = target_location + nearest_surface / 140 * car_velocity.length( ) controls.boost = enemy_time < 1 and abs( steer_toward_target(my_car, target_location)) <= 0.1 # Jump h = (Vec3(target_ball.physics.location) - distance_from_surface(Vec3( target_ball.physics.location))).length() if jump_ready( h) >= earliest_intersection and steer_toward_target( my_car, target_location) < 1: controls.pitch = 0 controls.yaw = 0 controls.roll = 0 controls.jump = True controls.boost = False else: jump_attack() # Draw self.renderer.draw_line_3d(car_location, ball_location + nearest_surface, self.renderer.cyan()) self.renderer.draw_rect_3d(ball_location + nearest_surface, 8, 8, True, self.renderer.cyan(), centered=True) controls.throttle = 1 else: target_location = -send_location controls.throttle = 1 return target_location def recovery(): tx = (self.map_size[1] - car_location.x * sign(car_velocity.x)) * safe_div(car_velocity.x) ty = (self.map_size[0] - car_location.y * sign(car_velocity.y)) * safe_div(car_velocity.y) tt = 0 if car_location.z / 325 - (car_velocity.z / 650)**2 >= 0: tz = car_velocity.z / 650 + math.sqrt(car_location.z / 325 - (car_velocity.z / 650)**2) else: tz = car_velocity.z / 650 - math.sqrt(car_location.z / 325 + (car_velocity.z / 650)**2) if tx >= tz <= ty: controls.roll = clamp(-car_rotation.roll, -1, 1) controls.pitch = clamp(-car_rotation.pitch, -1, 1) tt = tz elif tx >= ty <= tz: point = (math.pi / 2 + sign(abs(car_rotation.yaw) - math.pi / 2) * math.pi / 2) * sign(car_rotation.yaw) controls.roll = clamp( math.pi / 2 * sign(car_velocity.y) * sign(abs(car_rotation.yaw) - math.pi / 2) - car_rotation.roll, -1, 1) controls.pitch = clamp(point - car_rotation.yaw, -1, 1) tt = ty draw_point = Vec3( car_location.x + car_velocity.x * tt, car_location.y + car_velocity.y * tt, car_location.z + car_velocity.z * tt - 325 * tt**2) self.renderer.draw_line_3d(car_location, draw_point, self.renderer.pink()) self.renderer.draw_rect_3d(draw_point, 8, 8, True, self.renderer.pink(), centered=True) # Variables my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) car_rotation = my_car.physics.rotation car_direction = Vec3( math.cos(car_rotation.yaw) * math.cos(car_rotation.pitch), math.sin(car_rotation.yaw) * math.cos(car_rotation.pitch), math.sin(car_rotation.pitch)) ball_prediction = self.get_ball_prediction_struct() ball_location = Vec3(packet.game_ball.physics.location) ball_velocity = Vec3(packet.game_ball.physics.velocity) send_location = Vec3(0, sign(0.5 - self.team) * self.map_size[0], 0) earliest_intersection, easiest_intersection = intersect_time(True) team_size, car_index = distance_order(1) nearest_enemy, enemy_time = nearest_player(0, 460) nearest_friendly, friendly_time = nearest_player(0, 460) in_goal = (ball_location + send_location).length() > ( car_location + send_location).length() target_location = car_location mode = "" override = None # Controls controls = SimpleControllerState() # Half-flip to quickly turn if car_velocity.length() <= 500 and get_angle( car_velocity, target_location - car_location) >= math.pi / 3 * 2: override = self.reverse_flip(packet) # Assign role in the team if abs(send_location.y + Vec3(predict_ball(2).physics.location).y ) <= 1000 or abs(send_location.y + ball_location.y) <= 1000: if in_goal: mode = "Attack" else: mode = "Defense" else: if car_index == 1: if in_goal: mode = "Attack" else: mode = "Defense" elif car_index < team_size: if my_car.boost == 100 and car_index == 2: mode = "Standby" else: mode = "Refuel" else: mode = "Goalie" # Recovery if my_car.double_jumped: recovery() # Demolition if mode == "Demo": target_location = demo() # Attack the ball if mode == "Attack": avoid_bump() target_location = attack() controls.use_item = True # Stand by for hit if mode == "Standby": avoid_bump() target_location = standby() # Collect boost if mode == "Refuel": avoid_bump() target_location = refuel() # Retreat if mode == "Defense": avoid_bump() target_location = defend() # Goalie if mode == "Goalie": avoid_bump() target_location = goalie() controls.steer = steer_toward_target(my_car, target_location) # Draw if False: self.renderer.draw_string_2d( 800, 200, 1, 1, "X: " + str(packet.game_cars[1 - self.index].physics.location.x), self.renderer.white()) self.renderer.draw_string_2d( 800, 220, 1, 1, "Y: " + str(packet.game_cars[1 - self.index].physics.location.y), self.renderer.white()) self.renderer.draw_string_2d(1400, 200, 1, 1, "Map: " + str(self.map), self.renderer.white()) self.renderer.draw_string_2d( 50, 680 + car_index * 20 * (0.5 - self.team) * 2, 1, 1, "Noob Bot " + str(car_index) + ": " + str(mode), self.renderer.white()) self.renderer.draw_line_3d(target_location, distance_from_surface(target_location), self.renderer.yellow()) if override: return override else: return controls def flip(self, packet, dir_x, dir_y, first_jump): self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=first_jump)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, yaw=dir_x, pitch=dir_y)), ControlStep(duration=0.8, controls=SimpleControllerState()), ]) return self.active_sequence.tick(packet) def jump_once(self, packet): self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)) ]) return self.active_sequence.tick(packet) def reverse_flip(self, packet): self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, pitch=1)), ControlStep(duration=0.25, controls=SimpleControllerState(jump=False, pitch=-1)), ControlStep(duration=0.3, controls=SimpleControllerState(roll=1, pitch=-1)), ControlStep(duration=0.05, controls=SimpleControllerState()), ]) return self.active_sequence.tick(packet) def correct_direction(self, packet, dir): self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True, throttle=dir)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False, throttle=dir)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, throttle=dir, pitch=1)), ControlStep(duration=0.25, controls=SimpleControllerState(jump=False, throttle=dir, pitch=-1)), ControlStep(duration=0.3, controls=SimpleControllerState(roll=1, throttle=-dir, pitch=-1)), ControlStep(duration=0.05, controls=SimpleControllerState(throttle=-dir)), ]) return self.active_sequence.tick(packet)
class MyBot(BaseAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.controls = SimpleControllerState() self.bot_car = None self.ball = None self.allies=[] self.foes=[] self.ball_prediction = None self.posts=((Vec3(893,-5120,0),Vec3(-893,-5120,0)),(Vec3(893,5120,0),Vec3(-893,5120,0))) self.back_corners=((Vec3(3672,-4096,0),Vec3(-3672,-4096,0)),(Vec3(3672,4096,0),Vec3(-3672,4096,0))) self.collision_posts=((Vec3(843,-5070,0),Vec3(-843,-5070,0)),(Vec3(843,5070,0),Vec3(-843,5070,0))) self.goal_corners=((Vec3(-893,-6000,0),Vec3(893,-5120,642.775)),(Vec3(-893,5120,0),Vec3(893,6000,642.775))) self.boxes=((Vec3(-1600,-6000,0),Vec3(1600,-4120,2044)),(Vec3(-1600,4120,0),Vec3(1600,6000,2044))) self.defending = False self.rotating = False self.supporting = 0 self.clearing = False self.shooting = False self.air_recovery = False self.current_strike = None self.skip_ticks_to_test = 0 def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) def get_output(self, packet: GameTickPacket) -> SimpleControllerState: """ Keep our boost pad info updated with which pads are currently active""" self.boost_pad_tracker.update_boost_status(packet) """Update cars and ball""" #ball if self.ball is None: self.ball = Ball(packet) else: self.ball.update(packet) self.ball_prediction = self.get_ball_prediction_struct() #draw 3 sec of path self.renderer.draw_polyline_3d([Vec3(ball_slice.physics.location) for ball_slice in self.ball_prediction.slices[:180:5]],self.renderer.yellow()) #self if self.bot_car is None: self.bot_car = Car(self.index,packet) elif self.bot_car.index != self.index: self.bot_car = Car(self.index,packet) else: self.bot_car.update(packet) #check if number of players has changed, and reset allies and foes if it has if len(self.allies)+len(self.foes)+1!=len(packet.game_cars): self.allies,self.foes = [],[] #allies if len(self.allies)==0: for index in range(packet.num_cars): if packet.game_cars[index].team==self.bot_car.team and index!=self.bot_car.index: self.allies.append(Car(index,packet)) else: for car in self.allies: car.update(packet) #foes if len(self.foes)==0: for index in range(packet.num_cars): if packet.game_cars[index].team!=self.bot_car.team: self.foes.append(Car(index,packet)) else: for car in self.foes: car.update(packet) if self.skip_ticks_to_test > 0: self.skip_ticks_to_test -= 1 return SimpleControllerState() """Continue and active sequences""" if self.active_sequence is not None and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls self.controls = SimpleControllerState() """put cars in positions (for testing) (set long left atm) if (Vec3(packet.game_ball.physics.location).length() > 200 or self.bot_car.location.y > 50) and self.bot_car.team==0: car_state0= CarState(boost_amount=45.333, physics=Physics(velocity=Vector3(0,0, 0),location=Vector3(256,-3840, 0),rotation=Rotator(0, 0.5*math.pi, 0),angular_velocity=Vector3(0, 0, 0))) car_state1= CarState(boost_amount=45.333, physics=Physics(velocity=Vector3(0,0, 0),location=Vector3(-256,3840, 0),rotation=Rotator(0, -0.5*math.pi, 0),angular_velocity=Vector3(0, 0, 0))) if self.bot_car.index!=self.bot_car.team: car_state0,car_state1=car_state1,car_state0 ball_state= BallState(Physics(velocity=Vector3(x=0,y=0,z=0),location=Vector3(x=0,y=0,z=92.75),rotation=Rotator(0,0,0),angular_velocity=Vector3(0,0,0))) self.set_game_state(GameState(ball=ball_state,cars={0:car_state0,1:car_state1})) self.skip_ticks_to_test = 10 return SimpleControllerState() """ """draw in info for blocking testing self.renderer.draw_string_2d(20,20,3,3, f"z: {self.bot_car.location.z}", self.renderer.white()) if self.bot_car.stable: return self.long_jump(packet) else: return SimpleControllerState() """ """kickoff NOTE: the diagonal flips need to be more sideways than forward when updating for the diagonal and long""" if self.ball.location.flat().length()<1 and self.ball.velocity.flat().length()<1 and packet.game_info.is_kickoff_pause: ally_on_short = False for ally in self.allies: if Vec3(-2048,-2560,0).dist(ally.location)<50 or Vec3(-2048,2560,0).dist(ally.location)<50 or Vec3(2048,-2560,0).dist(ally.location)<50 or Vec3(2048,2560,0).dist(ally.location)<50: ally_on_short = True if self.bot_car.location.flat().dist(Vec3(-2048,-2560,0))<50 or self.bot_car.location.flat().dist(Vec3(2048,2560,0))<50: self.active_sequence, first_frame = right_diagonal(packet) return first_frame elif self.bot_car.location.flat().dist(Vec3(2048,-2560,0))<50 or self.bot_car.location.flat().dist(Vec3(-2048,2560,0))<50: self.active_sequence, first_frame = left_diagonal(packet) return first_frame elif (self.bot_car.location.flat().dist(Vec3(-256,-3840))<50 or self.bot_car.location.flat().dist(Vec3(256,3840,0))<50) and not ally_on_short: self.active_sequence, first_frame = long_right(packet) return first_frame elif (self.bot_car.location.flat().dist(Vec3(256,-3840,0))<50 or self.bot_car.location.flat().dist(Vec3(-256,3840,0))<50) and not ally_on_short: self.active_sequence, first_frame = long_left(packet) return first_frame elif (self.bot_car.location.flat().dist(Vec3(0,-4608,0))<50 or self.bot_car.location.flat().dist(Vec3(0,4608,0))<50) and len(self.allies)==0: self.active_sequence, first_frame = back_kick(packet) return first_frame else: self.active_sequence, first_frame = kickoff_idle(packet) return first_frame """defend check""" if self.ball.velocity.flat().length()!=0: post0_ang = self.posts[self.bot_car.team][0].__sub__(self.ball.location).flat().ang_to(Vec3(1,0,0)) ball_vel_ang = self.ball.velocity.flat().ang_to(Vec3(1,0,0)) post1_ang = self.posts[self.bot_car.team][1].__sub__(self.ball.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < ball_vel_ang < post1_ang moving_at_posts = self.ball.velocity.y<0 and self.ball.location.y<4000 if self.bot_car.team==0 else self.ball.velocity.y>0 and self.ball.location.y>-4000 self.defending = True if between_posts and moving_at_posts else False """rotate check""" if self.rotating: #check for reasons to stop far_enough_behind_ball = self.bot_car.location.y-self.ball.location.y<-4000 if self.bot_car.team==0 else self.bot_car.location.y-self.ball.location.y>4000 about_to_hit_backwall = self.bot_car.location.y <-4100 if self.bot_car.team==0 else self.bot_car.location.y >4100 dunk_on_box = self.ball.location.within(self.boxes[(self.bot_car.team+1)%2][0],self.boxes[(self.bot_car.team+1)%2][1]) and min([foe.vec_to_ball.length() for foe in self.foes])>1000 and len(self.allies)==0 self.rotating = not( far_enough_behind_ball or about_to_hit_backwall or dunk_on_box ) else: #check for reasons to start wrong_side_of_ball_and_not_deep = self.bot_car.location.y-self.ball.location.y>0 and self.bot_car.location.y >-4000 if self.bot_car.team==0 else self.bot_car.location.y-self.ball.location.y<0 and self.bot_car.location.y <4000 vec_to_goal = Vec3(0, 5200*(self.bot_car.team*2-1),0) - self.bot_car.location ball_to_goal = Vec3(0, 5200*(self.bot_car.team*2-1),0) - self.ball.location unproductive_to_keep_chasing = vec_to_goal.length() < ball_to_goal.length() self.rotating = wrong_side_of_ball_and_not_deep """support check""" self.supporting=0 try: if self.bot_car.orientation.forward.ang_to(self.bot_car.vec_to_ball)<1.5 and (self.bot_car.team ==0 and self.bot_car.velocity.normalized().y>-0.7 or self.bot_car.team ==1 and self.bot_car.velocity.normalized().y<0.7): #self in a position to look to go for ally in self.allies: if ally.orientation.forward.ang_to(ally.vec_to_ball)<1.5 and (ally.team ==0 and ally.velocity.normalized().y>-0.7 or ally.team ==1 and ally.velocity.normalized().y<0.7) and (ally.assumed_maneuver =="BALL" or ally.assumed_maneuver =="SUPPORT"): if ally.vec_to_ball.length() < self.bot_car.vec_to_ball.length(): self.supporting += 1 else: #self in a position to look to go, allowing an extra 500 for bots that are facing ball for ally in self.allies: if ally.orientation.forward.ang_to(ally.vec_to_ball)<1.5 and (ally.team ==0 and ally.velocity.normalized().y>-0.7 or ally.team ==1 and ally.velocity.normalized().y<0.7) and (ally.assumed_maneuver =="BALL" or ally.assumed_maneuver =="SUPPORT"): if ally.vec_to_ball.length() < self.bot_car.vec_to_ball.length(): self.supporting += 1 else: if ally.vec_to_ball.length() < self.bot_car.vec_to_ball.length()+500: self.supporting += 1 except: stub="don't want to manually catch div 0" if self.ball.location.within(self.boxes[0][0],self.boxes[0][1]) or self.ball.location.within(self.boxes[1][0],self.boxes[1][1]): #box panic and dunk, both in one self.supporting = max(0,self.supporting-1) #draw in boxes for xy in [(-1600,4140),(-1600,-4140),(1600,4140),(1600,-4140)]: self.renderer.draw_line_3d(Vec3(xy[0],xy[1],0), Vec3(xy[0],xy[1],2000), self.renderer.red()) """clear check""" in_half = self.ball.location.y < -2000 if self.bot_car.team==0 else self.ball.location.y > 2000 self.clearing = in_half """shoot check""" self.shooting=True """air recovery check""" if self.current_strike is None: self.air_recovery = not self.bot_car.grounded and self.bot_car.location.z>100 else: self.air_recovery = not self.bot_car.grounded and self.current_strike.strike_type != "will add the aerial strike code later" and self.bot_car.location.z>100 """if ball threatening net but not on target overide""" if self.supporting ==0 and self.ball.location.y*math.copysign(1,self.bot_car.team*2-1)>3000: self.defending = True """defending, but third override""" if self.supporting==2 and self.defending: self.defending==False #dribble code is just linear target code with no offset and a little bit of turning if self.air_recovery: self.perform_air_recovery(packet) self.renderer.draw_string_3d(self.bot_car.location, 1, 1, f'AIR RECOVERY', self.renderer.white()) elif self.defending: self.defend(packet) self.renderer.draw_string_3d(self.bot_car.location, 1, 1, f'DEFENDING', self.renderer.white()) elif self.rotating: self.rotate(packet) self.renderer.draw_string_3d(self.bot_car.location, 1, 1, f'ROTATING', self.renderer.white()) elif self.supporting>0: self.support(packet,self.supporting) self.renderer.draw_string_3d(self.bot_car.location, 1, 1, f'SUPPORTING', self.renderer.white()) elif self.clearing: self.clear(packet) self.renderer.draw_string_3d(self.bot_car.location, 1, 1, f'CLEARING', self.renderer.white()) elif self.shooting: self.shoot(packet) self.renderer.draw_string_3d(self.bot_car.location, 1, 1, f'SHOOTING', self.renderer.white()) return self.controls """tools""" def steer_toward(self,car: Car, target:Vec3): #always call after throttle set angle = car.orientation.forward.signed_ang_to(target-car.location) if angle<-1.7 and car.grounded and car.vec_to_ball.flat().length()>500: self.controls.steer = -1 if car.velocity.length()>1200: self.controls.throttle*=-1 self.controls.handbrake=True elif angle<-0.1 and car.grounded: self.controls.steer = -1 self.controls.handbrake=False elif angle>1.7 and car.grounded and car.vec_to_ball.flat().length()>500: self.controls.steer = 1 if car.velocity.length()>1200: self.controls.throttle*=-1 self.controls.handbrake=True elif angle>0.1 and car.grounded: self.controls.steer = 1 self.controls.handbrake=False else: self.controls.steer = 0 self.controls.handbrake=False def point_in_field(self,vec): if abs(vec.x)>4096: vec = vec * (4096/abs(vec.x)) if abs(vec.y)>5120: vec = vec * (5120/abs(vec.y)) if abs(vec.z)>2044: vec = vec * (2044/abs(vec.z)) return vec """Routines""" def shoot(self,packet): #get vector of ball to the back of other net ideal_shot = Vec3(0,6000,0) - self.ball.location.flat() if self.bot_car.team==0 else Vec3(0,-6000,0) - self.ball.location.flat() #continue any strike after checking it if self.current_strike is not None: if check_strike(packet, self.ball_prediction, self.current_strike): self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes) self.controls = strike_controls self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) return else: self.current_strike = None #try to find strikes if self.ball.velocity.length()!=0 and self.current_strike is None and self.bot_car.stable: strikes = find_strikes(packet, self.ball_prediction, self.bot_car, ideal_shot) for strike in strikes: if strike.strike_type==strike_types.simple_linear: #linear if (Vec3(0,6000*(1-self.bot_car.team*2),0) - strike.slice_location).ang_to(self.bot_car.orientation.forward) < 2: #if linear strike is not a massive angle from the goal if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike elif strike.strike_type==strike_types.linear_jump: #long jump if (Vec3(0,6000*(1-self.bot_car.team*2-1),0) - strike.slice_location).ang_to(self.bot_car.orientation.forward) < 2: #if linear strike is not a massive angle from the goal if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike elif strike.strike_type==strike_types.linear_dblj: #double jump if (Vec3(0,6000*(1-self.bot_car.team*2-1),0) - strike.slice_location).ang_to(self.bot_car.orientation.forward) < 2: #if linear strike is not a massive angle from the goal if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike #execute straight away if one was chosen if self.current_strike is not None: self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes) self.controls = strike_controls self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) return #position to get a shot on the ball future_location, future_velocity = Vec3(self.ball.location), Vec3(self.ball.velocity) future_slice = find_slice_at_time(self.ball_prediction,packet.game_info.seconds_elapsed + 2) if future_slice is not None: future_location = Vec3(future_slice.physics.location) future_velocity = Vec3(future_slice.physics.velocity) self.renderer.draw_line_3d(self.ball.location, future_location, self.renderer.cyan()) target_location = self.point_in_field(future_location.flat()+ideal_shot.rescale(-500)) self.controls.throttle = 1.0 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return ################################################################################################## def clear(self,packet): #get vector of ball from the cone of own net ideal_shot = self.ball.location.flat() - Vec3(0,-8000,0) if self.bot_car.team==0 else self.ball.location.flat() - Vec3(0,8000,0) #find a future position based off the distance from the ball, using the current location as a backup future_location = self.ball.location future_velocity = self.ball.velocity #continue any strike after checking it if self.current_strike is not None and self.bot_car.stable: if check_strike(packet, self.ball_prediction, self.current_strike): self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes) self.controls = strike_controls #drive out of goal > priority in_goal = self.bot_car.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]) post0_ang = self.collision_posts[self.bot_car.team][0].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) std_ang_to_target = self.current_strike.slice_location.__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.collision_posts[self.bot_car.team][1].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < std_ang_to_target < post1_ang if not between_posts and in_goal: target_location = Vec3(0,(2*self.team-1)*5000,0) self.controls.throttle = 1 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) return else: self.current_strike = None #try to find strikes if self.ball.velocity.length()!=0 and self.current_strike is None: strikes = find_strikes(packet,self.ball_prediction,self.bot_car,ideal_shot) for strike in strikes: if strike.strike_type==strike_types.simple_linear: #linear if (strike.slice_location - Vec3(0,5500*(self.bot_car.team*2-1),0)).ang_to(self.bot_car.orientation.forward) < 2.2: #if linear strike is not a massive angle from the goal if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike elif strike.strike_type==strike_types.linear_jump: #long jump if (strike.slice_location - Vec3(0,5500*(self.bot_car.team*2-1),0)).ang_to(self.bot_car.orientation.forward) < 2: #if linear strike is not a massive angle from the goal if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike elif strike.strike_type==strike_types.linear_dblj: #double jump if (strike.slice_location - Vec3(0,5500*(self.bot_car.team*2-1),0)).ang_to(self.bot_car.orientation.forward) < 2: #if linear strike is not a massive angle from the goal if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike #execute straight away if one was chosen: #execute if self.current_strike is not None: #drive out of goal > priority in_goal = self.bot_car.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]) post0_ang = self.collision_posts[self.bot_car.team][0].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) std_ang_to_target = self.current_strike.slice_location.__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.collision_posts[self.bot_car.team][1].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < std_ang_to_target < post1_ang if not between_posts and in_goal: target_location = Vec3(0,(2*self.team-1)*5000,0) self.controls.throttle = 1 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return #execute self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes) self.controls = strike_controls self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) return #position for a better shot future_location, future_velocity = Vec3(self.ball.location), Vec3(self.ball.velocity) future_slice = find_slice_at_time(self.ball_prediction,packet.game_info.seconds_elapsed + 2) if future_slice is not None: future_location = Vec3(future_slice.physics.location) future_velocity = Vec3(future_slice.physics.velocity) self.renderer.draw_line_3d(self.ball.location, future_location, self.renderer.cyan()) target_location = self.point_in_field(future_location.flat()+ideal_shot.rescale(-500)) #drive out of goal > priority in_goal = self.bot_car.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]) post0_ang = self.collision_posts[self.bot_car.team][0].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) std_ang_to_target = target_location.__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.collision_posts[self.bot_car.team][1].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < std_ang_to_target < post1_ang if not between_posts and in_goal: target_location = Vec3(0,(2*self.team-1)*5000,0) self.controls.throttle = 1 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return self.controls.throttle = 1.0 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return def rotate(self,packet): #continue any strike after checking it if self.current_strike is not None: if check_strike(packet,self.ball_prediction,self.current_strike) and abs(self.current_strike.slice_location.y) > abs(self.bot_car.location.y): self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes) self.controls = strike_controls self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) return else: self.current_strike = None #aim at the post opposite where the ball is target_location = self.posts[self.bot_car.team][0] if self.ball.location.x < 0 else self.posts[self.bot_car.team][1] #wavedash to rotate quicker if self.bot_car.location.dist(target_location) > 3000 and self.bot_car.stable and self.bot_car.orientation.forward.ang_to(target_location-self.bot_car.location)<0.3 and 500<self.bot_car.velocity.length()<1600: self.active_sequence, self.controls = wavedash(packet) return #add something to avoid collisions later if self.bot_car.location.point_in_path(target_location - self.bot_car.location,self.ball.location): target_location = self.ball.location + Vec3(0,math.copysign(150,target_location.x),0) for ally in self.allies: if self.bot_car.location.point_in_path(target_location - self.bot_car.location,ally.location): target_location = ally.location + Vec3(0,math.copysign(150,target_location.x),0) #drive toward target self.controls.throttle = 1.0 self.steer_toward(self.bot_car,target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return ############################################################################################################################# def defend(self,packet): #get the vector of the ball to where it will hit the goal ( ball_to_goal = self.ball.velocity.flat() if ball_to_goal.length()!=0: ball_to_goal = ball_to_goal.rescale(((5120-abs(self.ball.location.y))/abs(ball_to_goal.y))) #target 2/3 way between ball and goal target_location = self.ball.location + ball_to_goal/1.5 #get vector of ball from the cone of own net ideal_shot = self.ball.location.flat() - Vec3(0,-8000,0) if self.bot_car.team==0 else self.ball.location.flat() - Vec3(0,8000,0) #ideal shot is to corner if on other side of ball going_to_overtake_ball = (self.bot_car.location-Vec3(0,6000*(2*self.bot_car.team-1),0)).scalar_proj(self.ball.location-Vec3(0,6000*(2*self.bot_car.team-1),0))+100 > Vec3(0,6000*(2*self.bot_car.team-1),0).dist(self.ball.location) if going_to_overtake_ball: ideal_shot = Vec3(math.copysign(4096,(ball_to_goal+self.ball.location).x),(self.team*2-1)*5120,0) - self.ball.location #continue any strike after checking it if self.current_strike is not None: if check_strike(packet,self.ball_prediction,self.current_strike): #otherwise, continue on strike self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes,defence=True) self.controls = strike_controls self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) #drive out of goal > priority in_goal = self.bot_car.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]) post0_ang = self.collision_posts[self.bot_car.team][0].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) std_ang_to_target = strike_location.__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.collision_posts[self.bot_car.team][1].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < std_ang_to_target < post1_ang if not between_posts and in_goal: target_location = Vec3(0,(2*self.team-1)*5000,0) self.controls.throttle = 1 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return return else: self.current_strike = None #try to find strikes if self.ball.velocity.length()!=0 and self.current_strike is None and self.bot_car.stable: strikes = find_strikes(packet,self.ball_prediction,self.bot_car,ideal_shot,defence=True) for strike in strikes: if strike.strike_type==strike_types.simple_linear: #linear, will check if line to strike location goes into net post0_ang = self.posts[self.bot_car.team][0].__sub__(self.ball.location).flat().ang_to(Vec3(1,0,0)) car_slice_ang = (strike.slice_location - self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.posts[self.bot_car.team][1].__sub__(self.ball.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < car_slice_ang < post1_ang if abs(self.bot_car.location.y)>abs(self.ball.location.y): #clear if on correct side if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike elif all(abs(ally.location.y-(1-ally.team*2)*6000) < abs(self.bot_car.location.y-(1-ally.team*2)*6000) or abs(ally.location.x)>2500 for ally in self.allies) and not between_posts: #clear to corner if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike elif strike.strike_type==strike_types.linear_jump or strike.strike_type==strike_types.linear_dblj: #linear, will check if line to strike location goes into net post0_ang = self.posts[self.bot_car.team][0].__sub__(self.ball.location).flat().ang_to(Vec3(1,0,0)) car_slice_ang = (strike.slice_location - self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.posts[self.bot_car.team][1].__sub__(self.ball.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < car_slice_ang < post1_ang if abs(self.bot_car.location.y)>abs(self.ball.location.y): #clear if on correct side if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike elif all(abs(ally.location.y-(1-ally.team*2)*6000) < abs(self.bot_car.location.y-(1-ally.team*2)*6000) or abs(ally.location.x)>2500 for ally in self.allies) and not between_posts: #clear to corner if self.current_strike is not None: self.current_strike = strike if strike.slice_time<self.current_strike.slice_time else self.current_strike else: self.current_strike = strike #execute straight away if self.current_strike is not None: self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes,defence=True) self.controls = strike_controls self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) #drive out of goal > priority in_goal = self.bot_car.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]) post0_ang = self.collision_posts[self.bot_car.team][0].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) std_ang_to_target = strike_location.__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.collision_posts[self.bot_car.team][1].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < std_ang_to_target < post1_ang if not between_posts and in_goal: target_location = Vec3(0,(2*self.team-1)*5000,0) self.controls.throttle = 1 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return return """ keep the rest for now, esp for defence """ #changed to if car is further from goal than ball if Vec3(0,6000*(2*self.bot_car.team-1),0).dist(self.bot_car.location) > Vec3(0,6000*(2*self.bot_car.team-1),0).dist(self.ball.location)-100: offset = self.bot_car.vec_to_ball.flat().cross(Vec3(0,0,1)).normalized() if offset.y>0 and self.ball.velocity.y <0 or offset.y<0 and self.ball.velocity.y >0: offset = -offset target_location = target_location + 150*offset self.controls.throttle=1.0 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return #Drive to the point, using atan to slow when close to the point (judged by d/v) est_time = -1 try: est_time = self.bot_car.location.dist(target_location) / self.bot_car.velocity.flat().scalar_proj((target_location - self.bot_car.location).flat()) except: stub="catch div 0" self.controls.throttle = (2*math.atan(est_time)/math.pi)*1.2-0.2 if est_time>0 else 1 self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return def support(self, packet, position:int): #continue any strike after checking it if self.current_strike is not None: if check_strike(packet,self.ball_prediction,self.current_strike) and self.current_strike.slice_time-packet.game_info.seconds_elapsed < 1.5: self.active_sequence, strike_controls, strike_location, strike_time = execute_strike(packet,self.bot_car,self.current_strike,self.foes) self.controls = strike_controls self.renderer.draw_rect_3d(strike_location, 8, 8, True, self.renderer.red(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, strike_location, self.renderer.white()) self.renderer.draw_string_2d(20,20,3,3,f"throttle: {self.controls.throttle}",self.renderer.white()) return else: self.current_strike = None target_location = Vec3(0,0,0) if position==1: target_location = self.ball.location.flat() + Vec3(-self.ball.location.x/2,(self.bot_car.team*2-1)*3000,0) else: target_location = self.ball.location.flat() + (Vec3(0,(self.bot_car.team*2-1)*6500,0) - self.ball.location.flat()).rescale(6000) target_location = self.point_in_field(target_location) #second man in net on defence, or if would drive up wall if self.ball.location.y *(2*self.bot_car.team-1)>0 and self.ball.velocity.y *(2*self.bot_car.team-1)>0 or abs(target_location.y)>4600: target_location = Vec3(0,5200*(2*self.bot_car.team-1),0) #if it needs to drive around posts, do it in_goal = self.bot_car.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]) post0_ang = self.collision_posts[self.bot_car.team][0].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) std_ang_to_target = target_location.__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) facing_ang = self.bot_car.orientation.forward.ang_to(Vec3(1,0,1)) post1_ang = self.collision_posts[self.bot_car.team][1].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) travel_between_posts = post0_ang < std_ang_to_target < post1_ang facing_between_posts = post0_ang < facing_ang < post1_ang if not in_goal and not travel_between_posts: target_location = Vec3(0,5000*(2*self.bot_car.team-1),0) for ally in self.allies: if ally.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]): target_location = Vec3(-1*math.copysign(950,self.ball.location.x),4900,0) self.controls.throttle = min(self.bot_car.location.dist(target_location)**2/1000**2,1) if in_goal and self.bot_car.orientation.forward.y*(1-2*self.bot_car.team) >0.7 and abs(self.bot_car.location.y) <5220: self.controls.throttle = 0 if self.bot_car.velocity.length() <20 else -1*math.copysign(1,self.bot_car.velocity.dot(self.bot_car.orientation.forward)) self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return #exit goal if needed ##try: in_goal = self.bot_car.location.within(self.goal_corners[self.bot_car.team][0],self.goal_corners[self.bot_car.team][1]) post0_ang = self.collision_posts[self.bot_car.team][0].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) std_ang_to_target = target_location.__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) post1_ang = self.collision_posts[self.bot_car.team][1].__sub__(self.bot_car.location).flat().ang_to(Vec3(1,0,0)) between_posts = post0_ang < std_ang_to_target < post1_ang if not between_posts and in_goal: target_location = Vec3(0,(2*self.team-1)*5000,0) self.controls.throttle = min(self.bot_car.location.dist(target_location)**2/800**2+0.1,1) self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return ##except: ##stub="catch div 0 errors" self.controls.throttle = min(self.bot_car.location.dist(target_location)**2/1000**2,1) self.steer_toward(self.bot_car, target_location) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) self.renderer.draw_line_3d(self.bot_car.location, target_location, self.renderer.white()) return def perform_air_recovery(self, packet): try: self.controls.steer = self.bot_car.orientation.right.dot(self.bot_car.velocity.flat().normalized()) self.controls.pitch = self.bot_car.orientation.up.dot(self.bot_car.velocity.flat().normalized()) self.controls.roll = self.bot_car.orientation.right.dot(Vec3(0,0,1)) except: stub="I'm too lazy to catch div 0 properly" return
class MyBot(BaseAgent): # Default constructor def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() # Track boost pad information def initialize_agent(self): self.boost_pad_tracker.initialize_boosts(self.get_field_info()) # Main controller function - called many times per second def get_output(self, packet: GameTickPacket) -> SimpleControllerState: # Get currently active boost pad info self.boost_pad_tracker.update_boost_status(packet) # Continue sequences from previous call if self.active_sequence and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: return controls # Gather information about car and ball my_car = packet.game_cars[self.index] car_location = Vec3(my_car.physics.location) car_velocity = Vec3(my_car.physics.velocity) ball_location = Vec3(packet.game_ball.physics.location) if car_location.dist(ball_location) > 1500: # Set path of car to future ball location ball_prediction = self.get_ball_prediction_struct() # This can predict bounces, etc ball_in_future = find_slice_at_time(ball_prediction, packet.game_info.seconds_elapsed + 2) target_location = Vec3(ball_in_future.physics.location) self.renderer.draw_line_3d(ball_location, target_location, self.renderer.cyan()) else: target_location = ball_location # Draw rendering lines self.renderer.draw_line_3d(car_location, target_location, self.renderer.white()) self.renderer.draw_string_3d(car_location, 1, 1, f'Speed: {car_velocity.length():.1f}', self.renderer.white()) self.renderer.draw_rect_3d(target_location, 8, 8, True, self.renderer.cyan(), centered=True) # Front flip if car is moving at a certain speed if 750 < car_velocity.length() < 800: return self.begin_front_flip(packet) controls = SimpleControllerState() controls.steer = steer_toward_target(my_car, target_location) controls.throttle = 1.0 return controls # Car flip function def begin_front_flip(self, packet): # Do a front flip self.active_sequence = Sequence([ ControlStep(duration=0.05, controls=SimpleControllerState(jump=True)), ControlStep(duration=0.05, controls=SimpleControllerState(jump=False)), ControlStep(duration=0.2, controls=SimpleControllerState(jump=True, pitch=-1)), ControlStep(duration=0.8, controls=SimpleControllerState()), ]) # Return the controls associated with the beginning of the sequence return self.active_sequence.tick(packet)
def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker()
class Agent(DecisionAgent): def __init__(self, name, team, index): super().__init__(name, team, index) self.active_sequence: Sequence = None self.boost_pad_tracker = BoostPadTracker() self.init_db() def initialize_agent(self): # Set up information about the boost pads now that the game is active and the info is available self.boost_pad_tracker.initialize_boosts(self.get_field_info()) def init_db(self): self.client = pymongo.MongoClient("mongodb+srv://first_child:[email protected]/RocketBot?retryWrites=true&w=majority") self.db = self.client.get_database("RocketBot") self.flip_physics = self.db.get_collection("flip_physics") def write_flip_physics(self, flip_physics): if flip_physics is None: log_warn("Attempt to write None to database. Nothing will be written.", {}) return self.flip_physics.insert_one(flip_physics) def draw_state(self, parsed_packet: ParsedPacket, packet: rl.GameTickPacket): # Draw ball prediction line for where the ball is going to go ball_prediction = self.get_ball_prediction_struct() slices = list(map(lambda x : Vector(x.physics.location), ball_prediction.slices)) self.renderer.draw_polyline_3d(slices[::10], self.renderer.white()) # Write to the car the appropriate string self.write_string(parsed_packet.my_car.physics.location, self.display_on_car(parsed_packet, packet)) # Determine whether or not the ball is going to go into the goal goal_overlap: Vector = self.get_goal_overlap() if goal_overlap is not None: # The ball is going in self.draw_circle(goal_overlap, 100) def get_goal_overlap(self) -> Vector: ball_prediction = self.get_ball_prediction_struct() slices = list(map(lambda x : Vector(x.physics.location), ball_prediction.slices)) threshold = self.field_info.my_goal.location.y for (index, loc) in enumerate(slices): if abs(loc.y) < threshold: continue if index < len(slices) - 1 and abs(slices[index + 1].y) < threshold: continue return loc colissions: int = 0 def get_output(self, packet: GameTickPacket) -> SimpleControllerState: # Parse the packet to gather relevant information parsed_packet = parse_packet(self.team, packet) my_car = parsed_packet.my_car ball = parsed_packet.ball self.field_info = parse_field_info(self.team, self.get_field_info()) # Draw the ball if appropriate legend_entries: [LegendEntry] = [] if self.WRITE_STATE: state: str = f"{self.state}" legend_entries += [ LegendEntry(f"{self.state.__class__.__name__}", self.renderer.white()), ] if self.DRAW_BALL_PHYSICS: legend_entries += [ LegendEntry("Velocity", self.renderer.green()), LegendEntry("Angular Velocity", self.renderer.blue()), ] self.draw_physics_info(ball_physics) # self.draw_car_hitbox(parsed_packet.my_car.physics.location, parsed_packet.my_car.hitbox, Orientation(parsed_packet.my_car.physics.rotation)) # Draw if the car is currently colliding with the ball if __is_colliding( parsed_packet.my_car.physics.location, parsed_packet.my_car.hitbox, Orientation(parsed_packet.my_car.physics.rotation), parsed_packet.ball.physics.location, parsed_packet.ball.hitbox ): self.colissions += 1 # legend_entries.append(LegendEntry(f"Colissions: {self.colissions}", self.renderer.orange())) self.draw_legend(legend_entries) # Draw the state / debug information self.draw_state(parsed_packet, packet) # Keep our boost pad info updated with which pads are currently active self.boost_pad_tracker.update_boost_status(packet) # For fernado, make the bot shit talk a little bit if (my_car.physics.location.dist(ball.physics.location)) < 165: self.send_quick_chat(team_only=False, quick_chat=QuickChatSelection.Reactions_CloseOne) if self.current_flip_physics: self.current_flip_physics["contact"] = True # Check for current sequence and continue sequence if there is one if self.active_sequence and not self.active_sequence.done: controls = self.active_sequence.tick(packet) if controls is not None: self.prev_seq_done = False continue_sequence = self.sequence_hook(controls) if continue_sequence: return controls # Determine game state (different from draw state) self.state = self.next_state(parsed_packet, packet) return self.state.get_output(parsed_packet, packet, self)