Ejemplo n.º 1
0
    def _launch_game(self):
        # Reserve a whole bunch of ports for the weird multiplayer implementation.
        if self._num_agents > 1:
            self._ports = portspicker.pick_unused_ports(self._num_agents * 2)
            logging.info("Ports used for multiplayer: %s", self._ports)
        else:
            self._ports = []

        # Actually launch the game processes.
        self._sc2_procs = [
            self._run_config.start(extra_ports=self._ports,
                                   want_rgb=interface.HasField("render"))
            for interface in self._interface_options
        ]
        self._controllers = [p.controller for p in self._sc2_procs]

        if self._battle_net_map:
            available_maps = self._controllers[0].available_maps()
            available_maps = set(available_maps.battlenet_map_names)
            unavailable = [
                m.name for m in self._maps
                if m.battle_net not in available_maps
            ]
            if unavailable:
                raise ValueError(
                    "Requested map(s) not in the battle.net cache: %s" %
                    ",".join(unavailable))
Ejemplo n.º 2
0
    def _launch_mp(self, map_inst, interfaces):
        # Reserve a whole bunch of ports for the weird multiplayer implementation.
        self._ports = portspicker.pick_unused_ports(self._num_agents * 2)
        logging.info("Ports used for multiplayer: %s", self._ports)

        # Actually launch the game processes.
        self._sc2_procs = [
            self._run_config.start(extra_ports=self._ports,
                                   want_rgb=interface.HasField("render"))
            for interface in interfaces
        ]
        self._controllers = [p.controller for p in self._sc2_procs]

        # Save the maps so they can access it. Don't do it in parallel since SC2
        # doesn't respect tmpdir on windows, which leads to a race condition:
        # https://github.com/Blizzard/s2client-proto/issues/102
        for c in self._controllers:
            c.save_map(map_inst.path, map_inst.data(self._run_config))

        # Create the game. Set the first instance as the host.
        create = sc_pb.RequestCreateGame(
            local_map=sc_pb.LocalMap(map_path=map_inst.path),
            disable_fog=self._disable_fog,
            realtime=self._realtime)
        if self._random_seed is not None:
            create.random_seed = self._random_seed
        for p in self._players:
            if isinstance(p, Agent):
                create.player_setup.add(type=sc_pb.Participant)
            else:
                create.player_setup.add(type=sc_pb.Computer,
                                        race=p.race,
                                        difficulty=p.difficulty)
        self._controllers[0].create_game(create)

        # Create the join requests.
        agent_players = (p for p in self._players if isinstance(p, Agent))
        join_reqs = []
        for agent_index, p in enumerate(agent_players):
            ports = self._ports[:]
            join = sc_pb.RequestJoinGame(options=interfaces[agent_index])
            join.shared_port = 0  # unused
            join.server_ports.game_port = ports.pop(0)
            join.server_ports.base_port = ports.pop(0)
            for _ in range(self._num_agents - 1):
                join.client_ports.add(game_port=ports.pop(0),
                                      base_port=ports.pop(0))

            join.race = p.race
            join.player_name = p.name
            join_reqs.append(join)

        # Join the game. This must be run in parallel because Join is a blocking
        # call to the game that waits until all clients have joined.
        self._parallel.run((c.join_game, join)
                           for c, join in zip(self._controllers, join_reqs))

        # Save them for restart.
        self._create_req = create
        self._join_reqs = join_reqs
Ejemplo n.º 3
0
    def __init__(self):
        self._num_agents = 2
        self._run_config = run_configs.get()
        self._processes = []
        self._controllers = []
        self._saved_maps = set()

        # Reserve LAN ports.
        self._lan_ports = portspicker.pick_unused_ports(self._num_agents * 2)

        # Start SC2 processes.
        for _ in range(self._num_agents):
            process = self._run_config.start(extra_ports=self._lan_ports)
            self._processes.append(process)
            self._controllers.append(process.controller)
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
 def testInvalidReservation(self):
     with self.assertRaises(ValueError):
         portspicker.pick_unused_ports(0)
Ejemplo n.º 6
0
 def testNonContiguousReservation(self, num_ports):
     reserved = portspicker.pick_unused_ports(num_ports)
     self.assertLen(reserved, num_ports)
     portspicker.return_ports(reserved)
Ejemplo n.º 7
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)
Ejemplo n.º 8
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.
Ejemplo n.º 9
0
 def _launch_mp(self, map_inst, interfaces):
   # Reserve a whole bunch of ports for the weird multiplayer implementation.
   self._ports = portspicker.pick_unused_ports((self._num_agents + self._num_observers + 1) * 2)