def step(self, obs):
    super(SparseAgent, self).step(obs)
    if obs.last():
        reward = obs.reward
        self.qlearn.learn(str(self.previous_state), self.previous_action, reward, 'terminal')
        self.qlearn.q_table.to_pickle((DATA_FILE + '.gz'), 'gzip')
        self.previous_action = None
        self.previous_state = None
        self.move_number = 0
        return actions.FunctionCall(_NO_OP, [])
    unit_type = obs.observation['screen'][_UNIT_TYPE]
    if obs.first():
        (player_y, player_x) = (obs.observation['feature_minimap'][_PLAYER_RELATIVE] == _PLAYER_SELF).nonzero()
        self.base_top_left = (1 if (player_y.any() and (player_y.mean() <= 31)) else 0)
        (self.cc_y, self.cc_x) = (unit_type == _TERRAN_COMMANDCENTER).nonzero()
    (cc_y, cc_x) = (unit_type == _TERRAN_COMMANDCENTER).nonzero()
    cc_count = (1 if cc_y.any() else 0)
    (depot_y, depot_x) = (unit_type == _TERRAN_SUPPLY_DEPOT).nonzero()
    supply_depot_count = int(round((len(depot_y) / 69)))
    (barracks_y, barracks_x) = (unit_type == _TERRAN_BARRACKS).nonzero()
    barracks_count = int(round((len(barracks_y) / 137)))
    if (self.move_number == 0):
        self.move_number += 1
        current_state = np.zeros(8)
        current_state[0] = cc_count
        current_state[1] = supply_depot_count
        current_state[2] = barracks_count
        current_state[3] = obs.observation['player'][_ARMY_SUPPLY]
        hot_squares = np.zeros(4)
        (enemy_y, enemy_x) = (obs.observation['feature_minimap'][_PLAYER_RELATIVE] == _PLAYER_HOSTILE).nonzero()
        for i in range(0, len(enemy_y)):
            y = int(math.ceil(((enemy_y[i] + 1) / 32)))
            x = int(math.ceil(((enemy_x[i] + 1) / 32)))
            hot_squares[(((y - 1) * 2) + (x - 1))] = 1
        if (not self.base_top_left):
            hot_squares = hot_squares[::(- 1)]
        for i in range(0, 4):
            current_state[(i + 4)] = hot_squares[i]
        if (self.previous_action is not None):
            self.qlearn.learn(str(self.previous_state), self.previous_action, 0, str(current_state))
        rl_action = self.qlearn.choose_action(str(current_state))
        self.previous_state = current_state
        self.previous_action = rl_action
        (smart_action, x, y) = self.splitAction(self.previous_action)
        if ((smart_action == ACTION_BUILD_BARRACKS) or (smart_action == ACTION_BUILD_SUPPLY_DEPOT)):
            (unit_y, unit_x) = (unit_type == _TERRAN_SCV).nonzero()
            if unit_y.any():
                i = random.randint(0, (len(unit_y) - 1))
                target = [unit_x[i], unit_y[i]]
                return actions.FunctionCall(_SELECT_POINT, [_NOT_QUEUED, target])
        elif (smart_action == ACTION_BUILD_MARINE):
            if barracks_y.any():
                i = random.randint(0, (len(barracks_y) - 1))
                target = [barracks_x[i], barracks_y[i]]
                return actions.FunctionCall(_SELECT_POINT, [_SELECT_ALL, target])
        elif (smart_action == ACTION_ATTACK):
            if (_SELECT_ARMY in obs.observation['available_actions']):
                return actions.FunctionCall(_SELECT_ARMY, [_NOT_QUEUED])
    elif (self.move_number == 1):
        self.move_number += 1
        (smart_action, x, y) = self.splitAction(self.previous_action)
        if (smart_action == ACTION_BUILD_SUPPLY_DEPOT):
            if ((supply_depot_count < 2) and (_BUILD_SUPPLY_DEPOT in obs.observation['available_actions'])):
                if self.cc_y.any():
                    if (supply_depot_count == 0):
                        target = self.transformDistance(round(self.cc_x.mean()), (- 35), round(self.cc_y.mean()), 0)
                    elif (supply_depot_count == 1):
                        target = self.transformDistance(round(self.cc_x.mean()), (- 25), round(self.cc_y.mean()), (- 25))
                    return actions.FunctionCall(_BUILD_SUPPLY_DEPOT, [_NOT_QUEUED, target])
        elif (smart_action == ACTION_BUILD_BARRACKS):
            if ((barracks_count < 2) and (_BUILD_BARRACKS in obs.observation['available_actions'])):
                if self.cc_y.any():
                    if (barracks_count == 0):
                        target = self.transformDistance(round(self.cc_x.mean()), 15, round(self.cc_y.mean()), (- 9))
                    elif (barracks_count == 1):
                        target = self.transformDistance(round(self.cc_x.mean()), 15, round(self.cc_y.mean()), 12)
                    return actions.FunctionCall(_BUILD_BARRACKS, [_NOT_QUEUED, target])
        elif (smart_action == ACTION_BUILD_MARINE):
            if (_TRAIN_MARINE in obs.observation['available_actions']):
                return actions.FunctionCall(_TRAIN_MARINE, [_QUEUED])
        elif (smart_action == ACTION_ATTACK):
            do_it = True
            if ((len(obs.observation['single_select']) > 0) and (obs.observation['single_select'][0][0] == _TERRAN_SCV)):
                do_it = False
            if ((len(obs.observation['multi_select']) > 0) and (obs.observation['multi_select'][0][0] == _TERRAN_SCV)):
                do_it = False
            if (do_it and (_ATTACK_MINIMAP in obs.observation['available_actions'])):
                x_offset = random.randint((- 1), 1)
                y_offset = random.randint((- 1), 1)
                return actions.FunctionCall(_ATTACK_MINIMAP, [_NOT_QUEUED, self.transformLocation((int(x) + (x_offset * 8)), (int(y) + (y_offset * 8)))])
    elif (self.move_number == 2):
        self.move_number = 0
        (smart_action, x, y) = self.splitAction(self.previous_action)
        if ((smart_action == ACTION_BUILD_BARRACKS) or (smart_action == ACTION_BUILD_SUPPLY_DEPOT)):
            if (_HARVEST_GATHER in obs.observation['available_actions']):
                (unit_y, unit_x) = (unit_type == _NEUTRAL_MINERAL_FIELD).nonzero()
                if unit_y.any():
                    i = random.randint(0, (len(unit_y) - 1))
                    m_x = unit_x[i]
                    m_y = unit_y[i]
                    target = [int(m_x), int(m_y)]
                    return actions.FunctionCall(_HARVEST_GATHER, [_QUEUED, target])
    return actions.FunctionCall(_NO_OP, [])
