Beispiel #1
0
    async def handle_unit(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        unit: Unit,
        th_tag: int,
    ) -> None:
        if self.policy.pass_own_threats:
            air_threats: Units = air_threats_near_bases
            ground_threats: Units = ground_threats_near_bases
        else:
            air_threats: Units = self.enemy_air_threats
            ground_threats: Units = self.enemy_ground_threats

        ths: Units = self.bot.townhalls.ready.tags_in([th_tag])
        if ths:
            th: Unit = ths.first
            if self.priority_enemy_units:
                await self.do_queen_micro(unit, self.priority_enemy_units)
            elif self.policy.defend_against_air and air_threats:
                await self.do_queen_micro(unit, air_threats)
            elif self.policy.defend_against_ground and ground_threats:
                await self.do_queen_micro(unit, ground_threats)
            else:
                if unit.energy >= 25:
                    unit(AbilityId.EFFECT_INJECTLARVA, th)
                # regardless of policy, chase away enemy close to th
                # but if queen gets too far away, walk back to th
                elif unit.distance_to(th) > 7:
                    unit.move(th.position)
                elif self.bot.enemy_units.filter(
                        lambda enemy: enemy.position.distance_to(unit) < 10):
                    unit.attack(
                        self.find_closest_enemy(unit, self.bot.enemy_units))
Beispiel #2
0
 def attack_prime(self, unit: Unit, target: Unit) -> bool:
     if (
             self.WORKERS
     ):  # probably should change this name as it's referring to closest enemy workers to the reaper
         workers = self.WORKERS.filter(
             lambda unit: unit.distance_to(unit.position) < 20)
         if len(workers) > 0:
             prime_target = min(self.WORKERS,
                                key=lambda x: x.health_percentage)
             self.ai.do(unit.attack(prime_target))
             return True
     self.ai.do(unit.attack(target))
     return True
Beispiel #3
0
    async def do_queen_micro(self,
                             queen: Unit,
                             enemy: Units,
                             grid: Optional[np.ndarray] = None) -> None:
        if not queen:
            return

        in_range_enemies: Units = self.bot.enemy_units.in_attack_range_of(
            queen)
        in_range_enemies = in_range_enemies.exclude_type(
            {UnitID.EGG, UnitID.LARVA})
        if in_range_enemies:
            target: Unit = self._get_target_from_in_range_enemies(
                in_range_enemies)
            if target:
                if self.attack_ready(queen, target):
                    queen.attack(target)
                elif self.map_data and grid is not None:
                    await self.move_towards_safe_spot(queen, grid)
                else:
                    distance: float = queen.ground_range + queen.radius + target.radius
                    move_to: Point2 = target.position.towards(queen, distance)
                    if self.bot.in_pathing_grid(move_to):
                        queen.move(move_to)
            else:
                queen.attack(in_range_enemies.center)
        elif enemy:
            target = enemy.closest_to(queen)
            queen.attack(target)
        elif self.bot.all_enemy_units:
            target = self.bot.all_enemy_units.closest_to(queen)
            queen.attack(target)
Beispiel #4
0
 def to_commmand(self, unit: Unit) -> UnitCommand:
     if self.ability is not None:
         action = unit(self.ability, self.target)
     elif self.is_attack:
         action = unit.attack(self.target)
     else:
         action = unit.move(self.target)
     return action
Beispiel #5
0
    def execute_command(self, unit: Unit, command: CombatAction):
        if command.ability is not None:
            action = unit(command.ability, command.target)
        elif command.is_attack:
            action = unit.attack(command.target)
        else:
            action = unit.move(command.target)

        if self.prevent_double_actions(action):
            self.ai.do(action)
Beispiel #6
0
    async def attack_priority_targets(self, dt: Unit, prism: Unit):
        self.knowledge.roles.set_task(UnitTask.Reserved, dt)

        enemy_ground_ACs = self.knowledge.unit_cache.enemy_in_range(
            dt.position,
            15).of_type([UnitTypeId.SPORECRAWLER, UnitTypeId.MISSILETURRET])
        if enemy_ground_ACs:
            target = enemy_ground_ACs.closest_to(dt)
            self.do(dt.attack(target))
            return True

        enemy_bad_AAs = self.knowledge.unit_cache.enemy_in_range(prism.position, 15) \
            .filter(lambda u: u.can_attack_air and not u.is_flying
                              and u.distance_to(prism) <= 10)

        if enemy_bad_AAs:
            target = enemy_bad_AAs.closest_to(dt)
            self.do(dt.attack(target))
            return True

        enemy_workers = self.knowledge.unit_cache.enemy_in_range(
            dt.position, 13).of_type([
                UnitTypeId.SCV, UnitTypeId.PROBE, UnitTypeId.DRONE,
                UnitTypeId.MULE
            ])
        if enemy_workers:
            target = enemy_workers.closest_to(dt)
            self.do(dt.attack(target))
            return True

        enemy_add_ons = self.knowledge.unit_cache.enemy_in_range(
            dt.position, 7).of_type([UnitTypeId.STARPORTTECHLAB])
        if enemy_add_ons:
            target = enemy_add_ons.closest_to(dt)
            self.do(dt.attack(target))
            return True

        enemy_add_ons = self.knowledge.unit_cache.enemy_in_range(
            dt.position, 7).of_type([
                UnitTypeId.FACTORYTECHLAB, UnitTypeId.BARRACKSTECHLAB,
                UnitTypeId.STARPORTREACTOR
            ])
        if enemy_add_ons:
            target = enemy_add_ons.closest_to(dt)
            self.do(dt.attack(target))
            return True

        enemy_ground_AAs = self.knowledge.unit_cache.enemy_in_range(dt.position, 7) \
            .filter(lambda u: u.can_attack_air and not u.is_flying)

        if enemy_ground_AAs:
            target = enemy_ground_AAs.closest_to(dt)
            self.do(dt.attack(target))
            return True

        self.do(dt.attack(self.knowledge.enemy_start_location))
        return True
