Exemple #1
0
    def testVsAgent(self):
        parallel = run_parallel.RunParallel()
        for _ in range(NUM_MATCHES):
            with host_remote_agent.VsAgent() as game:
                game.create_game("Simple64")
                controllers = [
                    remote_controller.RemoteController(host=host,
                                                       port=host_port)
                    for host, host_port in zip(game.hosts, game.host_ports)
                ]

                join = sc_pb.RequestJoinGame(options=sc_pb.InterfaceOptions(
                    raw=True))
                join.race = sc_common.Random
                join.shared_port = 0
                join.server_ports.game_port = game.lan_ports[0]
                join.server_ports.base_port = game.lan_ports[1]
                join.client_ports.add(game_port=game.lan_ports[2],
                                      base_port=game.lan_ports[3])

                parallel.run((c.join_game, join) for c in controllers)
                for _ in range(STEPS):
                    parallel.run(c.step for c in controllers)
                    response_observations = [c.observe() for c in controllers]

                    if response_observations[0].player_result:
                        break

                parallel.run(c.leave for c in controllers)
                parallel.run(c.close for c in controllers)
Exemple #2
0
 def test_avoids_deadlock(self):
     b = Barrier(2)
     pool = run_parallel.RunParallel(timeout=2)
     with self.assertRaises(ValueError):
         pool.run([int, b.wait, bad])
     # Release the thread waiting on the barrier so the process can exit cleanly.
     b.clear()
Exemple #3
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            race=None,
            agent_interface_format=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            realtime=False,
            replay_dir=None,
            controller=None,
            update_game_info=False,
            crop_to_playable_area=False,
            show_cloaked=False,
            show_burrowed_shadows=False,
            show_placeholders=False,
            raw_affects_selection=True,
            use_pysc2_feature=True,
            map_name=None):
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if not race:
            race = sc2_env.Race.random

        self._num_agents = 1
        self._discount = discount
        self._step_mul = step_mul or 8
        self._realtime = realtime
        self._save_replay_episodes = 1 if replay_dir else 0
        self._replay_dir = replay_dir

        self._score_index = -1  # Win/loss only.
        self._score_multiplier = 1
        self._episode_length = 0  # No limit.

        self._map_name = map_name
        self._update_game_info = update_game_info
        self.raw = not use_pysc2_feature

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

        self._controllers = [controller]

        interface = self._get_interface(
            agent_interface_format=agent_interface_format,
            require_raw=True,
            crop_to_playable_area=crop_to_playable_area,
            show_cloaked=show_cloaked,
            show_burrowed_shadows=show_burrowed_shadows,
            show_placeholders=show_placeholders,
            raw_affects_selection=raw_affects_selection)

        self._finalize([agent_interface_format], [interface], visualize)
Exemple #4
0
 def _launch_gamecores(self):
     num = len(self._agents)
     self._run_config = run_configs.get()
     self._sc2_procs = [
         self._run_config.start(extra_ports=self._ports) for _ in range(num)
     ]
     self._controllers = [p.controller for p in self._sc2_procs]
     self._parallel = run_parallel.RunParallel()
Exemple #5
0
 def test_exception(self):
     pool = run_parallel.RunParallel()
     out = pool.run([lambda: 1, ValueError])
     self.assertEqual(out[0], 1)
     self.assertIsInstance(out[1], ValueError)
     with self.assertRaises(ValueError):
         pool.run([bad])
     with self.assertRaises(ValueError):
         pool.run([int, bad])
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            race=None,
            agent_interface_format=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            replay_dir=None,
            controller=None,
            map_name=None):
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if not race:
            race = sc2_env.Race.random

        self._num_agents = 1
        self._discount = discount
        self._step_mul = step_mul or 8
        self._save_replay_episodes = 1 if replay_dir else 0
        self._replay_dir = replay_dir

        self._score_index = -1  # Win/loss only.
        self._score_multiplier = 1
        self._episode_length = 0  # No limit.

        self._map_name = map_name

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

        self._controllers = [controller]

        interface = self._get_interface(
            agent_interface_format=agent_interface_format, require_raw=True)

        self._finalize([agent_interface_format], [interface], visualize)
Exemple #7
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            map_name=None,
            battle_net_map=False,
            players=None,
            agent_interface_format=None,
            discount=1.,
            discount_zero_after_timeout=False,
            visualize=False,
            step_mul=None,
            realtime=False,
            save_replay_episodes=0,
            replay_dir=None,
            replay_prefix=None,
            game_steps_per_episode=None,
            score_index=None,
            score_multiplier=None,
            random_seed=None,
            disable_fog=False,
            ensure_available_actions=True,
            version=None):
        """Create a SC2 Env.

    You must pass a resolution that you want to play at. You can send either
    feature layer resolution or rgb resolution or both. If you send both you
    must also choose which to use as your action space. Regardless of which you
    choose you must send both the screen and minimap resolutions.

    For each of the 4 resolutions, either specify size or both width and
    height. If you specify size then both width and height will take that value.

    Args:
      _only_use_kwargs: Don't pass args, only kwargs.
      map_name: Name of a SC2 map. Run bin/map_list to get the full list of
          known maps. Alternatively, pass a Map instance. Take a look at the
          docs in maps/README.md for more information on available maps. Can
          also be a list of map names or instances, in which case one will be
          chosen at random per episode.
      battle_net_map: Whether to use the battle.net versions of the map(s).
      players: A list of Agent and Bot instances that specify who will play.
      agent_interface_format: A sequence containing one AgentInterfaceFormat
        per agent, matching the order of agents specified in the players list.
        Or a single AgentInterfaceFormat to be used for all agents.
      discount: Returned as part of the observation.
      discount_zero_after_timeout: If True, the discount will be zero
          after the `game_steps_per_episode` timeout.
      visualize: Whether to pop up a window showing the camera and feature
          layers. This won't work without access to a window manager.
      step_mul: How many game steps per agent step (action/observation). None
          means use the map default.
      realtime: Whether to use realtime mode. In this mode the game simulation
          automatically advances (at 22.4 gameloops per second) rather than
          being stepped manually. The number of game loops advanced with each
          call to step() won't necessarily match the step_mul specified. The
          environment will attempt to honour step_mul, returning observations
          with that spacing as closely as possible. Game loops will be skipped
          if they cannot be retrieved and processed quickly enough.
      save_replay_episodes: Save a replay after this many episodes. Default of 0
          means don't save replays.
      replay_dir: Directory to save replays. Required with save_replay_episodes.
      replay_prefix: An optional prefix to use when saving replays.
      game_steps_per_episode: Game steps per episode, independent of the
          step_mul. 0 means no limit. None means use the map default.
      score_index: -1 means use the win/loss reward, >=0 is the index into the
          score_cumulative with 0 being the curriculum score. None means use
          the map default.
      score_multiplier: How much to multiply the score by. Useful for negating.
      random_seed: Random number seed to use when initializing the game. This
          lets you run repeatable games/tests.
      disable_fog: Whether to disable fog of war.
      ensure_available_actions: Whether to throw an exception when an
          unavailable action is passed to step().
      version: The version of SC2 to use, defaults to the latest.

    Raises:
      ValueError: if no map is specified.
      ValueError: if wrong number of players are requested for a map.
      ValueError: if the resolutions aren't specified correctly.
    """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if not players:
            raise ValueError("You must specify the list of players.")

        for p in players:
            if not isinstance(p, (Agent, Bot)):
                raise ValueError(
                    "Expected players to be of type Agent or Bot. Got: %s." %
                    p)

        num_players = len(players)
        self._num_agents = sum(1 for p in players if isinstance(p, Agent))
        self._players = players

        if not 1 <= num_players <= 2 or not self._num_agents:
            raise ValueError("Only 1 or 2 players with at least one agent is "
                             "supported at the moment.")

        if not map_name:
            raise ValueError("Missing a map name.")

        self._battle_net_map = battle_net_map
        self._maps = [maps.get(name) for name in to_list(map_name)]
        min_players = min(m.players for m in self._maps)
        max_players = max(m.players for m in self._maps)
        if self._battle_net_map:
            for m in self._maps:
                if not m.battle_net:
                    raise ValueError("%s isn't known on Battle.net" % m.name)

        if max_players == 1:
            if self._num_agents != 1:
                raise ValueError(
                    "Single player maps require exactly one Agent.")
        elif not 2 <= num_players <= min_players:
            raise ValueError(
                "Maps support 2 - %s players, but trying to join with %s" %
                (min_players, num_players))

        if save_replay_episodes and not replay_dir:
            raise ValueError("Missing replay_dir")

        self._realtime = realtime
        self._last_step_time = None
        self._save_replay_episodes = save_replay_episodes
        self._replay_dir = replay_dir
        self._replay_prefix = replay_prefix
        self._random_seed = random_seed
        self._disable_fog = disable_fog
        self._ensure_available_actions = ensure_available_actions
        self._discount = discount
        self._discount_zero_after_timeout = discount_zero_after_timeout
        self._default_step_mul = step_mul
        self._default_score_index = score_index
        self._default_score_multiplier = score_multiplier
        self._default_episode_length = game_steps_per_episode

        self._run_config = run_configs.get(version=version)
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.
        self._game_info = None

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if isinstance(agent_interface_format, AgentInterfaceFormat):
            agent_interface_format = [agent_interface_format
                                      ] * self._num_agents

        if len(agent_interface_format) != self._num_agents:
            raise ValueError(
                "The number of entries in agent_interface_format should "
                "correspond 1-1 with the number of agents.")

        self._action_delay_fns = [
            aif.action_delay_fn for aif in agent_interface_format
        ]

        self._interface_formats = agent_interface_format
        self._interface_options = [
            self._get_interface(interface_format,
                                require_raw=visualize and i == 0)
            for i, interface_format in enumerate(agent_interface_format)
        ]

        self._launch_game()
        self._create_join()

        self._finalize(visualize)
