Exemple #1
0
 def avoid_effects(self, unit):
     """Dodge any effects"""
     if not self.main.state.effects or unit.type_id == UnitTypeId.ULTRALISK:
         return False
     effects_radius = {
         EffectId.PSISTORMPERSISTENT: 1.5,
         EffectId.THERMALLANCESFORWARD: 0.3,
         EffectId.NUKEPERSISTENT: 8,
         EffectId.BLINDINGCLOUDCP: 2,
         EffectId.RAVAGERCORROSIVEBILECP: 0.5,
         EffectId.LURKERMP: 0.3,
     }  # Exchange it for '.radius' when the data gets implemented
     ignored_effects = (
         EffectId.SCANNERSWEEP,
         EffectId.GUARDIANSHIELDPERSISTENT,
         EffectId.LIBERATORTARGETMORPHDELAYPERSISTENT,
         EffectId.LIBERATORTARGETMORPHPERSISTENT,
     )  # Placeholder(must find better way to handle some of these)
     for effect in self.main.state.effects:
         if effect.id in ignored_effects:
             continue
         danger_zone = effects_radius[effect.id] + unit.radius + 0.4
         if unit.position.distance_to_closest(effect.positions) > danger_zone:
             break
         perimeter_of_effect = Point2.center(effect.positions).furthest(list(unit.position.neighbors8))
         self.main.add_action(unit.move(perimeter_of_effect.towards(unit.position, -danger_zone)))
         return True
     return False
Exemple #2
0
    def should_retreat(self, unit: Unit) -> bool:
        if unit.shield_max + unit.health_max > 0:
            health_percentage = (unit.shield + unit.health) / (unit.shield_max + unit.health_max)
        else:
            health_percentage = 0
        if health_percentage < 0.2:  # or unit.weapon_cooldown < 0:
            # low hp or unit can't attack
            return True

        for effect in self.ai.state.effects:
            if effect.id == EffectId.RAVAGERCORROSIVEBILECP:
                if Point2.center(effect.positions).distance_to(unit) < 3:
                    return True
            if effect.id == EffectId.BLINDINGCLOUDCP:
                if Point2.center(effect.positions).distance_to(unit) < 4:
                    return True
            if effect.id == EffectId.PSISTORMPERSISTENT:
                if Point2.center(effect.positions).distance_to(unit) < 4:
                    return True
        return False
Exemple #3
0
 def is_revealed_by_enemy(self, dt: Unit) -> bool:
     detectors = self.knowledge.unit_cache.enemy_in_range(dt.position, 20) \
         .filter(lambda x: (x.detect_range - 1) > dt.distance_to(x.position))
     if detectors.exists:
         if detectors.filter(lambda x: x.is_flying).exists:
             self.enemy_air_detector = True
         return True
     for effect in self.ai.state.effects:
         if effect.id == EffectId.SCANNERSWEEP:
             if Point2.center(effect.positions).distance_to(
                     dt.position) < 15:
                 return True
     return False
Exemple #4
0
    async def DefendMainBase(self):
        close_enemies = self.known_enemy_units.closer_than(
            50, self.start_location)

        if close_enemies.amount > 3:
            enemy_center = Point2.center(
                [enemy.position for enemy in close_enemies])

            defensors = self.belicUnits
            defensors = defensors.sorted(lambda unit: unit.distance_to(
                enemy_center)).take(close_enemies.amount + 10)
            await self.do_actions(
                [defensor.attack(enemy_center) for defensor in defensors])
