def move_phoenix(self, phoenix: Unit):
        enemy_main = self.knowledge.enemy_expansion_zones[0].center_location
        if phoenix.distance_to(enemy_main) <= 10:
            self.reached_enemy_main = True

        if not self.reached_enemy_main:
            target = self.select_target()
            self.do(phoenix.move(target))

            if target != self.last_target:
                self.last_target = target
                self.print(f"scouting {target}, interval {self.time_interval}")
        else:
            # This else makes it scout around possible main tech positions
            if self.last_target is None:
                self.last_target = self.select_target()

            if self.ai.enemy_race == Race.Protoss:
                new_target = self.knowledge.enemy_expansion_zones[
                    0].behind_mineral_position_center.towards(
                        self.knowledge.enemy_expansion_zones[0].
                        mineral_line_center, 20).random_on_distance(7)
                if phoenix.distance_to(self.last_target) <= 3:
                    self.do(phoenix.move(new_target))
                    self.last_target = new_target
            elif self.ai.enemy_race == Race.Terran:
                new_target = self.knowledge.enemy_expansion_zones[
                    1].behind_mineral_position_center.towards(
                        self.knowledge.enemy_expansion_zones[1].
                        mineral_line_center, 20).random_on_distance(7)
                if phoenix.distance_to(self.last_target) <= 3:
                    self.do(phoenix.move(new_target))
                    self.last_target = new_target
Ejemplo n.º 2
0
    async def handle_unit(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        unit: Unit,
        th_tag: int = 0,
    ) -> 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

        transfuse_target: Unit = self.get_transfuse_target(unit.position)
        self.used_transfuse_this_step: bool = False
        if (transfuse_target and transfuse_target is not unit
                and not self.used_transfuse_this_step):
            unit(AbilityId.TRANSFUSION_TRANSFUSION, transfuse_target)
            self.used_transfuse_this_step = True
        elif self.priority_enemy_units:
            await self.do_queen_micro(unit, self.priority_enemy_units)
        elif self.policy.attack_condition():
            await self.do_queen_offensive_micro(unit,
                                                self.policy.attack_target)
        elif self.policy.defend_against_ground and ground_threats:
            await self.do_queen_micro(unit, ground_threats)
        elif self.policy.defend_against_air and air_threats:
            await self.do_queen_micro(unit, air_threats)
        elif unit.distance_to(self.policy.rally_point) > 12:
            unit.move(self.policy.rally_point)
Ejemplo n.º 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)
Ejemplo n.º 4
0
    async def _control_inject_queen_near_base(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        queen: Unit,
        townhall: Unit,
        grid: Optional[np.ndarray] = None,
    ) -> None:
        """
        Between injects, we want the Queen to have the following behavior:
        - Attack any enemy that gets too close
        - Move the Queen back if she goes too far from the townhall
        - Stay out of the mineral line, incase bot has custom mineral gathering (don't block workers)
        """
        # don't do anything else, just move the queen back
        if queen.distance_to(townhall) > 8:
            queen.move(townhall)
            return

        close_threats: Units = Units([], self.bot)
        # we can only have close threats if enemy are near our bases in the first place
        # so save calculation otherwise
        if air_threats_near_bases or ground_threats_near_bases:
            close_threats = self.bot.enemy_units.filter(
                lambda enemy: enemy.position.distance_to(townhall) < 12)

        if close_threats:
            await self.do_queen_micro(queen, close_threats, grid)
        # every now and then, check queen is not in the mineral field blocking workers
        elif self.bot.state.game_loop % 32 == 0:
            close_mfs: Units = self.bot.mineral_field.filter(
                lambda mf: mf.distance_to(townhall) < 8)
            # make a small adjustment away from the minerals
            if close_mfs and queen.distance_to(close_mfs.center) < 6:
                queen.move(queen.position.towards(close_mfs.center, -1))