Exemple #8
0
  def __init__(self,  # pylint: disable=invalid-name
               _only_use_kwargs=None,
               map_name=None,
               players=None,
               agent_race=None,  # deprecated
               bot_race=None,  # deprecated
               difficulty=None,  # deprecated
               screen_size_px=None,  # deprecated
               minimap_size_px=None,  # deprecated
               feature_screen_size=None,
               feature_screen_width=None,
               feature_screen_height=None,
               feature_minimap_size=None,
               feature_minimap_width=None,
               feature_minimap_height=None,
               rgb_screen_size=None,
               rgb_screen_width=None,
               rgb_screen_height=None,
               rgb_minimap_size=None,
               rgb_minimap_width=None,
               rgb_minimap_height=None,
               action_space=None,
               camera_width_world_units=None,
               discount=1.,
               visualize=False,
               step_mul=None,
               save_replay_episodes=0,
               replay_dir=None,
               game_steps_per_episode=None,
               score_index=None,
               score_multiplier=None,
               use_feature_units=False,
               random_seed=None,
               disable_fog=False):
    """Create a SC2 Env.

    You must pass a resolution that you want to play at. You can send either
    feature layer resolution or rgb resolution or both. If you send both you
    must also choose which to use as your action space. Regardless of which you
    choose you must send both the screen and minimap resolutions.

    For each of the 4 resolutions, either specify size or both width and
    height. If you specify size then both width and height will take that value.

    Args:
      _only_use_kwargs: Don't pass args, only kwargs.
      map_name: Name of a SC2 map. Run bin/map_list to get the full list of
          known maps. Alternatively, pass a Map instance. Take a look at the
          docs in maps/README.md for more information on available maps.
      players: A list of Agent and Bot instances that specify who will play.
      agent_race: Deprecated. Use players instead.
      bot_race: Deprecated. Use players instead.
      difficulty: Deprecated. Use players instead.
      screen_size_px: Deprecated. Use feature_screen_... instead.
      minimap_size_px: Deprecated. Use feature_minimap_... instead.
      feature_screen_size: Sets feature_screen_width and feature_screen_width.
      feature_screen_width: The width of the feature layer screen observation.
      feature_screen_height: The height of the feature layer screen observation.
      feature_minimap_size: Sets feature_minimap_width and
          feature_minimap_height.
      feature_minimap_width: The width of the feature layer minimap observation.
      feature_minimap_height: The height of the feature layer minimap
          observation.
      rgb_screen_size: Sets rgb_screen_width and rgb_screen_height.
      rgb_screen_width: The width of the rgb screen observation.
      rgb_screen_height: The height of the rgb screen observation.
      rgb_minimap_size: Sets rgb_minimap_width and rgb_minimap_height.
      rgb_minimap_width: The width of the rgb minimap observation.
      rgb_minimap_height: The height of the rgb minimap observation.
      action_space: If you pass both feature and rgb sizes, then you must also
          specify which you want to use for your actions as an ActionSpace enum.
      camera_width_world_units: The width of your screen in world units. If your
          feature_screen=(64, 48) and camera_width is 24, then each px
          represents 24 / 64 = 0.375 world units in each of x and y. It'll then
          represent a camera of size (24, 0.375 * 48) = (24, 18) world units.
      discount: Returned as part of the observation.
      visualize: Whether to pop up a window showing the camera and feature
          layers. This won't work without access to a window manager.
      step_mul: How many game steps per agent step (action/observation). None
          means use the map default.
      save_replay_episodes: Save a replay after this many episodes. Default of 0
          means don't save replays.
      replay_dir: Directory to save replays. Required with save_replay_episodes.
      game_steps_per_episode: Game steps per episode, independent of the
          step_mul. 0 means no limit. None means use the map default.
      score_index: -1 means use the win/loss reward, >=0 is the index into the
          score_cumulative with 0 being the curriculum score. None means use
          the map default.
      score_multiplier: How much to multiply the score by. Useful for negating.
      use_feature_units: Whether to include feature unit data in observations.
      random_seed: Random number seed to use when initializing the game. This
          lets you run repeatable games/tests.
      disable_fog: Whether to disable fog of war.

    Raises:
      ValueError: if the agent_race, bot_race or difficulty are invalid.
      ValueError: if too many players are requested for a map.
      ValueError: if the resolutions aren't specified correctly.
      DeprecationWarning: if screen_size_px or minimap_size_px are sent.
      DeprecationWarning: if agent_race, bot_race or difficulty are sent.
    """
    if _only_use_kwargs:
      raise ValueError("All arguments must be passed as keyword arguments.")

    if screen_size_px or minimap_size_px:
      raise DeprecationWarning(
          "screen_size_px and minimap_size_px are deprecated. Use the feature "
          "or rgb variants instead. Make sure to check your observations too "
          "since they also switched from screen/minimap to feature and rgb "
          "variants.")

    if agent_race or bot_race or difficulty:
      raise DeprecationWarning(
          "Explicit agent and bot races are deprecated. Pass an array of "
          "sc2_env.Bot and sc2_env.Agent instances instead.")

    map_inst = maps.get(map_name)
    self._map_name = map_name

    if not players:
      players = list()
      players.append(Agent(Race.random))

      if not map_inst.players or map_inst.players >= 2:
        players.append(Bot(Race.random, Difficulty.very_easy))

    for p in players:
      if not isinstance(p, (Agent, Bot)):
        raise ValueError(
            "Expected players to be of type Agent or Bot. Got: %s." % p)

    num_players = len(players)
    self._num_agents = sum(1 for p in players if isinstance(p, Agent))
    self._players = players

    if not 1 <= num_players <= 2 or not self._num_agents:
      raise ValueError(
          "Only 1 or 2 players with at least one agent is "
          "supported at the moment.")

    if save_replay_episodes and not replay_dir:
      raise ValueError("Missing replay_dir")

    if map_inst.players and num_players > map_inst.players:
      raise ValueError(
          "Map only supports %s players, but trying to join with %s" % (
              map_inst.players, num_players))

    self._discount = discount
    self._step_mul = step_mul or map_inst.step_mul
    self._save_replay_episodes = save_replay_episodes
    self._replay_dir = replay_dir
    self._random_seed = random_seed
    self._disable_fog = disable_fog

    if score_index is None:
      self._score_index = map_inst.score_index
    else:
      self._score_index = score_index
    if score_multiplier is None:
      self._score_multiplier = map_inst.score_multiplier
    else:
      self._score_multiplier = score_multiplier

    self._episode_length = game_steps_per_episode
    if self._episode_length is None:
      self._episode_length = map_inst.game_steps_per_episode

    self._run_config = run_configs.get()
    self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

    interface = self._get_interface(
        feature_screen_size, feature_screen_width, feature_screen_height,
        feature_minimap_size, feature_minimap_width, feature_minimap_height,
        rgb_screen_size, rgb_screen_width, rgb_screen_height, rgb_minimap_size,
        rgb_minimap_width, rgb_minimap_height, action_space,
        camera_width_world_units, use_feature_units, visualize)

    if self._num_agents == 1:
      self._launch_sp(map_inst, interface)
    else:
      self._launch_mp(map_inst, interface)

    self._finalize(interface, action_space, use_feature_units, visualize)