Exemple #5
0
    async def on_step(self, iteration):
        self.shared.attackers = self.units.tags_in(self.allocated)
        if self.attack_objective:
            await self.attack_objective.tick()
            if self.attack_objective.is_complete():
                self.shared.victims = Units([], self.bot)
                self.attack_objective = None
            else:
                self.shared.victims = self.attack_objective.enemies
                return

        # for cleanup in self.cleanup_objectives:
        #   await cleanup.tick()
        #   if cleanup.is_complete():
        #     self.shared.victims = Units([], self.bot)
        #     self.cleanup_objectives.remove(cleanup)

        if (self.supply_used > 196
                or self.shared.optimism > 1.5) and not self.attack_objective:
            known_enemy_units = self.shared.known_enemy_units.values()
            enemy_bases = self.enemy_structures(BaseStructures)
            if enemy_bases.exists:
                self.attack_objective = AttackObjective(
                    self,
                    enemy_bases.furthest_to(
                        Point2.center([u.position for u in known_enemy_units]
                                      ) if known_enemy_units else self.
                        enemy_start_locations[0]).position)
            elif self.enemy_structures.exists:
                self.attack_objective = AttackObjective(
                    self,
                    self.enemy_structures.closest_to(
                        self.units.center).position)
            else:
                self.attack_objective = AttackObjective(
                    self, self.enemy_start_locations[0])
Exemple #6
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
    async def update_influence(self):
        power = ExtendedPower(self.unit_values)
        self.path_finder_terrain.reset()  # Reset
        self.path_finder_ground.reset()  # Reset

        positions = []

        for mf in self.ai.mineral_field:  # type: Unit
            # In 4.8.5+ minerals are no linger visible in pathing grid
            positions.append(mf.position)

        # for mf in self.ai.mineral_walls:  # type: Unit
        #     # In 4.8.5+ minerals are no linger visible in pathing grid
        #     positions.append(mf.position)

        self.path_finder_terrain.create_block(positions, (2, 1))
        self.path_finder_ground.create_block(positions, (2, 1))

        self.set_rocks(self.path_finder_terrain)
        self.set_rocks(self.path_finder_ground)

        for building in self.ai.structures + self.knowledge.known_enemy_structures:  # type: Unit
            if building.type_id in buildings_2x2:
                self.path_finder_ground.create_block(building.position, (2, 2))
            elif building.type_id in buildings_3x3:
                self.path_finder_ground.create_block(building.position, (3, 3))
            elif building.type_id in buildings_5x5:
                self.path_finder_ground.create_block(building.position, (5, 3))
                self.path_finder_ground.create_block(building.position, (3, 5))

        self.set_rocks(self.path_finder_ground)

        self.path_finder_ground.normalize_influence(20)
        self.path_finder_air.normalize_influence(20)

        for enemy_type in self.cache.enemy_unit_cache:  # type: UnitTypeId
            enemies: Units = self.cache.enemy_unit_cache.get(
                enemy_type, Units([], self.ai))
            if len(enemies) == 0:
                continue

            example_enemy: Unit = enemies[0]
            power.clear()
            power.add_unit(enemy_type, 100)

            if self.unit_values.can_shoot_air(example_enemy):
                positions: List[Point2] = map(
                    lambda u: u.position,
                    enemies)  # need to be specified in both places
                s_range = self.unit_values.air_range(example_enemy)

                if example_enemy.type_id == UnitTypeId.CYCLONE:
                    s_range = 7

                self.path_finder_air.add_influence(positions, power.air_power,
                                                   s_range + 3)

            if self.unit_values.can_shoot_ground(example_enemy):
                positions = map(lambda u: u.position,
                                enemies)  # need to be specified in both places
                s_range = self.unit_values.ground_range(example_enemy)
                if example_enemy.type_id == UnitTypeId.CYCLONE:
                    s_range = 7

                if s_range < 2:
                    self.path_finder_ground.add_influence_walk(
                        positions, power.ground_power, 7)
                elif s_range < 5:
                    self.path_finder_ground.add_influence_walk(
                        positions, power.ground_power, 7)
                else:
                    self.path_finder_ground.add_influence(
                        positions, power.ground_power, s_range + 3)

        # influence, radius, points, can it hit air?
        effect_dict: Dict[EffectId, Tuple[float, float, List[Point2],
                                          bool]] = dict()
        for effect in self.ai.state.effects:
            values: Tuple[float, float, List[Point2], bool] = None

            if effect.id == EffectId.RAVAGERCORROSIVEBILECP:
                values = effect_dict.get(effect.id, (1000, 2.5, [], True))
                values[2].append(Point2.center(effect.positions))
            elif effect.id == EffectId.BLINDINGCLOUDCP:
                values = effect_dict.get(effect.id, (400, 3.5, [], False))
                values[2].append(Point2.center(effect.positions))
            elif effect.id == EffectId.NUKEPERSISTENT:
                values = effect_dict.get(effect.id, (900, 9, [], True))
                values[2].append(Point2.center(effect.positions))
            elif effect.id == EffectId.PSISTORMPERSISTENT:
                values = effect_dict.get(effect.id, (300, 3.5, [], True))
                values[2].append(Point2.center(effect.positions))
            elif effect.id == EffectId.LIBERATORTARGETMORPHDELAYPERSISTENT:
                values = effect_dict.get(effect.id, (200, 6, [], False))
                values[2].append(Point2.center(effect.positions))
            elif effect.id == EffectId.LIBERATORTARGETMORPHPERSISTENT:
                values = effect_dict.get(effect.id, (300, 6, [], False))
                values[2].append(Point2.center(effect.positions))
            elif effect.id == EffectId.LURKERMP:
                # Each lurker spine deals splash damage to a radius of 0.5
                values = effect_dict.get(effect.id, (1000, 1, [], False))
                values[2].extend(effect.positions)

            if values is not None and effect.id not in effect_dict:
                effect_dict[effect.id] = values

        for effects in effect_dict.values():
            if effects[3]:
                self.path_finder_air.add_influence(effects[2], effects[0],
                                                   effects[1])
            self.path_finder_ground.add_influence(effects[2], effects[0],
                                                  effects[1])
