class_docstr: An agent for solving the CollectMineralShards map with feature units.
  
  Controls the two marines independently:
  - select marine
  - move to nearest mineral shard that wasn't the previous target
  - swap marine and repeat
class_docstr_tok: ["An","agent","for","solving","the","CollectMineralShards","map","with","feature","units",".","Controls","the","two","marines","independently",":","-","select","marine","-","move","to","nearest","mineral","shard","that","was","n't","the","previous","target","-","swap","marine","and","repeat"]
code: def step(self, obs):
      super(CollectMineralShardsFeatureUnits, self).step(obs)
      marines = [
          unit
          for unit in obs.observation.feature_units
          if unit.alliance == _PLAYER_SELF
      ]
      if not marines:
          return FUNCTIONS.no_op()
      marine_unit = next(
          (
              m
              for m in marines
              if m.is_selected == self._marine_selected
          ),
          marines[0],
      )
      marine_xy = [marine_unit.x, marine_unit.y]
  
      if not marine_unit.is_selected:
          # Nothing selected or the wrong marine is selected.
          self._marine_selected = True
          return FUNCTIONS.select_point("select", marine_xy)
  
      if FUNCTIONS.Move_screen.id in obs.observation.available_actions:
          # Find and move to the nearest mineral.
          minerals = [
              [unit.x, unit.y]
              for unit in obs.observation.feature_units
              if unit.alliance == _PLAYER_NEUTRAL
          ]
  
          if self._previous_mineral_xy in minerals:
              # Don't go for the same mineral shard as other marine.
              minerals.remove(self._previous_mineral_xy)
  
          if minerals:
              # Find the closest.
              distances = numpy.linalg.norm(
                  numpy.array(minerals) - numpy.array(marine_xy), axis=1
              )
              closest_mineral_xy = minerals[numpy.argmin(distances)]
  
              # Swap to the other marine.
              self._marine_selected = False
              self._previous_mineral_xy = closest_mineral_xy
              return FUNCTIONS.Move_screen("now", closest_mineral_xy)
  
      return FUNCTIONS.no_op()
  
imports: import numpy
  from pysc2.agents import base_agent
  from pysc2.lib import actions
  from pysc2.lib import features
label_desc: Use image node_id 3 for calling the CollectMineralShardsFeatureUnits obj's underlying member method code with example usage: obj.step(obs) and returns: FUNCTIONS, FUNCTIONS, FUNCTIONS, FUNCTIONS