def get_sc2_action(self, gym_action) -> List[FunctionCall]: # Get coords by unravelling action. DQN only supports returning an integer as action. # How unravel works: # Ref: https://www.quora.com/What-is-a-simple-intuitive-example-for-the-unravel_index-in-Python coords = np.unravel_index(gym_action, self.unravel_shape) coords = [(coords[i], coords[i+1]) for i in range(0, len(coords), 2)] # PySC2 uses different conventions for observations (y,x) and actions (x,y) # ::-1 reverses the tuple i.e. (1,2) becomes (2,1) actions = [FUNCTIONS.move_unit(tag, "now", coord[::-1]) for tag, coord in zip(self.state['player_unit_stable_tags'], coords)] return actions
def get_sc2_action(self, gym_action) -> List[FunctionCall]: # Get coords by unravelling action. # How unravel works: # Ref: https://www.quora.com/What-is-a-simple-intuitive-example-for-the-unravel_index-in-Python coords = np.unravel_index(gym_action, (self.screen_shape[0], self.screen_shape[1])) # PySC2 uses different conventions for observations (y,x) and actions (x,y) # ::-1 reverses the tuple i.e. (1,2) becomes (2,1) if self.state['player_unit_stable_tags']: tag_to_move = self.state['player_unit_stable_tags'][ self.state["unit_to_move"]] actions = [FUNCTIONS.move_unit(tag_to_move, "now", coords[::-1])] else: actions = [FUNCTIONS.no_op()] return actions
def get_sc2_action(self, gym_action) -> List[FunctionCall]: # Get coords by unravelling action. DQN only supports returning an integer as action. # How unravel works: # Ref: https://www.quora.com/What-is-a-simple-intuitive-example-for-the-unravel_index-in-Python idx = int(gym_action / self.resolution) coords = gym_action % self.resolution coords = np.unravel_index(coords, self.unravel_shape) coords = (coords[0], coords[1]) target_unit = self.state['player_units_stable'][idx] target_tag = target_unit.tag.item() player_unit_tags = [ unit.tag.item() for unit in self.state["player_units"] ] # .item() to convert numpy.int64 to native python type (int) # PySC2 uses different conventions for observations (y,x) and actions (x,y) # ::-1 reverses the tuple i.e. (1,2) becomes (2,1) if target_tag not in player_unit_tags: actions = [FUNCTIONS.no_op()] else: actions = [FUNCTIONS.move_unit(target_tag, "now", coords[::-1])] return actions
def get_sc2_action(self, gym_action) -> List[FunctionCall]: if len(self.state["player_units_stable"]) == 0: return [FUNCTIONS.no_op()] # Get coords by unravelling action. DQN only supports returning an integer as action. # How unravel works: # Ref: https://www.quora.com/What-is-a-simple-intuitive-example-for-the-unravel_index-in-Python coords = np.unravel_index(gym_action, self.unravel_shape) # Get gym action for each marine gym_action_1, gym_action_2 = (coords[0] % self.number_adjacency, coords[1] % self.number_adjacency) # Get current coordinates for each marine marine_1_stable = self.state["player_units_stable"][0] marine_2_stable = self.state["player_units_stable"][1] # Get tags for each marine marine_1_tag = marine_1_stable.tag.item() marine_2_tag = marine_2_stable.tag.item() # Get target coordinates for each marine marine_1_curr_xy = next((unit.x, unit.y) for unit in self.state["player_units"] if unit.tag.item() == marine_1_tag) marine_2_curr_xy = next((unit.x, unit.y) for unit in self.state["player_units"] if unit.tag.item() == marine_2_tag) def get_target_xy(num, curr_coords): # 0: Up # 1: Down # 2: Left # 3: Right # 4: Up + Left # 5: Up + Right # 6: Down + Left # 7: Down + Right target_xy = list(curr_coords) # Determine target position if num in (0, 4, 5): # Up target_xy[1] = max(0, curr_coords[1] - 1) if num in (1, 6, 7): # Down target_xy[1] = min(self.screen_shape[1] - 1, curr_coords[1] + 1) if num in (2, 4, 6): # Left target_xy[0] = max(0, curr_coords[0] - 1) if num in (3, 5, 7): # Right target_xy[0] = min(self.screen_shape[0] - 1, curr_coords[0] + 1) return tuple(target_xy) marine_1_target_xy = get_target_xy(gym_action_1, marine_1_curr_xy) marine_2_target_xy = get_target_xy(gym_action_2, marine_2_curr_xy) # Assign action functions actions = [ FUNCTIONS.move_unit(marine_1_tag, "now", marine_1_target_xy), FUNCTIONS.move_unit(marine_2_tag, "now", marine_2_target_xy) ] return actions