Exemple #8
0
 def bases_centroid(self):
   return Point2.center([base.position for base in self.townhalls])
Exemple #9
0
 def resource_centroid(self, townhall):
     nodes = self.mineral_field.closer_than(15, townhall)
     if nodes.exists:
         return Point2.center([r.position for r in nodes])
     else:
         return self.game_info.map_center
 async def on_enemy_unit_left_vision(self, unit_tag: int):
     last_known_unit = self._enemy_units_previous_map.get(unit_tag, None)
     self.fogged_queue.append(last_known_unit.position)
     if len(self.fogged_queue) > 7:
         self.fogged_units.append(Point2.center(self.fogged_queue))
         self.fogged_queue = []
Exemple #11
0
    async def attack(self):
        """ Covers military AI, from the moment unit is recruited into defense,
         into staging to offense and retreat, and cycle. """
        global defense, offense, staging, retreat
        global staging_loc, isStaging
        forceMin = 4 + (self.time / 30)

        #Add all new units to defense force first
        for unit in (units for units in self.getAllUnits() if not units in defense and \
        not units in offense and not units in staging and not units in retreat):
            defense.append(unit)
            await self.do(unit.move(self.next_node))

        if defense:
            defense = list(units for units in self.getAllUnits()
                           if units in defense)
        if staging:
            staging = list(units for units in self.getAllUnits()
                           if units in staging)
        if offense:
            offense = list(units for units in self.getAllUnits()
                           if units in offense)

        #If defense force is big enough to attack, attack
        if len(defense) > forceMin:
            staging += defense
            defense = []
            for unit in staging:
                await self.do(unit.attack(staging_loc))
            print("D>S Defense:", len(defense), "|Staging:", len(staging),
                  "|Offense:", len(offense), "|ForceMin:", forceMin)
        elif defense:
            for unit in defense:
                if staging and len(staging) < forceMin:
                    staging += defense
                    defense = []
                    await self.do(unit.attack(staging_loc))
                elif unit.is_idle and unit.position.distance_to(
                        self.next_node) > 5:
                    await self.do(unit.attack(self.next_node))

        #Staging force until units are grouped together
        # OPTIMIZE: Need to organify the max radius of staging->offense
        if len(staging) >= forceMin:
            #p=[]
            #for unit in (units for units in self.getAllUnits() if units in staging):
            #p.append(unit.position)
            p = list(units.position for units in staging)
            if Point2.center(p).distance_to_furthest(p) < 8:
                target = self.find_enemy(self.state)
                offense += staging
                staging = []
                for unit in offense:
                    if unit in self.units(MEDIVAC) and unit.is_idle:
                        await self.do(
                            unit.attack(random.choice(offense).position))
                    elif unit.is_idle:
                        await self.do(unit.attack(target))
                print("S>O Defense:", len(defense), "|Staging:", len(staging),
                      "|Offense:", len(offense), "|ForceMin:", forceMin)
            else:
                for unit in staging:
                    if unit.is_idle and unit.position.distance_to(
                            staging_loc) > 5:
                        await self.do(unit.attack(staging_loc))

        if offense:
            #Retreat if offense too weak
            if len(offense) < forceMin / 4:
                retreat = offense
                offense = []
                for unit in retreat:
                    await self.do(unit.move(self.next_node))

                defense += retreat
                retreat = []
                print("O>D Defense:", len(defense), "|Staging:", len(staging),
                      "|Offense:", len(offense), "|ForceMin:", forceMin)
            #If part of/offense loses/kills target, retarget
            else:
                target = self.find_enemy(self.state)
                for unit in offense:
                    if unit in self.units(MEDIVAC) and unit.is_idle:
                        await self.do(
                            unit.attack(random.choice(offense).position))
                    elif unit.is_idle:
                        await self.do(unit.attack(target))
