def exec(self, bot) -> SimpleControllerState: man_ct = bot.info.time - self.maneuver_start_time controls = SimpleControllerState() car = bot.info.my_car vel_f = proj_onto_size(car.vel, car.forward) # Reverse a bit if vel_f > -50 and man_ct < 0.3: controls.throttle = -1 self.halfflip_start_time = bot.info.time return controls ct = bot.info.time - self.halfflip_start_time # States of jump if ct >= self._t_finishing: self._almost_finished = True controls.throttle = 1 controls.boost = self.boost if car.on_ground: self.done = True else: bot.maneuver = RecoveryManeuver() self.done = True elif ct >= self._t_roll_begin: controls.pitch = -1 controls.roll = 1 elif ct >= self._t_second_jump_end: controls.pitch = -1 elif ct >= self._t_second_jump_begin: controls.jump = 1 controls.pitch = 1 elif ct >= self._t_first_jump_end: controls.pitch = 1 else: controls.jump = 1 controls.throttle = -1 controls.pitch = 1 return controls
def initialize_agent(self): self.tournament = True self.print("Initalizing thread(s)...") if not self.tournament: self.gui = Gui(self) self.print("Starting the GUI...") self.gui.start() self.predictions = { "closest_enemy": 0, "own_goal": False, "goal": False, "ball_struct": None, "team_from_goal": (), "team_to_ball": (), "self_from_goal": 0, "self_to_ball": 0, "done": False } self.goalie = False self.air_bud = False self.debug = [[], []] self.debugging = False self.debug_lines = True self.debug_3d_bool = True self.debug_stack_bool = True self.debug_2d_bool = False self.show_coords = False self.debug_ball_path = False self.debug_ball_path_precision = 10 self.disable_driving = False self.prediction = Prediction(self) self.print("Starting the predictive service...") self.prediction.start() self.match_comms = None self.print("Building game information") mutators = self.get_match_settings().MutatorSettings() gravity = [ Vector(z=-650), Vector(z=-325), Vector(z=-1137.5), Vector(z=-3250) ] base_boost_accel = 991 + (2 / 3) boost_accel = [ base_boost_accel, base_boost_accel * 1.5, base_boost_accel * 2, base_boost_accel * 10 ] self.gravity = gravity[mutators.GravityOption()] self.boost_accel = boost_accel[mutators.BoostStrengthOption()] self.friends = () self.foes = () self.me = car_object(self.index) self.ball_to_goal = -1 self.ball = ball_object() self.game = game_object(not self.team) self.boosts = () self.friend_goal = goal_object(self.team) self.foe_goal = goal_object(not self.team) self.stack = [] self.time = 0 self.prev_time = 0 self.ready = False self.controller = SimpleControllerState() self.kickoff_flag = False self.kickoff_done = True self.last_time = 0 self.my_score = 0 self.foe_score = 0 self.playstyles = Playstyle self.playstyle = self.playstyles.Neutral self.can_shoot = None self.shooting = False self.shot_weight = -1 self.shot_time = -1 self.panic = False self.odd_tick = 0 # Use this for thing that can be run at 30 or 60 tps instead of 120
def wallHyperSpeedJump(self): controls = [] timers = [] wall = which_wall( self.me.location ) # 0 - orange backboard 1 - east wall 2 - blue backboard 3 - west wall aimVec = Vector( [self.me.location.data[0] * 1, self.me.location.data[1] * 1, 12000] ) # aimVec.data[2] = 12000 if wall == 0: aimVec.data[1] = 6000 elif wall == 1: aimVec.data[0] = -6000 elif wall == 2: aimVec.data[1] = -6000 else: aimVec.data[0] = 6000 targetLocal = toLocal(aimVec, self.me) target_angle = math.atan2(targetLocal.data[1], targetLocal.data[0]) _yaw = math.sin(target_angle) if _yaw < 0: yaw = -clamp(1, 0.5, abs(_yaw)) else: yaw = clamp(1, 0.5, abs(_yaw)) _pitch = math.cos(target_angle) if abs(_pitch) > 0.35: # print("bailing out of hyper jump") return False pitch = -clamp(0.35, 0.15, _pitch) if self.time - self.hyperJumpTimer > 0.2: self.hyperJumpTimer = self.time else: return if self.forward: throttle = 1 else: throttle = -1 pitch = -pitch controls.append(SimpleControllerState(jump=True, throttle=throttle, yaw=-yaw,)) timers.append(self.fakeDeltaTime * 3) controls.append(SimpleControllerState(jump=False, throttle=throttle)) timers.append(self.fakeDeltaTime * 2) controls.append( SimpleControllerState( jump=True, pitch=pitch, throttle=throttle, yaw=yaw, handbrake=True ) ) timers.append(self.fakeDeltaTime * 2) # print(f"hyper jumping {self.time}") self.activeState = Divine_Mandate(self, controls, timers) return True
def chase_controller(agent, target_object, target_speed): #note target location is an obj location = toLocal(target_object, agent.car) controller_state = SimpleControllerState() angle_to_ball = math.atan2(location.data[1], location.data[0]) current_speed = velocity2D(agent.car) ball_path = agent.get_ball_prediction_struct( ) #next 6 seconds of ball's path print(bal_path[1]) #to steer if angle_to_ball > 0.1: controller_state.steer = controller_state.yaw = 1 elif angle_to_ball < -0.1: controller_state.steer = controller_state.yaw = -1 else: controller_state.steer = controller_state.yaw = 0 #adjust speed if target_speed > current_speed: controller_state.throttle = 1.0 if target_speed > 1400 and agent.start > 2.2 and current_speed < 2250: controller_state.boost = True elif target_speed < current_speed: controller_state.throttle = 0 #techniquing time_diff = time.time() - agent.start #time since last technique if time_diff > 2.2 and distance2D( target_object.location, agent.car.location) > 1000 and abs(angle_to_ball) < 1.3: agent.start = time.time() elif time_diff <= 0.1: controller_state.jump = True controller_state.pitch = -1 elif time_diff >= 0.1 and time_diff <= 0.15: controller_state.jump = False elif time_diff > 0.15 and time_diff < 1: controller_state.jump = True controller_state.yaw = controller_state.steer controller_state.pitch = -1 return controller_state
def __init__(self): self.controls = SimpleControllerState() self.finished = True
def initialize_agent(self): #This runs once before the bot starts up self.controller_state = SimpleControllerState() self.car_status = 'none' self.jumps = [] self.average_xy_speed = 0
def shot_controller(agent, target_object, target_speed): #note target location is an obj local_goal_location = toLocal([0, FIELD_LENGTH / 2, 100], agent.car) goal_angle = math.atan2(local_goal_location.data[1], local_goal_location.data[0]) location = toLocal(target_object, agent.car) controller_state = SimpleControllerState() angle_to_target = math.atan2(location.data[1], location.data[0]) current_speed = velocity2D(agent.car) #to steer if angle_to_target > 0.1: controller_state.steer = controller_state.yaw = 1 elif angle_to_target < -0.1: controller_state.steer = controller_state.yaw = -1 else: controller_state.steer = controller_state.yaw = 0 #adjust speed if target_speed > current_speed: controller_state.throttle = 1.0 if target_speed > 1400 and agent.start > 2.2 and current_speed < 2250: controller_state.boost = True elif target_speed < current_speed: controller_state.throttle = 0 #techniquing time_diff = time.time() - agent.start #time since last technique if time_diff > 2.2 and distance2D(target_object, agent.car) > 270: agent.start = time.time() elif time_diff <= 0.1: controller_state.jump = True controller_state.pitch = -1 elif time_diff >= 0.1 and time_diff <= 0.15: controller_state.jump = False controller_state.pitch = -1 elif time_diff > 0.15 and time_diff < 1: controller_state.jump = True controller_state.yaw = math.sin(goal_angle) controller_state.pitch = -abs(math.cos(goal_angle)) return controller_state
class VirxERLU(BaseAgent): # Massive thanks to ddthj/GoslingAgent (GitHub repo) for the basis of VirxERLU def initialize_agent(self): self.tournament = True self.startup_time = time_ns() self.debug = [[], []] self.debugging = not self.tournament self.debug_lines = True self.debug_3d_bool = True self.debug_stack_bool = True self.debug_2d_bool = False self.show_coords = False self.debug_ball_path = False self.debug_ball_path_precision = 10 self.debug_vector = Vector() self.disable_driving = False self.goalie = False self.jump = True self.double_jump = True self.ground_shot = True self.aerials = True T = datetime.now() T = T.strftime("%Y-%m-%d %H;%M") self.traceback_file = (os.getcwd(), f"-traceback ({T}).txt") self.predictions = { "closest_enemy": 0, "own_goal": False, "goal": False, "team_from_goal": (), "team_to_ball": (), "self_from_goal": 0, "self_to_ball": 0, "was_down": False, "enemy_time_to_ball": 7, "self_min_time_to_ball": 7 } self.match_comms = MatchComms(self) self.print("Starting the match communication handler...") self.match_comms.start() self.ball_prediction_struct = None self.print("Building game information") match_settings = self.get_match_settings() mutators = match_settings.MutatorSettings() gravity = (Vector(z=-650), Vector(z=-325), Vector(z=-1137.5), Vector(z=-3250)) base_boost_accel = 991 + (2 / 3) boost_accel = (base_boost_accel, base_boost_accel * 1.5, base_boost_accel * 2, base_boost_accel * 10) boost_amount = ("default", "unlimited", "slow recharge", "fast recharge", "no boost") game_mode = ("soccer", "hoops", "dropshot", "hockey", "rumble", "heatseeker") self.gravity = gravity[mutators.GravityOption()] self.boost_accel = boost_accel[mutators.BoostStrengthOption()] self.boost_amount = boost_amount[mutators.BoostOption()] self.game_mode = game_mode[match_settings.GameMode()] if self.game_mode == "heatseeker": self.print("Preparing for heatseeker") self.goalie = True if not self.tournament: self.gui = Gui(self) self.print("Starting the GUI...") self.gui.start() self.friends = () self.foes = () self.me = car_object(self.index) self.ball_to_goal = -1 self.ball = ball_object() self.game = game_object() self.boosts = () self.friend_goal = goal_object(self.team) self.foe_goal = goal_object(not self.team) self.stack = [] self.time = 0 self.ready = False self.controller = SimpleControllerState() self.kickoff_flag = False self.kickoff_done = True self.shooting = False self.odd_tick = -1 self.best_shot_value = 92.75 self.future_ball_location_slice = 180 self.min_intercept_slice = 180 self.playstyles = Playstyle self.playstyle = self.playstyles.Neutral self.can_shoot = None self.shot_weight = -1 self.shot_time = -1 def retire(self): # Stop the currently running threads if not self.tournament: self.gui.stop() self.match_comms.stop() @staticmethod def is_hot_reload_enabled(): # The threads that VirxERLU uses aren't compatible with hot reloading # Use the Continue and Spawn option in the GUI instead return False def get_ready(self, packet): field_info = self.get_field_info() self.boosts = tuple( boost_object(i, boost.location, boost.is_full_boost) for i, boost in enumerate(field_info.boost_pads)) self.refresh_player_lists(packet) self.ball.update(packet) self.init() load_time = (time_ns() - self.startup_time) / 1e+6 print(f"{self.name}: Built game info in {load_time} milliseconds") if self.name in {"VirxEB", "ABot"}: print(f"{self.name}: Check me out at https://www.virxcase.dev!!!") self.ready = True def refresh_player_lists(self, packet): # Useful to keep separate from get_ready because humans can join/leave a match self.friends = tuple( car_object(i, packet) for i in range(packet.num_cars) if packet.game_cars[i].team is self.team and i != self.index) self.foes = tuple( car_object(i, packet) for i in range(packet.num_cars) if packet.game_cars[i].team != self.team) self.me = car_object(self.index, packet) def push(self, routine): self.stack.append(routine) def pop(self): return self.stack.pop() def line(self, start, end, color=None): if self.debugging and self.debug_lines: color = color if color is not None else self.renderer.grey() self.renderer.draw_line_3d( start.copy(), end.copy(), self.renderer.create_color(255, *color) if type(color) in {list, tuple} else color) def polyline(self, vectors, color=None): if self.debugging and self.debug_lines: color = color if color is not None else self.renderer.grey() vectors = tuple(vector.copy() for vector in vectors) self.renderer.draw_polyline_3d( vectors, self.renderer.create_color(255, *color) if type(color) in {list, tuple} else color) def sphere(self, location, radius, color=None): if self.debugging and self.debug_lines: x = Vector(x=radius) y = Vector(y=radius) z = Vector(z=radius) diag = Vector(1.0, 1.0, 1.0).scale(radius).x d1 = Vector(diag, diag, diag) d2 = Vector(-diag, diag, diag) d3 = Vector(-diag, -diag, diag) d4 = Vector(-diag, diag, -diag) self.line(location - x, location + x, color) self.line(location - y, location + y, color) self.line(location - z, location + z, color) self.line(location - d1, location + d1, color) self.line(location - d2, location + d2, color) self.line(location - d3, location + d3, color) self.line(location - d4, location + d4, color) def print(self, item): if not self.tournament: print(f"{self.name}: {item}") def dbg_3d(self, item): self.debug[0].append(str(item)) def dbg_2d(self, item): self.debug[1].append(str(item)) def clear(self): self.shooting = False self.shot_weight = -1 self.shot_time = -1 self.stack = [] def is_clear(self): return len(self.stack) < 1 def preprocess(self, packet): if packet.num_cars != len(self.friends) + len(self.foes) + 1: self.refresh_player_lists(packet) set(map(lambda car: car.update(packet), self.friends)) set(map(lambda car: car.update(packet), self.foes)) set(map(lambda pad: pad.update(packet), self.boosts)) self.ball.update(packet) self.me.update(packet) self.game.update(self.team, packet) self.time = self.game.time self.gravity = self.game.gravity # When a new kickoff begins we empty the stack if not self.kickoff_flag and self.game.round_active and self.game.kickoff: self.kickoff_done = False self.clear() # Tells us when to go for kickoff self.kickoff_flag = self.game.round_active and self.game.kickoff self.ball_to_goal = self.friend_goal.location.flat_dist( self.ball.location) self.odd_tick += 1 if self.odd_tick > 3: self.odd_tick = 0 self.ball_prediction_struct = self.get_ball_prediction_struct() def get_weight(self, shot=None, index=None): if index is not None: return self.max_shot_weight - math.ceil(index / 2) if shot is not None: if shot is self.best_shot: return self.max_shot_weight + 1 if shot is self.anti_shot: return self.max_shot_weight - 1 for shot_list in (self.offensive_shots, self.defensive_shots): try: return self.max_shot_weight - math.ceil( shot_list.index(shot) / 2) except ValueError: continue return self.max_shot_weight - 2 def get_output(self, packet): try: # Reset controller self.controller.__init__(use_item=True) # Get ready, then preprocess if not self.ready: self.get_ready(packet) self.preprocess(packet) if self.me.demolished: if not self.is_clear(): self.clear() elif self.game.round_active: self.dbg_3d(self.playstyle.name) stack_routine_name = '' if self.is_clear( ) else self.stack[0].__class__.__name__ if stack_routine_name in { 'Aerial', 'jump_shot', 'double_jump', 'ground_shot', 'short_shot' }: self.shooting = True if stack_routine_name is not 'short_shot': self.shot_weight = self.get_weight( self.stack[0].targets) self.shot_time = self.stack[0].intercept_time else: self.shooting = False self.shot_weight = -1 self.shot_time = -1 try: self.run( ) # Run strategy code; This is a very expensive function to run except Exception: t_file = os.path.join(self.traceback_file[0], self.name + self.traceback_file[1]) print(f"ERROR in {self.name}; see '{t_file}'") print_exc(file=open(t_file, "a")) # run the routine on the end of the stack if not self.is_clear(): try: r_name = self.stack[-1].__class__.__name__ self.stack[-1].run(self) except Exception: t_file = os.path.join(self.traceback_file[0], r_name + self.traceback_file[1]) print( f"ERROR in {self.name}'s {r_name} routine; see '{t_file}'" ) print_exc(file=open(t_file, "a")) # This is a ton of debugging stuff if self.debugging: if self.debug_3d_bool: if self.debug_stack_bool: self.debug[0] = itertools.chain( self.debug[0], ("STACK:", ), (item.__class__.__name__ for item in reversed(self.stack))) self.renderer.draw_string_3d( tuple(self.me.location), 2, 2, "\n".join(self.debug[0]), self.renderer.team_color(alt_color=True)) self.debug[0] = [] if self.show_coords: self.debug[1].insert( 0, f"Hitbox: [{self.me.hitbox.length} {self.me.hitbox.width} {self.me.hitbox.height}]" ) self.debug[1].insert( 0, f"Location: {round(self.me.location)}") car = self.me center = car.local(car.hitbox.offset) + car.location top = car.up * (car.hitbox.height / 2) front = car.forward * (car.hitbox.length / 2) right = car.right * (car.hitbox.width / 2) bottom_front_right = center - top + front + right bottom_front_left = center - top + front - right bottom_back_right = center - top - front + right bottom_back_left = center - top - front - right top_front_right = center + top + front + right top_front_left = center + top + front - right top_back_right = center + top - front + right top_back_left = center + top - front - right hitbox_color = self.renderer.team_color(alt_color=True) self.polyline((top_back_left, top_front_left, top_front_right, bottom_front_right, bottom_front_left, top_front_left), hitbox_color) self.polyline((bottom_front_left, bottom_back_left, bottom_back_right, top_back_right, top_back_left, bottom_back_left), hitbox_color) self.line(bottom_back_right, bottom_front_right, hitbox_color) self.line(top_back_right, top_front_right, hitbox_color) if self.debug_2d_bool: if not self.is_clear( ) and self.stack[0].__class__.__name__ in { 'Aerial', 'jump_shot', 'ground_shot', 'double_jump' }: self.dbg_2d( round(self.stack[0].intercept_time - self.time, 4)) self.renderer.draw_string_2d( 20, 300, 2, 2, "\n".join(self.debug[1]), self.renderer.team_color(alt_color=True)) self.debug[1] = [] if self.debug_ball_path and self.ball_prediction_struct is not None: self.polyline( tuple( Vector(ball_slice.physics.location.x, ball_slice.physics.location.y, ball_slice.physics.location.z) for ball_slice in self.ball_prediction_struct. slices[::self.debug_ball_path_precision])) else: self.debug = [[], []] return SimpleControllerState( ) if self.disable_driving else self.controller except Exception: t_file = os.path.join(self.traceback_file[0], "VirxERLU" + self.traceback_file[1]) print( f"ERROR with VirxERLU in {self.name}; see '{t_file}' and please report the bug at 'https://github.com/VirxEC/VirxERLU/issues'" ) print_exc(file=open(t_file, "a")) return SimpleControllerState() def handle_match_comm(self, msg): pass def test(self): pass def run(self): pass def handle_quick_chat(self, index, team, quick_chat): pass def init(self): pass
def initialize_agent(self): self.tournament = True self.startup_time = time_ns() self.debug = [[], []] self.debugging = not self.tournament self.debug_lines = True self.debug_3d_bool = True self.debug_stack_bool = True self.debug_2d_bool = False self.show_coords = False self.debug_ball_path = False self.debug_ball_path_precision = 10 self.debug_vector = Vector() self.disable_driving = False self.goalie = False self.jump = True self.double_jump = True self.ground_shot = True self.aerials = True T = datetime.now() T = T.strftime("%Y-%m-%d %H;%M") self.traceback_file = (os.getcwd(), f"-traceback ({T}).txt") self.predictions = { "closest_enemy": 0, "own_goal": False, "goal": False, "team_from_goal": (), "team_to_ball": (), "self_from_goal": 0, "self_to_ball": 0, "was_down": False, "enemy_time_to_ball": 7, "self_min_time_to_ball": 7 } self.match_comms = MatchComms(self) self.print("Starting the match communication handler...") self.match_comms.start() self.ball_prediction_struct = None self.print("Building game information") match_settings = self.get_match_settings() mutators = match_settings.MutatorSettings() gravity = (Vector(z=-650), Vector(z=-325), Vector(z=-1137.5), Vector(z=-3250)) base_boost_accel = 991 + (2 / 3) boost_accel = (base_boost_accel, base_boost_accel * 1.5, base_boost_accel * 2, base_boost_accel * 10) boost_amount = ("default", "unlimited", "slow recharge", "fast recharge", "no boost") game_mode = ("soccer", "hoops", "dropshot", "hockey", "rumble", "heatseeker") self.gravity = gravity[mutators.GravityOption()] self.boost_accel = boost_accel[mutators.BoostStrengthOption()] self.boost_amount = boost_amount[mutators.BoostOption()] self.game_mode = game_mode[match_settings.GameMode()] if self.game_mode == "heatseeker": self.print("Preparing for heatseeker") self.goalie = True if not self.tournament: self.gui = Gui(self) self.print("Starting the GUI...") self.gui.start() self.friends = () self.foes = () self.me = car_object(self.index) self.ball_to_goal = -1 self.ball = ball_object() self.game = game_object() self.boosts = () self.friend_goal = goal_object(self.team) self.foe_goal = goal_object(not self.team) self.stack = [] self.time = 0 self.ready = False self.controller = SimpleControllerState() self.kickoff_flag = False self.kickoff_done = True self.shooting = False self.odd_tick = -1 self.best_shot_value = 92.75 self.future_ball_location_slice = 180 self.min_intercept_slice = 180 self.playstyles = Playstyle self.playstyle = self.playstyles.Neutral self.can_shoot = None self.shot_weight = -1 self.shot_time = -1
def controller(self, agent, angle): controller_state = SimpleControllerState() steer_value = steer(angle) controller_state.steer = steer_value controller_state.throttle = 1 controller_state.handbrake = True if self.level == PowerSlideLevel.NORMAL: balance_threshold = 0.25 * abs( agent.me.angular_velocity.data[2])**2 + 0.05 if balance_threshold * -1 <= angle <= balance_threshold: controller_state.handbrake = False controller_state.boost = True if abs(agent.me.angular_velocity.data[2]) >= 0.15: controller_state.steer = sign( agent.me.angular_velocity.data[2]) * -1 else: controller_state.steer = 0 elif self.level == PowerSlideLevel.U_TURN: if abs(angle) < 1.15: controller_state.steer = steer_value * -1 controller_state.throttle = -1 controller_state.handbrake = False controller_state.boost = False if abs(angle) < 0.15: controller_state.steer = 0 return controller_state
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: self.game.read_game_information(packet, self.get_rigid_body_tick(), self.get_field_info()) self.controls = SimpleControllerState() next_state = self.state if self.state == State.RESET: self.timer = 0.0 # put the car in the middle of the field car_state = CarState(physics=Physics(location=Vector3(0, 0, 18), velocity=Vector3(0, 0, 0), rotation=Rotator(0, 0, 0), angular_velocity=Vector3( 0, 0, 0)), jumped=False, double_jumped=False) theta = random.uniform(0, 6.28) pos = Vector3(sin(theta) * 1000.0, cos(theta) * 1000.0, 100.0) # put the ball somewhere out of the way ball_state = BallState( physics=Physics(location=pos, velocity=Vector3(0, 0, 0), rotation=Rotator(0, 0, 0), angular_velocity=Vector3(0, 0, 0))) self.set_game_state( GameState(ball=ball_state, cars={self.game.id: car_state})) next_state = State.WAIT if self.state == State.WAIT: if self.timer > 0.2: next_state = State.INITIALIZE if self.state == State.INITIALIZE: self.action = Dodge(self.game.my_car) self.action.duration = 0.1 self.action.direction = vec2(self.game.ball.location) next_state = State.RUNNING if self.state == State.RUNNING: self.action.step(self.game.time_delta) self.controls = self.action.controls print(self.controls.jump) if self.timer > self.timeout: next_state = State.RESET self.timer += self.game.time_delta self.state = next_state return self.controls
def exampleController(agent, target_object, target_speed): location = toLocal(target_object, agent.me) controller_state = SimpleControllerState() angle_to_ball = math.atan2(location.data[1], location.data[0]) current_speed = velocity2D(agent.me) #steering if angle_to_ball > 0.1: controller_state.steer = controller_state.yaw = 1 elif angle_to_ball < -0.1: controller_state.steer = controller_state.yaw = -1 else: controller_state.steer = controller_state.yaw = 0 #throttle if target_speed > current_speed: controller_state.throttle = 1.0 if target_speed > 1400 and agent.start > 2.2 and current_speed < 2250: controller_state.boost = True elif target_speed < current_speed: controller_state.throttle = 0 #dodging time_difference = time.time() - agent.start if time_difference > 2.2 and distance2D( target_object, agent.me) > 1000 and abs(angle_to_ball) < 1.3: agent.start = time.time() elif time_difference <= 0.1: controller_state.jump = True controller_state.pitch = -1 elif time_difference >= 0.1 and time_difference <= 0.15: controller_state.jump = False controller_state.pitch = -1 elif time_difference > 0.15 and time_difference < 1: controller_state.jump = True controller_state.yaw = controller_state.steer controller_state.pitch = -1 return controller_state
def shotController(agent, target_object, target_speed): goal_local = toLocal([0, -sign(agent.team) * FIELD_LENGTH / 2, 100], agent.me) goal_angle = math.atan2(goal_local.data[1], goal_local.data[0]) location = toLocal(target_object, agent.me) controller_state = SimpleControllerState() angle_to_target = math.atan2(location.data[1], location.data[0]) current_speed = velocity2D(agent.me) #steering if angle_to_target > 0.1: controller_state.steer = controller_state.yaw = 1 elif angle_to_target < -0.1: controller_state.steer = controller_state.yaw = -1 else: controller_state.steer = controller_state.yaw = 0 #throttle if angle_to_target >= 1.4: target_speed -= 1400 else: if target_speed > 1400 and target_speed > current_speed and agent.start > 2.2 and current_speed < 2250: controller_state.boost = True if target_speed > current_speed: controller_state.throttle = 1.0 elif target_speed < current_speed: controller_state.throttle = 0 #dodging time_difference = time.time() - agent.start if time_difference > 2.2 and distance2D(target_object, agent.me) <= 270: agent.start = time.time() elif time_difference <= 0.1: controller_state.jump = True controller_state.pitch = -1 elif time_difference >= 0.1 and time_difference <= 0.15: controller_state.jump = False controller_state.pitch = -1 elif time_difference > 0.15 and time_difference < 1: controller_state.jump = True controller_state.yaw = math.sin(goal_angle) controller_state.pitch = -abs(math.cos(goal_angle)) return controller_state
def initialize_agent(self): self.ball_status = 3 self.timer = 0.0 self.controller_state = SimpleControllerState()
class GoslingAgent(BaseAgent): #This is the main object of Gosling Utils. It holds/updates information about the game and runs routines #All utils rely on information being structured and accessed the same way as configured in this class def initialize_agent(self): #A list of cars for both teammates and opponents self.friends = [] self.foes = [] #This holds the carobject for our agent self.me = car_object(self.index) self.ball = ball_object() self.game = game_object() #A list of boosts self.boosts = [] #goals self.friend_goal = goal_object(self.team) self.foe_goal = goal_object(not self.team) #A list that acts as the routines stack self.stack = [] #Game time self.time = 0.0 #Whether or not botAgent has run its get_ready() function self.ready = False #the controller that is returned to the framework after every tick self.controller = SimpleControllerState() #a flag that tells us when kickoff is happening self.kickoff_flag = False def get_ready(self,packet): #Preps all of the objects that will be updated during play field_info = self.get_field_info() for i in range(field_info.num_boosts): boost = field_info.boost_pads[i] self.boosts.append(boost_object(i,boost.location,boost.is_full_boost)) self.refresh_player_lists(packet) self.ball.update(packet) self.ready = True def refresh_player_lists(self,packet): #makes new freind/foe lists #Useful to keep separate from get_ready because humans can join/leave a match self.friends = [car_object(i,packet) for i in range(packet.num_cars) if packet.game_cars[i].team == self.team and i != self.index] self.foes = [car_object(i,packet) for i in range(packet.num_cars) if packet.game_cars[i].team != self.team] def push(self,routine): #Shorthand for adding a routine to the stack self.stack.append(routine) def pop(self): #Shorthand for removing a routine from the stack, returns the routine return self.stack.pop() def line(self,start,end,color=None): color = color if color != None else [255,255,255] self.renderer.draw_line_3d(start,end,self.renderer.create_color(255,*color)) def debug_stack(self): #Draws the stack on the screen white = self.renderer.white() for i in range(len(self.stack)-1,-1,-1): text = self.stack[i].__class__.__name__ self.renderer.draw_string_2d(10,50+(50*(len(self.stack)-i)),3,3,text,white) def clear(self): #Shorthand for clearing the stack of all routines self.stack = [] def preprocess(self,packet): #Calling the update functions for all of the objects if packet.num_cars != len(self.friends)+len(self.foes)+1: self.refresh_player_lists(packet) for car in self.friends: car.update(packet) for car in self.foes: car.update(packet) for pad in self.boosts: pad.update(packet) self.ball.update(packet) self.me.update(packet) self.game.update(packet) self.time = packet.game_info.seconds_elapsed #When a new kickoff begins we empty the stack if self.kickoff_flag == False and packet.game_info.is_round_active and packet.game_info.is_kickoff_pause: self.stack = [] #Tells us when to go for kickoff self.kickoff_flag = packet.game_info.is_round_active and packet.game_info.is_kickoff_pause def get_output(self,packet): #Reset controller self.controller.__init__() #Get ready, then preprocess if not self.ready: self.get_ready(packet) self.preprocess(packet) self.renderer.begin_rendering() #Run our strategy code self.run() #run the routine on the end of the stack if len(self.stack) > 0: self.stack[-1].run(self) self.renderer.end_rendering() #send our updated controller back to rlbot return self.controller def run(self): #override this with your strategy code pass
def get_output(self, packet): try: # Reset controller self.controller.__init__(use_item=True) # Get ready, then preprocess if not self.ready: self.get_ready(packet) self.preprocess(packet) if self.me.demolished: if not self.is_clear(): self.clear() elif self.game.round_active: self.dbg_3d(self.playstyle.name) stack_routine_name = '' if self.is_clear( ) else self.stack[0].__class__.__name__ if stack_routine_name in { 'Aerial', 'jump_shot', 'double_jump', 'ground_shot', 'short_shot' }: self.shooting = True if stack_routine_name is not 'short_shot': self.shot_weight = self.get_weight( self.stack[0].targets) self.shot_time = self.stack[0].intercept_time else: self.shooting = False self.shot_weight = -1 self.shot_time = -1 try: self.run( ) # Run strategy code; This is a very expensive function to run except Exception: t_file = os.path.join(self.traceback_file[0], self.name + self.traceback_file[1]) print(f"ERROR in {self.name}; see '{t_file}'") print_exc(file=open(t_file, "a")) # run the routine on the end of the stack if not self.is_clear(): try: r_name = self.stack[-1].__class__.__name__ self.stack[-1].run(self) except Exception: t_file = os.path.join(self.traceback_file[0], r_name + self.traceback_file[1]) print( f"ERROR in {self.name}'s {r_name} routine; see '{t_file}'" ) print_exc(file=open(t_file, "a")) # This is a ton of debugging stuff if self.debugging: if self.debug_3d_bool: if self.debug_stack_bool: self.debug[0] = itertools.chain( self.debug[0], ("STACK:", ), (item.__class__.__name__ for item in reversed(self.stack))) self.renderer.draw_string_3d( tuple(self.me.location), 2, 2, "\n".join(self.debug[0]), self.renderer.team_color(alt_color=True)) self.debug[0] = [] if self.show_coords: self.debug[1].insert( 0, f"Hitbox: [{self.me.hitbox.length} {self.me.hitbox.width} {self.me.hitbox.height}]" ) self.debug[1].insert( 0, f"Location: {round(self.me.location)}") car = self.me center = car.local(car.hitbox.offset) + car.location top = car.up * (car.hitbox.height / 2) front = car.forward * (car.hitbox.length / 2) right = car.right * (car.hitbox.width / 2) bottom_front_right = center - top + front + right bottom_front_left = center - top + front - right bottom_back_right = center - top - front + right bottom_back_left = center - top - front - right top_front_right = center + top + front + right top_front_left = center + top + front - right top_back_right = center + top - front + right top_back_left = center + top - front - right hitbox_color = self.renderer.team_color(alt_color=True) self.polyline((top_back_left, top_front_left, top_front_right, bottom_front_right, bottom_front_left, top_front_left), hitbox_color) self.polyline((bottom_front_left, bottom_back_left, bottom_back_right, top_back_right, top_back_left, bottom_back_left), hitbox_color) self.line(bottom_back_right, bottom_front_right, hitbox_color) self.line(top_back_right, top_front_right, hitbox_color) if self.debug_2d_bool: if not self.is_clear( ) and self.stack[0].__class__.__name__ in { 'Aerial', 'jump_shot', 'ground_shot', 'double_jump' }: self.dbg_2d( round(self.stack[0].intercept_time - self.time, 4)) self.renderer.draw_string_2d( 20, 300, 2, 2, "\n".join(self.debug[1]), self.renderer.team_color(alt_color=True)) self.debug[1] = [] if self.debug_ball_path and self.ball_prediction_struct is not None: self.polyline( tuple( Vector(ball_slice.physics.location.x, ball_slice.physics.location.y, ball_slice.physics.location.z) for ball_slice in self.ball_prediction_struct. slices[::self.debug_ball_path_precision])) else: self.debug = [[], []] return SimpleControllerState( ) if self.disable_driving else self.controller except Exception: t_file = os.path.join(self.traceback_file[0], "VirxERLU" + self.traceback_file[1]) print( f"ERROR with VirxERLU in {self.name}; see '{t_file}' and please report the bug at 'https://github.com/VirxEC/VirxERLU/issues'" ) print_exc(file=open(t_file, "a")) return SimpleControllerState()
def initialize_agent(self): #This runs once before the bot starts up self.controller_state = SimpleControllerState()
def get_controls(game_info, sub_state_machine): controls = SimpleControllerState() persistent = game_info.persistent return controls, persistent
def get_output(self, game: GameTickPacket) -> SimpleControllerState: controller = empty_controller = SimpleControllerState() """ Check if a goal was scored, append rewards """ if len(self.rewards) + 1 == len(self.fake_labels_list): if game.teams[0].score + game.teams[ 1].score > self.team0scored + self.team1scored: if game.teams[0].score > self.team0scored: self.team0scored = game.teams[0].score if self.team == 0: reward = [1] else: reward = [-1] elif game.teams[1].score > self.team1scored: self.team1scored = game.teams[1].score if self.team == [1]: reward = [1] else: reward = [-1] self.rewards.append(reward) # print('Rew: {} {} {}'.format(len(self.rewards), len(self.p_inputs_list), len(self.fake_labels_list))) """ Caclulate average loss, backprop and save after every batch """ if (self.team0scored + self.team1scored) % self.batch_size == 0 and ( self.team0scored + self.team1scored) > 0: self.episodes += 1 eprewards = np.array( self.rewards, dtype=float) # Create numpy array of rewards from list eprewards = np.vstack(eprewards) discounted_epr = discount_rewards( eprewards ) # Calculate discounted rewards going backwards from goal discounted_epr -= np.mean(discounted_epr) discounted_epr /= np.std(discounted_epr) lx = self.torch.stack(self.p_inputs_list).float().to( self.device).squeeze(1) ly = self.torch.Tensor(self.fake_labels_list).to( self.device) losses = self.loss_computator( lx, ly ) # Calculate 'difference' between NN controller outputs and actual (sampled) outputs t_discounted_epr = self.torch.from_numpy( discounted_epr).float().to(self.device) # print('RewLossShape: {} OutpLossShape: {}'.format(losses.shape, t_discounted_epr.shape)) losses *= t_discounted_epr # Combine reward losses with controller output losses loss = self.torch.mean(losses) loss.backward( self.torch.tensor(1.0 / self.batch_size).to( self.device)) """ Run optimizer after batch is complete """ self.optimizer.step() self.optimizer.zero_grad() self.torch.save(self.GURUNN.state_dict(), "model-2fc_BS32_a.pt") # Save self.p_inputs_list, self.fake_labels_list, self.rewards = [],[],[] # reset if self.episodes % 10 == 0: self.torch.save( self.GURUNN.state_dict(), f"model-2fc_BS32_a_ep{self.episodes}.pt" ) # Keep records of every 10 episodes elif self.fake_labels_list == []: # skip reward before first action None else: reward = [0] # assign 0 reward until goal scored self.rewards.append(reward) """ Check if game is active """ if not game.game_info.is_round_active: return empty_controller """ START HERE: run model forwards to get controller outputs, use samples (for training exploration) from these for actual controller outputs """ x = self.FlatInput.create_input_array(game) # normalised game data x = self.torch.Tensor(x).to(self.device) p_inputs = self.GURUNN(x) # probability of inputs self.p_inputs_list.append(p_inputs) p_inputs_nograd = p_inputs.squeeze().tolist( ) # Simplify tensor to list so as not to create a bunch of new tensors controller.throttle = 0 if np.random.uniform( ) < p_inputs_nograd[0] else 1 # sampled inputs used as outputs controller.jump = 0 if np.random.uniform() < p_inputs_nograd[1] else 1 controller.boost = 0 if np.random.uniform() < p_inputs_nograd[2] else 1 controller.handbrake = 0 if np.random.uniform( ) < p_inputs_nograd[3] else 1 s_steer1 = p_inputs_nograd[4] / sum( p_inputs_nograd[4:9] ) # for non-boolean inputs, descretized inputs have been used. These are then normalised and sampled s_steer2 = p_inputs_nograd[5] / sum(p_inputs_nograd[4:9]) + s_steer1 s_steer3 = p_inputs_nograd[6] / sum(p_inputs_nograd[4:9]) + s_steer2 s_steer4 = p_inputs_nograd[7] / sum(p_inputs_nograd[4:9]) + s_steer3 _ = np.random.uniform() if _ < s_steer1: controller.steer = -1 s_steer1 = 1 s_steer2 = s_steer3 = s_steer4 = s_steer5 = 0 elif _ < s_steer2: controller.steer = -0.5 s_steer2 = 1 s_steer1 = s_steer3 = s_steer4 = s_steer5 = 0 elif _ < s_steer3: controller.steer = 0 s_steer3 = 1 s_steer1 = s_steer2 = s_steer4 = s_steer5 = 0 elif _ < s_steer4: controller.steer = 0.5 s_steer4 = 1 s_steer1 = s_steer2 = s_steer3 = s_steer5 = 0 else: controller.steer = s_steer5 = 1 s_steer1 = s_steer2 = s_steer3 = s_steer4 = 0 s_pitch1 = p_inputs_nograd[9] / sum(p_inputs_nograd[9:12]) s_pitch2 = p_inputs_nograd[10] / sum(p_inputs_nograd[9:12]) + s_pitch1 _ = np.random.uniform() if _ < s_pitch1: controller.pitch = -1 s_pitch1 = 1 s_pitch2 = s_pitch3 = 0 elif _ < s_pitch2: controller.pitch = 0 s_pitch2 = 1 s_pitch1 = s_pitch3 = 0 else: controller.pitch = s_pitch3 = 1 s_pitch1 = s_pitch2 = 0 s_yaw1 = p_inputs_nograd[12] / sum(p_inputs_nograd[12:15]) s_yaw2 = p_inputs_nograd[13] / sum(p_inputs_nograd[12:15]) + s_yaw1 _ = np.random.uniform() if _ < s_yaw1: controller.yaw = -1 s_yaw1 = 1 s_yaw2 = s_yaw3 = 0 elif _ < s_yaw2: controller.yaw = 0 s_yaw2 = 1 s_yaw1 = s_yaw3 = 0 else: controller.yaw = s_yaw3 = 1 s_yaw1 = s_yaw2 = 0 s_roll1 = p_inputs_nograd[15] / sum(p_inputs_nograd[15:18]) s_roll2 = p_inputs_nograd[16] / sum(p_inputs_nograd[15:18]) + s_roll1 _ = np.random.uniform() if _ < s_roll1: controller.roll = -1 s_roll1 = 1 s_roll2 = s_roll3 = 0 elif _ < s_roll2: controller.roll = 0 s_roll2 = 1 s_roll1 = s_roll3 = 0 else: controller.roll = s_roll3 = 1 s_roll1 = s_roll2 = 0 s_inputs = [ controller.throttle, controller.jump, controller.boost, controller.handbrake, s_steer1, s_steer2, s_steer3, s_steer4, s_steer5, s_pitch1, s_pitch2, s_pitch3, s_yaw1, s_yaw2, s_yaw3, s_roll1, s_roll2, s_roll3 ] # fake labels; actual (sampled) outputs self.fake_labels_list.append(s_inputs) return controller
def exec(self, bot): if not self.announced_in_quick_chat: self.announced_in_quick_chat = True bot.send_quick_chat(QuickChats.CHAT_EVERYONE, QuickChats.Information_IGotIt) ct = bot.info.time car = bot.info.my_car up = car.up controls = SimpleControllerState() # Time remaining till intercept time T = self.intercept_time - bot.info.time # Expected future position xf = car.pos + car.vel * T + 0.5 * GRAVITY * T ** 2 # Expected future velocity vf = car.vel + GRAVITY * T # Is set to false while jumping to avoid FeelsBackFlipMan rotate = True if self.jumping: if self.jump_begin_time == -1: jump_elapsed = 0 self.jump_begin_time = ct else: jump_elapsed = ct - self.jump_begin_time # How much longer we can press jump and still gain upward force tau = JUMP_MAX_DUR - jump_elapsed # Add jump pulse if jump_elapsed == 0: vf += up * JUMP_SPEED xf += up * JUMP_SPEED * T rotate = False # Acceleration from holding jump vf += up * JUMP_SPEED * tau xf += up * JUMP_SPEED * tau * (T - 0.5 * tau) if self.do_second_jump: # Impulse from the second jump vf += up * JUMP_SPEED xf += up * JUMP_SPEED * (T - tau) if jump_elapsed < JUMP_MAX_DUR: controls.jump = True else: controls.jump = False if self.do_second_jump: if self.jump_pause_counter < 4: # Do a 4-tick pause between jumps self.jump_pause_counter += 1 else: # Time to start second jump # we do this by resetting our jump counter and pretend and our aerial started in the air self.jump_begin_time = -1 self.jumping = True self.do_second_jump = False else: # We are done jumping self.jumping = False else: controls.jump = False delta_pos = self.hit_pos - xf direction = normalize(delta_pos) car_to_hit_pos = self.hit_pos - car.pos dodging = self.dodge_begin_time != -1 if dodging: controls.jump = True # We are not pressing jump, so let's align the car if rotate and not dodging: if self.do_dodge and norm(car_to_hit_pos) < Ball.RADIUS + 80: # Start dodge self.dodge_begin_time = ct hit_local = dot(car_to_hit_pos, car.rot) hit_local.z = 0 dodge_direction = normalize(hit_local) controls.roll = 0 controls.pitch = -dodge_direction.x controls.yaw = sign(car.rot.get(2, 2)) * direction.y controls.jump = True else: # Adjust orientation if norm(delta_pos) > 50: pd = bot.fly.align(bot, looking_in_dir(delta_pos)) else: if self.target_rot is not None: pd = bot.fly.align(bot, self.target_rot) else: pd = bot.fly.align(bot, looking_in_dir(self.hit_pos - car.pos)) controls.roll = pd.roll controls.pitch = pd.pitch controls.yaw = pd.yaw if not dodging and angle_between(car.forward, direction) < 0.3: if norm(delta_pos) > 40: controls.boost = 1 controls.throttle = 0 else: controls.boost = 0 controls.throttle = clip01(0.5 * THROTTLE_AIR_ACCEL * T ** 2) else: controls.boost = 0 controls.throttle = 0 prediction = predict.ball_predict(bot, T) self.done = T < 0 if norm(self.hit_pos - prediction.pos) > 50: # Jump shot failed self.done = True bot.send_quick_chat(QuickChats.CHAT_EVERYONE, QuickChats.Apologies_Cursing) if bot.do_rendering: car_to_hit_dir = normalize(self.hit_pos - car.pos) color = bot.renderer.pink() rendering.draw_cross(bot, self.hit_pos, color, arm_length=100) rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.25), car_to_hit_dir, 40, 12, color) rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.5), car_to_hit_dir, 40, 12, color) rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.75), car_to_hit_dir, 40, 12, color) bot.renderer.draw_line_3d(car.pos, self.hit_pos, color) return controls
def execute(self, agent): controller_state = SimpleControllerState() controller_state.throttle = 0 return controller_state
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: self.game.read_game_information(packet, self.get_rigid_body_tick(), self.get_field_info()) self.controls = SimpleControllerState() next_state = self.state if self.state == State.RESET: self.timer = 0.0 b_position = Vector3(random.uniform(-1500, 1500), random.uniform( 2500, 3500), random.uniform( 300, 500)) b_velocity = Vector3(random.uniform(-300, 300), random.uniform(-100, 100), random.uniform(1000, 1500)) ball_state = BallState(physics=Physics( location=b_position, velocity=b_velocity, rotation=Rotator(0, 0, 0), angular_velocity=Vector3(0, 0, 0) )) # this just initializes the car and ball # to different starting points each time c_position = Vector3(b_position.x, 0 * random.uniform(-1500, -1000), 25) #c_position = Vector3(200, -1000, 25) car_state = CarState(physics=Physics( location=c_position, velocity=Vector3(0, 800, 0), rotation=Rotator(0, 1.6, 0), angular_velocity=Vector3(0, 0, 0) ), boost_amount=100) self.set_game_state(GameState( ball=ball_state, cars={self.game.id: car_state}) ) next_state = State.WAIT if self.state == State.WAIT: if self.timer > 0.2: next_state = State.INITIALIZE if self.state == State.INITIALIZE: self.aerial = Aerial(self.game.my_car) # self.aerial.up = normalize(vec3( # random.uniform(-1, 1), # random.uniform(-1, 1), # random.uniform(-1, 1))) self.turn = AerialTurn(self.game.my_car) # predict where the ball will be prediction = Ball(self.game.ball) self.ball_predictions = [vec3(prediction.location)] for i in range(100): prediction.step(0.016666) prediction.step(0.016666) self.ball_predictions.append(vec3(prediction.location)) # if the ball is in the air if prediction.location[2] > 500: self.aerial.target = prediction.location self.aerial.arrival_time = prediction.time simulation = self.aerial.simulate() # # check if we can reach it by an aerial if norm(simulation.location - self.aerial.target) < 100: prediction.step(0.016666) prediction.step(0.016666) self.aerial.target = prediction.location self.aerial.arrival_time = prediction.time self.target_ball = Ball(prediction) break next_state = State.RUNNING if self.state == State.RUNNING: self.log.write(f"{{\"car\":{self.game.my_car.to_json()}," f"\"ball\":{self.game.ball.to_json()}}}\n") self.aerial.step(self.game.time_delta) self.controls = self.aerial.controls if self.timer > self.timeout: next_state = State.RESET self.aerial = None self.turn = None self.timer += self.game.time_delta self.state = next_state self.renderer.begin_rendering() red = self.renderer.create_color(255, 230, 30, 30) purple = self.renderer.create_color(255, 230, 30, 230) white = self.renderer.create_color(255, 230, 230, 230) if self.aerial: r = 200 x = vec3(r, 0, 0) y = vec3(0, r, 0) z = vec3(0, 0, r) target = self.aerial.target self.renderer.draw_line_3d(target - x, target + x, purple) self.renderer.draw_line_3d(target - y, target + y, purple) self.renderer.draw_line_3d(target - z, target + z, purple) if self.ball_predictions: self.renderer.draw_polyline_3d(self.ball_predictions, purple) self.renderer.end_rendering() return self.controls
def go_to_point(packet, point, eta): controls = SimpleControllerState() if packet.my_pos.z > 700: point = packet.my_pos.flat() eta = 0.05 car_to_point = point - packet.my_pos rel_pos = vec.relative_location(packet.my_pos, point, packet.my_ori) ang = rel_pos.ang() smooth = ang + 2 * ang**3 if smooth < -1: smooth = -1 elif smooth > 1: smooth = 1 controls.steer = smooth dist = rel_pos.length() target_vel = dist / eta cur_vel = packet.my_vel.proj_onto_size(car_to_point) if cur_vel < 0: controls.throttle = 0.2 elif target_vel > 1400: controls.throttle = 1 if cur_vel > target_vel: # break controls.throttle = 0.7 controls.boost = 0 else: controls.boost = 1 else: if target_vel > cur_vel + 100: controls.throttle = 1 elif target_vel < cur_vel - 100: controls.throttle = -1 else: controls.throttle = 0 return controls
def with_aiming(self, bot, aim_cone: AimCone, time: float, dodge_hit: bool = True): # aim: | | | | # ball | bad | ok | good | # z pos: | | | | # -----------+-----------+-----------+-----------+ # too high | give | give | wait/ | # | up | up | improve | # -----------+ - - - - - + - - - - - + - - - - - + # medium | give | improve | aerial | # | up | aim | | # -----------+ - - - - - + - - - - - + - - - - - + # soon on | improve | slow | small | # ground | aim | curve | jump | # -----------+ - - - - - + - - - - - + - - - - - + # on ground | improve | fast | fast | # | aim?? | curve | straight | # -----------+ - - - - - + - - - - - + - - - - - + # FIXME if the ball is not on the ground we treat it as 'soon on ground' in all other cases self.controls = SimpleControllerState() self.aim_is_ok = False self.waits_for_fall = False self.ball_is_flying = False self.can_shoot = False self.using_curve = False self.curve_point = None self.ball_when_hit = None car = bot.info.my_car ball_soon = ball_predict(bot, time) car_to_ball_soon = ball_soon.pos - car.pos dot_facing_score = dot(normalize(car_to_ball_soon), normalize(car.forward)) vel_towards_ball_soon = proj_onto_size(car.vel, car_to_ball_soon) is_facing = 0 < dot_facing_score if ball_soon.pos.z < 110 or (ball_soon.pos.z < 475 and ball_soon.vel.z <= 0) or True: #FIXME Always true # The ball is on the ground or soon on the ground if 275 < ball_soon.pos.z < 475 and aim_cone.contains_direction( car_to_ball_soon): # Can we hit it if we make a small jump? vel_f = proj_onto_size(car.vel, xy(car_to_ball_soon)) car_expected_pos = car.pos + car.vel * time ball_soon_flat = xy(ball_soon.pos) diff = norm(car_expected_pos - ball_soon_flat) ball_in_front = dot(ball_soon.pos - car_expected_pos, car.vel) > 0 if bot.do_rendering: bot.renderer.draw_line_3d(car.pos, car_expected_pos, bot.renderer.lime()) bot.renderer.draw_rect_3d(car_expected_pos, 12, 12, True, bot.renderer.lime()) if vel_f > 400: if diff < 150 and ball_in_front: bot.maneuver = SmallJumpManeuver( bot, lambda b: b.info.ball.pos) if 110 < ball_soon.pos.z: # and ball_soon.vel.z <= 0: # The ball is slightly in the air, lets wait just a bit more self.waits_for_fall = True ball_landing = next_ball_landing(bot, ball_soon, size=100) time = time + ball_landing.time ball_soon = ball_predict(bot, time) car_to_ball_soon = ball_soon.pos - car.pos self.ball_when_hit = ball_soon # The ball is on the ground, are we in position for a shot? if aim_cone.contains_direction(car_to_ball_soon) and is_facing: # Straight shot self.aim_is_ok = True self.can_shoot = True if norm(car_to_ball_soon) < 240 + Ball.RADIUS and aim_cone.contains_direction(car_to_ball_soon)\ and vel_towards_ball_soon > 300: bot.drive.start_dodge(bot) offset_point = xy( ball_soon.pos) - 50 * aim_cone.get_center_dir() speed = self._determine_speed(norm(car_to_ball_soon), time) self.controls = bot.drive.towards_point(bot, offset_point, target_vel=speed, slide=True, boost_min=0, can_keep_speed=False) return self.controls elif aim_cone.contains_direction(car_to_ball_soon, math.pi / 5): # Curve shot self.aim_is_ok = True self.using_curve = True self.can_shoot = True offset_point = xy( ball_soon.pos) - 50 * aim_cone.get_center_dir() closest_dir = aim_cone.get_closest_dir_in_cone( car_to_ball_soon) self.curve_point = curve_from_arrival_dir( car.pos, offset_point, closest_dir) self.curve_point.x = clip(self.curve_point.x, -Field.WIDTH / 2, Field.WIDTH / 2) self.curve_point.y = clip(self.curve_point.y, -Field.LENGTH / 2, Field.LENGTH / 2) if dodge_hit and norm(car_to_ball_soon) < 240 + Ball.RADIUS and angle_between(car.forward, car_to_ball_soon) < 0.5\ and aim_cone.contains_direction(car_to_ball_soon) and vel_towards_ball_soon > 300: bot.drive.start_dodge(bot) speed = self._determine_speed(norm(car_to_ball_soon), time) self.controls = bot.drive.towards_point(bot, self.curve_point, target_vel=speed, slide=True, boost_min=0, can_keep_speed=False) return self.controls else: # We are NOT in position! self.aim_is_ok = False pass else: if aim_cone.contains_direction(car_to_ball_soon): self.waits_for_fall = True self.aim_is_ok = True #self.can_shoot = False pass # Allow small aerial (wait if ball is too high) elif aim_cone.contains_direction(car_to_ball_soon, math.pi / 4): self.ball_is_flying = True pass # Aim is ok, but ball is in the air
class VirxERLU(BaseAgent): # Massive thanks to ddthj/GoslingAgent (GitHub repo) for the basis of VirxERLU def initialize_agent(self): self.tournament = True self.print("Initalizing thread(s)...") if not self.tournament: self.gui = Gui(self) self.print("Starting the GUI...") self.gui.start() self.predictions = { "closest_enemy": 0, "own_goal": False, "goal": False, "ball_struct": None, "team_from_goal": (), "team_to_ball": (), "self_from_goal": 0, "self_to_ball": 0, "done": False } self.goalie = False self.air_bud = False self.debug = [[], []] self.debugging = False self.debug_lines = True self.debug_3d_bool = True self.debug_stack_bool = True self.debug_2d_bool = False self.show_coords = False self.debug_ball_path = False self.debug_ball_path_precision = 10 self.disable_driving = False self.prediction = Prediction(self) self.print("Starting the predictive service...") self.prediction.start() self.match_comms = None self.print("Building game information") mutators = self.get_match_settings().MutatorSettings() gravity = [ Vector(z=-650), Vector(z=-325), Vector(z=-1137.5), Vector(z=-3250) ] base_boost_accel = 991 + (2 / 3) boost_accel = [ base_boost_accel, base_boost_accel * 1.5, base_boost_accel * 2, base_boost_accel * 10 ] self.gravity = gravity[mutators.GravityOption()] self.boost_accel = boost_accel[mutators.BoostStrengthOption()] self.friends = () self.foes = () self.me = car_object(self.index) self.ball_to_goal = -1 self.ball = ball_object() self.game = game_object(not self.team) self.boosts = () self.friend_goal = goal_object(self.team) self.foe_goal = goal_object(not self.team) self.stack = [] self.time = 0 self.prev_time = 0 self.ready = False self.controller = SimpleControllerState() self.kickoff_flag = False self.kickoff_done = True self.last_time = 0 self.my_score = 0 self.foe_score = 0 self.playstyles = Playstyle self.playstyle = self.playstyles.Neutral self.can_shoot = None self.shooting = False self.shot_weight = -1 self.shot_time = -1 self.panic = False self.odd_tick = 0 # Use this for thing that can be run at 30 or 60 tps instead of 120 def retire(self): # Stop the currently running threads if not self.tournament: self.gui.stop() if len(self.friends) > 0: self.match_comms.stop() self.prediction.stop() @staticmethod def is_hot_reload_enabled(): # The tkinter GUI isn't compatible with hot reloading # Use the Continue and Spawn option in the GUI instead return False def get_ready(self, packet): field_info = self.get_field_info() self.boosts = tuple( boost_object(i, boost.location, boost.is_full_boost) for i, boost in enumerate(field_info.boost_pads)) self.refresh_player_lists(packet) self.ball.update(packet) foe_team = -1 if self.team == 1 else 1 team = -foe_team self.defensive_shots = ( (self.foe_goal.left_post, self.foe_goal.right_post), # Weight -> 4 (Vector(4000, foe_team * 3250, 100), Vector(2750, foe_team * 3250, 100)), # Weight -> 3 (Vector(-4000, foe_team * 3250, 100), Vector(-2750, foe_team * 3250, 100)), # Weight -> 3 (Vector(-3600, z=100), Vector(-1000, z=500)), # Weight -> 2 (Vector(3600, z=100), Vector(1000, z=500)) # Weight -> 2 ) self.panic_shots = ( (Vector(3100 * team, team * 3620, 100), Vector(3100 * team, team * 5120, 100)), # Weight -> 1 (Vector(-3100 * team, team * 3620, 100), Vector(-3100 * team, team * 5120, 100)) # Weight -> 1 ) # () => Weight -> 0 # Short short => Weight -> -1 self.offensive_shots = ( (self.foe_goal.left_post, self.foe_goal.right_post), # Weight -> 4 (Vector(foe_team * 893, foe_team * 5120, 100), Vector(foe_team * 893, foe_team * 4720, 320)), # Weight -> 3 (Vector(-foe_team * 893, foe_team * 5120, 100), Vector(-foe_team * 893, foe_team * 4720, 320)) # Weight -> 3 ) self.best_shot = (Vector(foe_team * 650, foe_team * 5125, 320), Vector(-foe_team * 650, foe_team * 5125, 320)) self.max_shot_weight = 4 self.init() self.ready = True self.print("Built") def refresh_player_lists(self, packet): # Useful to keep separate from get_ready because humans can join/leave a match self.friends = tuple( car_object(i, packet) for i in range(packet.num_cars) if packet.game_cars[i].team is self.team and i != self.index) self.foes = tuple( car_object(i, packet) for i in range(packet.num_cars) if packet.game_cars[i].team != self.team) if len(self.friends) > 0 and self.match_comms is None: self.match_comms = MatchComms(self) self.print("Starting the match communication handler...") self.match_comms.start() def push(self, routine): self.stack.append(routine) def pop(self): return self.stack.pop() def line(self, start, end, color=None): if self.debugging and self.debug_lines: color = color if color is not None else self.renderer.grey() if isinstance(start, Vector): start = start.copy().tuple() if isinstance(end, Vector): end = end.copy().tuple() self.renderer.draw_line_3d( start, end, color if type(color) != list else self.renderer.create_color( 255, *color)) def print(self, item): if not self.tournament: team = "Blue" if self.team == 0 else "Red" print(f"{self.name} ({team}): {item}") def dbg_3d(self, item): self.debug[0].append(str(item)) def dbg_2d(self, item): self.debug[1].append(str(item)) def clear(self): self.shooting = False self.shot_weight = -1 self.shot_time = -1 self.stack = [] return 'asdf' # This is here in case I call this instead of is_clear() - It should throw an error if I do def is_clear(self): return len(self.stack) < 1 def preprocess(self, packet): if packet.num_cars != len(self.friends) + len(self.foes) + 1: self.refresh_player_lists(packet) set(map(lambda car: car.update(packet), self.friends)) set(map(lambda car: car.update(packet), self.foes)) set(map(lambda pad: pad.update(packet), self.boosts)) self.ball.update(packet) self.me.update(packet) self.game.update(packet) self.time = self.game.time # When a new kickoff begins we empty the stack if not self.kickoff_flag and self.game.round_active and self.game.kickoff: self.kickoff_done = False self.clear() # Tells us when to go for kickoff self.kickoff_flag = self.game.round_active and self.game.kickoff self.ball_to_goal = self.friend_goal.location.flat_dist( self.ball.location) if self.odd_tick % 2 == 0: # This is ran @ 60 tps self.predictions['ball_struct'] = self.get_ball_prediction_struct() self.prediction.event.set() self.odd_tick += 1 if self.odd_tick > 3: self.odd_tick = 0 def get_output(self, packet): try: # Reset controller self.controller.__init__() # Get ready, then preprocess if not self.ready: self.get_ready(packet) self.preprocess(packet) if self.me.demolished: if not self.is_clear(): self.clear() elif self.game.round_active and self.predictions['done']: self.dbg_3d(self.playstyle.name) self.run( ) # Run strategy code; This is a very expensive function to run # run the routine on the end of the stack if not self.is_clear(): self.stack[-1].run(self) if self.is_clear() or self.stack[0].__class__.__name__ not in { 'Aerial', 'jump_shot', 'block_ground_shot' }: self.shooting = False self.shot_weight = -1 self.shot_time = -1 if self.debugging: if self.debug_3d_bool: if self.debug_stack_bool: self.debug[0] = itertools.chain( self.debug[0], ("STACK:", ), (item.__class__.__name__ for item in reversed(self.stack))) self.renderer.draw_string_3d( self.me.location.tuple(), 2, 2, "\n".join(self.debug[0]), self.renderer.team_color(alt_color=True)) self.debug[0] = [] if self.debug_2d_bool: if self.show_coords: self.debug[1].insert(0, str(self.me.location.int())) if not self.is_clear( ) and self.stack[0].__class__.__name__ in { 'Aerial', 'jump_shot', 'block_ground_shot' }: self.dbg_2d( round(self.stack[0].intercept_time - self.time, 4)) self.renderer.draw_string_2d( 20, 300, 2, 2, "\n".join(self.debug[1]), self.renderer.team_color(alt_color=True)) self.debug[1] = [] if self.debug_ball_path: if self.predictions['ball_struct'] is not None: for i in range( 0, self.predictions['ball_struct'].num_slices - (self.predictions['ball_struct'].num_slices % self.debug_ball_path_precision) - self.debug_ball_path_precision, self.debug_ball_path_precision): self.line( self.predictions['ball_struct'].slices[i]. physics.location, self.predictions['ball_struct'].slices[ i + self.debug_ball_path_precision]. physics.location) else: self.debug = [[], []] self.prev_time = self.time return SimpleControllerState( ) if self.disable_driving else self.controller except Exception: print(self.name) print_exc() return SimpleControllerState() def handle_match_comm(self, bot, team, msg): pass def test(self): pass def run(self): pass def handle_quick_chat(self, index, team, quick_chat): pass def init(self): pass
def send_player_input(self, player_index: int, input: SimpleControllerState): builder = input.to_flatbuffer(player_index) self.send_flatbuffer(builder, SocketDataType.PLAYER_INPUT)
def get_output(self, packet): try: # Reset controller self.controller.__init__() # Get ready, then preprocess if not self.ready: self.get_ready(packet) self.preprocess(packet) if self.me.demolished: if not self.is_clear(): self.clear() elif self.game.round_active and self.predictions['done']: self.dbg_3d(self.playstyle.name) self.run( ) # Run strategy code; This is a very expensive function to run # run the routine on the end of the stack if not self.is_clear(): self.stack[-1].run(self) if self.is_clear() or self.stack[0].__class__.__name__ not in { 'Aerial', 'jump_shot', 'block_ground_shot' }: self.shooting = False self.shot_weight = -1 self.shot_time = -1 if self.debugging: if self.debug_3d_bool: if self.debug_stack_bool: self.debug[0] = itertools.chain( self.debug[0], ("STACK:", ), (item.__class__.__name__ for item in reversed(self.stack))) self.renderer.draw_string_3d( self.me.location.tuple(), 2, 2, "\n".join(self.debug[0]), self.renderer.team_color(alt_color=True)) self.debug[0] = [] if self.debug_2d_bool: if self.show_coords: self.debug[1].insert(0, str(self.me.location.int())) if not self.is_clear( ) and self.stack[0].__class__.__name__ in { 'Aerial', 'jump_shot', 'block_ground_shot' }: self.dbg_2d( round(self.stack[0].intercept_time - self.time, 4)) self.renderer.draw_string_2d( 20, 300, 2, 2, "\n".join(self.debug[1]), self.renderer.team_color(alt_color=True)) self.debug[1] = [] if self.debug_ball_path: if self.predictions['ball_struct'] is not None: for i in range( 0, self.predictions['ball_struct'].num_slices - (self.predictions['ball_struct'].num_slices % self.debug_ball_path_precision) - self.debug_ball_path_precision, self.debug_ball_path_precision): self.line( self.predictions['ball_struct'].slices[i]. physics.location, self.predictions['ball_struct'].slices[ i + self.debug_ball_path_precision]. physics.location) else: self.debug = [[], []] self.prev_time = self.time return SimpleControllerState( ) if self.disable_driving else self.controller except Exception: print(self.name) print_exc() return SimpleControllerState()
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: delta_time = packet.game_info.seconds_elapsed - self.p_time self.p_time = packet.game_info.seconds_elapsed ball_prediction = self.get_ball_prediction_struct() if ball_prediction is None: c = SimpleControllerState() c.throttle = 1 return c my_car = packet.game_cars[self.index] car_loc = Vec3(my_car.physics.location) car_vel = Vec3(my_car.physics.velocity) car_rot = Orientation(my_car.physics.rotation) car_ang_vel = Vec3(my_car.physics.angular_velocity) dv = Vec3() self.controller_state.throttle = 1 if self.is_aerialing: self.target_loc, self.game_seconds, dv = look_for_aerial( ball_prediction, packet.game_info.seconds_elapsed, car_loc, car_vel, packet.game_info.world_gravity_z) self.time_in_air += delta_time if self.target_loc is None or (my_car.has_wheel_contact and self.time_in_air > 0.2): self.is_aerialing = False self.controller_state.boost = False self.time_in_air = 0 else: delta_t = self.game_seconds - packet.game_info.seconds_elapsed car_to_target = self.target_loc - car_loc dv = delta_v(car_to_target, car_vel, delta_t, packet.game_info.world_gravity_z) align_car_to(self.controller_state, car_ang_vel, car_rot, dv, car_rot.up) self.controller_state.boost = car_rot.forward.dot( dv.normalized()) > 0.6 and dv.length() > 400 self.controller_state.jump = False else: self.controller_state.jump = False self.controller_state.boost = False self.target_loc, self.game_seconds, dv = look_for_aerial( ball_prediction, packet.game_info.seconds_elapsed, car_loc, car_vel, packet.game_info.world_gravity_z) self.time_on_ground += delta_time if self.target_loc is not None and self.time_on_ground > 0.2: self.dv_length = dv.length() self.is_aerialing = True self.time_on_ground = 0 self.controller_state.jump = True if dv is None: dv = Vec3() self.renderer.begin_rendering() self.renderer.draw_line_3d(car_loc.render(), (car_loc + dv).render(), self.renderer.blue()) self.renderer.end_rendering() """self.set_game_state(GameState(cars={self.index: CarState( physics=Physics( location=Vector3(0, 0, 1000), velocity=Vector3(0, 0, 0) ) )}))""" return self.controller_state
def update(self): controller_state = SimpleControllerState() jump = flipHandler(self.agent, self.flip_obj) if jump: if self.targetCode == 1: controller_state.pitch = -1 controller_state.steer = 0 controller_state.throttle = 1 elif self.targetCode == 0: ball_local = toLocal(self.agent.ball.location, self.agent.me) ball_angle = math.atan2(ball_local.data[1], ball_local.data[0]) controller_state.jump = True controller_state.yaw = math.sin(ball_angle) pitch = -math.cos(ball_angle) controller_state.pitch = pitch if pitch > 0: controller_state.throttle = -1 else: controller_state.throttle = 1 elif self.targetCode == 2: controller_state.pitch = 0 controller_state.steer = 0 controller_state.yaw = 0 elif self.targetCode == 3: controller_state.pitch = 1 controller_state.steer = 0 controller_state.throttle = -1 elif self.targetCode == -1: controller_state.pitch = 0 controller_state.steer = 0 controller_state.throttle = 0 controller_state.jump = jump controller_state.boost = False if self.flip_obj.flipDone: self.active = False return controller_state
def __init__(self): self.controller = SimpleControllerState()