Ejemplo n.º 5
0
    async def on_unit_created(self, unit: Unit):
        """Send Overlords and lings to scouting spots."""
        if unit.type_id == UnitTypeId.OVERLORD:
            if self.hidden_ol_index + 1 >= len(self.hidden_ol_spots):
                return
            else:
                # if self.hidden_ol_index == 0:
                #     self.do(
                #         unit.move(
                #             self.knowledge.zone_manager.enemy_expansion_zones[1].center_location.towards(
                #                 self.knowledge.ai.game_info.map_center, 11
                #             )
                #         )
                #     )
                #     self.hidden_ol_index += 1
                if self.hidden_ol_index == 1:
                    self.do(unit.move(self.nydus_spot))
                    self.hidden_ol_index += 1
                else:
                    self.do(
                        unit.move(self.hidden_ol_spots[self.hidden_ol_index],
                                  queue=True))
                    self.hidden_ol_index += 1

        elif unit.type_id == UnitTypeId.ZERGLING:
            if self.scout_ling_count in self.ling_scout_location:
                self.do(
                    unit.move(self.ling_scout_location[self.scout_ling_count]))
                self.knowledge.roles.set_task(UnitTask.Scouting, unit)
                self.scout_ling_count += 1
Ejemplo n.º 6
0
    async def handle_unit(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        priority_enemy_units: Units,
        unit: Unit,
        th_tag: int = 0,
        grid: Optional[np.ndarray] = None,
        nydus_networks: Optional[Units] = None,
        nydus_canals: Optional[Units] = None,
    ) -> None:

        if priority_enemy_units:
            await self.do_queen_micro(unit, priority_enemy_units, grid)
        elif self.policy.attack_condition():
            await self.do_queen_offensive_micro(unit,
                                                self.policy.attack_target)
        elif self.policy.defend_against_ground and ground_threats_near_bases:
            await self.do_queen_micro(unit, ground_threats_near_bases, grid)
        elif self.policy.defend_against_air and air_threats_near_bases:
            await self.do_queen_micro(unit, air_threats_near_bases, grid)
        elif (self.map_data and grid is not None
              and not self.is_position_safe(grid, unit.position)):
            await self.move_towards_safe_spot(unit, grid)
        elif unit.distance_to(self.policy.rally_point) > 12:
            unit.move(self.policy.rally_point)
Ejemplo n.º 7
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))
Ejemplo n.º 8
0
    async def move_towards_safe_spot(self,
                                     unit: Unit,
                                     grid: np.ndarray,
                                     radius: int = 7) -> None:

        safe_spot: Point2 = self.find_closest_safe_spot(
            unit.position, grid, radius)
        path: List[Point2] = self.map_data.pathfind(unit.position,
                                                    safe_spot,
                                                    grid,
                                                    sensitivity=6)
        if path:
            unit.move(path[0])
Ejemplo n.º 9
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))
Ejemplo n.º 10
0
    def move_phoenix(self, phoenix: Unit):
        target = self.select_target()
        self.do(phoenix.move(target))

        if target != self.last_target:
            self.last_target = target
            self.print(f"scouting {target}, interval {self.time_interval}")
Ejemplo n.º 11
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
Ejemplo n.º 12
0
 async def on_unit_created(self, unit: Unit) -> None:
     # find new overlords a position to scout
     if self.ol_spots_index + 1 == len(self.hidden_ol_spots):
         return
     if unit.name == "Overlord":
         ol_spot = self.hidden_ol_spots[self.ol_spots_index]
         self.do(unit.move(ol_spot))
         self.ol_spots_index += 1
Ejemplo n.º 13
0
 async def on_unit_created(self, unit: Unit):
     # Scout with second ovie
     if unit.type_id == OVERLORD:
         if self.units(OVERLORD).amount == 2:
             positions = []
             if self.enemy_race == Race.Protoss:
                 # Scout for cannon rush
                 positions.append(self.own_natural)
             else:
                 # Scout for proxy rax
                 for expansion in self.expansion_locations:
                     if expansion == self.start_location or expansion == self.own_natural:
                         continue
                     if expansion.distance_to(
                             self.start_location
                     ) < 50 or expansion.distance_to(self.own_natural) < 50:
                         positions.append(expansion)
             for position in positions:
                 await self.do(unit.move(position, True))
         elif self.units(OVERLORD).amount == 3:
             await self.do(
                 unit.move(
                     self.enemy_natural.closest(
                         list(self.enemy_expansions_not_main_or_nat)),
                     True))
         elif self.units(OVERLORD).amount == 4:
             closest = self.enemy_natural.closest(
                 list(self.enemy_expansions_not_main_or_nat))
             exps: List[Point2] = list(
                 self.enemy_expansions_not_main_or_nat)
             if closest in exps:
                 exps.remove(closest)
             await self.do(unit.move(self.enemy_natural.closest(exps),
                                     True))
         else:
             # Randomly spread overlords
             if not self.unit_manager.spread_overlords.tags_in({unit.tag
                                                                }).exists:
                 random_position = Point2(
                     (random.randint(0, self._game_info.pathing_grid.width -
                                     1),
                      random.randint(
                          0, self._game_info.pathing_grid.height - 1)))
                 await self.do(unit.move(random_position))
         self.unit_manager.spread_overlords.append(unit)
