def _update_local_extractors(self, base_instance): local_workers = [] local_extractors = collect_units_by_tags(self.all_extractors, base_instance.vb_set) for e in local_extractors: n_unfilled = get_unfilled_workers(e) if n_unfilled == 0: # do nothing when balanced continue if not local_workers: local_workers = collect_units_by_tags(self.all_workers, base_instance.worker_set) # only add a worker when gas-first is True if self.is_gas_first: if n_unfilled > 0: # under-filled: grab a worker harvesting and have it work worker = find_first_if( units=local_workers, f=func_is_harvesting_local_mineral(base_instance)) if worker: return self._harvest_on_extractor(worker, e) if n_unfilled < 0: # over-filled: stop a worker worker = find_first_if(units=local_workers, f=func_is_harvesting_vb(e)) if worker: return act_stop(worker.tag)
def _make_base_coord_system(self, base_instance, dc): base_xy = (base_instance.unit.float_attr.pos_x, base_instance.unit.float_attr.pos_y) local_minerals = collect_units_by_tags(self._all_units, base_instance.mineral_set) local_gas = collect_units_by_tags(self._all_units, base_instance.gas_set) local_res = local_minerals + local_gas res_xy = mean_pos(local_res) return CoordSystem(pos_origin=base_xy, pos_ref=res_xy)
def _update_local_base(self, base_instance): base = base_instance.unit # it must have only ONE base n_unfilled = get_unfilled_workers(base) if n_unfilled == 0: # do nothing when balanced return None local_workers = collect_units_by_tags(self.all_workers, base_instance.worker_set) # only add a worker when mineral-first is True if not self.is_gas_first: if n_unfilled > 0: # under-filled: grab a worker harvesting gas, # and have the worker harvest mineral worker = find_first_if( units=local_workers, f=func_is_harvesting_local_vb(base_instance)) if worker: return self._harvest_on_base(worker, base) if n_unfilled < 0: # over-filled: stop a worker harvesting on mineral worker = find_first_if( units=local_workers, f=func_is_harvesting_local_mineral(base_instance)) if worker: return act_stop(worker.tag) return None
def _harvest_on_base(self, worker, base): # for the local minerals in base's neighborhood, # find the one with largest remaining content base_instance = self.dc.dd.base_pool.bases[base.tag] local_minerals = collect_units_by_tags(self.all_minerals, base_instance.mineral_set) if local_minerals: mineral = max(local_minerals, key=lambda u: u.int_attr.mineral_contents) return act_worker_harvests_on_target(mineral.tag, worker.tag) return None
def _rebalance_workers(self): actions = [] b_from, b_to = self._can_rebalance_workers() if not b_from or not b_to: return actions local_workers = collect_units_by_tags(self.all_workers, b_from.worker_set) workers_migrate = find_n_if(units=local_workers, n=3, f=func_is_harvesting_local_mineral(b_from)) for w in workers_migrate: base = b_to.unit act = self._harvest_on_base(w, base) append_valid_action(actions, act) self._rebalance_last_tried_gameloop = self.dc.sd.obs['game_loop'] return actions