Beispiel #7
0
    async def do_queen_micro(self, queen: Unit, enemy: Units) -> None:
        if not queen or not enemy:
            return
        in_range_enemies: Units = self.in_attack_range_of(queen, enemy)
        if in_range_enemies:
            if queen.weapon_cooldown == 0:
                target: Unit = self._get_target_from_in_range_enemies(
                    in_range_enemies)
                queen.attack(target)
            else:
                closest_enemy: Unit = self.find_closest_enemy(
                    queen, in_range_enemies)
                distance: float = (queen.ground_range + queen.radius +
                                   closest_enemy.radius)

                queen.move(closest_enemy.position.towards(queen, distance))

        else:
            target = self.find_closest_enemy(queen, enemy)
            queen.attack(target)
Beispiel #8
0
    async def do_queen_micro(self, queen: Unit, enemy: Units) -> None:
        if not queen or not enemy:
            return
        in_range_enemies: Units = enemy.in_attack_range_of(queen)
        if in_range_enemies:
            if queen.weapon_cooldown == 0:
                lowest_hp: Unit = min(
                    in_range_enemies, key=lambda e: (e.health + e.shield, e.tag)
                )
                queen.attack(lowest_hp)
            else:
                closest_enemy: Unit = in_range_enemies.closest_to(queen)
                distance: float = (
                    queen.ground_range + queen.radius + closest_enemy.radius
                )

                queen.move(closest_enemy.position.towards(queen, distance))

        else:
            queen.attack(enemy.center)
Beispiel #9
0
 async def do_queen_offensive_micro(self, queen: Unit,
                                    offensive_pos: Point2) -> None:
     if not queen or not offensive_pos:
         return
     enemy: Units = self.bot.enemy_units.exclude_type(
         {UnitID.MULE, UnitID.EGG, UnitID.LARVA})
     enemy_structures: Units = self.bot.enemy_structures
     queens: Units = self.bot.units(UnitID.QUEEN)
     own_close_queens: Units = queens.filter(
         lambda u: u.distance_to(queen) < 5)
     if enemy:
         in_range_enemies: Units = self.in_attack_range_of(queen, enemy)
         in_range_structures: Units = self.in_attack_range_of(
             queen, enemy_structures)
         if queen.weapon_cooldown == 0:
             if in_range_enemies:
                 target: Unit = self._get_target_from_in_range_enemies(
                     in_range_enemies)
                 queen.attack(target)
             elif in_range_structures:
                 queen.attack(
                     self.find_closest_enemy(queen, in_range_structures))
             else:
                 queen.move(offensive_pos)
         else:
             if own_close_queens.amount <= 3:
                 queen.move(queens.center)
             else:
                 queen.move(offensive_pos)
     else:
         queen.attack(offensive_pos)
Beispiel #10
0
    def follow_path(self, unit: Unit) -> None:
        """
        Follow the path set or set a new one if none exists.

        Args:
            unit (Unit): the unit moving

        Returns:
            None
        """
        if unit.tag not in self.pathing_dict:
            self.add_to_path_dict(unit, self.target)
        else:
            advance_factor = int(unit.movement_speed) + 2
            self.pathing_dict[unit.tag]["step"] += advance_factor
        curr_step = self.pathing_dict[unit.tag]["step"]
        if curr_step >= len(self.pathing_dict[unit.tag]["path"]):
            curr_step = len(self.pathing_dict[unit.tag]["path"]) - 1
        self.do(
            unit.attack(Point2(
                self.pathing_dict[unit.tag]["path"][curr_step])))
        if curr_step == len(self.pathing_dict[unit.tag]["path"]) - 1:
            del self.pathing_dict[unit.tag]
Beispiel #11
0
    async def do_queen_offensive_micro(self, queen: Unit,
                                       offensive_pos: Point2) -> None:
        if not queen or not offensive_pos:
            return
        enemy: Units = self.bot.enemy_units.exclude_type(
            {UnitID.MULE, UnitID.EGG, UnitID.LARVA})
        enemy_structures: Units = self.bot.enemy_structures
        queens: Units = self.bot.units(UnitID.QUEEN)
        own_close_queens: Units = queens.filter(
            lambda u: u.distance_to(queen) < 5)
        if enemy:
            in_range_enemies: Units = enemy.in_attack_range_of(queen)
            in_range_structures: Units = enemy_structures.in_attack_range_of(
                queen)
            if in_range_enemies:
                target: Unit = self._get_target_from_in_range_enemies(
                    in_range_enemies)
                if self.attack_ready(queen, target):
                    queen.attack(target)
                else:
                    # loose queen_control should try to rejoin the queen pack
                    if own_close_queens.amount <= 3:
                        queen.move(queens.center)
                    # otherwise move forward between attacks, since Queen is slow and can get stuck behind each other
                    else:
                        queen.move(offensive_pos)
            elif in_range_structures:
                target: Unit = self._get_target_from_in_range_enemies(
                    in_range_structures)
                if self.attack_ready(queen, target):
                    queen.attack(target)
                else:
                    if own_close_queens.amount <= 3:
                        queen.move(queens.center)
                    else:
                        queen.move(offensive_pos)
            else:
                queen.move(offensive_pos)

        else:
            queen.attack(offensive_pos)
Beispiel #12
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)
Beispiel #13
0
 async def execute_command(self, unit: Unit, command: CombatAction):
     if command.is_attack:
         self.do(unit.attack(command.target))
     else:
         self.do(unit.move(command.target))