示例#1
0
    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))
示例#2
0
    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)