Exemple #9
0
  def test_observe_players(self):
    players = 2  # Can be 1.
    run_config = run_configs.get()
    parallel = run_parallel.RunParallel()
    map_inst = maps.get("Simple64")

    screen_size_px = point.Point(64, 64)
    minimap_size_px = point.Point(32, 32)
    interface = sc_pb.InterfaceOptions(raw=True, score=True)
    screen_size_px.assign_to(interface.feature_layer.resolution)
    minimap_size_px.assign_to(interface.feature_layer.minimap_resolution)

    # Reserve a whole bunch of ports for the weird multiplayer implementation.
    ports = portspicker.pick_unused_ports((players + 2) * 2)
    logging.info("Valid Ports: %s", ports)

    # Actually launch the game processes.
    print_stage("start")
    sc2_procs = [run_config.start(extra_ports=ports, want_rgb=False)
                 for _ in range(players + 1)]
    controllers = [p.controller for p in sc2_procs]

    try:
      # Save the maps so they can access it.
      map_path = os.path.basename(map_inst.path)
      print_stage("save_map")
      parallel.run((c.save_map, map_path, map_inst.data(run_config))
                   for c in controllers)

      # Create the create request.
      create = sc_pb.RequestCreateGame(
          local_map=sc_pb.LocalMap(map_path=map_path))
      create.player_setup.add(type=sc_pb.Participant)
      if players == 1:
        create.player_setup.add(type=sc_pb.Computer, race=sc_common.Random,
                                difficulty=sc_pb.VeryEasy)
      else:
        create.player_setup.add(type=sc_pb.Participant)
      create.player_setup.add(type=sc_pb.Observer)

      # Create the join request.
      joins = []
      portIdx = 2
      for i in range(players + 1):
        join = sc_pb.RequestJoinGame(options=interface)
        if i < players:
          join.race = sc_common.Random
        else:
          join.observed_player_id = 0
        join.host_ip = sc2_procs[0].host
        join.shared_port = 0  # unused
        join.server_ports.game_port = ports[0]
        join.server_ports.base_port = ports[1]
        join.client_ports.add(game_port=ports[portIdx], base_port=ports[portIdx + 1])
        portIdx = portIdx + 2
        joins.append(join)

      # Create and Join
      print_stage("create")
      controllers[0].create_game(create)
      print_stage("join")
      parallel.run((c.join_game, join) for c, join in zip(controllers, joins))

      print_stage("run")
      for game_loop in range(1, 10):  # steps per episode
        # Step the game
        parallel.run((c.step, 16) for c in controllers)

        # Observe
        obs = parallel.run(c.observe for c in controllers)
        for p_id, o in enumerate(obs):
          self.assertEqual(o.observation.game_loop, game_loop * 16)
          if p_id == players:  # ie the observer
            self.assertEqual(o.observation.player_common.player_id, 0)
          else:
            self.assertEqual(o.observation.player_common.player_id, p_id + 1)

        # Act
        actions = [sc_pb.Action() for _ in range(players)]
        for action in actions:
          pt = (point.Point.unit_rand() * minimap_size_px).floor()
          pt.assign_to(action.action_feature_layer.camera_move.center_minimap)
        parallel.run((c.act, a) for c, a in zip(controllers[:players], actions))

      # Done this game.
      print_stage("leave")
      parallel.run(c.leave for c in controllers)
    finally:
      print_stage("quit")
      # Done, shut down. Don't depend on parallel since it might be broken.
      for c in controllers:
        c.quit()
      for p in sc2_procs:
        p.close()
      portspicker.return_ports(ports)
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            host="127.0.0.1",
            config_port=None,
            race=None,
            agent_interface_format=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            replay_dir=None):
        """Create a SC2 Env that connects to a remote instance of the game.

    This assumes that the game is already up and running, and it only needs to
    join. You need some other script to launch the process and call
    RequestCreateGame. It also assumes that it's a multiplayer game, and that
    the ports are consecutive.

    You must pass a resolution that you want to play at. You can send either
    feature layer resolution or rgb resolution or both. If you send both you
    must also choose which to use as your action space. Regardless of which you
    choose you must send both the screen and minimap resolutions.

    For each of the 4 resolutions, either specify size or both width and
    height. If you specify size then both width and height will take that value.

    Args:
      _only_use_kwargs: Don't pass args, only kwargs.
      host: Which ip to use. Either ipv4 or ipv6 localhost.
      config_port: Where to find the config port.
      race: Race for this agent.
      agent_interface_format: AgentInterfaceFormat object describing the
          format of communication between the agent and the environment.
      discount: Returned as part of the observation.
      visualize: Whether to pop up a window showing the camera and feature
          layers. This won't work without access to a window manager.
      step_mul: How many game steps per agent step (action/observation). None
          means use the map default.
      replay_dir: Directory to save a replay.

    Raises:
      ValueError: if the race is invalid.
      ValueError: if the resolutions aren't specified correctly.
      ValueError: if the host or port are invalid.
    """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if host not in ("127.0.0.1", "::1"):
            raise ValueError("Bad host arguments. Must be a localhost")
        if not config_port:
            raise ValueError("Must pass a config_port.")

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if not race:
            race = sc2_env.Race.random

        self._num_agents = 1
        self._discount = discount
        self._step_mul = step_mul or 8
        self._save_replay_episodes = 1 if replay_dir else 0
        self._replay_dir = replay_dir

        self._score_index = -1  # Win/loss only.
        self._score_multiplier = 1
        self._episode_length = 0  # No limit.
        self._discount_zero_after_timeout = False

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

        interface = self._get_interface(
            agent_interface_format=agent_interface_format,
            require_raw=visualize)

        self._launch_remote(host, config_port, race, interface)

        self._finalize([agent_interface_format], [interface], visualize)
