def step(self, actions): """Apply actions, step the world forward, and return observations.""" if self._state == environment.StepType.LAST: return self.reset() # RGP # If there are multiple actions, transform them from python objects to the protobuf format with `transform_action`. # Use only the first agent's observations. (self.obs[0].observation) # Then create a RequestAction protobuf request including all requested actions. # Send the action from the **first agent's** controller (_self.controllers[0]) # Note: Multiple independent agents (with individual observations) can no longer be supported in this environment. if (len(actions) > 1): transformed_actions = [ self._features.transform_action(self._obs[0].observation, a) for a in actions ] req_action = sc_pb.RequestAction(actions=transformed_actions) self._controllers[0].actions(req_action) else: # RGP: Unmodified code follows. self._parallel.run( (c.act, self._features.transform_action(o.observation, a)) for c, o, a in zip(self._controllers, self._obs, actions)) self._state = environment.StepType.MID return self._step()
async def execute(self) -> bool: templars = self.cache.own(self.allowed_types).ready for ht in templars: # type: Unit if ht.is_idle and ht.tag in self.already_merging_tags: self.knowledge.roles.clear_task(ht) self.already_merging_tags.remove(ht.tag) templars = templars.tags_not_in(self.already_merging_tags) if templars.amount > 1: unit: Unit = templars[0] self.already_merging_tags.append(unit.tag) target: Unit = templars.tags_not_in(self.already_merging_tags).closest_to(unit) # Reserve upcoming archon so that they aren't stolen by other states. self.knowledge.roles.set_task(UnitTask.Reserved, unit) self.knowledge.roles.set_task(UnitTask.Reserved, target) self.knowledge.print(f"[ARCHON] merging {str(unit.type_id)} and {str(unit.type_id)}") from s2clientprotocol import raw_pb2 as raw_pb from s2clientprotocol import sc2api_pb2 as sc_pb command = raw_pb.ActionRawUnitCommand( ability_id=AbilityId.MORPH_ARCHON.value, unit_tags=[unit.tag, target.tag], queue_command=False ) action = raw_pb.ActionRaw(unit_command=command) await self.ai._client._execute(action=sc_pb.RequestAction( actions=[sc_pb.Action(action_raw=action)] )) return True
def reset(self): # Move the camera in any direction # This runs the ResetEpisode trigger built into the map self.decomposed_rewards = [] action = actions.FUNCTIONS.move_camera([0, 0]) self.current_obs = self.sc2_env.step([action])[0] if self.reset_steps >= 10: self.sc2_env.reset() self.reset_steps = 0 self.reset_steps += 1 self.end_state = None self.decision_point = 1 self.num_waves = 0 data = self.sc2_env._controllers[0]._client.send( observation=sc_pb.RequestObservation()) actions_space = self.sc2_env._controllers[0]._client.send( action=sc_pb.RequestAction()) data = data.observation.raw_data.units self.getRewards(data) # Get channel states # state = self.get_channel_state(self.current_obs) # Get custom states state_1 = self.get_custom_state(data, 1) state_2 = self.get_custom_state(data, 2) for rt in self.reward_types: self.decomposed_reward_dict[rt] = 0 self.last_decomposed_reward_dict[rt] = 0 # self.use_custom_ability(action_to_ability_id['switch_player']) return state_1, state_2
def use_custom_ability(self, ability_id, player_id=1): # Sends a command directly to the SC2 protobuf API # Can cause the pysc2 client to desync, unless step_sc2env() is called afterward from s2clientprotocol import sc2api_pb2 from s2clientprotocol import common_pb2 from s2clientprotocol import spatial_pb2 def get_action_spatial(ability_id): target_point = common_pb2.PointI() target_point.x = 0 target_point.y = 0 action_spatial_unit_command = spatial_pb2.ActionSpatialUnitCommand(target_minimap_coord=target_point) action_spatial_unit_command.ability_id = ability_id action_spatial = spatial_pb2.ActionSpatial(unit_command=action_spatial_unit_command) action = sc2api_pb2.Action(action_feature_layer=action_spatial) return action player_action = get_action_spatial(ability_id) request_action = sc2api_pb2.RequestAction(actions=[player_action]) request = sc2api_pb2.Request(action=request_action) # Bypass pysc2 and send the proto directly client = self.sc2env._controllers[player_id - 1]._client if self.verbose: print('Calling client.send_req for player_id {}'.format(player_id)) if self.sc2env._state == 2: print('Game is over, cannot send action') return client.send_req(request)
def step(self, actions, step_mul=None): """Apply actions, step the world forward, and return observations. Args: actions: A list of actions meeting the action spec, one per agent, or a list per agent. Using a list allows multiple actions per frame, but will still check that they're valid, so disabling ensure_available_actions is encouraged. step_mul: If specified, use this rather than the environment's default. Returns: A tuple of TimeStep namedtuples, one per agent. """ if self._state == environment.StepType.LAST: return self.reset() skip = not self._ensure_available_actions actions = [[ f.transform_action(o.observation, a, skip_available=skip) for a in to_list(acts) ] for f, o, acts in zip(self._features, self._obs, actions)] if not self._realtime: actions = self._apply_action_delays(actions) self._parallel.run((c.actions, sc_pb.RequestAction(actions=a)) for c, a in zip(self._controllers, actions)) self._state = environment.StepType.MID return self._step(step_mul)
async def chat_send(self, message: str, team_only: bool): """ Writes a message to the chat """ ch = ChatChannel.Team if team_only else ChatChannel.Broadcast r = await self._execute(action=sc_pb.RequestAction(actions=[ sc_pb.Action(action_chat=sc_pb.ActionChat(channel=ch.value, message=message)) ]))
async def morph_Archons(self): if upgrade.PSISTORMTECH is self.state.upgrades or self.already_pending_upgrade(upgrade.PSISTORMTECH): archons = self.army(unit.ARCHON) ht_amount = int(archons.amount / 2) ht_thresh = ht_amount + 1 else: ht_thresh = 1 if self.units(unit.HIGHTEMPLAR).amount > ht_thresh: hts = self.units(unit.HIGHTEMPLAR).sorted(lambda u: u.energy) ht2 = hts[0] ht1 = hts[1] if ht2 and ht1: for ht in self.army(unit.HIGHTEMPLAR): if ht.tag == ht1.tag or ht.tag==ht2.tag: self.army.remove(ht) if ht1.distance_to(ht2) > 4: if ht1.distance_to(self.main_base_ramp.bottom_center) > 30: self.do(ht1.move(ht2)) self.do(ht2.move(ht1)) else: self.do(ht1.move(self.main_base_ramp.bottom_center)) self.do(ht2.move(self.main_base_ramp.bottom_center)) else: # print('morphing!') from s2clientprotocol import raw_pb2 as raw_pb from s2clientprotocol import sc2api_pb2 as sc_pb command = raw_pb.ActionRawUnitCommand( ability_id=ability.MORPH_ARCHON.value, unit_tags=[ht1.tag,ht2.tag], queue_command=False ) action = raw_pb.ActionRaw(unit_command=command) await self._client._execute(action=sc_pb.RequestAction( actions=[sc_pb.Action(action_raw=action)] ))
async def chat_send(self, message, team_only): ch = ChatChannel.Team if team_only else ChatChannel.Broadcast r = await self._execute(action=sc_pb.RequestAction( actions=[sc_pb.Action(action_chat=sc_pb.ActionChat( channel=ch.value, message=message ))] ))
async def move_camera_spatial(self, position: Union[Point2, Point3]): """ Moves camera to the target position using the spatial aciton interface """ from s2clientprotocol import spatial_pb2 as spatial_pb assert isinstance(position, (Point2, Point3)) action = sc_pb.Action(action_render=spatial_pb.ActionSpatial( camera_move=spatial_pb.ActionSpatialCameraMove( center_minimap=common_pb.PointI(x=position.x, y=position.y)))) await self._execute(action=sc_pb.RequestAction(actions=[action]))
async def move_camera_spatial(self, position: Union[Point2, Point3]): """Moves camera to the target position using the spatial aciton interface :param position:""" assert isinstance(position, (Point2, Point3)) action = sc_pb.Action(action_render=spatial_pb.ActionSpatial( camera_move=spatial_pb.ActionSpatialCameraMove( center_minimap=position.as_PointI))) await self._execute(action=sc_pb.RequestAction(actions=[action]))
def act(self, actions): """Send a single action. This is a shortcut for `actions`.""" if not isinstance(actions, list): actions = [actions] # for a in actions: # if a and a.ListFields(): # Skip no-ops. # actions.remove(a) return self.actions(sc_pb.RequestAction(actions=actions))
async def move_camera(self, position: Union[Unit, Point2, Point3]): """ Moves camera to the target position """ assert isinstance(position, (Unit, Point2, Point3)) if isinstance(position, Unit): position = position.position await self._execute(action=sc_pb.RequestAction(action=[ sc_pb.Action(action_raw=raw_pb.ActionRaw( camera_move=raw_pb.ActionRawCameraMove( center_world_space=common_pb.Point(x=position.x, y=position.y)))) ]))
async def actions(self, actions, return_successes=False): if not actions: return None elif not isinstance(actions, list): actions = [actions] res = await self._execute( action=sc_pb.RequestAction(actions=(sc_pb.Action(action_raw=a) for a in combine_actions(actions))) ) if return_successes: return [ActionResult(r) for r in res.action.result] else: return [ActionResult(r) for r in res.action.result if ActionResult(r) != ActionResult.Success]
async def chat_send(self, messages, team_only): if not isinstance(messages, list): return await self.chat_send([messages], team_only) ch = ChatChannel.Team if team_only else ChatChannel.Broadcast r = await self._execute(action=sc_pb.RequestAction(actions=[ sc_pb.Action(chat=[ sc_pb.ActionChat(channel=ch.value, message=message) for message in messages ]) ])) print(r) exit("-")
async def morph_archons(self): if self.units(UnitTypeId.HIGHTEMPLAR).ready.amount >= 2: ht1 = self.units(UnitTypeId.HIGHTEMPLAR).ready.random ht2 = next((ht for ht in self.units(UnitTypeId.HIGHTEMPLAR).ready if ht.tag != ht1.tag), None) if ht2: command = raw_pb.ActionRawUnitCommand( ability_id=AbilityId.MORPH_ARCHON.value, unit_tags=[ht1.tag, ht2.tag], queue_command=False ) action = raw_pb.ActionRaw(unit_command=command) await self._client._execute(action=sc_pb.RequestAction( actions=[sc_pb.Action(action_raw=action)] ))
async def toggle_autocast(self, units: Union[List[Unit], Units], ability: AbilityId): """ Toggle autocast of all specified units """ assert units assert isinstance(units, list) assert all(isinstance(u, Unit) for u in units) assert isinstance(ability, AbilityId) await self._execute(action=sc_pb.RequestAction(actions=[ sc_pb.Action(action_raw=raw_pb.ActionRaw( toggle_autocast=raw_pb.ActionRawToggleAutocast( ability_id=ability.value, unit_tags=(u.tag for u in units)))) ]))
async def move_camera(self, position: Union[Unit, Units, Point2, Point3]): """Moves camera to the target position :param position:""" assert isinstance(position, (Unit, Units, Point2, Point3)) if isinstance(position, Units): position = position.center if isinstance(position, Unit): position = position.position await self._execute(action=sc_pb.RequestAction(actions=[ sc_pb.Action(action_raw=raw_pb.ActionRaw( camera_move=raw_pb.ActionRawCameraMove( center_world_space=position.to3.as_Point))) ]))
async def whiteball(self): if self.units(UnitTypeId.HIGHTEMPLAR).idle.ready.amount >= 4: ht1 = self.units(UnitTypeId.HIGHTEMPLAR).idle.ready.random ht2 = next((ht for ht in self.units(UnitTypeId.HIGHTEMPLAR).idle.ready if ht.tag != ht1.tag), None) if ht2: from s2clientprotocol import raw_pb2 as raw_pb from s2clientprotocol import sc2api_pb2 as sc_pb command = raw_pb.ActionRawUnitCommand( ability_id=AbilityId.MORPH_ARCHON.value, unit_tags=[ht1.tag, ht2.tag], queue_command=False) action = raw_pb.ActionRaw(unit_command=command) await self._client._execute(action=sc_pb.RequestAction( actions=[sc_pb.Action(action_raw=action)]))
async def actions(self, actions, return_successes=False): if not actions: return None elif not isinstance(actions, list): actions = [actions] # On realtime=True, might get an error here: sc2.protocol.ProtocolError: ['Not in a game'] try: res = await self._execute( action=sc_pb.RequestAction(actions=(sc_pb.Action(action_raw=a) for a in combine_actions(actions))) ) except ProtocolError as e: return [] if return_successes: return [ActionResult(r) for r in res.action.result] else: return [ActionResult(r) for r in res.action.result if ActionResult(r) != ActionResult.Success]
async def actions(self, actions, game_data, return_successes=False): if not isinstance(actions, list): res = await self.actions([actions], game_data, return_successes) if res: return res[0] else: return None else: actions = combine_actions(actions) res = await self._execute(action=sc_pb.RequestAction(actions=[sc_pb.Action(action_raw=a) for a in actions])) res = [ActionResult(r) for r in res.action.result] if return_successes: return res else: return [r for r in res if r != ActionResult.Success]
def reset(self): # Move the camera in any direction # This runs the ResetEpisode trigger built into the map self.decomposed_rewards_all = [] self.decomposed_rewards = [] self.decomposed_rewards_mark = 0 action = actions.FUNCTIONS.move_camera([0, 0]) self.last_timestep = self.sc2_env.step([action])[0] observation = self.unpack_timestep(self.last_timestep) self.current_obs = observation self.actions_taken = 0 #np.set_printoptions(threshold=np.nan,linewidth=np.nan) state = observation[3]['feature_screen'] player_relative = np.array(state[5]) player_relative[np.array(state[6]) == 73] = 3 player_relative[np.array(state[12]) == 1] = 3 state[5] = player_relative.tolist() state = getOneHotState(state, self.input_screen_features) state = np.reshape(state, (1, -1)) self.end_state = None #print(self.agent_interface_format.camera_width_world_units) #print(self.agent_interface_format.use_camera_position) #print(observation) #input() data = self.sc2_env._controllers[0]._client.send( observation=sc_pb.RequestObservation()) self.sc2_env._controllers[0]._client.send(action=sc_pb.RequestAction()) data = data.observation.raw_data.units rewards, sof = self.getRewards(data) self.signal_of_finished = sof for key in self.decomposed_reward_dict: self.decomposed_reward_dict[key] = 0 return state
async def parse_response(self, response_bytes): response = sc_pb.Response() response.ParseFromString(response_bytes) if not response.HasField("status"): logger.critical("Proxy: RESPONSE HAS NO STATUS {response}") else: new_status = Status(response.status) if new_status != self.controller._status: logger.info( f"Controller({self.player.name}): {self.controller._status}->{new_status}" ) self.controller._status = new_status if self.player_id is None: if response.HasField("join_game"): self.player_id = response.join_game.player_id logger.info( f"Proxy({self.player.name}): got join_game for {self.player_id}" ) if self.result is None: if response.HasField("observation"): obs: sc_pb.ResponseObservation = response.observation if obs.player_result: self.result = { pr.player_id: Result(pr.result) for pr in obs.player_result } elif (self.timeout_loop and obs.HasField("observation") and obs.observation.game_loop > self.timeout_loop): self.result = {i: Result.Tie for i in range(1, 3)} logger.info(f"Proxy({self.player.name}) timing out") act = [ sc_pb.Action(action_chat=sc_pb.ActionChat( message="Proxy: Timing out")) ] await self.controller._execute(action=sc_pb.RequestAction( actions=act)) return response
def reset(self): # Move the camera in any direction # This runs the ResetEpisode trigger built into the map self.decomposed_rewards = [] action = actions.FUNCTIONS.move_camera([0, 0]) self.actions_taken = 0 self.current_obs = self.sc2_env.step([action])[0] self.end_state = None self.get_income_signal = 2 data = self.sc2_env._controllers[0]._client.send( observation=sc_pb.RequestObservation()) actions_space = self.sc2_env._controllers[0]._client.send( action=sc_pb.RequestAction()) data = data.observation.raw_data.units self.getRewards(data) state = self.get_custom_state(data) for rt in self.reward_types: self.decomposed_reward_dict[rt] = 0 self.last_decomposed_reward_dict[rt] = 0 return state
def perform(self, spawn_id): # Pass arguments print(self) unit_command = raw_pb.ActionRawUnitCommand(ability_id=self.sc2_id) unit_command.unit_tags.append(spawn_id) if self.require['target'] == 'point': unit_command.target_world_space_pos.x = self.require['pos_x'] unit_command.target_world_space_pos.y = self.require['pos_y'] elif self.require['target'] == 'unit': unit_command.target_unit_tag = self.require['unit_tag'] else: pass action_raw = raw_pb.ActionRaw(unit_command=unit_command) action = sc_pb.RequestAction() action.actions.add(action_raw=action_raw) msg = MessageToJson(action) print(type(msg)) return msg
def acts(self, act_list): #print('actions bef=', act_list) if len(act_list) > 0: return self.actions(sc_pb.RequestAction(actions=act_list))
def act(self, action): """Send a single action. This is a shortcut for `actions`.""" if action: return self.actions(sc_pb.RequestAction(actions=[action]))
action = sc_pb.RequestAction() action.actions.add(action_raw = action_raw) test_client.comm.send(action=action) """ """Move Units""" unit_tag_list=[] observation = sc_pb.RequestObservation() t=test_client.comm.send(observation=observation) for unit in t.observation.observation.raw_data.units: if unit.unit_type == 84: # Probe unit_type_tag unit_tag_list.append(unit.tag) unit_command = raw_pb.ActionRawUnitCommand() unit_command.ability_id = 16 # Move Ability unit_command.target_world_space_pos.x = 30 unit_command.target_world_space_pos.y = 30 for i in range(0,12): unit_command.unit_tags.append(unit_tag_list[i]) action_raw = raw_pb.ActionRaw(unit_command = unit_command) action = sc_pb.RequestAction() action.actions.add(action_raw = action_raw) test_client.comm.send(action=action) #conn.close()
def step(self, actions): actions = [int(a) for a in actions] self.last_action = self.one_hot(actions, self.n_actions) # Collect individual actions sc_actions = [] for a_id, action in enumerate(actions): if not self.heuristic: agent_action = self.get_agent_action(a_id, action) else: agent_action = self.get_agent_action_heuristic(a_id, action) if agent_action: sc_actions.append(agent_action) # Send action request req_actions = sc_pb.RequestAction(actions=sc_actions) try: res_actions = self.controller.actions(req_actions) # Make step in SC2, i.e. apply actions self.controller.step(self._step_mul) # Observe here so that we know if the episode is over. self._obs = self.controller.observe() except protocol.ProtocolError: self.full_restart() return 0, True, {} except protocol.ConnectionError: self.full_restart() return 0, True, {} self._total_steps += 1 self._episode_steps += 1 # Update what we know about units end_game = self.update_units() terminated = False reward = self.reward_battle() info = {"battle_won": False} if end_game is not None: # Battle is over terminated = True self.battles_game += 1 if end_game == 1: self.battles_won += 1 info["battle_won"] = True if not self.reward_sparse: reward += self.reward_win else: reward = 1 elif end_game == -1: if not self.reward_sparse: reward += self.reward_defeat else: reward = -1 elif self.episode_limit > 0 and self._episode_steps >= self.episode_limit: # Episode limit reached terminated = True if self.continuing_episode: info["episode_limit"] = True self.battles_game += 1 self.timeouts += 1 if self.debug_inputs or self.debug_rewards: print("Total Reward = %.f \n ---------------------" % reward) if self.reward_scale: reward /= (self.max_reward / self.reward_scale_rate) return reward, terminated, info
def reset(self): # Move the camera in any direction # This runs the ResetEpisode trigger built into the map self.decomposed_rewards = [] self.rewards = [] self.last_timestep = self.sc2_env.reset() action = actions.FUNCTIONS.move_camera([0, 0]) self.last_timestep = self.sc2_env.step([action])[0] observation, state, reward, done, info = self.unpack_timestep(self.last_timestep) self.current_obs = observation state = self.int_map_to_onehot(state) state = np.array(state) self.actions_taken = 0 from s2clientprotocol import sc2api_pb2 as sc_pb data = self.sc2_env._controllers[0]._client.send(observation=sc_pb.RequestObservation()) self.sc2_env._controllers[0]._client.send(action=sc_pb.RequestAction()) data = data.observation.raw_data.units damageByZealot = 0 damageToZealot = 0 damageByZergling = 0 damageToZergling = 0 damageByRoach = 0 damageToRoach = 0 damageByStalker = 0 damageToStalker = 0 damageByMarine = 0 damageToMarine = 0 damageByHydralisk = 0 damageToHydralisk = 0 wins = 0 losses = 0 rewards = [] unit_types = [] state = [] # print("#################") for x in data: # print(x.unit_type) if x.unit_type < 1922 and x.unit_type != 51: state.append(x.unit_type) state.append(x.pos.x) state.append(x.pos.y) if x.unit_type == 1922: damageByZealot = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1923: damageToZealot = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1924: damageByZergling = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1925: damageToZergling = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1926: damageByRoach = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1927: damageToRoach = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1928: damageByStalker = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1929: damageToStalker = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1930: damageByMarine = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1931: damageToMarine = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1932: damageByHydralisk = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1933: damageToHydralisk = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1934: wins = x.health rewards.append(x.health) unit_types.append(x.unit_type) if x.unit_type == 1935: # print("LOSSSSSSSESSSSSSSS") losses = x.health rewards.append(x.health) unit_types.append(x.unit_type) return state
def act(self, action): """Send a single action. This is a shortcut for `actions`.""" if action and action.ListFields(): # Skip no-ops. return self.actions(sc_pb.RequestAction(actions=[action]))