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 GoslingAgent 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 self.last_time = 0 self.my_score = 0 self.foe_score = 0 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