Exemple #11
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            map_name=None,
            save_map=True,
            host="127.0.0.1",
            host_port=None,
            lan_port=None,
            race=None,
            name="<unknown>",
            agent_interface_format=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            realtime=False,
            replay_dir=None,
            replay_prefix=None):
        """Create a SC2 Env that connects to a remote instance of the game.

        This assumes that the game is already up and running, and that it only
        needs to join the game - and leave once the game has ended. You need some
        other script to launch the SC2 process and call RequestCreateGame. Note
        that you must call close to leave the game when finished. Not doing so
        will lead to issues when attempting to create another game on the same
        SC2 process.

        This class assumes that the game is multiplayer. LAN ports may be
        specified either as a base port (from which the others will be implied),
        or as an explicit list.

        You must specify an agent_interface_format. See the `AgentInterfaceFormat`
        documentation for further detail.

        Args:
          _only_use_kwargs: Don't pass args, only kwargs.
          map_name: Name of a SC2 map. Run bin/map_list to get the full list of
              known maps. Alternatively, pass a Map instance. Take a look at the
              docs in maps/README.md for more information on available maps.
          save_map: Whether to save map data before joining the game.
          host: Host where the SC2 process we're connecting to is running.
          host_port: The WebSocket port for the SC2 process we're connecting to.
          lan_port: Either an explicit sequence of LAN ports corresponding to
              [server game port, ...base port, client game port, ...base port],
              or an int specifying base port - equivalent to specifying the
              sequence [lan_port, lan_port+1, lan_port+2, lan_port+3].
          race: Race for this agent.
          name: The name of this agent, for saving in the replay.
          agent_interface_format: AgentInterfaceFormat object describing the
              format of communication between the agent and the environment.
          discount: Returned as part of the observation.
          visualize: Whether to pop up a window showing the camera and feature
              layers. This won't work without access to a window manager.
          step_mul: How many game steps per agent step (action/observation). None
              means use the map default.
          realtime: Whether to use realtime mode. In this mode the game simulation
              automatically advances (at 22.4 gameloops per second) rather than
              being stepped manually. The number of game loops advanced with each
              call to step() won't necessarily match the step_mul specified. The
              environment will attempt to honour step_mul, returning observations
              with that spacing as closely as possible. Game loops will be skipped
              if they cannot be retrieved and processed quickly enough.
          replay_dir: Directory to save a replay.
          replay_prefix: An optional prefix to use when saving replays.

        Raises:
          ValueError: if the race is invalid.
          ValueError: if the resolutions aren't specified correctly.
          ValueError: if lan_port is a sequence but its length != 4.
        """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if not race:
            race = sc2_env.Race.random

        map_inst = map_name and maps.get(map_name)
        self._map_name = map_name
        self._game_info = None

        self._num_agents = 1
        self._discount = discount
        self._step_mul = step_mul or (map_inst.step_mul if map_inst else 8)
        self._realtime = realtime
        self._last_step_time = None
        self._save_replay_episodes = 1 if replay_dir else 0
        self._replay_dir = replay_dir
        self._replay_prefix = replay_prefix

        self._score_index = -1  # Win/loss only.
        self._score_multiplier = 1
        self._episode_length = sc2_env.MAX_STEP_COUNT
        self._ensure_available_actions = False
        self._discount_zero_after_timeout = False

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.
        self._in_game = False
        self._action_delay_fns = [None]

        interface = self._get_interface(
            agent_interface_format=agent_interface_format,
            require_raw=visualize)

        if isinstance(lan_port, collections.Sequence):
            if len(lan_port) != 4:
                raise ValueError("lan_port sequence must be of length 4")
            ports = lan_port[:]
        else:
            ports = [lan_port + p
                     for p in range(4)]  # 2 * num players *in the game*.

        self._connect_remote(host, host_port, ports, race, name, map_inst,
                             save_map, interface, agent_interface_format)

        self._finalize(visualize)
Exemple #12
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            map_name=None,
            host="127.0.0.1",
            host_port=None,
            lan_port=None,
            race=None,
            feature_screen_size=None,
            feature_screen_width=None,
            feature_screen_height=None,
            feature_minimap_size=None,
            feature_minimap_width=None,
            feature_minimap_height=None,
            rgb_screen_size=None,
            rgb_screen_width=None,
            rgb_screen_height=None,
            rgb_minimap_size=None,
            rgb_minimap_width=None,
            rgb_minimap_height=None,
            action_space=None,
            camera_width_world_units=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            replay_dir=None,
            use_feature_units=False):
        """Create a SC2 Env that connects to a remote instance of the game.

    This assumes that the game is already up and running, and it only needs to
    join. You need some other script to launch the process and call
    RequestCreateGame. It also assumes that it's a multiplayer game, and that
    the ports are consecutive.

    You must pass a resolution that you want to play at. You can send either
    feature layer resolution or rgb resolution or both. If you send both you
    must also choose which to use as your action space. Regardless of which you
    choose you must send both the screen and minimap resolutions.

    For each of the 4 resolutions, either specify size or both width and
    height. If you specify size then both width and height will take that value.

    Args:
      _only_use_kwargs: Don't pass args, only kwargs.
      map_name: Name of a SC2 map. Run bin/map_list to get the full list of
          known maps. Alternatively, pass a Map instance. Take a look at the
          docs in maps/README.md for more information on available maps.
      host: Host where the server is running.
      host_port: The port for the host.
      lan_port: Where to connect to the other SC2 instance.
      race: Race for this agent.
      feature_screen_size: Sets feature_screen_width and feature_screen_width.
      feature_screen_width: The width of the feature layer screen observation.
      feature_screen_height: The height of the feature layer screen observation.
      feature_minimap_size: Sets feature_minimap_width and
          feature_minimap_height.
      feature_minimap_width: The width of the feature layer minimap observation.
      feature_minimap_height: The height of the feature layer minimap
          observation.
      rgb_screen_size: Sets rgb_screen_width and rgb_screen_height.
      rgb_screen_width: The width of the rgb screen observation.
      rgb_screen_height: The height of the rgb screen observation.
      rgb_minimap_size: Sets rgb_minimap_width and rgb_minimap_height.
      rgb_minimap_width: The width of the rgb minimap observation.
      rgb_minimap_height: The height of the rgb minimap observation.
      action_space: If you pass both feature and rgb sizes, then you must also
          specify which you want to use for your actions as an ActionSpace enum.
      camera_width_world_units: The width of your screen in world units. If your
          feature_screen=(64, 48) and camera_width is 24, then each px
          represents 24 / 64 = 0.375 world units in each of x and y. It'll then
          represent a camera of size (24, 0.375 * 48) = (24, 18) world units.
      discount: Returned as part of the observation.
      visualize: Whether to pop up a window showing the camera and feature
          layers. This won't work without access to a window manager.
      step_mul: How many game steps per agent step (action/observation). None
          means use the map default.
      replay_dir: Directory to save a replay.
      use_feature_units: Whether to include feature unit data in observations.

    Raises:
      ValueError: if the agent_race, bot_race or difficulty are invalid.
      ValueError: if too many players are requested for a map.
      ValueError: if the resolutions aren't specified correctly.
    """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if not race:
            race = sc2_env.Race.random

        self._map = maps.get(map_name)

        self._num_players = 1
        self._discount = discount
        self._step_mul = step_mul or self._map.step_mul
        self._save_replay_episodes = 1 if replay_dir else 0
        self._replay_dir = replay_dir

        self._score_index = -1  # Win/loss only.
        self._score_multiplier = 1
        self._episode_length = 0  # No limit.

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

        interface = self._get_interface(
            feature_screen_size, feature_screen_width, feature_screen_height,
            feature_minimap_size, feature_minimap_width,
            feature_minimap_height, rgb_screen_size, rgb_screen_width,
            rgb_screen_height, rgb_minimap_size, rgb_minimap_width,
            rgb_minimap_height, action_space, camera_width_world_units,
            use_feature_units, visualize)

        self._launch_remote(host, host_port, lan_port, race, interface)

        self._finalize(interface, action_space, use_feature_units, visualize,
                       map_name)
Exemple #13
0
 def test_partial(self):
     pool = run_parallel.RunParallel()
     out = pool.run((max, 0, i - 2) for i in range(5))
     self.assertListEqual(out, [0, 0, 0, 1, 2])
