Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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