def try_recieve_agent_metadata(self): """ Checks whether any of the started bots have posted their AgentMetadata yet. If so, we put them on the agent_metadata_map such that we can kill their process later when we shut_down(kill_agent_process_ids=True) Returns how from how many bots we recieved metadata from. """ num_recieved = 0 while True: # will exit on queue.Empty try: single_agent_metadata = self.agent_metadata_queue.get( timeout=0.1) num_recieved += 1 self.helper_process_manager.start_or_update_helper_process( single_agent_metadata) self.agent_metadata_map[ single_agent_metadata.index] = single_agent_metadata process_configuration.configure_processes( self.agent_metadata_map, self.logger) except queue.Empty: return num_recieved except Exception as ex: self.logger.error(ex) return num_recieved return num_recieved
def run(self): self.quick_chat_manager.start_manager(self.quit_event) self.logger.debug("Successfully started quick chat manager") self.game_interface.start_match() self.logger.info("Match has started") self.logger.info("Press any character to exit") while not self.quit_event.is_set(): if msvcrt.kbhit(): msvcrt.getch() self.shut_down() break try: single_agent_metadata = self.agent_metadata_queue.get( timeout=1) self.helper_process_manager.start_or_update_helper_process( single_agent_metadata) self.agent_metadata_map[ single_agent_metadata.index] = single_agent_metadata process_configuration.configure_processes( self.agent_metadata_map, self.logger) except queue.Empty: pass except Exception as ex: self.logger.error(ex) pass
def try_recieve_agent_metadata(self): """ Checks whether any of the started bots have posted their AgentMetadata yet. If so, we put them on the agent_metadata_map such that we can kill their process later when we shut_down(kill_agent_process_ids=True) Returns how from how many bots we received metadata from. """ num_recieved = 0 while True: # will exit on queue.Empty try: single_agent_metadata: AgentMetadata = self.agent_metadata_queue.get(timeout=0.1) num_recieved += 1 if single_agent_metadata.name not in [pc.deduped_name for pc in self.match_config.player_configs]: self.logger.warn(f"Got agent metadata for {single_agent_metadata.name} but it shouldn't be running!") self.helper_process_manager.start_or_update_helper_process(single_agent_metadata) self.agent_metadata_map[single_agent_metadata.index] = single_agent_metadata process_configuration.configure_processes(self.agent_metadata_map, self.logger) except queue.Empty: self.num_metadata_received += num_recieved break # Let's go through the agent metadata map and see if we can expand it with any child processes. # We'll do it every time this function is called (generall periodically), # we don't know when an agent might spawn another process. if process_configuration.append_child_pids(self.agent_metadata_map): process_configuration.configure_processes(self.agent_metadata_map, self.logger) return num_recieved
def run(self): self.quick_chat_manager.start_manager(self.quit_event) self.logger.debug("Successfully started quick chat manager") self.game_interface.start_match() self.logger.info("Match has started") instructions = "Press 'r' to reload all agents, or 'q' to exit" self.logger.info(instructions) while not self.quit_event.is_set(): # Handle commands if msvcrt.kbhit(): command = msvcrt.getwch() if command.lower() == 'r': # r: reload self.reload_all_agents() elif command.lower( ) == 'q' or command == '\u001b': # q or ESC: quit self.shut_down() break # Print instructions again if a alphabet character was pressed but no command was found elif command.isalpha(): self.logger.info(instructions) try: single_agent_metadata = self.agent_metadata_queue.get( timeout=1) self.helper_process_manager.start_or_update_helper_process( single_agent_metadata) self.agent_metadata_map[ single_agent_metadata.index] = single_agent_metadata process_configuration.configure_processes( self.agent_metadata_map, self.logger) except queue.Empty: pass except Exception as ex: self.logger.error(ex) pass
def launch_bot_process_helper(self, early_starters_only=False, match_config: MatchConfig = None): # Start matchcomms here as it's only required for the bots. self.kill_matchcomms_server() self.matchcomms_server = launch_matchcomms_server() self.bot_processes = { ind: proc for ind, proc in self.bot_processes.items() if proc.is_alive() } num_started = 0 # Launch processes # TODO: this might be the right moment to fix the player indices based on a game tick packet. if not early_starters_only: packet = get_one_packet() # TODO: root through the packet and find discrepancies in the player index mapping. for i in range( min(self.num_participants, len(match_config.player_configs))): player_config = match_config.player_configs[i] if not player_config.has_bot_script(): continue if early_starters_only and not self.bot_bundles[ i].supports_early_start: continue spawn_id = player_config.spawn_id if early_starters_only: # Danger: we have low confidence in this since we're not leveraging the spawn id. participant_index = i else: participant_index = None self.logger.info( f'Player in slot {i} was sent with spawn id {spawn_id}, will search in the packet.' ) for n in range(0, packet.PlayersLength()): packet_spawn_id = packet.Players(n).SpawnId() if spawn_id == packet_spawn_id: self.logger.info( f'Looks good, considering participant index to be {n}' ) participant_index = n if participant_index is None: for prox_index, proc_info in self.bot_processes.items(): if spawn_id == proc_info.player_config.spawn_id: participant_index = prox_index if participant_index is None: raise Exception( f"Unable to determine the bot index for spawn id {spawn_id}" ) if participant_index not in self.bot_processes: bundle = get_bot_config_bundle(player_config.config_path) name = str(self.match_config.player_configs[i].deduped_name) if bundle.supports_standalone: executable = sys.executable if bundle.use_virtual_environment: executable = str( Path(bundle.config_directory) / 'venv' / 'Scripts' / 'python.exe') process = subprocess.Popen( [ executable, bundle.python_file, '--config-file', str(player_config.config_path), '--name', name, '--team', str(self.teams[i]), '--player-index', str(participant_index), '--spawn-id', str(spawn_id), '--matchcomms-url', self.matchcomms_server.root_url.geturl() ], cwd=Path(bundle.config_directory).parent) self.bot_processes[participant_index] = BotProcessInfo( process=None, subprocess=process, player_config=player_config) # Insert immediately into the agent metadata map because the standalone process has no way to communicate it back out self.agent_metadata_map[participant_index] = AgentMetadata( participant_index, name, self.teams[i], {process.pid}) else: reload_request = mp.Event() quit_callback = mp.Event() self.bot_reload_requests.append(reload_request) self.bot_quit_callbacks.append(quit_callback) process = mp.Process( target=SetupManager.run_agent, args=(self.quit_event, quit_callback, reload_request, self.bot_bundles[i], name, self.teams[i], participant_index, self.python_files[i], self.agent_metadata_queue, match_config, self.matchcomms_server.root_url, spawn_id)) process.start() self.bot_processes[participant_index] = BotProcessInfo( process=process, subprocess=None, player_config=player_config) num_started += 1 self.logger.info(f"Successfully started {num_started} bot processes") process_configuration.configure_processes(self.agent_metadata_map, self.logger) scripts_started = 0 for script_config in match_config.script_configs: script_config_bundle = get_script_config_bundle( script_config.config_path) if early_starters_only and not script_config_bundle.supports_early_start: continue executable = sys.executable if script_config_bundle.use_virtual_environment: executable = str( Path(script_config_bundle.config_directory) / 'venv' / 'Scripts' / 'python.exe') process = subprocess.Popen( [executable, script_config_bundle.script_file], cwd=Path(script_config_bundle.config_directory).parent) self.logger.info( f"Started script with pid {process.pid} using {process.args}") self.script_processes[process.pid] = process scripts_started += 1 self.logger.debug(f"Successfully started {scripts_started} scripts") return num_started