Exemple #14
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            map_name=None,
            players=None,
            agent_race=None,  # deprecated
            bot_race=None,  # deprecated
            difficulty=None,  # deprecated
            screen_size_px=None,  # deprecated
            minimap_size_px=None,  # deprecated
            agent_interface_format=None,
            discount=1.,
            discount_zero_after_timeout=False,
            visualize=False,
            step_mul=None,
            realtime=False,
            save_replay_episodes=0,
            replay_dir=None,
            replay_prefix=None,
            game_steps_per_episode=None,
            score_index=None,
            score_multiplier=None,
            random_seed=None,
            disable_fog=False,
            ensure_available_actions=True):
        """Create a SC2 Env.

    You must pass a resolution that you want to play at. You can send either
    feature layer resolution or rgb resolution or both. If you send both you
    must also choose which to use as your action space. Regardless of which you
    choose you must send both the screen and minimap resolutions.

    For each of the 4 resolutions, either specify size or both width and
    height. If you specify size then both width and height will take that value.

    Args:
      _only_use_kwargs: Don't pass args, only kwargs.
      map_name: Name of a SC2 map. Run bin/map_list to get the full list of
          known maps. Alternatively, pass a Map instance. Take a look at the
          docs in maps/README.md for more information on available maps.
      players: A list of Agent and Bot instances that specify who will play.
      agent_race: Deprecated. Use players instead.
      bot_race: Deprecated. Use players instead.
      difficulty: Deprecated. Use players instead.
      screen_size_px: Deprecated. Use agent_interface_formats instead.
      minimap_size_px: Deprecated. Use agent_interface_formats instead.
      agent_interface_format: A sequence containing one AgentInterfaceFormat
        per agent, matching the order of agents specified in the players list.
        Or a single AgentInterfaceFormat to be used for all agents.
      discount: Returned as part of the observation.
      discount_zero_after_timeout: If True, the discount will be zero
          after the `game_steps_per_episode` timeout.
      visualize: Whether to pop up a window showing the camera and feature
          layers. This won't work without access to a window manager.
      step_mul: How many game steps per agent step (action/observation). None
          means use the map default.
      realtime: Whether to use realtime mode. In this mode the game simulation
          automatically advances (at 22.4 gameloops per second) rather than
          being stepped manually. The number of game loops advanced with each
          call to step() won't necessarily match the step_mul specified. The
          environment will attempt to honour step_mul, returning observations
          with that spacing as closely as possible. Game loops will be skipped
          if they cannot be retrieved and processed quickly enough.
      save_replay_episodes: Save a replay after this many episodes. Default of 0
          means don't save replays.
      replay_dir: Directory to save replays. Required with save_replay_episodes.
      replay_prefix: An optional prefix to use when saving replays.
      game_steps_per_episode: Game steps per episode, independent of the
          step_mul. 0 means no limit. None means use the map default.
      score_index: -1 means use the win/loss reward, >=0 is the index into the
          score_cumulative with 0 being the curriculum score. None means use
          the map default.
      score_multiplier: How much to multiply the score by. Useful for negating.
      random_seed: Random number seed to use when initializing the game. This
          lets you run repeatable games/tests.
      disable_fog: Whether to disable fog of war.
      ensure_available_actions: Whether to throw an exception when an
          unavailable action is passed to step().

    Raises:
      ValueError: if the agent_race, bot_race or difficulty are invalid.
      ValueError: if too many players are requested for a map.
      ValueError: if the resolutions aren't specified correctly.
      DeprecationWarning: if screen_size_px or minimap_size_px are sent.
      DeprecationWarning: if agent_race, bot_race or difficulty are sent.
    """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if screen_size_px or minimap_size_px:
            raise DeprecationWarning(
                "screen_size_px and minimap_size_px are deprecated. Use the feature "
                "or rgb variants instead. Make sure to check your observations too "
                "since they also switched from screen/minimap to feature and rgb "
                "variants.")

        if agent_race or bot_race or difficulty:
            raise DeprecationWarning(
                "Explicit agent and bot races are deprecated. Pass an array of "
                "sc2_env.Bot and sc2_env.Agent instances instead.")

        map_inst = maps.get(map_name)
        self._map_name = map_name

        if not players:
            players = list()
            players.append(Agent(Race.random))

            if not map_inst.players or map_inst.players >= 2:
                players.append(Bot(Race.random, Difficulty.very_easy))

        for p in players:
            if not isinstance(p, (Agent, Bot)):
                raise ValueError(
                    "Expected players to be of type Agent or Bot. Got: %s." %
                    p)

        num_players = len(players)
        self._num_agents = sum(1 for p in players if isinstance(p, Agent))
        self._players = players

        if not 1 <= num_players <= 2 or not self._num_agents:
            raise ValueError("Only 1 or 2 players with at least one agent is "
                             "supported at the moment.")

        if save_replay_episodes and not replay_dir:
            raise ValueError("Missing replay_dir")

        if map_inst.players and num_players > map_inst.players:
            raise ValueError(
                "Map only supports %s players, but trying to join with %s" %
                (map_inst.players, num_players))

        self._discount = discount
        self._step_mul = step_mul or map_inst.step_mul
        self._realtime = realtime
        self._last_step_time = None
        self._save_replay_episodes = save_replay_episodes
        self._replay_dir = replay_dir
        self._replay_prefix = replay_prefix
        self._random_seed = random_seed
        self._disable_fog = disable_fog
        self._ensure_available_actions = ensure_available_actions
        self._discount_zero_after_timeout = discount_zero_after_timeout

        if score_index is None:
            self._score_index = map_inst.score_index
        else:
            self._score_index = score_index
        if score_multiplier is None:
            self._score_multiplier = map_inst.score_multiplier
        else:
            self._score_multiplier = score_multiplier

        self._episode_length = game_steps_per_episode
        if self._episode_length is None:
            self._episode_length = map_inst.game_steps_per_episode

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if isinstance(agent_interface_format, AgentInterfaceFormat):
            agent_interface_format = [agent_interface_format
                                      ] * self._num_agents

        if len(agent_interface_format) != self._num_agents:
            raise ValueError(
                "The number of entries in agent_interface_format should "
                "correspond 1-1 with the number of agents.")

        interfaces = []
        for i, interface_format in enumerate(agent_interface_format):
            require_raw = visualize and (i == 0)
            interfaces.append(
                self._get_interface(interface_format, require_raw))

        if self._num_agents == 1:
            self._launch_sp(map_inst, interfaces[0])
        else:
            self._launch_mp(map_inst, interfaces)

        self._finalize(agent_interface_format, interfaces, visualize)
Exemple #15
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            map_name=None,
            host="127.0.0.1",
            host_port=None,
            lan_port=None,
            race=None,
            agent_interface_format=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            realtime=False,
            crop_to_playable_area=False,
            show_cloaked=False,
            show_burrowed_shadows=False,
            show_placeholders=False,
            raw_affects_selection=True,
            use_pysc2_feature=True,
            update_game_info=False,
            replay_dir=None):
        """Create a SC2 Env that connects to a remote instance of the game.

    This assumes that the game is already up and running, and it only needs to
    join. You need some other script to launch the process and call
    RequestCreateGame. It also assumes that it's a multiplayer game, and that
    the ports are consecutive.

    You must pass a resolution that you want to play at. You can send either
    feature layer resolution or rgb resolution or both. If you send both you
    must also choose which to use as your action space. Regardless of which you
    choose you must send both the screen and minimap resolutions.

    For each of the 4 resolutions, either specify size or both width and
    height. If you specify size then both width and height will take that value.

    Args:
      _only_use_kwargs: Don't pass args, only kwargs.
      map_name: Name of a SC2 map. Run bin/map_list to get the full list of
          known maps. Alternatively, pass a Map instance. Take a look at the
          docs in maps/README.md for more information on available maps.
      host: Host where the server is running.
      host_port: The port for the host.
      lan_port: Where to connect to the other SC2 instance.
      race: Race for this agent.
      agent_interface_format: AgentInterfaceFormat object describing the
          format of communication between the agent and the environment.
      discount: Returned as part of the observation.
      visualize: Whether to pop up a window showing the camera and feature
          layers. This won't work without access to a window manager.
      step_mul: How many game steps per agent step (action/observation). None
          means use the map default.
      replay_dir: Directory to save a replay.

    Raises:
      ValueError: if the race is invalid.
      ValueError: if the resolutions aren't specified correctly.
    """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if not race:
            race = sc2_env.Race.random

        map_inst = map_name and maps.get(map_name)
        self._map_name = map_name

        self._num_agents = 1
        self._discount = discount
        self._step_mul = step_mul or (map_inst.step_mul if map_inst else 8)
        self._realtime = realtime
        self._save_replay_episodes = 1 if replay_dir else 0
        self._replay_dir = replay_dir
        self._update_game_info = update_game_info
        self.raw = not use_pysc2_feature

        self._score_index = -1  # Win/loss only.
        self._score_multiplier = 1
        self._episode_length = 0  # No limit.

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

        interface = self._get_interface(
            agent_interface_format=agent_interface_format,
            require_raw=True,
            crop_to_playable_area=crop_to_playable_area,
            show_cloaked=show_cloaked,
            show_burrowed_shadows=show_burrowed_shadows,
            show_placeholders=show_placeholders,
            raw_affects_selection=raw_affects_selection)

        self._connect_remote(host, host_port, lan_port, race, map_inst,
                             interface)

        self._finalize([agent_interface_format], [interface], visualize)
