def call_agent(self, agent: BaseAgent, agent_class): self.state_queue.put(self.game_tick_packet) _ = agent.get_output(self.game_tick_packet) controller_input = self.action_queue.get() if controller_input is None: get_logger("BotManager" + str(self.index))\ .error("Agent %s did not return any output.", str(agent_class.__name__)) return player_input = self.bot_input if isinstance(controller_input, list): # Write all player inputs get_logger("BotManager" + str(self.index)).error( "Sending legacy packet type, please convert to v4") controller_input = agent.convert_output_to_v4(controller_input) player_input.throttle = controller_input.throttle player_input.steer = controller_input.steer player_input.pitch = controller_input.pitch player_input.yaw = controller_input.yaw player_input.roll = controller_input.roll player_input.jump = controller_input.jump player_input.boost = controller_input.boost player_input.handbrake = controller_input.handbrake self.game_interface.update_player_input(player_input, self.index)
def call_agent(self, agent: BaseAgent, agent_class): controller_input = agent.get_output(self.game_tick_packet) if controller_input is None: get_logger("BotManager" + str(self.index))\ .error("Agent %s did not return any output.", str(agent_class.__name__)) return player_input = self.bot_input if isinstance(controller_input, list): # Write all player inputs get_logger("BotManager" + str(self.index)).error( "Sending legacy packet type, please convert to v4") controller_input = agent.convert_output_to_v4(controller_input) player_input.throttle = controller_input.throttle player_input.steer = controller_input.steer player_input.pitch = controller_input.pitch player_input.yaw = controller_input.yaw player_input.roll = controller_input.roll player_input.jump = controller_input.jump player_input.boost = controller_input.boost player_input.handbrake = controller_input.handbrake if hasattr(controller_input, 'use_item'): # This is needed for rare cases where bots don't conform to the spec, # e.g. Stick returns itself rather than a SimpleControllerState. player_input.use_item = controller_input.use_item self.game_interface.update_player_input(player_input, self.index)
def call_agent(self, agent: BaseAgent, agent_class): # Call begin rendering on the agent's behalf. If they call begin_rendering again internally, no harm done. agent.renderer.begin_rendering() controller_input = agent.get_output(self.game_tick_packet) if controller_input is None: get_logger("BotManager" + str(self.index))\ .error("Agent %s did not return any output.", str(agent_class.__name__)) return player_input = self.bot_input if isinstance(controller_input, list): # Write all player inputs get_logger("BotManager" + str(self.index)).error("Sending legacy packet type, please convert to v4") controller_input = agent.convert_output_to_v4(controller_input) player_input.throttle = controller_input.throttle player_input.steer = controller_input.steer player_input.pitch = controller_input.pitch player_input.yaw = controller_input.yaw player_input.roll = controller_input.roll player_input.jump = controller_input.jump player_input.boost = controller_input.boost player_input.handbrake = controller_input.handbrake if hasattr(controller_input, 'use_item'): # This is needed for rare cases where bots don't conform to the spec, # e.g. Stick returns itself rather than a SimpleControllerState. player_input.use_item = controller_input.use_item self.game_interface.update_player_input(player_input, self.index) # Send the rendering at the end, to minimize any impact on latency. The agent may have already called # end_rendering internally, if that's the case then this will just no-op. agent.renderer.end_rendering()
def set_render_manager(self, agent: BaseAgent): """ Sets the render manager for the agent. :param agent: An instance of an agent. """ rendering_manager = self.game_interface.renderer.get_rendering_manager( self.index, self.team) agent._set_renderer(rendering_manager)
def load_bot_config(index, bot_configuration, config_bundle: BotConfigBundle, looks_config_object, overall_config, name_dict, human_index_tracker: IncrementingInteger): """ Loads the config data of a single bot :param index: This is the bot index (where it appears in game_cars) :param bot_configuration: This is the game_tick_packet configuration that is sent back to the game :param config_bundle: A config object for a single bot :param overall_config: This is the config for the entire session not one particular bot :param name_dict: A mapping of used names so we can make sure to not reuse bot names. :param human_index_tracker: An object of type HumanIndexManager that helps set human_index correctly. :return: """ team_num = get_team(overall_config, index) bot_configuration.team = team_num # Setting up data about what type of bot it is bot_type = overall_config.get(PARTICIPANT_CONFIGURATION_HEADER, PARTICIPANT_TYPE_KEY, index) bot_configuration.bot, bot_configuration.rlbot_controlled = get_bot_options( bot_type) bot_configuration.bot_skill = overall_config.getfloat( PARTICIPANT_CONFIGURATION_HEADER, PARTICIPANT_BOT_SKILL_KEY, index) if not bot_configuration.bot: bot_configuration.human_index = human_index_tracker.increment() loadout_header = BOT_CONFIG_LOADOUT_HEADER if team_num == 1 and looks_config_object.has_section( BOT_CONFIG_LOADOUT_ORANGE_HEADER): loadout_header = BOT_CONFIG_LOADOUT_ORANGE_HEADER # Setting up the bots name bot_name = config_bundle.config_obj.get(BOT_CONFIG_MODULE_HEADER, BOT_NAME_KEY) bot_configuration.name = get_sanitized_bot_name(name_dict, bot_name) BaseAgent._parse_bot_loadout(bot_configuration, looks_config_object, loadout_header) python_file = 'NO_MODULE_FOR_PARTICIPANT' bot_parameters = None if bot_configuration.rlbot_controlled: # Python file relative to the config location. python_file = config_bundle.get_absolute_path(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY) agent_class_wrapper = import_agent(python_file) bot_parameters = agent_class_wrapper.get_loaded_class( ).base_create_agent_configurations() bot_parameters.parse_file( config_bundle.config_obj, config_directory=config_bundle.config_directory) return bot_name, team_num, python_file, bot_parameters
def __init__(self, name, team, index): sys.path.append(path) from output_formatter import OutputFormatter from input_formatter import InputFormatter import torch BaseAgent.__init__(self, name, team, index) self.actor_model = None self.single_model = None self.torch = torch self.output_formatter = OutputFormatter() self.input_formatter = InputFormatter(self.index, self.index, self.team)
def update_metadata_queue(self, agent: BaseAgent): """ Adds a new instance of AgentMetadata into the `agent_metadata_queue` using `agent` data. :param agent: An instance of an agent. """ pids = {os.getpid(), *agent.get_extra_pids()} helper_process_request = agent.get_helper_process_request() self.agent_metadata_queue.put( AgentMetadata(self.index, self.name, self.team, pids, helper_process_request))
def __init__(self, name, team, index): sys.path.append(path) from output_formatter import OutputFormatter from input_formatter import InputFormatter from cool_atba import Atba import torch BaseAgent.__init__(self, name, team, index) self.atba = Atba() self.torch = torch self.output_formatter = OutputFormatter() self.input_formatter = InputFormatter(self.index, self.index, self.team)
def __init__(self, name, team, index): from leviathan.output_formatter import OutputFormatter from leviathan.input_formatter import InputFormatter from leviathan.cool_atba import Atba import torch BaseAgent.__init__(self, name, team, index) self.pipe = None self.actor_model = None self.team_model = None self.game_memory = None self.atba = Atba() self.torch = torch self.output_formatter = OutputFormatter() self.input_formatter = InputFormatter(self.index, self.index)
def __init__(self, config_directory, config_obj: ConfigObject, config_file_name: str = None): super().__init__(config_directory, config_obj, config_file_name) self.base_agent_config = BaseAgent.base_create_agent_configurations() self.base_agent_config.parse_file(self.config_obj, config_directory=config_directory) self.python_file = self.get_absolute_path(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY) self.looks_path = self.get_absolute_path(BOT_CONFIG_MODULE_HEADER, LOOKS_CONFIG_KEY) self.loadout_generator_file = self.get_absolute_path(BOT_CONFIG_MODULE_HEADER, LOADOUT_GENERATOR_FILE_KEY)
def __init__(self, name, file_path=None): self.looks_path = None self.logger = get_logger('agent_preset') if file_path is not None and os.path.isfile(file_path): config_bundle = get_bot_config_bundle(file_path) self.looks_path = config_bundle.get_absolute_path( BOT_CONFIG_MODULE_HEADER, LOOKS_CONFIG_KEY) python_file_path = config_bundle.get_absolute_path( BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY) else: python_file_path = inspect.getfile(BaseAgent) try: self.agent_class = import_agent( python_file_path).get_loaded_class() super().__init__( self.agent_class.base_create_agent_configurations(), file_path, name) except (ValueError, ModuleNotFoundError, FileNotFoundError) as e: raise ValueError(f"Problem when processing {file_path}: {str(e)}") except ImportError as e: self.logger.debug( f"Will not use custom config for {file_path} because we failed to load: {str(e)}" ) super().__init__(BaseAgent.base_create_agent_configurations(), file_path, name) # Make sure the path to the python file actually gets set to that path, even if there was no config at file_path self.config.set_value(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY, python_file_path)
def __init__(self, name, file_path=None): basic_config = BaseAgent.base_create_agent_configurations() if file_path is not None and os.path.isfile(file_path): file_path = os.path.realpath(file_path) basic_config.parse_file(file_path) else: base_agent_path = os.path.join(get_python_root(), "rlbot", "agents", "base_agent.py") try: rel_path = os.path.relpath(base_agent_path, get_python_root()) except ValueError: rel_path = base_agent_path basic_config.set_value(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY, rel_path) python_file_path = os.path.realpath( os.path.join( os.path.dirname(os.path.realpath(file_path)), basic_config.get(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY))) try: self.agent_class = import_agent( python_file_path).get_loaded_class() except (ValueError, ModuleNotFoundError): self.agent_class = BaseAgent super().__init__(self.agent_class.base_create_agent_configurations(), file_path, name) # Make sure the path to the python file actually gets set to that path, even if there was no config at file_path self.config.set_value( BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY, basic_config.get(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY))
def get_looks_config(config_bundle): """ Creates a looks config from the config bundle :param config_bundle: :return: """ looks_path = config_bundle.get_absolute_path(BOT_CONFIG_MODULE_HEADER, LOOKS_CONFIG_KEY) return BaseAgent._create_looks_configurations().parse_file(looks_path)
def initialize(cls, agent: BaseAgent, packet: GameTickPacket): cls.agent = agent cls.field = Field(agent.team, agent.get_field_info()) cls.cars = [ Car(index=i, packet=packet) for i in range(packet.num_cars) ] cls.agent_car = cls.cars[cls.agent.index] cls.teammates = [car for car in cls.cars if car.team == cls.agent.team] cls.opponents = [car for car in cls.cars if car.team != cls.agent.team] cls.ball = Ball(packet=packet) cls.current_prediction = BallPredictor( cls.agent.get_ball_prediction_struct()) cls.update(packet)
def ball_path(bot: BaseAgent, color, duration: float = 4.0, step_size: int = 10): ball_prediction = bot.get_ball_prediction_struct() if ball_prediction is not None and duration > 0 and step_size > 0: time_passed = 0 steps_taken = 0 locations = [ball_prediction.slices[0].physics.location] while time_passed < duration and steps_taken + step_size < ball_prediction.num_slices: steps_taken += step_size time_passed += step_size * 0.016666 locations.append( ball_prediction.slices[steps_taken].physics.location) if steps_taken > 0: renderer().draw_polyline_3d(locations, color)
def __init__(self, config_directory, config_obj: ConfigObject, config_file_name: str = None): self.config_directory = config_directory self.config_file_name = config_file_name self.config_path = os.path.join(self.config_directory, self.config_file_name) self.config_obj = config_obj self.base_agent_config = BaseAgent.base_create_agent_configurations() self.base_agent_config.parse_file(self.config_obj, config_directory=config_directory) self.name = config_obj.get(BOT_CONFIG_MODULE_HEADER, BOT_NAME_KEY) self.looks_path = self.get_absolute_path(BOT_CONFIG_MODULE_HEADER, LOOKS_CONFIG_KEY) self.python_file = self.get_absolute_path(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY)
def __init__(self, config_directory, config_obj: ConfigObject, config_file_name: str = None): self.config_directory = config_directory self.config_file_name = config_file_name self.config_path = os.path.join(self.config_directory, self.config_file_name) self.config_obj = config_obj self.base_agent_config = BaseAgent.base_create_agent_configurations() self.base_agent_config.parse_file(self.config_obj, config_directory=config_directory) self.name = config_obj.get(BOT_CONFIG_MODULE_HEADER, BOT_NAME_KEY) self.looks_path = self.get_absolute_path(BOT_CONFIG_MODULE_HEADER, LOOKS_CONFIG_KEY) self.python_file = self.get_absolute_path(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY) self.loadout_generator_file = self.get_absolute_path( BOT_CONFIG_MODULE_HEADER, LOADOUT_GENERATOR_FILE_KEY) self.supports_early_start = self.base_agent_config.get( BOT_CONFIG_MODULE_HEADER, SUPPORTS_EARLY_START_KEY)
def import_agent(self, config_path): """ does not init the agent class. only returns it using rlbot framework :return: the agent class """ my_path = os.path.dirname(os.path.realpath(__file__)) #retriving python file path base_config = BaseAgent.base_create_agent_configurations() base_config.parse_file(config_path) agent_python_file = base_config.get(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY) #importing agent class python_path = os.path.join(os.path.dirname(config_path), agent_python_file) agent_class = import_agent(python_path).get_loaded_class() #retriving agent config agent_config = agent_class.base_create_agent_configurations() agent_config.parse_file(config_path) return agent_class, agent_config
def get_output(self, packet: GameTickPacket) -> SimpleControllerState: rb = BaseAgent.get_rigid_body_tick(self) if rb.players[0].input.throttle != 0: print(rb.players[0].input.throttle) return self.controller_state
def __init__(self, name, file_path=None): super().__init__(BaseAgent._create_looks_configurations(), file_path, name)
def bootstrap_python_bot(bot_name, directory): sanitized_name = convert_to_filename(bot_name) bot_directory = Path(directory or '.') with tempfile.TemporaryDirectory() as tmpdirname: tmpdir = Path(tmpdirname) print('created temporary directory', tmpdir) download_and_extract_zip( download_url= 'https://github.com/RLBot/RLBotPythonExample/archive/master.zip', local_zip_path=tmpdir / 'RLBotPythonExample.zip', local_folder_path=tmpdir) try: move(tmpdir / 'RLBotPythonExample-master', bot_directory / sanitized_name) except FileExistsError: return { 'error': f'There is already a bot named {sanitized_name}, please choose a different name!' } # Choose appropriate file names based on the bot name code_dir = bot_directory / sanitized_name / sanitized_name python_file = code_dir / f'{sanitized_name}.py' config_file = code_dir / f'{sanitized_name}.cfg' # We're making some big assumptions here that the file structure / names in RLBotPythonExample will not change. move(bot_directory / sanitized_name / 'python_example', code_dir) move(code_dir / 'python_example.py', python_file) move(code_dir / 'python_example.cfg', config_file) # Update the config file to point to the renamed files, and show the correct bot name. # This is not an ideal way of modifying the config file, because: # - It uses our custom ConfigObject class, which is limited / buggy, and we should be moving away from it # - The ConfigObject class is not capable of 'round-tripping', i.e. if you parse a config file and then # write it again, the comment lines will not be preserved. # - It can still write comments, but only if they have a 'description' that has been added programmatically # (see base_create_agent_configurations). # # One route is to add 'description' items for all the stuff we care about, including the stuff here # https://github.com/RLBot/RLBotPythonExample/blob/master/python_example/python_example.cfg#L11-L27 # so that the resulting file is sortof the same (might have slightly different formatting). That's annoying # and hard to maintain though, and again we'd be investing more in this custom config class that I would # prefer to get rid of. # # Alternatives: # # Use the configobj library https://configobj.readthedocs.io/en/latest/configobj.html # - I tried this in https://github.com/IamEld3st/RLBotGUI/commit/a30308940dd5a0e4a45db6ccc088e6e75a9f69f0 # which worked well for me, but people reported issues during installation. If we can get the installation # ironed out, it will be a nice solution for modifying cfg files in general. # # Do a simple find-and-replace in the file # - Very crude, but it can be reliable if we use specific commit hashes like I did in # https://github.com/IamEld3st/RLBotGUI/commit/a30308940dd5a0e4a45db6ccc088e6e75a9f69f0 # - It would get us up and running with the new features until we can figure out a proper config modification # solution. raw_bot_config = configparser.RawConfigParser() raw_bot_config.read(config_file, encoding='utf8') agent_config = BaseAgent.base_create_agent_configurations() agent_config.parse_file(raw_bot_config) agent_config.set_value(BOT_CONFIG_MODULE_HEADER, BOT_NAME_KEY, bot_name) agent_config.set_value(BOT_CONFIG_MODULE_HEADER, PYTHON_FILE_KEY, f'{sanitized_name}.py') with open(config_file, 'w', encoding='utf8') as f: f.write(str(agent_config)) # This is intended to open the example python file in the default system editor for .py files. # Hopefully this will be VS Code or notepad++ or something. If it gets executed as a python script, no harm done. os.startfile(python_file) return config_file
def __init__(self, config_directory, config_obj): self.config_directory = config_directory self.config_obj = config_obj self.base_agent_config = BaseAgent.base_create_agent_configurations() self.base_agent_config.parse_file(self.config_obj)
def get_output(self, parsed_packet: ParsedPacket, packet: GameTickPacket, agent: BaseAgent) -> SimpleControllerState: target_location = agent.field_info.my_goal.location return agent.move_towards_point(parsed_packet.my_car, target_location, True)