Ejemplo n.º 14
0
 async def on_unit_created(self, unit: Unit):
     if self.knowledge.ai is not None:
         await self.knowledge.on_unit_created(unit)
     if unit.type_id == UnitTypeId.OVERLORD:
         if self.ol_spot_index + 1 >= len(self.hidden_ol_spots):
             return
         else:
             self.do(unit.move(self.hidden_ol_spots[self.ol_spot_index]))
             self.ol_spot_index += 1
Ejemplo n.º 15
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)
Ejemplo n.º 16
0
    async def spread_creep(self, queen: Unit,
                           grid: Optional[np.ndarray]) -> None:
        if self.creep_target_index >= len(self.creep_targets):
            self.creep_target_index = 0

        if self.first_tumor and self.policy.first_tumor_position:
            queen(AbilityId.BUILD_CREEPTUMOR_QUEEN,
                  self.policy.first_tumor_position)
            # retry a few times, sometimes queen gets blocked when spawning
            if self.first_tumor_retry_attempts > 5:
                self.first_tumor = False
            self.first_tumor_retry_attempts += 1
            return

        should_lay_tumor: bool = True
        # if using map_data, creep will follow ground path to the targets
        if self.map_data:
            if grid is None:
                grid = self.map_data.get_pyastar_grid()
            pos: Point2 = self._find_closest_to_target_using_path(
                self.creep_targets[self.creep_target_index], self.creep_map,
                grid)

        else:
            pos: Point2 = self._find_closest_to_target(
                self.creep_targets[self.creep_target_index], self.creep_map)

        if (not pos or (self.policy.should_tumors_block_expansions is False
                        and self.position_blocks_expansion(pos))
                or self.position_near_enemy_townhall(pos)
                or self.position_near_nydus_worm(pos)
                or self._existing_tumors_too_close(pos)):
            should_lay_tumor = False

        if should_lay_tumor:
            queen(AbilityId.BUILD_CREEPTUMOR_QUEEN, pos)
            self.pending_positions.append((pos, self.bot.time))

        # can't lay tumor right now, go back home
        elif queen.distance_to(self.policy.rally_point) > 7:
            queen.move(self.policy.rally_point)

        self.creep_target_index += 1
Ejemplo n.º 17
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)
Ejemplo n.º 18
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)
Ejemplo n.º 19
0
    async def handle_unit(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        unit: Unit,
        priority_enemy_units: Units,
        th_tag: int = 0,
    ) -> None:

        if priority_enemy_units:
            await self.do_queen_micro(unit, priority_enemy_units)
        elif self.policy.attack_condition():
            await self.do_queen_offensive_micro(unit,
                                                self.policy.attack_target)
        elif self.policy.defend_against_ground and ground_threats_near_bases:
            await self.do_queen_micro(unit, ground_threats_near_bases)
        elif self.policy.defend_against_air and air_threats_near_bases:
            await self.do_queen_micro(unit, air_threats_near_bases)
        elif unit.distance_to(self.policy.rally_point) > 12:
            unit.move(self.policy.rally_point)