def test_multi_player(agents, disable_fog):
    players = 2
    if len(agents) == 2:
        agent1, agent2 = agents
    run_config = run_configs.get()
    parallel = run_parallel.RunParallel()
    map_inst = maps.get(FLAGS.map)

    screen_size_px = point.Point(64, 64)
    minimap_size_px = point.Point(32, 32)
    interface = sc_pb.InterfaceOptions(raw=True, score=True)
    screen_size_px.assign_to(interface.feature_layer.resolution)
    minimap_size_px.assign_to(interface.feature_layer.minimap_resolution)

    # Reserve a whole bunch of ports for the weird multiplayer implementation.
    ports = [portpicker.pick_unused_port() for _ in range(1 + players * 2)]
    print("Valid Ports: %s", ports)

    # Actually launch the game processes.
    print("start")
    sc2_procs = [run_config.start(extra_ports=ports) for _ in range(players)]
    controllers = [p.controller for p in sc2_procs]

    try:
        # Save the maps so they can access it.
        map_path = os.path.basename(map_inst.path)
        print("save_map")
        parallel.run((c.save_map, map_path, run_config.map_data(map_inst.path))
                     for c in controllers)

        # Create the create request.
        real_time = True
        create = sc_pb.RequestCreateGame(
            local_map=sc_pb.LocalMap(map_path=map_path), realtime=real_time)
        for _ in range(players):
            create.player_setup.add(type=sc_pb.Participant)

        # Create the join request.
        join1 = sc_pb.RequestJoinGame(race=races[FLAGS.agent1_race],
                                      options=interface)
        join1.shared_port = ports.pop()
        join1.server_ports.game_port = ports.pop()
        join1.server_ports.base_port = ports.pop()
        join1.client_ports.add(game_port=ports.pop(), base_port=ports.pop())

        join2 = copy.copy(join1)
        join2.race = races[FLAGS.agent2_race]

        # This is where actually game plays
        # Create and Join
        print("create")
        controllers[0].create_game(create)
        print("join")
        parallel.run((c.join_game, join)
                     for c, join in zip(controllers, [join1, join2]))

        controllers[0]._client.send(debug=sc_pb.RequestDebug(
            debug=[debug_pb2.DebugCommand(game_state=1)]))
        if disable_fog[0]:
            controllers[0].disable_fog()
        if disable_fog[1]:
            controllers[1].disable_fog()

        print("run")
        game_info = controllers[0].game_info()
        extractors = features.Features(game_info)
        for game_loop in range(1, 100000):  # steps per episode
            # Step the game
            step_mul = FLAGS.step_mul
            if not real_time:
                parallel.run((c.step, step_mul) for c in controllers)
            else:
                time.sleep(FLAGS.sleep_time)

            # Observe
            obs = parallel.run(c.observe for c in controllers)
            agent_obs = [extractors.transform_obs(o.observation) for o in obs]
            game_info = [None for c in controllers]

            if not any(o.player_result for o in obs):  # Episode over.
                game_info = parallel.run(c.game_info for c in controllers)
            timesteps = tuple(
                environment.TimeStep(step_type=0,
                                     reward=0,
                                     discount=0,
                                     observation=o,
                                     game_info=info)
                for o, info in zip(agent_obs, game_info))

            # Act
            if agent1 is not None:
                actions1 = agent1.step(timesteps[0])
            else:
                actions1 = []
            actions2 = agent2.step(timesteps[1])
            actions = [actions1, actions2]
            funcs_with_args = [(c.acts, a)
                               for c, a in zip(controllers, actions)]
            parallel.run(funcs_with_args)

        # Done with the game.
        print("leave")
        parallel.run(c.leave for c in controllers)
    finally:
        print("quit")
        # Done, shut down. Don't depend on parallel since it might be broken.
        for c in controllers:
            c.quit()
        for p in sc2_procs:
            p.close()
Exemple #17
0
 def test_run_in_parallel(self):
     b = Barrier(3)
     pool = run_parallel.RunParallel()
     out = pool.run([b.wait, b.wait, b.wait])
     self.assertItemsEqual(out, [0, 1, 2])
Exemple #18
0
 def test_returns_expected_values(self):
     pool = run_parallel.RunParallel()
     out = pool.run([int])
     self.assertListEqual(out, [0])
     out = pool.run([lambda: 1, lambda: 2, lambda: "asdf", lambda: {1: 2}])
     self.assertListEqual(out, [1, 2, "asdf", {1: 2}])
Exemple #19
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            host="127.0.0.1",
            config_port=None,
            race=None,
            name="<unknown>",
            agent_interface_format=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            realtime=False,
            replay_dir=None,
            replay_prefix=None):
        """Create a SC2 Env that connects to a remote instance of the game.

        This assumes that the game is already up and running, and it only needs to
        join. You need some other script to launch the process and call
        RequestCreateGame. It also assumes that it's a multiplayer game, and that
        the ports are consecutive.

        You must pass a resolution that you want to play at. You can send either
        feature layer resolution or rgb resolution or both. If you send both you
        must also choose which to use as your action space. Regardless of which you
        choose you must send both the screen and minimap resolutions.

        For each of the 4 resolutions, either specify size or both width and
        height. If you specify size then both width and height will take that value.

        Args:
          _only_use_kwargs: Don't pass args, only kwargs.
          host: Which ip to use. Either ipv4 or ipv6 localhost.
          config_port: Where to find the config port.
          race: Race for this agent.
          name: The name of this agent, for saving in the replay.
          agent_interface_format: AgentInterfaceFormat object describing the
              format of communication between the agent and the environment.
          discount: Returned as part of the observation.
          visualize: Whether to pop up a window showing the camera and feature
              layers. This won't work without access to a window manager.
          step_mul: How many game steps per agent step (action/observation). None
              means use the map default.
          realtime: Whether to use realtime mode. In this mode the game simulation
              automatically advances (at 22.4 gameloops per second) rather than
              being stepped manually. The number of game loops advanced with each
              call to step() won't necessarily match the step_mul specified. The
              environment will attempt to honour step_mul, returning observations
              with that spacing as closely as possible. Game loops will be skipped
              if they cannot be retrieved and processed quickly enough.
          replay_dir: Directory to save a replay.
          replay_prefix: An optional prefix to use when saving replays.

        Raises:
          ValueError: if the race is invalid.
          ValueError: if the resolutions aren't specified correctly.
          ValueError: if the host or port are invalid.
        """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if host not in ("127.0.0.1", "::1"):
            raise ValueError("Bad host arguments. Must be a localhost")
        if not config_port:
            raise ValueError("Must pass a config_port.")

        if agent_interface_format is None:
            raise ValueError("Please specify agent_interface_format.")

        if not race:
            race = sc2_env.Race.random

        self._num_agents = 1
        self._discount = discount
        self._step_mul = step_mul or 8
        self._realtime = realtime
        self._last_step_time = None
        self._save_replay_episodes = 1 if replay_dir else 0
        self._replay_dir = replay_dir
        self._replay_prefix = replay_prefix

        self._score_index = -1  # Win/loss only.
        self._score_multiplier = 1
        self._episode_length = sc2_env.MAX_STEP_COUNT
        self._ensure_available_actions = False
        self._discount_zero_after_timeout = False
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.
        self._game_info = None
        self._action_delay_fns = [None]

        interface = self._get_interface(
            agent_interface_format=agent_interface_format,
            require_raw=visualize)

        self._launch_remote(host, config_port, race, name, interface,
                            agent_interface_format)

        self._finalize(visualize)
