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 initialize_agent(self): self.tournament = TOURNAMENT_MODE self.extra_debugging = EXTRA_DEBUGGING self.startup_time = time_ns() self.true_name = re.split(r' \(\d+\)$', self.name)[0] 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 = self.true_name == self.name self.show_coords = False self.debug_ball_path = False self.debug_ball_path_precision = 10 self.disable_driving = False T = datetime.now() T = T.strftime("%Y-%m-%d %H;%M") self.traceback_file = ( os.getcwd(), f"-traceback ({T}).txt" ) if not self.tournament and self.extra_debugging: self.gui = Gui(self) self.print("Starting the GUI...") self.gui.start() if self.matchcomms_root is not None: self.match_comms = MatchComms(self) self.print("Starting the match communication handler...") self.match_comms.start() 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" ) ball_size = ( 92.75, 69.25, 139.5, 239.75 ) 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()] self.ball_radius = ball_size[mutators.BallSizeOption()] 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.delta_time = 1 / 120 self.future_ball_location_slice = 180 self.balL_prediction_struct = None
class VirxERLU(StandaloneBot): # Massive thanks to ddthj/GoslingAgent (GitHub repo) for the basis of VirxERLU # VirxERLU on VirxEC Showcase -> https://virxerlu.virxcase.dev/ # Wiki -> https://github.com/VirxEC/VirxERLU/wiki def initialize_agent(self): self.tournament = TOURNAMENT_MODE self.extra_debugging = EXTRA_DEBUGGING self.startup_time = time_ns() self.true_name = re.split(r' \(\d+\)$', self.name)[0] 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 = self.true_name == self.name self.show_coords = False self.debug_ball_path = False self.debug_ball_path_precision = 10 self.disable_driving = False T = datetime.now() T = T.strftime("%Y-%m-%d %H;%M") self.traceback_file = ( os.getcwd(), f"-traceback ({T}).txt" ) if not self.tournament and self.extra_debugging: self.gui = Gui(self) self.print("Starting the GUI...") self.gui.start() if self.matchcomms_root is not None: self.match_comms = MatchComms(self) self.print("Starting the match communication handler...") self.match_comms.start() 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" ) ball_size = ( 92.75, 69.25, 139.5, 239.75 ) 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()] self.ball_radius = ball_size[mutators.BallSizeOption()] 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.delta_time = 1 / 120 self.future_ball_location_slice = 180 self.balL_prediction_struct = None def retire(self): # Stop the currently running threads if not self.tournament and self.extra_debugging: self.gui.stop() if self.matchcomms_root is not None: self.match_comms.stop() def is_hot_reload_enabled(self): # The tkinter GUI isn't compatible with hot reloading # Use the Continue and Spawn option in the RLBotGUI instead return not self.extra_debugging 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") 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.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.delta_time = self.game.time - self.time 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() if self.tournament and self.matchcomms_root is not None: while 1: try: msg = self.matchcomms.incoming_broadcast.get_nowait() except Exception: break try: self.handle_match_comm(msg) except Exception: print_exc() 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: 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 else: self.shooting = False 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")) 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 self.delta_time != 0: self.debug[1].insert(0, f"TPS: {round(1 / self.delta_time)}") 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 run(self): pass def handle_quick_chat(self, index, team, quick_chat): pass def init(self): pass
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 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
class VirxERLU(BaseAgent): # Massive thanks to ddthj/GoslingAgent (GitHub repo) for the basis of VirxERLU # VirxERLU on VirxEC Showcase -> https://virxerlu.virxcase.dev/ # Wiki -> https://github.com/VirxEC/VirxERLU/wiki def initialize_agent(self): self.tournament = False 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.disable_driving = False if not self.tournament: self.gui = Gui(self) self.print("Starting the GUI...") self.gui.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) boost_amount = ("default", "unlimited", "slow recharge", "fast recharge", "no boost") self.gravity = gravity[mutators.GravityOption()] self.boost_accel = boost_accel[mutators.BoostStrengthOption()] self.boost_amount = boost_amount[mutators.BoostOption()] 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.best_shot_value = 92 self.odd_tick = -1 self.future_ball_location_slice = 180 self.balL_prediction_struct = None def retire(self): # Stop the currently running threads if not self.tournament: self.gui.stop() if self.match_comms is not None: self.match_comms.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) self.best_shot_value = math.floor((92.75 + self.me.hitbox.width / 2)) self.print(f"Best shot value: {self.best_shot_value}") self.init() self.ready = True load_time = (time_ns() - self.startup_time) / 1e+6 print(f"{self.name}: Built game info in {load_time} milliseconds") 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) 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() 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 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.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.ball_prediction_struct = self.get_ball_prediction_struct() self.odd_tick += 1 if self.odd_tick > 3: self.odd_tick = 0 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: try: self.run( ) # Run strategy code; This is a very expensive function to run except Exception: print(self.name) print_exc() 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', '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 = [[], []] # 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', 'double_jump' }: self.shooting = False return SimpleControllerState( ) if self.disable_driving else self.controller except Exception: print(self.name) print_exc() return SimpleControllerState() def handle_match_comm(self, msg): pass def run(self): pass def handle_quick_chat(self, index, team, quick_chat): pass def init(self): pass