Ejemplo n.º 20
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)
Ejemplo n.º 21
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)
Ejemplo n.º 22
0
    async def handle_unit(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        unit: Unit,
        priority_enemy_units: Units,
        th_tag: int = 0,
    ) -> None:

        should_spread_creep: bool = self._check_queen_can_spread_creep(unit)
        self.creep_targets = self.policy.creep_targets

        if priority_enemy_units:
            await self.do_queen_micro(unit, priority_enemy_units)
        elif (self.policy.defend_against_air and air_threats_near_bases
              and not should_spread_creep):
            await self.do_queen_micro(unit, air_threats_near_bases)
        elif (self.policy.defend_against_ground and ground_threats_near_bases
              and not should_spread_creep):
            await self.do_queen_micro(unit, ground_threats_near_bases)
        elif self.bot.enemy_units and self.bot.enemy_units.filter(
                # custom filter to replace in_attack_range_of so that it can be used with memory units
                lambda enemy: enemy.position.distance_to(unit) < max(
                    unit.air_range, unit.ground_range)):
            unit.move(self.policy.rally_point)
        elif (unit.energy >= 25 and len(unit.orders) == 0
              and self.creep_coverage < self.policy.target_perc_coverage):
            await self.spread_creep(unit)
        elif unit.distance_to(self.policy.rally_point) > 7:
            if len(unit.orders) > 0:
                if unit.orders[0].ability.button_name != "CreepTumor":
                    unit.move(self.policy.rally_point)
            elif len(unit.orders) == 0:
                unit.move(self.policy.rally_point)
Ejemplo n.º 23
0
 async def harass_command(self, dt: Unit, prism: Unit):
     self.knowledge.roles.set_task(UnitTask.Reserved, dt)
     if self.is_revealed_by_enemy(dt):
         if dt.distance_to(
                 prism) <= 5 and prism.shield_health_percentage >= 0.4:
             self.do(dt.smart(prism))
             return True
         else:
             self.do(dt.move(prism))
             return True
     else:
         await self.attack_priority_targets(dt, prism)
     return True
Ejemplo n.º 24
0
    async def up_and_down(self, harass_prism: Unit):
        self.knowledge.roles.set_task(UnitTask.Reserved, harass_prism)

        if harass_prism.has_buff(BuffId.LOCKON):
            cyclones = self.knowledge.unit_cache.enemy_in_range(
                harass_prism.position3d, 20).of_type(UnitTypeId.CYCLONE)
            if cyclones:
                closest_cyclone = cyclones.closest_to(harass_prism)
                position = harass_prism.position.towards(closest_cyclone, -18)
                self.do(harass_prism.move(position))
                return True

        if harass_prism.health_percentage <= 0.2:
            self.do(
                harass_prism(AbilityId.UNLOADALLAT_WARPPRISM,
                             harass_prism.position))
            return True

        if harass_prism.distance_to(self.get_enemy_main_platform()) <= 12 and \
                (not self.is_revealed_by_enemy(harass_prism)) and \
                harass_prism.cargo_used > 0:
            self.do(
                harass_prism(AbilityId.UNLOADALLAT_WARPPRISM,
                             harass_prism.position))
            return True
        target = self.get_enemy_main_platform()

        dts = self.knowledge.unit_cache.by_tags(
            [self.ninja_dt_1_tag, self.ninja_dt_2_tag])
        if dts.exists and harass_prism.cargo_used < 4:
            target = dts.center
            for dt in dts:
                if self.is_revealed_by_enemy(dt):
                    self.do(harass_prism.move(dt.position))
                    return True
        self.prism_evasive_move_to(harass_prism, target)
        return True
Ejemplo n.º 25
0
    async def attack_command(self, unit: Unit, prism: Unit):
        self.knowledge.roles.set_task(UnitTask.Reserved, unit)
        if self.is_revealed_by_enemy(unit):
            if unit.distance_to(
                    prism) <= 8 and prism.shield_health_percentage >= 0.4:
                self.do(unit.smart(prism))
                return True

            else:
                base = self.knowledge.own_main_zone.center_location
                self.do(unit.move(base))
                return True

        else:
            await self.attack_priority_targets(unit, prism)
        return True