def step(self, obs):
    super(SparseAgent, self).step(obs)
    if obs.last():
        reward = obs.reward
        self.qlearn.learn(str(self.previous_state), self.previous_action, reward, 'terminal')
        self.qlearn.q_table.to_pickle((DATA_FILE + '.gz'), 'gzip')
        self.previous_action = None
        self.previous_state = None
        self.move_number = 0
        return actions.FunctionCall(_NO_OP, [])
    unit_type = obs.observation['screen'][_UNIT_TYPE]
    if obs.first():
        (player_y, player_x) = (obs.observation['feature_minimap'][_PLAYER_RELATIVE] == _PLAYER_SELF).nonzero()
        self.base_top_left = (1 if (player_y.any() and (player_y.mean() <= 31)) else 0)
        (self.cc_y, self.cc_x) = (unit_type == _TERRAN_COMMANDCENTER).nonzero()
    (cc_y, cc_x) = (unit_type == _TERRAN_COMMANDCENTER).nonzero()
    cc_count = (1 if cc_y.any() else 0)
    (depot_y, depot_x) = (unit_type == _TERRAN_SUPPLY_DEPOT).nonzero()
    supply_depot_count = int(round((len(depot_y) / 69)))
    (barracks_y, barracks_x) = (unit_type == _TERRAN_BARRACKS).nonzero()
    barracks_count = int(round((len(barracks_y) / 137)))
    if (self.move_number == 0):
        self.move_number += 1
        current_state = np.zeros(8)
        current_state[0] = cc_count
        current_state[1] = supply_depot_count
        current_state[2] = barracks_count
        current_state[3] = obs.observation['player'][_ARMY_SUPPLY]
        hot_squares = np.zeros(4)
        (enemy_y, enemy_x) = (obs.observation['feature_minimap'][_PLAYER_RELATIVE] == _PLAYER_HOSTILE).nonzero()
        for i in range(0, len(enemy_y)):
            y = int(math.ceil(((enemy_y[i] + 1) / 32)))
            x = int(math.ceil(((enemy_x[i] + 1) / 32)))
            hot_squares[(((y - 1) * 2) + (x - 1))] = 1
        if (not self.base_top_left):
            hot_squares = hot_squares[::(- 1)]
        for i in range(0, 4):
            current_state[(i + 4)] = hot_squares[i]
        if (self.previous_action is not None):
            self.qlearn.learn(str(self.previous_state), self.previous_action, 0, str(current_state))
        rl_action = self.qlearn.choose_action(str(current_state))
        self.previous_state = current_state
        self.previous_action = rl_action
        (smart_action, x, y) = self.splitAction(self.previous_action)
        if ((smart_action == ACTION_BUILD_BARRACKS) or (smart_action == ACTION_BUILD_SUPPLY_DEPOT)):
            (unit_y, unit_x) = (unit_type == _TERRAN_SCV).nonzero()
            if unit_y.any():
                i = random.randint(0, (len(unit_y) - 1))
                target = [unit_x[i], unit_y[i]]
                return actions.FunctionCall(_SELECT_POINT, [_NOT_QUEUED, target])
        elif (smart_action == ACTION_BUILD_MARINE):
            if barracks_y.any():
                i = random.randint(0, (len(barracks_y) - 1))
                target = [barracks_x[i], barracks_y[i]]
                return actions.FunctionCall(_SELECT_POINT, [_SELECT_ALL, target])
        elif (smart_action == ACTION_ATTACK):
            if (_SELECT_ARMY in obs.observation['available_actions']):
                return actions.FunctionCall(_SELECT_ARMY, [_NOT_QUEUED])
    elif (self.move_number == 1):
        self.move_number += 1
        (smart_action, x, y) = self.splitAction(self.previous_action)
        if (smart_action == ACTION_BUILD_SUPPLY_DEPOT):
            if ((supply_depot_count < 2) and (_BUILD_SUPPLY_DEPOT in obs.observation['available_actions'])):
                if self.cc_y.any():
                    if (supply_depot_count == 0):
                        target = self.transformDistance(round(self.cc_x.mean()), (- 35), round(self.cc_y.mean()), 0)
                    elif (supply_depot_count == 1):
                        target = self.transformDistance(round(self.cc_x.mean()), (- 25), round(self.cc_y.mean()), (- 25))
                    return actions.FunctionCall(_BUILD_SUPPLY_DEPOT, [_NOT_QUEUED, target])
        elif (smart_action == ACTION_BUILD_BARRACKS):
            if ((barracks_count < 2) and (_BUILD_BARRACKS in obs.observation['available_actions'])):
                if self.cc_y.any():
                    if (barracks_count == 0):
                        target = self.transformDistance(round(self.cc_x.mean()), 15, round(self.cc_y.mean()), (- 9))
                    elif (barracks_count == 1):
                        target = self.transformDistance(round(self.cc_x.mean()), 15, round(self.cc_y.mean()), 12)
                    return actions.FunctionCall(_BUILD_BARRACKS, [_NOT_QUEUED, target])
        elif (smart_action == ACTION_BUILD_MARINE):
            if (_TRAIN_MARINE in obs.observation['available_actions']):
                return actions.FunctionCall(_TRAIN_MARINE, [_QUEUED])
        elif (smart_action == ACTION_ATTACK):
            do_it = True
            if ((len(obs.observation['single_select']) > 0) and (obs.observation['single_select'][0][0] == _TERRAN_SCV)):
                do_it = False
            if ((len(obs.observation['multi_select']) > 0) and (obs.observation['multi_select'][0][0] == _TERRAN_SCV)):
                do_it = False
            if (do_it and (_ATTACK_MINIMAP in obs.observation['available_actions'])):
                x_offset = random.randint((- 1), 1)
                y_offset = random.randint((- 1), 1)
                return actions.FunctionCall(_ATTACK_MINIMAP, [_NOT_QUEUED, self.transformLocation((int(x) + (x_offset * 8)), (int(y) + (y_offset * 8)))])
    elif (self.move_number == 2):
        self.move_number = 0
        (smart_action, x, y) = self.splitAction(self.previous_action)
        if ((smart_action == ACTION_BUILD_BARRACKS) or (smart_action == ACTION_BUILD_SUPPLY_DEPOT)):
            if (_HARVEST_GATHER in obs.observation['available_actions']):
                (unit_y, unit_x) = (unit_type == _NEUTRAL_MINERAL_FIELD).nonzero()
                if unit_y.any():
                    i = random.randint(0, (len(unit_y) - 1))
                    m_x = unit_x[i]
                    m_y = unit_y[i]
                    target = [int(m_x), int(m_y)]
                    return actions.FunctionCall(_HARVEST_GATHER, [_QUEUED, target])
    return actions.FunctionCall(_NO_OP, [])