async def execute_order(self, unit: Unit): assert ( unit.tag in self.knowledge.building_solver.structure_target_move_location ), f"{unit.tag}\n{self.knowledge.building_solver.structure_target_move_location}" assert isinstance(unit, Unit), f"{unit}" unit_is_busy: bool = not (unit.is_idle or unit.is_moving or unit.is_using_ability(AbilityId.LIFT) or unit.is_using_ability(AbilityId.LAND)) if unit_is_busy: return land_location: Point2 = self.knowledge.building_solver.structure_target_move_location[ unit.tag] # Structure has arrived and landed, done! if unit.position == land_location and not unit.is_flying and not unit.is_using_ability( AbilityId.LIFT): self.knowledge.building_solver.structure_target_move_location.pop( unit.tag) # Structure is landed but not in right position: lift elif unit.position != land_location and not unit.is_flying and unit.is_idle: self.do(unit(AbilityId.LIFT)) # Structure is flying but not close to land location, order move command elif (unit.is_flying and land_location.distance_to(unit) > 2 and (not unit.is_moving or isinstance(unit.order_target, Point2) and unit.order_target != land_location) and not unit.is_using_ability(AbilityId.LIFT)): self.do(unit.move(land_location)) # Structure is close to land location but flying, order land command elif unit.is_flying and land_location.distance_to( unit) < 2 and not unit.is_using_ability(AbilityId.LAND): # TODO If land location is blocked, attempt to find another land location instead self.do(unit(AbilityId.LAND, land_location))
async def _manage_nydus_attack( self, canal: Unit, network: Unit, unit: Unit, unit_distance_to_target: float, grid: Optional[np.ndarray] = None, ) -> None: """ Get a Queen through the nydus and out the other side! @param canal: The canal is the worm placed on the map @param network: This is built at home @param unit: In this case, the queen we want to move through @param unit_distance_to_target: @return: """ # user does not have some predefined nydus logic, so we unload the proxy canal for them if len(canal.passengers_tags) > 0 and not self.policy.nydus_move_function: canal(AbilityId.UNLOADALL_NYDUSWORM) # worm has popped somewhere, but we are waiting for it to finish, move next to network ready to go # usually we want queens last in anyway, so this gives a chance for other units to enter the nydus if not canal.is_ready and unit.distance_to(canal) > 30: unit.move(network.position) # both canal and network must be ready else: # unit needs to go through the nydus if unit_distance_to_target > 45 and unit.distance_to(network) < 70: # user has some custom code for moving units through nydus if self.policy.nydus_move_function: self.policy.nydus_move_function(unit, self.policy.nydus_target) # manage this ourselves else: network(AbilityId.LOAD_NYDUSNETWORK, unit) # else queen should micro on the other side # remember that all queens already have transfuse code baked in else: # queen has enough energy for a transfuse and a tumor, so put a tumor down where she currently is if unit.energy >= 75 and self.bot.has_creep(unit.position): # check if there are too many tumors already tumors: Units = self.bot.structures.filter( lambda s: s.type_id in {UnitID.CREEPTUMORBURROWED, UnitID.CREEPTUMORQUEEN} and s.distance_to(unit) < 15 ) if tumors.amount < 7: unit(AbilityId.BUILD_CREEPTUMOR_QUEEN, unit.position) if unit.is_using_ability(AbilityId.BUILD_CREEPTUMOR_QUEEN): return # get priority target, ie: target the flying enemies first target: Optional[Unit] = self._get_target_from_close_enemies(unit) if target: if self.attack_ready(unit, target): unit.attack(target) elif self.map_data and grid is not None: await self.move_towards_safe_spot(unit, grid) else: distance: float = ( unit.ground_range + unit.radius + target.radius ) move_to: Point2 = target.position.towards(unit, distance) if self.bot.in_pathing_grid(move_to): unit.move(move_to) # check if there is anything around here to attack, # if not then we attack the general attack target the user has passed in # TODO: In the future, this is where we would want the queens to come home # At the moment a nydus queen is on a one way trip elif ( self.enemy_ground_units_near_nydus_target.amount == 0 and self.enemy_flying_units_near_nydus_target.amount == 0 ): await self.do_queen_offensive_micro(unit, self.policy.attack_target) # there are targets, but nothing in range so move towards the nydus target else: unit.move(self.policy.nydus_target)