Ejemplo n.º 26
0
    async def handle_unit(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        unit: Unit,
        th_tag: int = 0,
    ) -> 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

        should_spread_creep: bool = self._check_queen_can_spread_creep(unit)
        self.creep_targets = self.policy.creep_targets
        transfuse_target: Unit = self.get_transfuse_target(unit.position)
        # allow transfuse if energy has built up
        if unit.energy >= 50 and transfuse_target and transfuse_target is not unit:
            unit(AbilityId.TRANSFUSION_TRANSFUSION, transfuse_target)
        elif self.priority_enemy_units:
            await self.do_queen_micro(unit, self.priority_enemy_units)
        elif self.policy.defend_against_air and air_threats and not should_spread_creep:
            await self.do_queen_micro(unit, air_threats)
        elif (
            self.policy.defend_against_ground
            and ground_threats
            and not should_spread_creep
        ):
            await self.do_queen_micro(unit, ground_threats)
        elif self.bot.enemy_units and self.bot.enemy_units.filter(
            # custom filter to replace in_attack_range_of so that it can be used with memory units
            lambda enemy: enemy.position.distance_to(unit)
            < max(unit.air_range, unit.ground_range)
        ):
            unit.move(self.policy.rally_point)
        elif (
            unit.energy >= 25
            and len(unit.orders) == 0
            and self.creep_coverage < self.policy.target_perc_coverage
        ):
            await self.spread_creep(unit)
        elif unit.distance_to(self.policy.rally_point) > 7:
            if len(unit.orders) > 0:
                if unit.orders[0].ability.button_name != "CreepTumor":
                    unit.move(self.policy.rally_point)
            elif len(unit.orders) == 0:
                unit.move(self.policy.rally_point)
Ejemplo n.º 27
0
 def dodge_effects(self, unit: Unit) -> bool:
     """Dodge any effects"""
     if not self.ai.state.effects:
         return False
     for effect in self.ai.state.effects:
         if effect.id == GUARDIANSHIELDPERSISTENT:
             continue
         effect_data = self.ai.game_data.effects[effect.id]
         danger_zone = effect_data.radius + unit.radius + .1
         closest_effect_position_to_unit = unit.position.closest(
             effect.positions)
         if not unit.position.distance_to_point2(
                 closest_effect_position_to_unit) < danger_zone:
             continue
         neighbors8_of_unit = list(unit.position.neighbors8)
         center_of_effect = Point2.center(effect.positions)
         furthest_neighbor_to_effect = center_of_effect.furthest(
             neighbors8_of_unit)
         move_away = -1 * danger_zone
         self.ai.add_action(
             unit.move(
                 furthest_neighbor_to_effect.towards(
                     unit.position, move_away)))
     return True
Ejemplo n.º 28
0
    async def handle_unit(
        self,
        air_threats_near_bases: Units,
        ground_threats_near_bases: Units,
        priority_enemy_units: Units,
        unit: Unit,
        th_tag: int = 0,
        grid: Optional[np.ndarray] = None,
        nydus_networks: Optional[Units] = None,
        nydus_canals: Optional[Units] = None,
    ) -> None:

        should_spread_creep: bool = self._check_queen_can_spread_creep(unit)
        self.creep_targets = self.policy.creep_targets

        if priority_enemy_units:
            await self.do_queen_micro(unit, priority_enemy_units, grid)
        elif (self.policy.defend_against_air and air_threats_near_bases
              and not should_spread_creep):
            await self.do_queen_micro(unit, air_threats_near_bases, grid)
        elif (self.policy.defend_against_ground and ground_threats_near_bases
              and not should_spread_creep):
            await self.do_queen_micro(unit, ground_threats_near_bases, grid)
        elif self.bot.enemy_units and self.bot.enemy_units.filter(
                # custom filter to replace in_attack_range_of so that it can be used with memory units
                lambda enemy: enemy.position.distance_to(unit) < max(
                    unit.air_range, unit.ground_range)):
            unit.move(self.policy.rally_point)
        elif (unit.energy >= 25 and len(unit.orders) == 0
              and self.creep_coverage < self.policy.target_perc_coverage):
            await self.spread_creep(unit, grid)
        elif (self.map_data and grid is not None
              and not self.is_position_safe(grid, unit.position)):
            await self.move_towards_safe_spot(unit, grid)
        elif unit.distance_to(self.policy.rally_point) > 7:
            if len(unit.orders) > 0:
                if unit.orders[0].ability.button_name != "CreepTumor":
                    unit.move(self.policy.rally_point)
            elif len(unit.orders) == 0:
                unit.move(self.policy.rally_point)
        # check if tumor has been placed at a location yet
        self._clear_pending_positions()
Ejemplo n.º 29
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))
Ejemplo n.º 30
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)