Exemple #20
0
  def test_multi_player(self):
    players = 2
    run_config = run_configs.get()
    parallel = run_parallel.RunParallel()
    map_inst = maps.get("Simple64")

    screen_size_px = point.Point(64, 64)
    minimap_size_px = point.Point(32, 32)
    interface = sc_pb.InterfaceOptions()
    screen_size_px.assign_to(interface.feature_layer.resolution)
    minimap_size_px.assign_to(interface.feature_layer.minimap_resolution)

    # Reserve a whole bunch of ports for the weird multiplayer implementation.
    ports = portspicker.pick_unused_ports(players * 2)
    logging.info("Valid Ports: %s", ports)

    # Actually launch the game processes.
    print_stage("start")
    sc2_procs = [run_config.start(extra_ports=ports) for _ in range(players)]
    controllers = [p.controller for p in sc2_procs]

    try:
      # Save the maps so they can access it.
      map_path = os.path.basename(map_inst.path)
      print_stage("save_map")
      parallel.run((c.save_map, map_path, map_inst.data(run_config))
                   for c in controllers)

      # Create the create request.
      create = sc_pb.RequestCreateGame(
          local_map=sc_pb.LocalMap(map_path=map_path))
      for _ in range(players):
        create.player_setup.add(type=sc_pb.Participant)

      # Create the join request.
      join = sc_pb.RequestJoinGame(race=sc_common.Random, options=interface)
      join.shared_port = 0  # unused
      join.server_ports.game_port = ports.pop(0)
      join.server_ports.base_port = ports.pop(0)
      for _ in range(players - 1):
        join.client_ports.add(game_port=ports.pop(0), base_port=ports.pop(0))

      # Play a few short games.
      for _ in range(2):  # 2 episodes
        # Create and Join
        print_stage("create")
        controllers[0].create_game(create)
        print_stage("join")
        parallel.run((c.join_game, join) for c in controllers)

        print_stage("run")
        for game_loop in range(1, 10):  # steps per episode
          # Step the game
          parallel.run(c.step for c in controllers)

          # Observe
          obs = parallel.run(c.observe for c in controllers)
          for p_id, o in enumerate(obs):
            self.assertEqual(o.observation.game_loop, game_loop)
            self.assertEqual(o.observation.player_common.player_id, p_id + 1)

          # Act
          actions = [sc_pb.Action() for _ in range(players)]
          for action in actions:
            pt = (point.Point.unit_rand() * minimap_size_px).floor()
            pt.assign_to(action.action_feature_layer.camera_move.center_minimap)
          parallel.run((c.act, a) for c, a in zip(controllers, actions))

        # Done this game.
        print_stage("leave")
        parallel.run(c.leave for c in controllers)
    finally:
      print_stage("quit")
      # Done, shut down. Don't depend on parallel since it might be broken.
      for c in controllers:
        c.quit()
      for p in sc2_procs:
        p.close()
      portspicker.return_ports(ports)
Exemple #21
0
    def start_game(self, show_cloaked=True, disable_fog=False, players=2):
        """Start a multiplayer game with options."""
        self._disable_fog = disable_fog
        run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.
        map_inst = maps.get("Flat64")
        self._map_data = map_inst.data(run_config)

        self._ports = portspicker.pick_unused_ports(4) if players == 2 else []
        self._sc2_procs = [
            run_config.start(extra_ports=self._ports, want_rgb=False)
            for _ in range(players)
        ]
        self._controllers = [p.controller for p in self._sc2_procs]

        if players == 2:
            for c in self._controllers:  # Serial due to a race condition on Windows.
                c.save_map(map_inst.path, self._map_data)

        self._interface = sc_pb.InterfaceOptions()
        self._interface.raw = True
        self._interface.raw_crop_to_playable_area = True
        self._interface.show_cloaked = show_cloaked
        self._interface.score = False
        self._interface.feature_layer.width = 24
        self._interface.feature_layer.resolution.x = 64
        self._interface.feature_layer.resolution.y = 64
        self._interface.feature_layer.minimap_resolution.x = 64
        self._interface.feature_layer.minimap_resolution.y = 64

        create = sc_pb.RequestCreateGame(
            random_seed=1,
            disable_fog=self._disable_fog,
            local_map=sc_pb.LocalMap(map_path=map_inst.path))
        for _ in range(players):
            create.player_setup.add(type=sc_pb.Participant)
        if players == 1:
            create.local_map.map_data = self._map_data
            create.player_setup.add(type=sc_pb.Computer,
                                    race=sc_common.Random,
                                    difficulty=sc_pb.VeryEasy)

        join = sc_pb.RequestJoinGame(race=sc_common.Protoss,
                                     options=self._interface)
        if players == 2:
            join.shared_port = 0  # unused
            join.server_ports.game_port = self._ports[0]
            join.server_ports.base_port = self._ports[1]
            join.client_ports.add(game_port=self._ports[2],
                                  base_port=self._ports[3])

        self._controllers[0].create_game(create)
        self._parallel.run((c.join_game, join) for c in self._controllers)

        self._info = self._controllers[0].game_info()
        self._features = features.features_from_game_info(self._info,
                                                          use_raw_units=True)

        self._map_size = point.Point.build(self._info.start_raw.map_size)
        print("Map size:", self._map_size)
        self.in_game = True
        self.step()  # Get into the game properly.
  def _setup(self,
             player_setup,
             map_name,
             screen_size_px=(64, 64),
             minimap_size_px=(64, 64),
             camera_width_world_units=None,
             discount=1.,
             visualize=False,
             step_mul=None,
             save_replay_episodes=0,
             replay_dir=None,
             game_steps_per_episode=None,
             score_index=None,
             score_multiplier=None):

    if save_replay_episodes and not replay_dir:
      raise ValueError("Missing replay_dir")

    self._map = maps.get(map_name)
    self._discount = discount
    self._step_mul = step_mul or self._map.step_mul
    self._save_replay_episodes = save_replay_episodes
    self._replay_dir = replay_dir
    self._total_steps = 0

    if score_index is None:
      self._score_index = self._map.score_index
    else:
      self._score_index = score_index
    if score_multiplier is None:
      self._score_multiplier = self._map.score_multiplier
    else:
      self._score_multiplier = score_multiplier
    self._last_score = None

    self._episode_length = (game_steps_per_episode or
                            self._map.game_steps_per_episode)
    self._episode_steps = 0

    self._run_config = run_configs.get()
    self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

    screen_size_px = point.Point(*screen_size_px)
    minimap_size_px = point.Point(*minimap_size_px)
    interface = sc_pb.InterfaceOptions(
        raw=visualize, score=True,
        feature_layer=sc_pb.SpatialCameraSetup(
            width=camera_width_world_units or 24))
    screen_size_px.assign_to(interface.feature_layer.resolution)
    minimap_size_px.assign_to(interface.feature_layer.minimap_resolution)

    self._launch(interface, player_setup)

    game_info = self._controllers[0].game_info()
    static_data = self._controllers[0].data()

    self._features = features.Features(game_info)
    if visualize:
      self._renderer_human = renderer_human.RendererHuman()
      self._renderer_human.init(game_info, static_data)
    else:
      self._renderer_human = None

    self._episode_count = 0
    self._obs = None
    self._state = environment.StepType.LAST  # Want to jump to `reset`.
    logging.info("Environment is ready.")
