def test_load_random_map(self): """Test loading a few random maps.""" all_maps = maps.get_maps() run_config = run_configs.get() with run_config.start() as controller: # Test only a few random maps when run locally to minimize time. count = 5 map_sample = random.sample(all_maps.items(), min(count, len(all_maps))) for _, map_class in sorted(map_sample): m = map_class() logging.info("Loading map: %s", m.name) create = sc_pb.RequestCreateGame(local_map=sc_pb.LocalMap( map_path=m.path, map_data=m.data(run_config))) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Computer, race=sc_pb.Random, difficulty=sc_pb.VeryEasy) join = sc_pb.RequestJoinGame(race=sc_pb.Random, options=sc_pb.InterfaceOptions(raw=True)) controller.create_game(create) controller.join_game(join) # Verify it has the right mods and isn't running into licensing issues. info = controller.game_info() logging.info("Mods for %s: %s", m.name, info.mod_names) self.assertIn("Mods/Void.SC2Mod", info.mod_names) self.assertIn("Mods/VoidMulti.SC2Mod", info.mod_names) # Verify it can be played without making actions. for _ in range(3): controller.step() controller.observe()
def test_error(self): with run_configs.get().start() as controller: with self.assertRaises(remote_controller.RequestError): controller.create_game(sc_pb.RequestCreateGame()) # Missing map, etc. with self.assertRaises(protocol.ProtocolError): controller.join_game(sc_pb.RequestJoinGame()) # No game to join.
def test_list_all_maps(self): """Make sure all maps can be read.""" all_maps = maps.get_maps() run_config = run_configs.get() for _, map_class in sorted(all_maps.items()): map_inst = map_class() logging.info("map: %s", map_inst.name) self.assertTrue(map_inst.data(run_config), msg="Failed on %s" % map_inst)
def _initialize(self): """Initialize play/replay connection.""" run_config = run_configs.get() self._map_inst = maps.get(self._config.map_name) self._map_data = self._map_inst.data(run_config) self._sc2_proc = run_config.start() self._controller = self._sc2_proc.controller
def _replay_info(replay_path): """Query a replay for information.""" if not replay_path.lower().endswith("sc2replay"): print("Must be a replay.") return run_config = run_configs.get() with run_config.start() as controller: info = controller.replay_info(run_config.replay_data(replay_path)) print("-" * 60) print(info)
def test_ping(self): count = 100 with run_configs.get().start() as controller: with stopwatch.sw("first"): controller.ping() for _ in range(count): controller.ping() self.assertEqual(stopwatch.sw["ping"].num, count)
def _replay_index(replay_dir): """Output information for a directory of replays.""" run_config = run_configs.get() replay_dir = run_config.abs_replay_path(replay_dir) print("Checking: ", replay_dir) with run_config.start() as controller: print("-" * 60) print(",".join(( "filename", "build", "map_name", "game_duration_loops", "players", "P1-outcome", "P1-race", "P1-apm", "P2-race", "P2-apm", ))) bad_replays = [] for file_path in run_config.replay_paths(replay_dir): file_name = os.path.basename(file_path) info = controller.replay_info(run_config.replay_data(file_path)) if info.HasField("error"): print("failed:", file_name, info.error, info.error_details) bad_replays.append(file_name) else: out = [ file_name, info.base_build, info.map_name, info.game_duration_loops, len(info.player_info), sc_pb.Result.Name(info.player_info[0].player_result.result), sc_pb.Race.Name(info.player_info[0].player_info.race_actual), info.player_info[0].player_apm, ] if len(info.player_info) >= 2: out += [ sc_pb.Race.Name(info.player_info[1].player_info.race_actual), info.player_info[1].player_apm, ] print(u",".join(str(s) for s in out)) if bad_replays: print("Replays with errors:") print("\n".join(bad_replays))
def main(unused_argv): """Dump stats about all the actions that are in use in a set of replays.""" run_config = run_configs.get() if not gfile.Exists(FLAGS.replays): sys.exit("{} doesn't exist.".format(FLAGS.replays)) stats_queue = multiprocessing.Queue() stats_thread = threading.Thread(target=stats_printer, args=(stats_queue,)) stats_thread.start() try: # For some reason buffering everything into a JoinableQueue makes the # program not exit, so save it into a list then slowly fill it into the # queue in a separate thread. Grab the list synchronously so we know there # is work in the queue before the SC2 processes actually run, otherwise # The replay_queue.join below succeeds without doing any work, and exits. print("Getting replay list:", FLAGS.replays) replay_list = sorted(run_config.replay_paths(FLAGS.replays)) print(len(replay_list), "replays found.\n") replay_queue = multiprocessing.JoinableQueue(FLAGS.parallel * 10) replay_queue_thread = threading.Thread(target=replay_queue_filler, args=(replay_queue, replay_list)) replay_queue_thread.daemon = True replay_queue_thread.start() for i in range(FLAGS.parallel): p = ReplayProcessor(i, run_config, replay_queue, stats_queue) p.daemon = True p.start() time.sleep(1) # Stagger startups, otherwise they seem to conflict somehow replay_queue.join() # Wait for the queue to empty. except KeyboardInterrupt: print("Caught KeyboardInterrupt, exiting.") finally: stats_queue.put(None) # Tell the stats_thread to print and exit. stats_thread.join()
def __init__(self, map_name, screen_size_px=(64, 64), minimap_size_px=(64, 64), camera_width_world_units=None, discount=1., visualize=False, agent_race=None, bot_race=None, difficulty=None, step_mul=None, save_replay_steps=0, replay_dir=None, game_steps_per_episode=None, score_index=None, score_multiplier=None): """Create a SC2 Env. Args: 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. screen_size_px: The size of your screen output in pixels. minimap_size_px: The size of your minimap output in pixels. camera_width_world_units: The width of your screen in world units. If your screen_size_px=(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. agent_race: One of P,T,Z,R default random. This is the race you control. bot_race: One of P,T,Z,R default random. This is the race controlled by the built-in bot. difficulty: One of 1-9,A. How strong should the bot be? step_mul: How many game steps per agent step (action/observation). None means use the map default. save_replay_steps: How many game steps to wait before saving a replay. Default of 0 means don't save replays. replay_dir: Directory to save replays to. Required with save_replay_steps. 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. Raises: ValueError: if the agent_race, bot_race or difficulty are invalid. """ # Make the destructor happy. self._renderer_human = None self._controller = None self._sc2_proc = None if save_replay_steps and not replay_dir: raise ValueError("Missing replay_dir") if agent_race and agent_race not in races: raise ValueError("Bad agent_race args") if bot_race and bot_race not in races: raise ValueError("Bad bot_race args") if difficulty and str(difficulty) not in difficulties: raise ValueError("Bad difficulty") self._map = maps.get(map_name) self._discount = discount self._step_mul = step_mul or self._map.step_mul self._save_replay_steps = save_replay_steps 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._sc2_proc = self._run_config.start() self._controller = self._sc2_proc.controller 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) create = sc_pb.RequestCreateGame(local_map=sc_pb.LocalMap( map_path=self._map.path, map_data=self._map.data( self._run_config))) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Computer, race=races[bot_race or "R"], difficulty=difficulties[difficulty or "1"]) join = sc_pb.RequestJoinGame(race=races[agent_race or "R"], options=interface) self._controller.create_game(create) self._controller.join_game(join) game_info = self._controller.game_info() static_data = self._controller.data() self._features = features.Features(game_info) if visualize: self._renderer_human = renderer_human.RendererHuman() self._renderer_human.init(game_info, static_data) self._episode_count = 0 self._obs = None self._state = environment.StepType.LAST # Want to jump to `reset`. logging.info("Environment is ready.")
def _extract_info(replay_name, player_id): logging.info('enter _extract_info') logging.info('replay_name: {}, player_id: {}'.format( replay_name, player_id)) # set the correct sc2 bin path according to the game_version game_version = FLAGS.game_version if game_version != '4.7.1' or 'SC2PATH' in os.environ: # os.environ['SC2PATH'] = '/root/{}'.format(game_version) os.environ['SC2PATH'] = path.join(FLAGS.sc2mv_bin_root, game_version) # reset env/process replay from the beginning run_config = run_configs.get() replay_path = path.join(FLAGS.replay_dir, '%s.SC2Replay' % replay_name) replay_data = run_config.replay_data(replay_path) # read once with run_config.start(version=FLAGS.game_version) as controller: replay_info = controller.replay_info(replay_data) assert player_id in set(p.player_info.player_id for p in replay_info.player_info) player_info = get_player_info_by_player_id(replay_info, player_id) # collect all infos before starting the replay map_name = str(replay_info.map_name) race_actual = _PB_RACE_TO_STR[player_info.player_info.race_actual] race_requested = _PB_RACE_TO_STR[ player_info.player_info.race_requested] result = _PB_RESULT_TO_STR[player_info.player_result.result] mmr = player_info.player_mmr apm = player_info.player_apm game_duration_loops = replay_info.game_duration_loops game_version = replay_info.game_version map_data = None if replay_info.local_map_path: map_data = run_config.map_data(replay_info.local_map_path) print('using local_map_path {}'.format( replay_info.local_map_path)) # collect all infos after starting the replay controller.start_replay( sc_pb.RequestStartReplay(replay_data=replay_data, map_data=map_data, options=get_dft_sc2_interface(), observed_player_id=player_id, disable_fog=False)) game_info = controller.game_info() start_pos = game_info.start_raw.start_locations[0] # and deem as success status = 'success' logging.info('leave _extract_info') return MyResult(replay_name=replay_name, player_id=player_id, map_name=map_name, race_actual=race_actual, race_requested=race_requested, result=result, mmr=mmr, apm=apm, game_duration_loops=game_duration_loops, game_version=game_version, start_pos_x=start_pos.x, start_pos_y=start_pos.y, status=status)
def __init__( self, # pylint: disable=invalid-name _only_use_kwargs=None, map_name=None, players=None, agent_names=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., visualize=False, step_mul=None, realtime=False, save_replay_episodes=0, replay_dir=None, game_steps_per_episode=None, score_index=None, score_multiplier=None, random_seed=None, disable_fog=False, crop_to_playable_area=False, show_cloaked=False, show_burrowed_shadows=False, show_placeholders=False, raw_affects_selection=True, update_game_info=False, use_pysc2_feature=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. 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. 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. 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 agent_names is None: self._agent_names = [None] * self._num_agents else: assert len(agent_names) == self._num_agents self._agent_names = agent_names 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._save_replay_episodes = save_replay_episodes self._replay_dir = replay_dir self._random_seed = random_seed self._disable_fog = disable_fog self._version = version self._update_game_info = update_game_info 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.") self.raw = not use_pysc2_feature interfaces = [] for i, interface_format in enumerate(agent_interface_format): interfaces.append( self._get_interface(interface_format, self.raw, crop_to_playable_area, show_cloaked, show_burrowed_shadows, show_placeholders, raw_affects_selection)) 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)
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, 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 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. 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 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._num_agents = 1 self._discount = discount self._step_mul = step_mul or (map_inst.step_mul if map_inst else 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. self._in_game = False 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, map_inst, save_map, interface) self._finalize([agent_interface_format], [interface], visualize)
def __init__( self, replay_file_path, agent, player_id=1, screen_size_px=(64, 64), # (60, 60) minimap_size_px=(64, 64), # (60, 60) discount=1., frames_per_game=1): print("Parsing " + replay_file_path) self.replay_file_name = replay_file_path.split("/")[-1].split(".")[0] self.agent = agent self.discount = discount self.frames_per_game = frames_per_game self.run_config = run_configs.get() self.sc2_proc = self.run_config.start() self.controller = self.sc2_proc.controller replay_data = self.run_config.replay_data(self.replay_file_name + '.SC2Replay') ping = self.controller.ping() self.info = self.controller.replay_info(replay_data) # print(self.info) if not self._valid_replay(self.info, ping): self.sc2_proc.close() # print(self.info) raise Exception( "{} is not a valid replay file!".format(self.replay_file_name + '.SC2Replay')) # global FILE_OP # FILE_OP.write(self.replay_file_name + '.SC2Replay') # self.replay_file_name = self.info.map_name+'_'+self.replay_file_name # for player_info in self.info.player_info: # race = sc_common.Race.Name(player_info.player_info.race_actual) # self.replay_file_name = race + '_' + self.replay_file_name screen_size_px = point.Point(*screen_size_px) minimap_size_px = point.Point(*minimap_size_px) interface = sc_pb.InterfaceOptions( raw=False, score=True, feature_layer=sc_pb.SpatialCameraSetup(width=24)) screen_size_px.assign_to(interface.feature_layer.resolution) minimap_size_px.assign_to(interface.feature_layer.minimap_resolution) map_data = None if self.info.local_map_path: map_data = self.run_config.map_data(self.info.local_map_path) self._episode_length = self.info.game_duration_loops self._episode_steps = 0 self.controller.start_replay( sc_pb.RequestStartReplay(replay_data=replay_data, map_data=map_data, options=interface, observed_player_id=player_id)) self._state = StepType.FIRST
def main(unused_argv): """Run SC2 to play a game or a replay.""" stopwatch.sw.enabled = FLAGS.profile or FLAGS.trace stopwatch.sw.trace = FLAGS.trace if (FLAGS.map and FLAGS.replay) or (not FLAGS.map and not FLAGS.replay): sys.exit("Must supply either a map or replay.") if FLAGS.replay and not FLAGS.replay.lower().endswith("sc2replay"): sys.exit("Replay must end in .SC2Replay.") if FLAGS.realtime and FLAGS.replay: # TODO(tewalds): Support realtime in replays once the game supports it. sys.exit("realtime isn't possible for replays yet.") if FLAGS.render and (FLAGS.realtime or FLAGS.full_screen): sys.exit( "disable pygame rendering if you want realtime or full_screen.") if platform.system() == "Linux" and (FLAGS.realtime or FLAGS.full_screen): sys.exit("realtime and full_screen only make sense on Windows/MacOS.") if not FLAGS.render and FLAGS.render_sync: sys.exit("render_sync only makes sense with pygame rendering on.") run_config = run_configs.get() interface = sc_pb.InterfaceOptions() interface.raw = FLAGS.render interface.score = True interface.feature_layer.width = 24 interface.feature_layer.resolution.x = FLAGS.feature_screen_size interface.feature_layer.resolution.y = FLAGS.feature_screen_size interface.feature_layer.minimap_resolution.x = FLAGS.feature_minimap_size interface.feature_layer.minimap_resolution.y = FLAGS.feature_minimap_size if FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size: if FLAGS.rgb_screen_size < FLAGS.rgb_minimap_size: sys.exit("Screen size can't be smaller than minimap size.") interface.render.resolution.x = FLAGS.rgb_screen_size interface.render.resolution.y = FLAGS.rgb_screen_size interface.render.minimap_resolution.x = FLAGS.rgb_minimap_size interface.render.minimap_resolution.y = FLAGS.rgb_minimap_size max_episode_steps = FLAGS.max_episode_steps if FLAGS.map: map_inst = maps.get(FLAGS.map) if map_inst.game_steps_per_episode: max_episode_steps = map_inst.game_steps_per_episode create = sc_pb.RequestCreateGame( realtime=FLAGS.realtime, disable_fog=FLAGS.disable_fog, local_map=sc_pb.LocalMap(map_path=map_inst.path, map_data=map_inst.data(run_config))) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add( type=sc_pb.Computer, race=sc2_env.Race[FLAGS.bot_race], difficulty=sc2_env.Difficulty[FLAGS.difficulty]) join = sc_pb.RequestJoinGame(race=sc2_env.Race[FLAGS.user_race], options=interface) version = None else: replay_data = run_config.replay_data(FLAGS.replay) start_replay = sc_pb.RequestStartReplay( replay_data=replay_data, options=interface, disable_fog=FLAGS.disable_fog, observed_player_id=FLAGS.observed_player) version = get_replay_version(replay_data) with run_config.start(version=version, full_screen=FLAGS.full_screen) as controller: if FLAGS.map: controller.create_game(create) controller.join_game(join) else: info = controller.replay_info(replay_data) print(" Replay info ".center(60, "-")) print(info) print("-" * 60) map_path = FLAGS.map_path or info.local_map_path if map_path: start_replay.map_data = run_config.map_data(map_path) controller.start_replay(start_replay) if FLAGS.render: renderer = renderer_human.RendererHuman( fps=FLAGS.fps, step_mul=FLAGS.step_mul, render_sync=FLAGS.render_sync, video=FLAGS.video) renderer.run(run_config, controller, max_game_steps=FLAGS.max_game_steps, game_steps_per_episode=max_episode_steps, save_replay=FLAGS.save_replay) else: # Still step forward so the Mac/Windows renderer works. try: while True: frame_start_time = time.time() if not FLAGS.realtime: controller.step(FLAGS.step_mul) obs = controller.observe() if obs.player_result: break time.sleep( max(0, frame_start_time + 1 / FLAGS.fps - time.time())) except KeyboardInterrupt: pass print("Score: ", obs.observation.score.score) print("Result: ", obs.player_result) if FLAGS.map and FLAGS.save_replay: replay_save_loc = run_config.save_replay( controller.save_replay(), "local", FLAGS.map) print("Replay saved to:", replay_save_loc) # Save scores so we know how the human player did. with open(replay_save_loc.replace("SC2Replay", "txt"), "w") as f: f.write("{}\n".format(obs.observation.score.score)) if FLAGS.profile: print(stopwatch.sw)
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, 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. 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. 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._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 = 0 # No limit. 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. 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)
def run(self): try: self.is_running = True """A run loop to have agents and an environment interact.""" total_frames = 0 total_episodes = 0 results = [0, 0, 0] start_time = time() print("start_time before training:", strftime("%Y-%m-%d %H:%M:%S", localtime(start_time))) while time() - start_time < self.max_time_for_training: self.opponent, _ = self.player.get_match() agents = [self.player, self.opponent] # if self.use_replay_expert_reward: run_config = run_configs.get( version=self.replay_version ) # the replays released by blizzard are all 3.16.1 version with self.create_env(self.player, self.opponent) as env: # set the obs and action spec observation_spec = env.observation_spec() action_spec = env.action_spec() for agent, obs_spec, act_spec in zip( agents, observation_spec, action_spec): agent.setup(obs_spec, act_spec) self.teacher.setup(self.player.agent.obs_spec, self.player.agent.action_spec) print('player:', self.player) if debug else None print('opponent:', self.opponent) if debug else None print('teacher:', self.teacher) if debug else None trajectory = [] start_time = time() # in seconds. print("start_time before reset:", strftime("%Y-%m-%d %H:%M:%S", localtime(start_time))) # one opponent match (may include several games) defaultly lasts for no more than 2 hour while time() - start_time < self.max_time_per_one_opponent: # Note: the pysc2 environment don't return z # AlphaStar: home_observation, away_observation, is_final, z = env.reset() total_episodes += 1 print("total_episodes:", total_episodes) timesteps = env.reset() for a in agents: a.reset() # check the condition that the replay is over but the game is not with run_config.start(full_screen=False) as controller: # here we must use the with ... as ... statement, or it will cause an error #controller = run_config.start(full_screen=False) # start replay reward raw_affects_selection = False raw_crop_to_playable_area = False screen_resolution = point.Point(64, 64) minimap_resolution = point.Point(64, 64) camera_width = 24 interface = sc_pb.InterfaceOptions( raw=True, score=True, # Omit to disable. feature_layer=sc_pb.SpatialCameraSetup( width=camera_width), # Omit to disable. render=None, # By default cloaked units are completely hidden. This shows some details. show_cloaked=False, # By default burrowed units are completely hidden. This shows some details for those that produce a shadow. show_burrowed_shadows=False, # Return placeholder units (buildings to be constructed), both for raw and feature layers. show_placeholders=False, # see below raw_affects_selection=raw_affects_selection, # see below raw_crop_to_playable_area= raw_crop_to_playable_area) screen_resolution.assign_to( interface.feature_layer.resolution) minimap_resolution.assign_to( interface.feature_layer.minimap_resolution) replay_files = os.listdir(self.replay_path) # random select a replay file from the candidate replays random.shuffle(replay_files) replay_path = self.replay_path + replay_files[0] print('replay_path:', replay_path) replay_data = run_config.replay_data(replay_path) replay_info = controller.replay_info(replay_data) infos = replay_info.player_info observe_id_list = [] observe_result_list = [] for info in infos: print('info:', info) if debug else None player_info = info.player_info result = info.player_result.result print('player_info', player_info) if debug else None if player_info.race_actual == com_pb.Protoss: observe_id_list.append( player_info.player_id) observe_result_list.append(result) win_observe_id = 0 for i, result in enumerate(observe_result_list): if result == sc_pb.Victory: win_observe_id = observe_id_list[i] break start_replay = sc_pb.RequestStartReplay( replay_data=replay_data, options=interface, disable_fog=False, # FLAGS.disable_fog observed_player_id= win_observe_id, # FLAGS.observed_player map_data=None, realtime=False) controller.start_replay(start_replay) feat = F.features_from_game_info( game_info=controller.game_info(), raw_resolution=AAIFP.raw_resolution, hide_specific_actions=AAIFP. hide_specific_actions, use_feature_units=True, use_raw_units=True, use_unit_counts=True, use_raw_actions=True, show_cloaked=True, show_burrowed_shadows=True, show_placeholders=True) replay_obs = None replay_bo = [] replay_o = controller.observe() replay_obs = feat.transform_obs(replay_o) # end replay reward [home_obs, away_obs] = timesteps is_final = home_obs.last() player_memory = self.player.agent.initial_state() opponent_memory = self.opponent.agent.initial_state( ) teacher_memory = self.teacher.initial_state() # initial build order player_bo = [] episode_frames = 0 # default outcome is 0 (means draw) outcome = 0 # in one episode (game) # start_episode_time = time() # in seconds. print( "start_episode_time before is_final:", strftime("%Y-%m-%d %H:%M:%S", localtime(start_episode_time))) while not is_final: total_frames += 1 episode_frames += 1 state = self.player.agent.agent_nn.preprocess_state_all( home_obs.observation, build_order=player_bo) state_op = self.player.agent.agent_nn.preprocess_state_all( away_obs.observation) # baseline_state = self.player.agent.agent_nn.get_scalar_list(home_obs.observation, build_order=player_bo) # baseline_state_op = self.player.agent.agent_nn.get_scalar_list(away_obs.observation) baseline_state = self.player.agent.agent_nn.get_baseline_state_from_multi_source_state( state) baseline_state_op = self.player.agent.agent_nn.get_baseline_state_from_multi_source_state( state_op) player_step = self.player.agent.step_from_state( state, player_memory) player_function_call, player_action, player_logits, player_new_memory = player_step print("player_function_call:", player_function_call) if debug else None opponent_step = self.opponent.agent.step_from_state( state_op, opponent_memory) opponent_function_call, opponent_action, opponent_logits, opponent_new_memory = opponent_step # Q: how to do it ? # teacher_logits = self.teacher(home_obs, player_action, teacher_memory) # may change implemention of teacher_logits teacher_step = self.teacher.step_from_state( state, teacher_memory) teacher_function_call, teacher_action, teacher_logits, teacher_new_memory = teacher_step print("teacher_function_call:", teacher_function_call) if debug else None env_actions = [ player_function_call, opponent_function_call ] player_action_spec = action_spec[0] action_masks = U.get_mask( player_action, player_action_spec) z = None timesteps = env.step(env_actions) [home_next_obs, away_next_obs] = timesteps # print the observation of the agent # print("home_obs.observation:", home_obs.observation) reward = home_next_obs.reward print("reward: ", reward) if debug else None is_final = home_next_obs.last() # calculate the build order player_bo = L.calculate_build_order( player_bo, home_obs.observation, home_next_obs.observation) print("player build order:", player_bo) if debug else None # calculate the unit counts of bag player_ucb = L.calculate_unit_counts_bow( home_obs.observation).reshape( -1).numpy().tolist() print("player unit count of bow:", sum(player_ucb)) if debug else None # start replay_reward # note the controller should step the same steps as with the rl actor (keep the time as the same) controller.step(STEP_MUL) replay_next_o = controller.observe() replay_next_obs = feat.transform_obs( replay_next_o) # calculate the build order for replay replay_bo = L.calculate_build_order( replay_bo, replay_obs, replay_next_obs) print("replay build order:", player_bo) if debug else None # calculate the unit counts of bag for replay replay_ucb = L.calculate_unit_counts_bow( replay_obs).reshape(-1).numpy().tolist() print("replay unit count of bow:", sum(replay_ucb)) if debug else None # end replay_reward game_loop = home_obs.observation.game_loop[0] print("game_loop", game_loop) if debug else None # note, original AlphaStar pseudo-code has some mistakes, we modified # them here traj_step = Trajectory( state=state, baseline_state=baseline_state, baseline_state_op=baseline_state_op, memory=player_memory, z=z, masks=action_masks, action=player_action, behavior_logits=player_logits, teacher_logits=teacher_logits, is_final=is_final, reward=reward, build_order=player_bo, z_build_order= replay_bo, # we change it to the sampled build order unit_counts=player_ucb, z_unit_counts= replay_ucb, # we change it to the sampled unit counts game_loop=game_loop, ) trajectory.append(traj_step) player_memory = tuple( h.detach() for h in player_new_memory) opponent_memory = tuple( h.detach() for h in opponent_new_memory) teacher_memory = tuple( h.detach() for h in teacher_new_memory) home_obs = home_next_obs away_obs = away_next_obs # for replay reward replay_obs = replay_next_obs replay_o = replay_next_o if is_final: outcome = reward print("outcome: ", outcome) if debug else None results[outcome + 1] += 1 if len(trajectory) >= AHP.sequence_length: trajectories = U.stack_namedtuple( trajectory) if self.player.learner is not None: if self.player.learner.is_running: print("Learner send_trajectory!") self.player.learner.send_trajectory( trajectories) trajectory = [] else: print("Learner stops!") print("Actor also stops!") return # use max_frames to end the loop # whether to stop the run if self.max_frames and total_frames >= self.max_frames: print("Beyond the max_frames, return!") return # use max_frames_per_episode to end the episode if self.max_frames_per_episode and episode_frames >= self.max_frames_per_episode: print( "Beyond the max_frames_per_episode, break!" ) break # end of replay if replay_o.player_result: print(replay_o.player_result) break self.coordinator.send_outcome( self.player, self.opponent, outcome) # use max_frames_per_episode to end the episode if self.max_episodes and total_episodes >= self.max_episodes: print("Beyond the max_episodes, return!") print("results: ", results) if debug else None print("win rate: ", results[2] / (1e-8 + sum(results))) if debug else None return # close the replays except Exception as e: print( "ActorLoop.run() Exception cause return, Detials of the Exception:", e) print(traceback.format_exc()) finally: self.is_running = False
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 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._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._connect_remote(host, host_port, lan_port, race, map_inst, interface) self._finalize(interface, action_space, use_feature_units, visualize)
def host(): """Run a host which expects one player to connect remotely.""" run_config = run_configs.get() map_inst = maps.get(FLAGS.map) if not FLAGS.rgb_screen_size or not FLAGS.rgb_minimap_size: logging.info( "Use --rgb_screen_size and --rgb_minimap_size if you want rgb " "observations.") while True: start_port = portpicker.pick_unused_port() ports = [start_port + p for p in range(4)] # 2 * num_players if all(portpicker.is_port_free(p) for p in ports): break host_proc = run_config.start(extra_ports=ports, host=FLAGS.host, timeout_seconds=300, window_loc=(50, 50)) client_proc = run_config.start(extra_ports=ports, host=FLAGS.host, connect=False, window_loc=(700, 50)) create = sc_pb.RequestCreateGame( realtime=FLAGS.realtime, local_map=sc_pb.LocalMap(map_path=map_inst.path)) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Participant) controller = host_proc.controller controller.save_map(map_inst.path, map_inst.data(run_config)) controller.create_game(create) print("-" * 80) print("Join host: play_vs_agent --map %s --host %s --host_port %s " "--lan_port %s" % (FLAGS.map, FLAGS.host, client_proc.port, start_port)) print("-" * 80) join = sc_pb.RequestJoinGame() join.shared_port = 0 # unused join.server_ports.game_port = ports.pop(0) join.server_ports.base_port = ports.pop(0) join.client_ports.add(game_port=ports.pop(0), base_port=ports.pop(0)) join.race = sc2_env.Race[FLAGS.user_race] if FLAGS.render: join.options.raw = True join.options.score = True if FLAGS.feature_screen_size and FLAGS.feature_minimap_size: fl = join.options.feature_layer fl.width = 24 fl.resolution.x = FLAGS.feature_screen_size fl.resolution.y = FLAGS.feature_screen_size fl.minimap_resolution.x = FLAGS.feature_minimap_size fl.minimap_resolution.y = FLAGS.feature_minimap_size if FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size: join.options.render.resolution.x = FLAGS.rgb_screen_size join.options.render.resolution.y = FLAGS.rgb_screen_size join.options.render.minimap_resolution.x = FLAGS.rgb_minimap_size join.options.render.minimap_resolution.y = FLAGS.rgb_minimap_size controller.join_game(join) if FLAGS.render: renderer = renderer_human.RendererHuman(fps=FLAGS.fps, render_feature_grid=False) renderer.run(run_configs.get(), controller, max_episodes=1) else: # Still step forward so the Mac/Windows renderer works. try: while True: frame_start_time = time.time() if not FLAGS.realtime: controller.step() obs = controller.observe() if obs.player_result: break time.sleep( max(0, frame_start_time - time.time() + 1 / FLAGS.fps)) except KeyboardInterrupt: pass for p in [host_proc, client_proc]: p.close()
def _replay_index(replay_dir): """Output information for a directory of replays.""" run_config = run_configs.get() replay_dir = run_config.abs_replay_path(replay_dir) print("Checking:", replay_dir) replay_paths = list(run_config.replay_paths(replay_dir)) print("Found %s replays" % len(replay_paths)) if not replay_paths: return data = run_config.replay_data(replay_paths[0]) ver = replay.get_replay_version(data) FLAGS.set_default("sc2_version", ver.game_version) run_config = run_configs.get() # In case the version changed. print("Launching version:", run_config.version.game_version) with run_config.start(want_rgb=False) as controller: print("-" * 60) print(",".join(( "filename", "version", "map_name", "game_duration_loops", "players", "P1-outcome", "P1-race", "P1-apm", "P2-race", "P2-apm", ))) try: bad_replays = [] for file_path in replay_paths: file_name = os.path.basename(file_path) data = run_config.replay_data(file_path) try: info = controller.replay_info(data) except remote_controller.RequestError as e: bad_replays.append("%s: %s" % (file_name, e)) continue if info.HasField("error"): print("failed:", file_name, info.error, info.error_details) bad_replays.append(file_name) else: out = [ file_name, info.game_version, info.map_name, info.game_duration_loops, len(info.player_info), sc_pb.Result.Name( info.player_info[0].player_result.result), sc_common.Race.Name( info.player_info[0].player_info.race_actual), info.player_info[0].player_apm, ] if len(info.player_info) >= 2: out += [ sc_common.Race.Name( info.player_info[1].player_info.race_actual), info.player_info[1].player_apm, ] print(u",".join(str(s) for s in out)) except KeyboardInterrupt: pass finally: if bad_replays: print("\n") print("Replays with errors:") print("\n".join(bad_replays))
def __init__(self, map_name, screen_size_px=(64, 64), minimap_size_px=(64, 64), camera_width_world_units=None, discount=1., visualize=False, agent_race=None, bot_race=None, difficulty=None, step_mul=None, save_replay_steps=0, replay_dir=None, game_steps_per_episode=None, score_index=None, score_multiplier=None): """Create a SC2 Env. Args: 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. screen_size_px: The size of your screen output in pixels. minimap_size_px: The size of your minimap output in pixels. camera_width_world_units: The width of your screen in world units. If your screen_size_px=(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. agent_race: One of P,T,Z,R default random. This is the race you control. bot_race: One of P,T,Z,R default random. This is the race controlled by the built-in bot. difficulty: One of 1-9,A. How strong should the bot be? step_mul: How many game steps per agent step (action/observation). None means use the map default. save_replay_steps: How many game steps to wait before saving a replay. Default of 0 means don't save replays. replay_dir: Directory to save replays to. Required with save_replay_steps. 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. Raises: ValueError: if the agent_race, bot_race or difficulty are invalid. """ # Make the destructor happy. self._renderer_human = None self._controller = None self._sc2_proc = None if save_replay_steps and not replay_dir: raise ValueError("Missing replay_dir") if agent_race and agent_race not in races: raise ValueError("Bad agent_race args") if bot_race and bot_race not in races: raise ValueError("Bad bot_race args") if difficulty and str(difficulty) not in difficulties: raise ValueError("Bad difficulty") self._map = maps.get(map_name) self._discount = discount self._step_mul = step_mul or self._map.step_mul self._save_replay_steps = save_replay_steps 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._sc2_proc = self._run_config.start() self._controller = self._sc2_proc.controller 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) create = sc_pb.RequestCreateGame(local_map=sc_pb.LocalMap( map_path=self._map.path, map_data=self._map.data(self._run_config))) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Computer, race=races[bot_race or "R"], difficulty=difficulties[difficulty or "1"]) join = sc_pb.RequestJoinGame(race=races[agent_race or "R"], options=interface) self._controller.create_game(create) self._controller.join_game(join) game_info = self._controller.game_info() static_data = self._controller.data() self._features = features.Features(game_info) if visualize: self._renderer_human = renderer_human.RendererHuman() self._renderer_human.init(game_info, static_data) self._episode_count = 0 self._obs = None self._state = environment.StepType.LAST # Want to jump to `reset`. logging.info("Environment is ready.")
def get_random_trajectory(self): function_dict = {} for _FUNCTION in actions._FUNCTIONS: #print(_FUNCTION) function_dict[_FUNCTION.ability_id] = _FUNCTION.name race_list = ['Terran', 'Zerg', 'Protoss'] """How many agent steps the agent has been trained for.""" run_config = run_configs.get() sc2_proc = run_config.start() controller = sc2_proc.controller #print ("source: {}".format(source)) #root_path = '/media/kimbring2/Steam/StarCraftII/Replays/4.8.2.71663-20190123_035823-1' root_path = self.source file_list = glob.glob(root_path + '*.*') #print ("file_list: {}".format(file_list)) for i in range(0, 500): #print("i: " + str(i)) replay_file_path = random.choice(file_list) #print ("replay_file_path: {}".format(replay_file_path)) #replay_file_path = root_path + '0a0f62052fe4311368910ad38c662bf979e292b86ad02b49b41a87013e58c432.SC2Replay' #replay_file_path = root_path + '/0a1b09abc9e98f4e0c3921ae0a427c27e97c2bbdcf34f50df18dc41cea3f3249.SC2Replay' #replay_file_path_2 = root_path + '/0a01d32e9a98e1596b88bc2cdec7752249b22aca774e3305dae2e93efef34be3.SC2Replay' #replay_file_path_0 = human_data #print ("replay_file_path: {}".format(replay_file_path)) try: replay_data = run_config.replay_data(replay_file_path) ping = controller.ping() info = controller.replay_info(replay_data) print("ping: " + str(ping)) print("replay_info: " + str(info)) player0_race = info.player_info[0].player_info.race_actual player0_mmr = info.player_info[0].player_mmr player0_apm = info.player_info[0].player_apm player0_result = info.player_info[0].player_result.result print("player0_race: " + str(player0_race)) print("player0_mmr: " + str(player0_mmr)) print("player0_apm: " + str(player0_apm)) print("player0_result: " + str(player0_result)) home_race = race_list.index(self.home_race_name) + 1 if (home_race == player0_race): print("player0_race pass") else: print("player0_race fail") continue if (player0_mmr >= self.replay_filter): print("player0_mmr pass ") else: print("player0_mmr fail") continue player1_race = info.player_info[0].player_info.race_actual player1_mmr = info.player_info[0].player_mmr player1_apm = info.player_info[0].player_apm player1_result = info.player_info[0].player_result.result print("player1_race: " + str(player1_race)) print("player1_mmr: " + str(player1_mmr)) print("player1_apm: " + str(player1_apm)) print("player1_result: " + str(player1_result)) away_race = race_list.index(self.away_race_name) + 1 if (away_race == player1_race): print("player1_race pass ") else: print("player1_race fail ") continue if (player1_mmr >= self.replay_filter): print("player1_mmr pass ") else: print("player1_mmr fail") continue screen_size_px = (128, 128) minimap_size_px = (64, 64) player_id = 1 discount = 1. step_mul = 8 screen_size_px = point.Point(*screen_size_px) minimap_size_px = point.Point(*minimap_size_px) interface = sc_pb.InterfaceOptions(raw=False, score=True, feature_layer=sc_pb.SpatialCameraSetup(width=24)) screen_size_px.assign_to(interface.feature_layer.resolution) minimap_size_px.assign_to(interface.feature_layer.minimap_resolution) map_data = None if info.local_map_path: map_data = run_config.map_data(info.local_map_path) _episode_length = info.game_duration_loops _episode_steps = 0 controller.start_replay(sc_pb.RequestStartReplay(replay_data=replay_data, map_data=map_data, options=interface, observed_player_id=player_id)) _state = StepType.FIRST if (info.HasField("error") or info.base_build != ping.base_build or # different game version info.game_duration_loops < 1000 or len(info.player_info) != 2): # Probably corrupt, or just not interesting. print("error") continue feature_screen_size = 128 feature_minimap_size = 64 rgb_screen_size = None rgb_minimap_size = None action_space = None use_feature_units = True aif = sc2_env.parse_agent_interface_format( feature_screen=feature_screen_size, feature_minimap=feature_minimap_size, rgb_screen=rgb_screen_size, rgb_minimap=rgb_minimap_size, action_space=action_space, use_feature_units=use_feature_units) _features = features.features_from_game_info(controller.game_info(), agent_interface_format=aif) build_info = [] build_name = [] replay_step = 0 print("True loop") while True: replay_step += 1 #print("replay_step: " + str(replay_step)) controller.step(step_mul) obs = controller.observe() #self.home_trajectory.append(obs) if (len(obs.actions) != 0): action = (obs.actions)[0] action_spatial = action.action_feature_layer unit_command = action_spatial.unit_command ability_id = unit_command.ability_id function_name = function_dict[ability_id] if (function_name != 'build_queue'): function_name_parse = function_name.split('_') function_name_first = function_name_parse[0] #print("function_name_first: " + str(function_name_first)) if (function_name_first == 'Build' or function_name_first == 'Train'): unit_name = function_name_parse[1] unit_info = int(units_new.get_unit_type(self.home_race_name, unit_name)[0]) #print("unit_name: " + str(unit_name)) #print("unit_info: " + str(unit_info)) #print("function_name_parse[1]: " + str(function_name_parse[1])) build_name.append(unit_name) build_info.append(unit_info) if obs.player_result: # Episide over. _state = StepType.LAST discount = 0 else: discount = discount _episode_steps += step_mul agent_obs = _features.transform_obs(obs) self.home_trajectory.append(agent_obs) step = TimeStep(step_type=_state, reward=0, discount=discount, observation=agent_obs) score_cumulative = agent_obs['score_cumulative'] score_cumulative_dict = {} score_cumulative_dict['score'] = score_cumulative.score score_cumulative_dict['idle_production_time'] = score_cumulative.idle_production_time score_cumulative_dict['idle_worker_time'] = score_cumulative.idle_worker_time score_cumulative_dict['total_value_units'] = score_cumulative.total_value_units score_cumulative_dict['total_value_structures'] = score_cumulative.total_value_structures score_cumulative_dict['killed_value_units'] = score_cumulative.killed_value_units score_cumulative_dict['killed_value_structures'] = score_cumulative.killed_value_structures score_cumulative_dict['collected_minerals'] = score_cumulative.collected_minerals score_cumulative_dict['collected_vespene'] = score_cumulative.collected_vespene score_cumulative_dict['collection_rate_minerals'] = score_cumulative.collection_rate_minerals score_cumulative_dict['collection_rate_vespene'] = score_cumulative.collection_rate_vespene score_cumulative_dict['spent_minerals'] = score_cumulative.spent_minerals score_cumulative_dict['spent_vespene'] = score_cumulative.spent_vespene #print("obs.player_result: " + str(obs.player_result)) if obs.player_result: break _state = StepType.MID self.home_BO = build_info self.away_BU = score_cumulative_dict break except: continue
def human(): """Run a host which expects one player to connect remotely.""" run_config = run_configs.get() map_inst = maps.get(FLAGS.map) if not FLAGS.rgb_screen_size or not FLAGS.rgb_minimap_size: logging.info("Use --rgb_screen_size and --rgb_minimap_size if you want rgb " "observations.") ports = [FLAGS.config_port + p for p in range(5)] # tcp + 2 * num_players if not all(portpicker.is_port_free(p) for p in ports): sys.exit("Need 5 free ports after the config port.") proc = None ssh_proc = None tcp_conn = None udp_sock = None try: proc = run_config.start(extra_ports=ports[1:], timeout_seconds=300, host=FLAGS.host, window_loc=(50, 50)) tcp_port = ports[0] settings = { "remote": FLAGS.remote, "game_version": proc.version.game_version, "realtime": FLAGS.realtime, "map_name": map_inst.name, "map_path": map_inst.path, "map_data": map_inst.data(run_config), "ports": { "server": {"game": ports[1], "base": ports[2]}, "client": {"game": ports[3], "base": ports[4]}, } } create = sc_pb.RequestCreateGame( realtime=settings["realtime"], local_map=sc_pb.LocalMap(map_path=settings["map_path"])) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Participant) controller = proc.controller controller.save_map(settings["map_path"], settings["map_data"]) controller.create_game(create) if FLAGS.remote: ssh_proc = lan_sc2_env.forward_ports( FLAGS.remote, proc.host, [settings["ports"]["client"]["base"]], [tcp_port, settings["ports"]["server"]["base"]]) print("-" * 80) print("Join: play_vs_agent --host %s --config_port %s" % (proc.host, tcp_port)) print("-" * 80) tcp_conn = lan_sc2_env.tcp_server( lan_sc2_env.Addr(proc.host, tcp_port), settings) if FLAGS.remote: udp_sock = lan_sc2_env.udp_server( lan_sc2_env.Addr(proc.host, settings["ports"]["client"]["game"])) lan_sc2_env.daemon_thread( lan_sc2_env.tcp_to_udp, (tcp_conn, udp_sock, lan_sc2_env.Addr(proc.host, settings["ports"]["server"]["game"]))) lan_sc2_env.daemon_thread(lan_sc2_env.udp_to_tcp, (udp_sock, tcp_conn)) join = sc_pb.RequestJoinGame() join.shared_port = 0 # unused join.server_ports.game_port = settings["ports"]["server"]["game"] join.server_ports.base_port = settings["ports"]["server"]["base"] join.client_ports.add(game_port=settings["ports"]["client"]["game"], base_port=settings["ports"]["client"]["base"]) join.race = sc2_env.Race[FLAGS.user_race] if FLAGS.render: join.options.raw = True join.options.score = True if FLAGS.feature_screen_size and FLAGS.feature_minimap_size: fl = join.options.feature_layer fl.width = 24 FLAGS.feature_screen_size.assign_to(fl.resolution) FLAGS.feature_minimap_size.assign_to(fl.minimap_resolution) if FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size: FLAGS.rgb_screen_size.assign_to(join.options.render.resolution) FLAGS.rgb_minimap_size.assign_to(join.options.render.minimap_resolution) controller.join_game(join) if FLAGS.render: renderer = renderer_human.RendererHuman( fps=FLAGS.fps, render_feature_grid=False) renderer.run(run_configs.get(), controller, max_episodes=1) else: # Still step forward so the Mac/Windows renderer works. try: while True: frame_start_time = time.time() if not FLAGS.realtime: controller.step() obs = controller.observe() if obs.player_result: break time.sleep(max(0, frame_start_time - time.time() + 1 / FLAGS.fps)) except KeyboardInterrupt: pass finally: if tcp_conn: tcp_conn.close() if proc: proc.close() if udp_sock: udp_sock.close() if ssh_proc: ssh_proc.terminate() for _ in range(5): if ssh_proc.poll() is not None: break time.sleep(1) if ssh_proc.poll() is None: ssh_proc.kill() ssh_proc.wait()
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 = [portpicker.pick_unused_port() for _ in range(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()
def main(): """Dump stats about all the actions that are in use in a set of replays.""" run_config = run_configs.get() filter_file = FLAGS.filter_file if not gfile.Exists(filter_file): sys.exit("{} doesn't exist.".format(filter_file)) print("Generating replay list using:", filter_file) # Instantiate empty replay list replay_list = [] # Import filter JSON filtered_data = json.load(open(filter_file)) # Identify replay directory from filter replay_dir = filtered_data['ReplaysDirectory'] # Iterate through replays denoted in filter for replay in filtered_data['Replays']: for key in replay: if key: # Generate the replay filename replay_file = os.path.join(replay_dir, key + '.SC2Replay') # Append replay file path to replay list replay_list.append(replay_file) # Ensure the path for the states directory exists # else create it. if not os.path.exists(FLAGS.states_dir): os.makedirs(FLAGS.states_dir) stats_queue = multiprocessing.Queue() stats_thread = threading.Thread(target=stats_printer, args=(stats_queue, FLAGS.parallel, FLAGS.print_time)) stats_thread.start() try: # For some reason buffering everything into a JoinableQueue makes the # program not exit, so save it into a list then slowly fill it into the # queue in a separate thread. Grab the list synchronously so we know there # is work in the queue before the SC2 processes actually run, otherwise # The replay_queue.join below succeeds without doing any work, and exits. replay_queue = multiprocessing.JoinableQueue(FLAGS.parallel * 10) replay_queue_thread = threading.Thread(target=replay_queue_filler, args=(replay_queue, replay_list)) replay_queue_thread.daemon = True replay_queue_thread.start() for i in range(FLAGS.parallel): p = ReplayProcessor(i, run_config, replay_queue, stats_queue, FLAGS.step_mul, FLAGS.states_dir, FLAGS.winner_only) p.daemon = True p.start() time.sleep(1) # Stagger startups, otherwise they seem to conflict somehow replay_queue.join() # Wait for the queue to empty. except KeyboardInterrupt: print("Caught KeyboardInterrupt, exiting.") finally: stats_queue.put(None) # Tell the stats_thread to print and exit. stats_thread.join()
def main(unused_argv): interface = sc_pb.InterfaceOptions() interface.raw = True interface.score = True interface.feature_layer.width = 24 interface.feature_layer.resolution.x = 84 interface.feature_layer.resolution.y = 84 interface.feature_layer.minimap_resolution.x = 64 interface.feature_layer.minimap_resolution.y = 64 timeline = [] start = time.time() run_config = run_configs.get() proc = run_config.start() process = psutil.Process(proc.pid) episode = 0 def add(s): cpu = process.cpu_times().user mem = process.memory_info().rss / 2**20 # In Mb step = Timestep(episode, time.time() - start, cpu, mem, s) print(step) timeline.append(step) if mem > FLAGS.mem_limit: raise MemoryException("%s Mb mem limit exceeded" % FLAGS.mem_limit) try: add("Started process") controller = proc.controller map_inst = maps.get("Simple64") create = sc_pb.RequestCreateGame( realtime=False, disable_fog=False, local_map=sc_pb.LocalMap(map_path=map_inst.path, map_data=map_inst.data(run_config))) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Computer, race=sc_common.Random, difficulty=sc_pb.CheatInsane) join = sc_pb.RequestJoinGame(race=sc_common.Random, options=interface) controller.create_game(create) add("Created game") controller.join_game(join) episode += 1 add("Joined game") for _ in range(FLAGS.episodes): for i in range(2000): controller.step(16) obs = controller.observe() if obs.player_result: add("Lost on step %s" % i) break if i > 0 and i % 100 == 0: add("Step %s" % i) controller.restart() episode += 1 add("Restarted") add("Done") except KeyboardInterrupt: pass except (MemoryException, protocol.ConnectionError) as e: print(e) finally: proc.close() print("Timeline:") for t in timeline: print(t)
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, Observer)): raise ValueError( "Expected players to be of type Agent, Bot, or Observer. Got: %s." % p) num_players = len(players) self._num_agents = sum(1 for p in players if isinstance(p, Agent)) self._num_observers = sum(1 for p in players if isinstance(p, Observer)) self._players = players if save_replay_episodes and not replay_dir: raise ValueError("Missing replay_dir") if map_inst.players and (num_players - self._num_observers) > 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 + self._num_observers) if len(agent_interface_format) != (self._num_agents + self._num_observers): raise ValueError( "The number of entries in agent_interface_format should " "correspond 1-1 with the number of agents plus the number of observers.") 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)
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, 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._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( agent_interface_format=agent_interface_format, require_raw=True) self._connect_remote(host, host_port, lan_port, race, map_inst, interface) self._finalize([agent_interface_format], [interface], visualize)
def extract_actions(counter, replays_path, save_path, batch_size, step_mul): # Check if the replays_path exists if not os.path.isdir(replays_path): raise ValueError('The path ' + replays_path + ' does not exist.') # Make list of the paths to all the replays cwd = os.getcwd() replay_paths = [] for replay in os.listdir(replays_path): replay_path = os.path.join(cwd, replays_path, replay) if os.path.isfile(replay_path) and replay.lower().endswith( '.sc2replay'): replay_paths.append(replay_path) # Check if the save_path exists. Otherwise we need to create it if not os.path.isdir(save_path): os.makedirs(save_path) # Used for picking up from where an exception was thrown. replays_range_left_in_batch = (0, 0) while True: try: run_config = run_configs.get() with run_config.start() as controller: while True: # Variables for later batch_start = 0 batch_end = 0 # Check if we resumed here from an exception if replays_range_left_in_batch == (0, 0): # Everything is good with counter.get_lock(): if counter.value * batch_size > len(replay_paths): print( ' Reached the end of the replay list. Returning...' ) return batch_number = counter.value counter.value += 1 batch_start = batch_number * batch_size batch_end = batch_number * batch_size + batch_size if batch_end > len(replay_paths) - 1: batch_end = len(replay_paths) - 1 else: # We resumed here from an exception. Skip the replay that caused an exception. batch_start = replays_range_left_in_batch[0] + 1 batch_end = replays_range_left_in_batch[1] print( ' Resuming with batch from a crash. Resuming from ' + str(batch_start) + ' to ' + str(batch_end)) for index in range(batch_start, batch_end): print( '================================================================================ Processing replay #' + str(index + 1)) replays_range_left_in_batch = (index, batch_end) replay_path = replay_paths[index] replay_data = run_config.replay_data(replay_path) info = controller.replay_info(replay_data) interface = sc_pb.InterfaceOptions() interface.raw = True interface.score = False for player in info.player_info: player_game_data_points = [] start_replay = sc_pb.RequestStartReplay( replay_data=replay_data, options=interface, disable_fog=False, observed_player_id=player.player_info.player_id ) controller.start_replay(start_replay) controller.step() time_step = 0 resources = [] upgrades = [] in_progress = [] friendly_unit_list = [] enemy_unit_list = [] try: while True: time_step += step_mul controller.step(step_mul) obs = controller.observe() for action in obs.actions: mapped_action = get_macro_action( action) if mapped_action is not None: # print('________________________________________________________________________________') # print('Time step (step/seconds): ' + str(time_step) + '/' + str(time_step/22.4)) # print('Resources (minerals, vespene, food(cap, used, army, workers), idle_workers, army_count, warp_gates): ' + str(resources[0]) + ', ' + str(resources[1]) + ', (' + str(resources[2]) + ', ' + str(resources[3]) + ', ' + str(resources[4]) + ', ' + str(resources[5]) + '), ' + str(resources[6]) + ', ' + str(resources[7]) + ', ' + str(resources[8])) # print('In progress: ' + str(in_progress_dic(in_progress))) # print('Upgrades: ' + str(upgrades_dic(upgrades))) # print('Friendly buildings: ' + str(buildings_dic(friendly_unit_list))) # print('Friendly units: ' + str(units_dic(friendly_unit_list))) # print('Enemy buildings: ' + str(buildings_dic(enemy_unit_list))) # print('Enemy units: ' + str(units_dic(enemy_unit_list))) # print('--------------------------------------------------------------------------------') # action_id = np.argmax(mapped_action) # print('Action: ' + str(action_id) + ': ' + c.protoss_macro_actions[np.argmax(mapped_action)]) # print('________________________________________________________________________________') new_data_point = [] new_data_point.append( time_step) # 1 new_data_point += resources # 9 new_data_point += upgrades # 26 new_data_point += in_progress # 70 new_data_point += friendly_unit_list # 44 new_data_point += enemy_unit_list # 44 new_data_point += mapped_action # 54 player_game_data_points.append( new_data_point) resources = get_resources( obs.observation) upgrades = get_upgrades( obs.observation.raw_data.player. upgrade_ids) in_progress = get_units_in_progress( obs.observation.raw_data.units) friendly_unit_list = get_friendly_unit_list( obs.observation.raw_data.units) enemy_unit_list = get_enemy_unit_list( obs.observation.raw_data.units) # The game has finished if there is a player_result if obs.player_result: print( ' Replay #' + str(index + 1) + ' from player ' + str(player.player_info.player_id) + '\'s perspective has finished.') break except KeyboardInterrupt: return # Save the data for this player. replay_save_path = os.path.join( cwd, save_path, replay_path.split('/')[-1].split('.')[0] + '_' + str(player.player_info.player_id)) save_replay_data(replay_save_path, player_game_data_points) print( ' Finished processing game #' + str(index + 1) + '.') # Everything went smothely with this replay batch. Reset the counter and move on. replays_range_left_in_batch = (0, 0) except KeyboardInterrupt: return except WebSocketTimeoutException: print( ' Websocket timed out.' ) except pysc2.lib.protocol.ConnectionError: print( ' Websocket timed out.' ) except: print( ' Something went wrong. Skipping this replay.' )
def main(unused_argv): stopwatch.sw.enable() results = [] try: for config, interface in configs: print((" Starting: %s " % config).center(60, "-")) timeline = [] run_config = run_configs.get() if FLAGS.replay: replay_data = run_config.replay_data(FLAGS.replay) start_replay = sc_pb.RequestStartReplay( replay_data=replay_data, options=interface, disable_fog=False, observed_player_id=2) version = replay.get_replay_version(replay_data) run_config = run_configs.get( version=version) # Replace the run config. else: map_inst = maps.get(FLAGS.map) create = sc_pb.RequestCreateGame( realtime=False, disable_fog=False, random_seed=1, local_map=sc_pb.LocalMap( map_path=map_inst.path, map_data=map_inst.data(run_config))) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Computer, race=sc_common.Terran, difficulty=sc_pb.VeryEasy) join = sc_pb.RequestJoinGame(options=interface, race=sc_common.Protoss) with run_config.start( want_rgb=interface.HasField("render")) as controller: if FLAGS.replay: info = controller.replay_info(replay_data) print(" Replay info ".center(60, "-")) print(info) print("-" * 60) if info.local_map_path: start_replay.map_data = run_config.map_data( info.local_map_path) controller.start_replay(start_replay) else: controller.create_game(create) controller.join_game(join) for _ in range(FLAGS.count): controller.step(FLAGS.step_mul) start = time.time() obs = controller.observe() timeline.append(time.time() - start) if obs.player_result: break results.append((config, timeline)) except KeyboardInterrupt: pass names, values = zip(*results) print("\n\nTimeline:\n") print(",".join(names)) for times in zip(*values): print(",".join("%0.2f" % (t * 1000) for t in times)) print(stopwatch.sw)
def main(unused_argv, version=STANDARD_VERSION): version = REPLAY_VERSION replay_files = [] for root, dir, files in os.walk(os.path.join(REPLAY_DIR, version)): for file in files: if file.endswith(".SC2Replay"): replay_files.append(os.path.join(root, file)) for replay_file in replay_files: print('Going to parse replay "{}".'.format(replay_file), file=sys.stderr) REPLAYS_SINGLE = os.path.join( REPLAYS_PARSED_DIR, version + '_2', os.path.relpath(replay_file, os.path.join(REPLAY_DIR, version)).replace( '.SC2Replay', '')) LOG_SINGLE = os.path.join( REPO_DIR, 'log', version + '_2', os.path.relpath(replay_file, os.path.join(REPLAY_DIR, version)).replace( '.SC2Replay', '')) os.makedirs(REPLAYS_SINGLE, exist_ok=True) os.makedirs(LOG_SINGLE, exist_ok=True) run_config = run_configs.get() PATH = MAP_PATH + '-v' + version + '.SC2Map' replay_data = run_config.replay_data(replay_file) with run_config.start(game_version=get_replay_version(replay_data), full_screen=False) as controller: print('Starting replay...', file=sys.stderr) controller.start_replay( RequestStartReplay( replay_data=replay_data, # Overwrite map_data because we know where our map is located # (so we don't care about the map path stored in the replay). map_data=run_config.map_data(PATH), # Observe from Team Minerals so player_relative features work. observed_player_id=1, # Controls what type of observations we will receive options=InterfaceOptions( # Raw observations include absolute unit owner, position, # and type we enable them for constructing a baseline. raw=True, # Score observations include statistics collected over the # game, most aren't applicable to this map, so disable them. score=False, # Feature layer observations are those described in the # SC2LE paper. We want to learn on those, so enable them. feature_layer=SpatialCameraSetup( width=24, resolution=Size2DI(x=SCREEN_RESOLUTION, y=SCREEN_RESOLUTION), minimap_resolution=Size2DI( x=MINIMAP_RESOLUTION, y=MINIMAP_RESOLUTION))), # Ensure that fog of war won't hinder observations. disable_fog=True)) info = controller.replay_info(replay_data=replay_data) time = info.game_duration_seconds if time > 6000: os.remove(replay_file) print( 'removed %s because game time exceeded 1 hour (actual replay duration was %.2f)' % (replay_file, time)) break else: print('File okay, Duration is %.2f' % (time)) round_num = 0 curr_battle = None last_num_units, curr_num_units = -1, -1 last_num_wins_minerals, curr_num_wins_minerals = -1, -1 last_num_wins_vespene, curr_num_wins_vespene = -1, -1 units = [] obs = controller.observe() while not obs.player_result: # We advance 16 steps at a time here because this is the largest # value which still ensures that we will have at least one # observation between different phases (units spawn, units # engage, outcome determined, units remove) when wait time is # set to 1.0 game seconds in editor. controller.step(16) obs = controller.observe() #save unit and win values from last round last_num_units = curr_num_units last_num_wins_minerals = curr_num_wins_minerals last_num_wins_vespene = curr_num_wins_vespene #get values from active round curr_num_units = len(obs.observation.raw_data.units) curr_num_wins_minerals = \ obs.observation.player_common.minerals curr_num_wins_vespene = \ obs.observation.player_common.vespene if curr_num_units != 0 and last_num_units == 0 and curr_battle is None: broodling = False units = obs.observation.raw_data.units for unit in units: if unit.unit_type == 289: broodling = True round_num += 1 print('Parsing Round {}...'.format(round_num), file=sys.stderr) assert curr_battle is None curr_battle = obs.observation unit_array = obs.observation.raw_data.units units = [] units.append([]) units.append([]) for unit in unit_array: if unit.owner == 1: units[0].append(unit.unit_type) elif unit.owner == 2: units[1].append(unit.unit_type) outcome = None if (curr_num_wins_minerals > last_num_wins_minerals) and ( curr_num_wins_vespene > last_num_wins_vespene): units.append([2]) outcome = [0, 0, 1] elif (curr_num_wins_minerals > last_num_wins_minerals) \ and (last_num_wins_minerals != -1): units.append([0]) outcome = [1, 0, 0] elif (curr_num_wins_vespene > last_num_wins_vespene) \ and (last_num_wins_vespene != -1): units.append([1]) outcome = [0, 1, 0] if outcome is not None: if curr_battle is not None: parsed_replay_path = os.path.join( REPO_DIR, 'Proc_Data_', version, os.path.relpath( replay_file, os.path.join(REPLAY_DIR, version)).replace( '.SC2Replay', ''), os.path.relpath( replay_file, os.path.join(REPLAY_DIR, version)).replace( '.SC2Replay', '') + '_' + str(round_num)) print('Round %s parsed and saved as: %s' % (round_num, parsed_replay_path), file=sys.stderr) player_relative = curr_battle.feature_layer_data.renders.player_relative height_map = curr_battle.feature_layer_data.renders.height_map visibility = curr_battle.feature_layer_data.renders.visibility_map creep = curr_battle.feature_layer_data.renders.creep power = curr_battle.feature_layer_data.renders.power player_id = curr_battle.feature_layer_data.renders.player_id unit_type = curr_battle.feature_layer_data.renders.unit_type selected = curr_battle.feature_layer_data.renders.selected hit_points = curr_battle.feature_layer_data.renders.unit_hit_points energy = curr_battle.feature_layer_data.renders.unit_energy shields = curr_battle.feature_layer_data.renders.unit_shields unit_density = curr_battle.feature_layer_data.renders.unit_density unit_density_aa = curr_battle.feature_layer_data.renders.unit_density_aa feature_layers = [] # # computing feature layers in a Nx84x84 Tensor # # Player Relative data_pr = np.frombuffer(player_relative.data, dtype=np.int32) \ .reshape((1, 42, 42)) data_processed = data_pr[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # # height map data_hm = np.frombuffer(height_map.data, dtype=np.int32) \ .reshape((1, 42, 42)) data_processed = data_hm[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # # visibility data_vi = np.frombuffer(visibility.data, dtype=np.int32) \ .reshape((1, 42, 42)) data_processed = data_vi[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # # creep data_cr = np.frombuffer(creep.data, dtype=np.int8) \ .reshape((1, -1, 2)) data_processed = data_cr[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # # power data_pw = np.frombuffer(power.data, dtype=np.int8) \ .reshape((1, -1, 2)) data_processed = data_pw[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # player id data_id = np.frombuffer(player_id.data, dtype=np.int32) \ .reshape((1, 42, 42)) data_processed = data_id[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # unit_type data_ut = np.frombuffer(unit_type.data, dtype=np.int32) \ .reshape((1, 84, 84)) feature_layers.append(data_ut[0]) # # # selected data_se = np.frombuffer(selected.data, dtype=np.int8) \ .reshape((1, -1, 2)) data_processed = data_se[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # hit points data_hp = np.frombuffer(hit_points.data, dtype=np.int32) \ .reshape((1, 84, 84)) feature_layers.append(data_hp[0]) # # energy data_en = np.frombuffer(energy.data, dtype=np.int32) \ .reshape((1, 84, 84)) feature_layers.append(data_en[0]) # # shields data_sh = np.frombuffer(shields.data, dtype=np.int32) \ .reshape((1, 84, 84)) feature_layers.append(data_sh[0]) # # unit density data_de = np.frombuffer(unit_density.data, dtype=np.int32) \ .reshape((1, 42, 42)) data_processed = data_de[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) # # unit density aa data_da = np.frombuffer(unit_density_aa.data, dtype=np.int32) \ .reshape((1, 42, 42)) data_processed = data_da[0].copy() data_processed = np.resize(data_processed, (84, 84)) feature_layers.append(data_processed) layers = [] for layer in feature_layers: layer = np.reshape(layer, (84, 84)) layers.append(layer) layers = np.reshape(layers, (13 * 84, 84)) layers = np.append(layers, outcome) data = pd.DataFrame(layers) os.makedirs(parsed_replay_path, exist_ok=True) data.to_csv(os.path.join(parsed_replay_path, 'Layer.csv'), header=False, index=False, compression='gzip') units = np.array(units) df = pd.DataFrame(units) df.to_csv( os.path.join( LOG_SINGLE, os.path.relpath( replay_file, os.path.join(REPLAY_DIR, version)).replace( '.SC2Replay', '_' + str(round_num) + '.csv'))) units = [] curr_battle = None # if (error_flag == False): # replay_parsed_file = os.path.join( # REPLAYS_PARSED_DIR, # os.path.relpath(replay_file, REPLAY_DIR).replace( # '.SC2Replay', '.SC2Replay_parsed')) # print('Replay completed. Saving parsed replay to "{}".' # .format(replay_parsed_file), file=sys.stderr) # os.makedirs(REPLAYS_PARSED_DIR, exist_ok=True) # with open(replay_parsed_file, 'wb') as file: # file.write(simulation.SerializeToString()) # os.rename(replay_file, os.path.join(REPO_DIR, "parsed_basic", os.path.relpath(replay_file, REPLAY_DIR))) os.makedirs(os.path.join(REPO_DIR, 'parsed_basic', version), exist_ok=True) os.rename( replay_file, os.path.join( REPO_DIR, "parsed_basic", version, os.path.relpath(replay_file, os.path.join(REPLAY_DIR, version)))) print('Done.', file=sys.stderr)
def mnet_v6d6_run_il_loss_test(): mycfg = { 'test': False, 'use_self_fed_heads': False, 'use_value_head': False, 'use_loss_type': 'il', 'il_multi_label_loss': True, 'use_lstm': True, 'lstm_cell_type': 'lstm', 'lstm_layer_norm': True, 'batch_size': 2, 'rollout_len': 1, 'lstm_duration': 1, 'nlstm': 256, 'hs_len': 256 * 2, 'weight_decay': 0.0005, 'arg_scope_type': 'mnet_v6_type_a', 'use_base_mask': True, 'vec_embed_version': 'v2d1', 'last_act_embed_version': 'v2', 'zstat_embed_version': 'v7', 'trans_version': 'v5', 'gather_batch': True, 'use_astar_glu': True, 'use_astar_func_embed': True, 'pos_logits_mode': '3x3up2', 'pos_n_blk': 3, 'pos_n_skip': 2, } converter = PB2AllConverter(dict_space=True, zmaker_version='v5', zstat_data_src=FLAGS.zstat_data_src, game_version=FLAGS.game_version, sort_executors='v1', delete_dup_action='v2', input_map_size=(128, 128), output_map_size=(256, 256)) ob_space, ac_space = converter.space.spaces # build the net nc = net_config_cls(ob_space, ac_space, **mycfg) inputs = net_inputs_placeholders_fun(nc) out = net_build_fun(inputs, nc, scope='mnet_v6d6_il_loss') print('Successfully created the net.') converter.reset(replay_name=FLAGS.replay_name, player_id=FLAGS.player_id, mmr=6000, map_name=FLAGS.map_name) run_config = run_configs.get() replay_data = run_config.replay_data( path.join(FLAGS.replay_dir, FLAGS.replay_name + '.SC2Replay')) with run_config.start(version=FLAGS.game_version) as controller: replay_info = controller.replay_info(replay_data) print(replay_info) controller.start_replay( sc_pb.RequestStartReplay(replay_data=replay_data, map_data=None, options=get_replay_actor_interface( FLAGS.map_name), observed_player_id=FLAGS.player_id, disable_fog=False)) controller.step() last_pb = None last_game_info = None sess = tf.Session() tf.global_variables_initializer().run(session=sess) for _ in range(1000): pb_obs = controller.observe() game_info = controller.game_info() if last_pb is None: last_pb = pb_obs last_game_info = game_info continue if pb_obs.player_result: # episode ends, the zstat to this extent is what we need break # pb2all: X, A, weight as data data = converter.convert(pb=(last_pb, last_game_info), next_pb=(pb_obs, game_info)) if len(data) > 0: X, A = data[0][0] feed_dict = {} for key in X: feed_dict[inputs.X[key]] = [X[key]] * mycfg['batch_size'] for key in A: feed_dict[inputs.A[key]] = [A[key]] * mycfg['batch_size'] feed_dict[inputs.S] = ( [np.array([0] * mycfg['hs_len'], dtype=np.float32)] * mycfg['batch_size']) feed_dict[inputs.M] = ([np.array(1, dtype=np.bool)] * mycfg['batch_size']) loss = sess.run(out.loss.loss_endpoints, feed_dict) ab = A['A_AB'] avail_actions = np.nonzero(X['MASK_AB'])[0] avail_selections = np.nonzero(X['MASK_SELECTION'][ab])[0] selection_units = A['A_SELECT'] print('Avail action num: {}, select {}'.format( len(avail_actions), ZERG_ABILITIES[ab][0])) # print(ZERG_ABILITIES[ab][0]) print('Avail unit num: {}, select {}'.format( len(avail_selections), selection_units[:sum([(i != 600) for i in selection_units])])) print('Loss endpoints: {}'.format(loss)) # update & step the replay last_pb = pb_obs last_game_info = game_info controller.step(1) # step_mul controller.quit()
def __init__(self): # Start the SC2 process. self._run_config = run_configs.get() self._process = self._run_config.start() self._controller = self._process.controller self._saved_maps = set()
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.")
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) 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.")
def mnet_v6d6_run_ppo2_loss_test(): mycfg = { 'test': False, 'use_self_fed_heads': False, 'use_value_head': True, 'use_loss_type': 'rl_ppo2', 'use_lstm': True, 'lstm_cell_type': 'lstm', 'lstm_layer_norm': True, 'batch_size': 8, 'rollout_len': 4, 'lstm_duration': 1, 'nlstm': 256, 'hs_len': 256 * 2, 'weight_decay': 0.0005, 'arg_scope_type': 'mnet_v6_type_a', 'use_base_mask': True, 'vec_embed_version': 'v3', 'last_act_embed_version': 'v2', 'zstat_embed_version': 'v4d1', 'zstat_index_base_wavelen': 555.6, 'trans_version': 'v4', 'use_astar_glu': True, 'use_astar_func_embed': True, 'n_v': 5, 'lam': 0.8, 'gather_batch': True, 'merge_pi': False, 'distillation': True, 'value_net_version': 'trans_v1', } converter = PB2AllConverter(dict_space=True, zmaker_version='v5', zstat_data_src=FLAGS.zstat_data_src, game_version=FLAGS.game_version, sort_executors='v1') ob_space, ac_space = converter.space.spaces # build the net nc = net_config_cls(ob_space, ac_space, **mycfg) nc.reward_weights = np.ones(shape=nc.reward_weights_shape, dtype=np.float32) inputs = net_inputs_placeholders_fun(nc) keys = list(inputs.X.keys()) for key in keys: inputs.X['OPPO_' + key] = inputs.X[key] out = net_build_fun(inputs, nc, scope='mnet_v6d6_rl_ppo2_loss') converter.reset(replay_name=FLAGS.replay_name, player_id=FLAGS.player_id, mmr=6000, map_name=FLAGS.map_name) run_config = run_configs.get() replay_data = run_config.replay_data( path.join(FLAGS.replay_dir, FLAGS.replay_name + '.SC2Replay')) with run_config.start(version=FLAGS.game_version) as controller: replay_info = controller.replay_info(replay_data) print(replay_info) controller.start_replay( sc_pb.RequestStartReplay(replay_data=replay_data, map_data=None, options=get_replay_actor_interface( FLAGS.map_name), observed_player_id=FLAGS.player_id, disable_fog=False)) controller.step() last_pb = None last_game_info = None sess = tf.Session() tf.global_variables_initializer().run(session=sess) while True: pb_obs = controller.observe() game_info = controller.game_info() if last_pb is None: last_pb = pb_obs last_game_info = game_info continue if pb_obs.player_result: # episode end, the zstat to this extent is what we need break # pb2all: X, A, weights as data data = converter.convert(pb=(last_pb, last_game_info), next_pb=(pb_obs, game_info)) if data: feed_dict = {} X, A = data[0][0] for key in X: feed_dict[inputs.X[key]] = [X[key]] * mycfg['batch_size'] # if 'OPPO_'+key in inputs.X: # feed_dict[inputs.X['OPPO_'+key]] = [X[key]] * mycfg['batch_size'] for key in A: feed_dict[inputs.A[key]] = [A[key]] * mycfg['batch_size'] feed_dict[inputs.neglogp[key]] = [0] * mycfg['batch_size'] feed_dict[inputs.flatparam[key]] = np.zeros( shape=inputs.flatparam[key].shape) feed_dict[inputs.r] = [[0] * nc.n_v] * mycfg['batch_size'] feed_dict[inputs.discount] = [1] * mycfg['batch_size'] feed_dict[inputs.S] = [ np.array([0] * mycfg['hs_len'], dtype=np.float32) ] * mycfg['batch_size'] feed_dict[inputs.M] = [np.array(1, dtype=np.bool) ] * mycfg['batch_size'] loss = sess.run([ out.loss.pg_loss, out.loss.value_loss, out.loss.entropy_loss, out.loss.loss_endpoints ], feed_dict) print('Loss endpoints: {}'.format(loss)) # update and step the replay last_pb = pb_obs last_game_info = game_info controller.step(1) # step_mul
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()
def main(argv): import a3c.common.a3c scenarios.load_scenarios() run_config = run_configs.get() interface = sc_pb.InterfaceOptions() interface.raw = False interface.score = True interface.feature_layer.width = 24 interface.feature_layer.resolution.x = FLAGS.screen_resolution interface.feature_layer.resolution.y = FLAGS.screen_resolution interface.feature_layer.minimap_resolution.x = 64 interface.feature_layer.minimap_resolution.y = 64 queue = FakeQueue() # shared.gamma_n = FLAGS.gamma ** FLAGS.n_step_return env = helpers.get_env_wrapper(False) s_space = env.observation_space.shape none_state = np.zeros(s_space) none_state = none_state.reshape(s_space) replay_agent = Agent(env.action_space.n, t_queue=queue, none_state=none_state) for fname in glob.glob(os.path.join(FLAGS.dir, '*.SC2Replay')): replay_data = run_config.replay_data(fname) start_replay = sc_pb.RequestStartReplay( replay_data=replay_data, options=interface, disable_fog=True, observed_player_id=1) game_version = get_game_version(replay_data) with run_config.start(game_version=game_version, full_screen=False) as controller: controller.start_replay(start_replay) feat = features.Features(controller.game_info()) obs = controller.observe() s = get_obs(env._input_layers, obs) results = 0 last_reward = 0 while True: actions = [] for a in obs.actions: try: temp = feat.reverse_action(a) x = 0 y = 0 if temp[0] not in [0, 7]: x = temp.arguments[1][0] y = temp.arguments[1][1] actions.append([env._actions.index(temp[0]), x ,y]) except ValueError: pass if len(actions) < 1: try: controller.step(FLAGS.step_mul) except ProtocolError: break; obs = controller.observe() s = get_obs(env._input_layers, obs) continue r = obs.observation.score.score controller.step(FLAGS.step_mul) obs = controller.observe() s_ = get_obs(env._input_layers, obs) if r == 0 and last_reward != 0: s_ = None print('Episode end') results += 1 if not FLAGS.raw_rewards: replay_agent.train(s, actions[0][0], actions[0][1], actions[0][2], r, s_) else: queue.put([s, actions[0][0], actions[0][1], actions[0][2], r, s_]) if obs.player_result: break if r == 0 and last_reward != 0: last_reward = 0 else: s = s_ last_reward = r with gzip.open('./replay_info/info.gz', 'wb+') as outfile: print('pushed: {}'.format(results)) #json.dump(queue.get(), outfile) pickle.dump(queue.get(), outfile)
def test_replay_a_replay(self): run_config = run_configs.get() with run_config.start(want_rgb=False) as controller: map_inst = maps.get("Flat64") map_data = map_inst.data(run_config) interface = sc_pb.InterfaceOptions(raw=True) # Play a quick game to generate a replay. create = sc_pb.RequestCreateGame(local_map=sc_pb.LocalMap( map_path=map_inst.path, map_data=map_data)) create.player_setup.add(type=sc_pb.Participant) create.player_setup.add(type=sc_pb.Computer, race=sc_common.Terran, difficulty=sc_pb.VeryEasy) join = sc_pb.RequestJoinGame(race=sc_common.Terran, options=interface) controller.create_game(create) controller.join_game(join) controller.step(100) obs = controller.observe() replay_data = controller.save_replay() # Run through the replay the first time, verifying that it finishes, but # wasn't recording a replay. start_replay = sc_pb.RequestStartReplay(replay_data=replay_data, map_data=map_data, options=interface, observed_player_id=1) controller.start_replay(start_replay) controller.step(1000) obs2 = controller.observe() self.assertEqual(obs.observation.game_loop, obs2.observation.game_loop) with self.assertRaises(protocol.ProtocolError): controller.save_replay() # Run through the replay a second time, verifying that it finishes, and # *was* recording a replay. start_replay.record_replay = True controller.start_replay(start_replay) controller.step(1000) obs2 = controller.observe() self.assertEqual(obs.observation.game_loop, obs2.observation.game_loop) replay_data2 = controller.save_replay() # Make sure the replay isn't too small. Variance is fine but empty is not. self.assertGreater(len(replay_data2), len(replay_data) * 0.8) # Run through the replay a third time, verifying that it finishes, but # still wasn't recording a replay. start_replay.record_replay = False controller.start_replay(start_replay) controller.step(1000) obs3 = controller.observe() self.assertEqual(obs.observation.game_loop, obs3.observation.game_loop) with self.assertRaises(protocol.ProtocolError): controller.save_replay()