text: /*! \file sc2_coordinator.h
      \brief Frontend for running a game.
  
      The coordinator acts as a game and bot manager. It is used to launch StarCraft and setup proto connections
      between a user's bot and the running StarCraft instance. With it a user steps forward a simulation and it will
      fill out bot interface data.
  */
  
  #pragma once
  
  #include <vector>
  #include <string>
  #include "sc2api/sc2_game_settings.h"
  #include "sc2api/sc2_proto_interface.h"
  
  namespace sc2 {
  
  class Agent;
  class ReplayObserver;
  class CoordinatorImp;
  
  //! Coordinator of one or more clients. Used to start, step and stop games and replays.
  class Coordinator {
  public:
      Coordinator();
      ~Coordinator();
  
      // Initialization and setup.
  
      //! Used to load settings. Settings will be discovered in the following order:
      //!     1. If command line arguments are provided it will use them. Invoke binary with --help to see expected arguments.
      //!     2. (Recommended) If the StarCraft II binary has been run the function will auto discover its location.
      //! \param argc Provided in main signature.
      //! \param argv Provided in main signature.
      //! \param game_settings The name of the settings file.
      //! \return True if settings were found or discovered, false otherwise.
      bool LoadSettings(int argc, char** argv);
  
      //! Specifies whether bots or replays OnStep function should be run in parallel. If set to true make sure your bots are thread-safe
      //! if they reach into shared code.
      //! \param value True to multithread, false otherwise.
      void SetMultithreaded(bool value);
  
      //! Specifies whether the game should run in realtime or not. If the game is running in real time that means the coordinator is
      //! not stepping it forward. The game is running and your bot reaches into it asynchronously to read state.
      //! \param value True to be realtime, false otherwise.
      void SetRealtime(bool value);
  
      //! Sets the number of game loops to run for each step.
      //! \param step_size Number of gameloops to run for each step.
      void SetStepSize(int step_size);
  
      //! Sets the path to the StarCraft II binary.
      //! \param path Absolute file path.
      void SetProcessPath(const std::string& path);
  
      //! Set the correct data version of a replay to allow faster replay loading. Saves a few seconds if replay is not up to date.
      //!  Works only in combination with correct process path set by "SetProcessPath".
      //! \param version Look in "protocol/buildinfo/versions.json" for the property "data-hash". Or read it from "ReplayInfo.data_version".
      void SetDataVersion(const std::string& version);
  
      //! Sets the timeout for network operations.
      //! \param value timeout_ms in milliseconds.
      void SetTimeoutMS(uint32_t timeout_ms = kDefaultProtoInterfaceTimeout);
  
      //! Sets the first port number to use. Subsequent port assignments are sequential.
      //! \param port_start First port number.
      void SetPortStart(int port_start);
  
      //! Indicates whether feature layers should be provided in the observation.
      //! \param settings Configuration of feature layer settings.
      //! \sa FeatureLayerSettings
      void SetFeatureLayers(const FeatureLayerSettings& settings);
  
      //!
      //! \sa RenderSettings
      void SetRender(const RenderSettings& settings);
  
      //! Sets the game window dimensions.
      //! \param width Width of game window.
      //! \param height Height of game window.
      void SetWindowSize(int width, int height);
  
      //! Sets the game window location.
      //! \param x X position of game window.
      //! \param y y position of game window.
      void SetWindowLocation(int x, int y);
  
      //! Uses generalized abilities where possible. Example: BUILD_TECHLAB_BARRACKS, BUILD_TECHLAB_FACTORY, BUILD_TECHLAB_STARPORT 
      //! ability ids are generalized to BUILD_TECHLAB ability id in the observation.
      void SetUseGeneralizedAbilityId(bool value);
  
      //! Sets the replay perspective. Use 0 to observe all players.
      void SetReplayPerspective(int player_id);
  
      //! Appends a command line argument to be fed to StarCraft II when starting.
      // \param option The string to be appended to the executable invoke.
      void AddCommandLine(const std::string& option);
  
      //! Sets up the bots and whether they are controlled by in-built AI, human or a custom bot.
      // \param participants A vector of player setups for each participant in the game.
      // \sa PlayerSetup
      void SetParticipants(const std::vector<PlayerSetup>& participants);
  
      void SetReplayRecovery(bool value);
  
      //! Add an instance of ReplayObserver, each ReplayObserver will run a separate StarCraft II client.
      // \param replay_observer A pointer to the replay observer to utilize.
      // \sa ReplayObserver
      void AddReplayObserver(ReplayObserver* replay_observer);
  
      // Start-up.
  
      //! Uses settings gathered from LoadSettings, specifically the path to the executable, to run StarCraft II.
      void LaunchStarcraft();
  
      //! Attaches to a running Starcraft.
      void Connect(int port);
  
      //! Starts a game on a certain map. There are multiple ways to specify a map:
      //! Absolute path: Any .SC2Map file.
      //! Relative path: Any .SC2Map file relative to either the library or installation maps folder.
      //! Map name: Any BattleNet published map that has been locally cached.
      //! \param map_path Path to the map to run.
      //! \return True if the game started, false if there was errors or the game didn't start, override OnError callback to see the exact errors.
      bool StartGame(const std::string& map_path = std::string());
  
      //! Creates a game but does not join the agents to the game
      //! \param map_path Path to the map to run.
      //! Returns true if the game was successfully created
      bool CreateGame(const std::string& map_path = std::string());
  
      //! Joins agents to the game
      //! Returns true if the agents were successfully connected to the game
      bool JoinGame();
  
      //! Sets up the sc2 game ports to use
      //! param num_agents Number of agents in the game
      //! param port_start Starting port number
      //! param check_single  Checks if the game is a single player or multiplayer game
      void SetupPorts(size_t num_agents, int port_start, bool check_single = true);
  
      // Run.
  
      //! Helper function used to actually run a bot. This function will behave differently in real-time compared to
      //! non real-time. In real-time there is no step sent over the wire but instead will request and read observations as the game runs.
      //! * For non-real time Update will perform the following:
      //!     1. Step the simulation forward by a certain amount of game steps, this essentially moves the game loops forward.
      //!     2. Wait for the step to complete, the step is completed when a response is received and read from the StarCraft II binary.
      //!         * When the step is completed an Observation has been received. It is parsed and various client events are dispatched.
      //!     3. Call the user's OnStep function.
      //! * Real time applications will perform the following:
      //!     1. The Observation is directly requested. The process will block while waiting for it.
      //!     2. The Observation is parsed and client events are dispatched.
      //!     3. Unit actions batched from the ActionInterface are dispatched.
      //! \return False if the game has ended, true otherwise.
      bool Update();
  
      //! Requests for the currently running game to end.
      void LeaveGame();
  
      // Status.
  
      //! Returns true if all running games have ended.
      bool AllGamesEnded() const;
  
      // Replay specific.
      //! Sets the path for to a folder of replays to analyze.
      // \param path The folder path.
      bool SetReplayPath(const std::string& path);
      //! Loads replays from a file.
      // \param path The file path.
      bool LoadReplayList(const std::string& file_path);
      //! Saves replays to a file.
      // \param path The file path.
      void SaveReplayList(const std::string& file_path);
      //! Determines if there are unprocessed replays.
      //!< \return Is true if there are replays left.
      bool HasReplays() const;
  
      // Misc.
  
      //! Blocks for all bots to receive any pending responses
      void WaitForAllResponses();
      //! Saves a binary blob as a map to a remote location.
      // \param data The map data.
      // \param data_size The size of map data.
      // \param remote_path The file path to save the data to.
      //!< \return Is true if the save is successful.
      bool RemoteSaveMap(const void* data, int data_size, std::string remote_path);
      //! Gets the game executable path.
      //!< \return The game executable path.
      std::string GetExePath() const;
  
  private:
      CoordinatorImp* imp_;
  };
  
  }
  