Exemple #23
0
    def __init__(
            self,  # pylint: disable=invalid-name
            _only_use_kwargs=None,
            map_name=None,
            players=None,
            agent_race=None,  # deprecated
            bot_race=None,  # deprecated
            difficulty=None,  # deprecated
            screen_size_px=None,  # deprecated
            minimap_size_px=None,  # deprecated
            feature_screen_size=None,
            feature_screen_width=None,
            feature_screen_height=None,
            feature_minimap_size=None,
            feature_minimap_width=None,
            feature_minimap_height=None,
            rgb_screen_size=None,
            rgb_screen_width=None,
            rgb_screen_height=None,
            rgb_minimap_size=None,
            rgb_minimap_width=None,
            rgb_minimap_height=None,
            action_space=None,
            camera_width_world_units=None,
            discount=1.,
            visualize=False,
            step_mul=None,
            save_replay_episodes=0,
            replay_dir=None,
            game_steps_per_episode=None,
            score_index=None,
            score_multiplier=None,
            use_feature_units=False,
            random_seed=None):
        """Create a SC2 Env.

    You must pass a resolution that you want to play at. You can send either
    feature layer resolution or rgb resolution or both. If you send both you
    must also choose which to use as your action space. Regardless of which you
    choose you must send both the screen and minimap resolutions.

    For each of the 4 resolutions, either specify size or both width and
    height. If you specify size then both width and height will take that value.

    Args:
      _only_use_kwargs: Don't pass args, only kwargs.
      map_name: Name of a SC2 map. Run bin/map_list to get the full list of
          known maps. Alternatively, pass a Map instance. Take a look at the
          docs in maps/README.md for more information on available maps.
      players: A list of Agent and Bot instances that specify who will play.
      agent_race: Deprecated. Use players instead.
      bot_race: Deprecated. Use players instead.
      difficulty: Deprecated. Use players instead.
      screen_size_px: Deprecated. Use feature_screen_... instead.
      minimap_size_px: Deprecated. Use feature_minimap_... instead.
      feature_screen_size: Sets feature_screen_width and feature_screen_width.
      feature_screen_width: The width of the feature layer screen observation.
      feature_screen_height: The height of the feature layer screen observation.
      feature_minimap_size: Sets feature_minimap_width and
          feature_minimap_height.
      feature_minimap_width: The width of the feature layer minimap observation.
      feature_minimap_height: The height of the feature layer minimap
          observation.
      rgb_screen_size: Sets rgb_screen_width and rgb_screen_height.
      rgb_screen_width: The width of the rgb screen observation.
      rgb_screen_height: The height of the rgb screen observation.
      rgb_minimap_size: Sets rgb_minimap_width and rgb_minimap_height.
      rgb_minimap_width: The width of the rgb minimap observation.
      rgb_minimap_height: The height of the rgb minimap observation.
      action_space: If you pass both feature and rgb sizes, then you must also
          specify which you want to use for your actions as an ActionSpace enum.
      camera_width_world_units: The width of your screen in world units. If your
          feature_screen=(64, 48) and camera_width is 24, then each px
          represents 24 / 64 = 0.375 world units in each of x and y. It'll then
          represent a camera of size (24, 0.375 * 48) = (24, 18) world units.
      discount: Returned as part of the observation.
      visualize: Whether to pop up a window showing the camera and feature
          layers. This won't work without access to a window manager.
      step_mul: How many game steps per agent step (action/observation). None
          means use the map default.
      save_replay_episodes: Save a replay after this many episodes. Default of 0
          means don't save replays.
      replay_dir: Directory to save replays. Required with save_replay_episodes.
      game_steps_per_episode: Game steps per episode, independent of the
          step_mul. 0 means no limit. None means use the map default.
      score_index: -1 means use the win/loss reward, >=0 is the index into the
          score_cumulative with 0 being the curriculum score. None means use
          the map default.
      score_multiplier: How much to multiply the score by. Useful for negating.
      use_feature_units: Whether to include feature unit data in observations.
      random_seed: Random number seed to use when initializing the game. This
          lets you run repeatable games/tests.

    Raises:
      ValueError: if the agent_race, bot_race or difficulty are invalid.
      ValueError: if too many players are requested for a map.
      ValueError: if the resolutions aren't specified correctly.
      DeprecationWarning: if screen_size_px or minimap_size_px are sent.
      DeprecationWarning: if agent_race, bot_race or difficulty are sent.
    """
        if _only_use_kwargs:
            raise ValueError(
                "All arguments must be passed as keyword arguments.")

        if screen_size_px or minimap_size_px:
            raise DeprecationWarning(
                "screen_size_px and minimap_size_px are deprecated. Use the feature "
                "or rgb variants instead. Make sure to check your observations too "
                "since they also switched from screen/minimap to feature and rgb "
                "variants.")

        if agent_race or bot_race or difficulty:
            raise DeprecationWarning(
                "Explicit agent and bot races are deprecated. Pass an array of "
                "sc2_env.Bot and sc2_env.Agent instances instead.")

        if not players:
            players = [
                Agent(Race.random),
                Bot(Race.random, Difficulty.very_easy)
            ]

        for p in players:
            if not isinstance(p, (Agent, Bot)):
                raise ValueError(
                    "Expected players to be of type Agent or Bot. Got: %s." %
                    p)

        self._num_players = sum(1 for p in players if isinstance(p, Agent))
        self._players = players

        if not 1 <= len(players) <= 2 or not 1 <= self._num_players <= 2:
            raise ValueError("Only 1 or 2 players is supported at the moment.")

        feature_screen_px = features.point_from_size_width_height(
            feature_screen_size, feature_screen_width, feature_screen_height)
        feature_minimap_px = features.point_from_size_width_height(
            feature_minimap_size, feature_minimap_width,
            feature_minimap_height)
        rgb_screen_px = features.point_from_size_width_height(
            rgb_screen_size, rgb_screen_width, rgb_screen_height)
        rgb_minimap_px = features.point_from_size_width_height(
            rgb_minimap_size, rgb_minimap_width, rgb_minimap_height)

        if bool(feature_screen_px) != bool(feature_minimap_px):
            raise ValueError("Must set all the feature layer sizes.")
        if bool(rgb_screen_px) != bool(rgb_minimap_px):
            raise ValueError("Must set all the rgb sizes.")
        if not feature_screen_px and not rgb_screen_px:
            raise ValueError("Must set either the feature layer or rgb sizes.")

        if rgb_screen_px and (rgb_screen_px.x < rgb_minimap_px.x
                              or rgb_screen_px.y < rgb_minimap_px.y):
            raise ValueError(
                "Screen (%s) can't be smaller than the minimap (%s)." %
                (rgb_screen_px, rgb_minimap_px))

        if feature_screen_px and rgb_screen_px and not action_space:
            raise ValueError(
                "You must specify the action space if you have both observations."
            )

        if save_replay_episodes and not replay_dir:
            raise ValueError("Missing replay_dir")

        self._map = maps.get(map_name)

        if self._map.players and self._num_players > self._map.players:
            raise ValueError(
                "Map only supports %s players, but trying to join with %s" %
                (self._map.players, self._num_players))

        self._discount = discount
        self._step_mul = step_mul or self._map.step_mul
        self._save_replay_episodes = save_replay_episodes
        self._replay_dir = replay_dir
        self._total_steps = 0
        self._random_seed = random_seed

        if score_index is None:
            self._score_index = self._map.score_index
        else:
            self._score_index = score_index
        if score_multiplier is None:
            self._score_multiplier = self._map.score_multiplier
        else:
            self._score_multiplier = score_multiplier
        self._last_score = None

        self._episode_length = game_steps_per_episode
        if self._episode_length is None:
            self._episode_length = self._map.game_steps_per_episode
        self._episode_steps = 0

        self._run_config = run_configs.get()
        self._parallel = run_parallel.RunParallel()  # Needed for multiplayer.

        interface = sc_pb.InterfaceOptions(raw=(visualize
                                                or use_feature_units),
                                           score=True)
        if feature_screen_px:
            interface.feature_layer.width = camera_width_world_units or 24
            feature_screen_px.assign_to(interface.feature_layer.resolution)
            feature_minimap_px.assign_to(
                interface.feature_layer.minimap_resolution)
        if rgb_screen_px:
            rgb_screen_px.assign_to(interface.render.resolution)
            rgb_minimap_px.assign_to(interface.render.minimap_resolution)

        if self._num_players == 1:
            self._launch_sp(interface)
        else:
            self._launch_mp(interface)

        game_info = self._controllers[0].game_info()
        static_data = self._controllers[0].data()

        if game_info.options.render != interface.render:
            logging.warning(
                "Actual interface options don't match requested options:\n"
                "Requested:\n%s\n\nActual:\n%s", interface, game_info.options)

        self._features = features.Features(game_info=game_info,
                                           action_space=action_space,
                                           use_feature_units=use_feature_units)
        if visualize:
            self._renderer_human = renderer_human.RendererHuman()
            self._renderer_human.init(game_info, static_data)
        else:
            self._renderer_human = None

        self._episode_count = 0
        self._obs = None
        self._state = environment.StepType.LAST  # Want to jump to `reset`.
        logging.info("Environment is ready.")