Exemple #12
0
    async def ArmiesMacro(self):
        if self.belicUnits.amount > 60 and (self.time - self.lastAttack > 5):
            self.lastAttack = self.time
            all_positions = [
                item.position for sublist in
                [self.known_enemy_units, self.known_enemy_structures]
                for item in sublist
            ]
            attack_position = Point2.center(all_positions +
                                            [self.enemy_start_locations[0]])

            enemy_struct = None
            enemy_unit = None
            try:
                enemy_struct = self.known_enemy_structures.closest_to(
                    attack_position)
            except:
                pass
            try:
                enemy_unit = self.known_enemy_units.closest_to(attack_position)
            except:
                pass

            if enemy_unit is None and enemy_struct is None:
                actions = [
                    marine.attack(attack_position)
                    for marine in self.belicUnits if not marine.is_attacking
                ]
            elif enemy_unit is None:
                actions = [
                    marine.attack(enemy_struct.position)
                    for marine in self.belicUnits if not marine.is_attacking
                ]
            elif enemy_struct is None:
                actions = [
                    marine.attack(enemy_unit.position)
                    for marine in self.belicUnits if not marine.is_attacking
                ]
            else:
                if enemy_unit.position.distance_to(
                        attack_position) < enemy_struct.position.distance_to(
                            attack_position):
                    actions = [
                        marine.attack(enemy_unit.position)
                        for marine in self.belicUnits
                        if not marine.is_attacking
                    ]
                else:
                    actions = [
                        marine.attack(enemy_struct.position)
                        for marine in self.belicUnits
                        if not marine.is_attacking
                    ]

            await self.do_actions(actions)

        #make medivac follow marines
        medivacs = self.units(MEDIVAC).idle
        if self.belicUnits.amount == 0:
            await self.do_actions(
                [medivac.move(self.start_location) for medivac in medivacs])
        else:
            actions = [
                medivac.move(
                    self.belicUnits.sorted(
                        lambda unit: unit.health + medivac.position.
                        distance_to(unit.position)).first.position)
                for medivac in medivacs
            ]
            await self.do_actions(actions)