def human_runner(controller, join): """Run the human agent in a thread.""" j = sc_pb.RequestJoinGame() j.CopyFrom(join) j.race = sc2_env.Race[FLAGS.user_race] if FLAGS.render: j.options.raw = True j.options.feature_layer.width = 24 j.options.feature_layer.resolution.x = 64 j.options.feature_layer.resolution.y = 64 j.options.feature_layer.minimap_resolution.x = 64 j.options.feature_layer.minimap_resolution.y = 64 # j.options.render.resolution.x = 256 # j.options.render.resolution.y = 192 # j.options.render.minimap_resolution.x = 128 # j.options.render.minimap_resolution.y = 128 controller.join_game(j) if FLAGS.render: renderer = renderer_human.RendererHuman(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(FLAGS.step_mul) obs = controller.observe() if obs.player_result: break time.sleep(max(0, frame_start_time - time.time() + 1 / 22.4)) except KeyboardInterrupt: pass controller.quit()
def _finalize(self, interface, action_space, use_feature_units, visualize): game_info = self._controllers[0].game_info() static_data = self._controllers[0].data() if not self._map_name: self._map_name = game_info.map_name 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._metrics = metrics.Metrics(self._map_name) self._metrics.increment_instance() self._last_score = None self._total_steps = 0 self._episode_steps = 0 self._episode_count = 0 self._obs = None self._state = environment.StepType.LAST # Want to jump to `reset`. logging.info("Environment is ready on map: %s", self._map_name)
def _finalize(self, agent_interface_formats, interfaces, visualize): game_info = self._parallel.run(c.game_info for c in self._controllers) if not self._map_name: self._map_name = game_info[0].map_name for g, interface in zip(game_info, interfaces): if g.options.render != interface.render: logging.warning( "Actual interface options don't match requested options:\n" "Requested:\n%s\n\nActual:\n%s", interface, g.options) self._features = [ features.features_from_game_info( game_info=g, use_feature_units=agent_interface_format.use_feature_units, use_raw_units=agent_interface_format.use_raw_units, use_unit_counts=agent_interface_format.use_unit_counts, use_camera_position=agent_interface_format.use_camera_position, action_space=agent_interface_format.action_space, hide_specific_actions=agent_interface_format. hide_specific_actions) for g, agent_interface_format in zip( game_info, agent_interface_formats) ] if visualize: static_data = self._controllers[0].data() self._renderer_human = renderer_human.RendererHuman() self._renderer_human.init(game_info[0], static_data) else: self._renderer_human = None self._metrics = metrics.Metrics(self._map_name) self._metrics.increment_instance() self._last_score = None self._total_steps = 0 self._episode_steps = 0 self._episode_count = 0 self._obs = [None] * len(interfaces) self._agent_obs = [None] * len(interfaces) self._state = environment.StepType.LAST # Want to jump to `reset`. logging.info("Environment is ready on map: %s", self._map_name)
def _finalize(self, visualize): self._delayed_actions = [ collections.deque() for _ in self._action_delay_fns ] if visualize: self._renderer_human = renderer_human.RendererHuman() self._renderer_human.init(self._controllers[0].game_info(), self._controllers[0].data()) else: self._renderer_human = None self._metrics = metrics.Metrics(self._map_name) self._metrics.increment_instance() self._last_score = None self._total_steps = 0 self._episode_steps = 0 self._episode_count = 0 self._obs = [None] * self._num_agents self._agent_obs = [None] * self._num_agents self._state = environment.StepType.LAST # Want to jump to `reset`. logging.info("Environment is ready")
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 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.screen_resolution interface.feature_layer.resolution.y = FLAGS.screen_resolution interface.feature_layer.minimap_resolution.x = FLAGS.minimap_resolution interface.feature_layer.minimap_resolution.y = FLAGS.minimap_resolution 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.races[FLAGS.bot_race], difficulty=sc2_env.difficulties[FLAGS.difficulty]) join = sc_pb.RequestJoinGame(race=sc2_env.races[FLAGS.user_race], options=interface) game_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) game_version = get_game_version(replay_data) with run_config.start(game_version=game_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) 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 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 = portspicker.pick_contiguous_unused_ports(4) # 2 * num_players 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: agent_remote --map %s --host %s --host_port %s " "--lan_port %s" % (FLAGS.map, FLAGS.host, client_proc.port, ports[0])) 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 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 for p in [host_proc, client_proc]: p.close() portspicker.return_ports(ports)
def __init__(self, # pylint: disable=invalid-name _only_use_kwargs=None, map_name=None, 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: _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. 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 _only_use_kwargs: raise ValueError("All arguments must be passed as keyword arguments.") 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 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] join.player_name = FLAGS.user_name 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. 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 __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 main(unused_argv): """Run SC2 to play a game or a replay.""" if FLAGS.trace: stopwatch.sw.trace() elif FLAGS.profile: stopwatch.sw.enable() 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.raw_affects_selection = True interface.raw_crop_to_playable_area = True interface.score = True interface.show_cloaked = True interface.show_burrowed_shadows = True interface.show_placeholders = True if FLAGS.feature_screen_size and FLAGS.feature_minimap_size: interface.feature_layer.width = FLAGS.feature_camera_width FLAGS.feature_screen_size.assign_to(interface.feature_layer.resolution) FLAGS.feature_minimap_size.assign_to( interface.feature_layer.minimap_resolution) interface.feature_layer.crop_to_playable_area = True interface.feature_layer.allow_cheating_layers = True if FLAGS.render and FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size: FLAGS.rgb_screen_size.assign_to(interface.render.resolution) FLAGS.rgb_minimap_size.assign_to(interface.render.minimap_resolution) max_episode_steps = FLAGS.max_episode_steps if FLAGS.map: create = sc_pb.RequestCreateGame( realtime=FLAGS.realtime, disable_fog=FLAGS.disable_fog) try: map_inst = maps.get(FLAGS.map) except maps.lib.NoMapError: if FLAGS.battle_net_map: create.battlenet_map_name = FLAGS.map else: raise else: if map_inst.game_steps_per_episode: max_episode_steps = map_inst.game_steps_per_episode if FLAGS.battle_net_map: create.battlenet_map_name = map_inst.battle_net else: create.local_map.map_path = map_inst.path create.local_map.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], ai_build=sc2_env.BotBuild[FLAGS.bot_build]) join = sc_pb.RequestJoinGame( options=interface, race=sc2_env.Race[FLAGS.user_race], player_name=FLAGS.user_name) 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 = replay.get_replay_version(replay_data) run_config = run_configs.get(version=version) # Replace the run config. with run_config.start( full_screen=FLAGS.full_screen, window_size=FLAGS.window_size, want_rgb=interface.HasField("render")) 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, len(info.player_info)) 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)