예제 #1
0
    async def execute(self) -> bool:
        unit: Unit

        all_defenders = self.knowledge.roles.all_from_task(UnitTask.Defending)

        for i in range(0, len(self.knowledge.expansion_zones)):
            zone: 'Zone' = self.knowledge.expansion_zones[i]
            zone_tags = self.defender_tags[i]

            zone_defenders_all = all_defenders.tags_in(zone_tags)
            zone_worker_defenders = zone_defenders_all(self.worker_type)
            zone_defenders = zone_defenders_all.exclude_type(self.worker_type)
            enemies = zone.known_enemy_units

            # Let's loop zone starting from our main, which is the one we want to defend the most
            # Check that zone is either in our control or is our start location that has no Nexus
            if zone_defenders.exists or zone.is_ours or zone == self.knowledge.own_main_zone:
                if not self.defense_required(enemies):
                    # Delay before removing defenses in case we just lost visibility of the enemies
                    if zone.last_scouted_center == self.knowledge.ai.time \
                            or self.zone_seen_enemy[i] + PlanZoneDefense.ZONE_CLEAR_TIMEOUT < self.ai.time:
                        self.knowledge.roles.clear_tasks(zone_defenders_all)
                        zone_defenders.clear()
                        zone_tags.clear()
                        continue  # Zone is well under control.
                else:
                    self.zone_seen_enemy[i] = self.ai.time

                if enemies.exists:
                    # enemy_center = zone.assaulting_enemies.center
                    enemy_center = enemies.closest_to(
                        zone.center_location).position
                elif zone.assaulting_enemies:
                    enemy_center = zone.assaulting_enemies.closest_to(
                        zone.center_location).position
                else:
                    enemy_center = zone.gather_point

                defense_required = ExtendedPower(self.unit_values)
                defense_required.add_power(zone.assaulting_enemy_power)
                defense_required.multiply(1.5)

                defenders = ExtendedPower(self.unit_values)

                for unit in zone_defenders:
                    self.combat.add_unit(unit)
                    defenders.add_unit(unit)

                # Add units to defenders that are being warped in.
                for unit in self.knowledge.roles.units(
                        UnitTask.Idle).not_ready:
                    if unit.distance_to(zone.center_location) < zone.radius:
                        # unit is idle in the zone, add to defenders
                        self.combat.add_unit(unit)
                        self.knowledge.roles.set_task(UnitTask.Defending, unit)
                        zone_tags.append(unit.tag)

                if not defenders.is_enough_for(defense_required):
                    defense_required.substract_power(defenders)
                    for unit in self.knowledge.roles.get_defenders(
                            defense_required, zone.center_location):
                        if unit.distance_to(
                                zone.center_location) < zone.radius:
                            # Only count units that are close as defenders
                            defenders.add_unit(unit)

                        self.knowledge.roles.set_task(UnitTask.Defending, unit)
                        self.combat.add_unit(unit)
                        zone_tags.append(unit.tag)

                if len(enemies) > 1 or (len(enemies) == 1
                                        and enemies[0].type_id
                                        not in self.unit_values.worker_types):
                    # Pull workers to defend only and only if the enemy isn't one worker scout
                    if defenders.is_enough_for(defense_required):
                        # Workers should return to mining.
                        for unit in zone_worker_defenders:
                            zone.go_mine(unit)
                            if unit.tag in zone_tags:  # Just in case, should be in zone tags always.
                                zone_tags.remove(unit.tag)
                        # Zone is well under control without worker defense.
                    else:
                        await self.worker_defence(defenders.power,
                                                  defense_required,
                                                  enemy_center, zone,
                                                  zone_tags,
                                                  zone_worker_defenders)

                self.combat.execute(enemy_center, MoveType.SearchAndDestroy)
        return True  # never block
예제 #2
0
    def execute(self, target: Point2, move_type=MoveType.Assault):
        our_units = self.get_all_units()
        if len(our_units) < 1:
            return

        self.own_groups: List[CombatUnits] = self.group_own_units(
            our_units, 12)

        total_power = ExtendedPower(self.unit_values)

        for group in self.own_groups:
            total_power.add_power(group.power)

        if self.debug:
            fn = lambda group: group.center.distance_to(self.ai.start_location)
            sorted_list = sorted(self.own_groups, key=fn)
            for i in range(0, len(sorted_list)):
                sorted_list[i].debug_index = i

        for group in self.own_groups:
            center = group.center
            closest_enemies = self.closest_group(center, self.enemy_groups)

            if closest_enemies is None:
                if move_type == MoveType.PanicRetreat:
                    self.move_to(group, target, move_type)
                else:
                    self.attack_to(group, target, move_type)
            else:
                power = group.power
                enemy_power = ExtendedPower(closest_enemies)
                enemy_center = closest_enemies.center

                is_in_combat = group.is_in_combat(closest_enemies)
                # pseudocode for attack

                if move_type == MoveType.DefensiveRetreat or move_type == MoveType.PanicRetreat:
                    self.move_to(group, target, move_type)
                    break

                if power.power > self.regroup_threshold * total_power.power:
                    # Most of the army is here
                    if (group.is_too_spread_out() and not is_in_combat):
                        self.regroup(group, group.center)
                    else:
                        self.attack_to(group, target, move_type)

                elif is_in_combat:
                    if not power.is_enough_for(enemy_power, 0.75):
                        # Regroup if possible
                        own_closest_group = self.closest_group(
                            center, self.own_groups)

                        if own_closest_group:
                            self.move_to(group, own_closest_group.center,
                                         MoveType.ReGroup)
                        else:
                            # fight to bitter end
                            self.attack_to(group, closest_enemies.center,
                                           move_type)
                    else:
                        self.attack_to(group, closest_enemies.center,
                                       move_type)
                else:
                    if group.power.is_enough_for(self.all_enemy_power, 0.85):
                        # We have enough units here to crush everything the enemy has
                        self.attack_to(group, closest_enemies.center,
                                       move_type)
                    else:
                        # Regroup if possible
                        if move_type == MoveType.Assault:
                            # Group towards attack target
                            own_closest_group = self.closest_group(
                                target, self.own_groups)
                        else:
                            # Group up with closest group
                            own_closest_group = self.closest_group(
                                center, self.own_groups)

                        if own_closest_group:
                            self.move_to(group, own_closest_group.center,
                                         MoveType.ReGroup)
                        else:
                            # fight to bitter end
                            self.attack_to(group, closest_enemies.center,
                                           move_type)

                # if move_type == MoveType.SearchAndDestroy:
                #     enemy_closest_group = self.closest_group(center, self.enemy_groups)
                #     if enemy_closest_group:
                #         self.attack_to(actions, group, closest_enemies.center, move_type)
                #     else:
                #         self.attack_to(actions, group, target, move_type)
                # elif power.is_enough_for(enemy_power, 0.75):
                #     if move_type == MoveType.PanicRetreat:
                #         self.move_to(actions, group, target, move_type)
                #     else:
                #         self.attack_to(actions, group, closest_enemies.center, move_type)
                #
                # elif distance > 12:
                #     own_closest_group = self.closest_group(center, self.own_groups)
                #
                #     if own_closest_group:
                #         self.move_to(actions, group, own_closest_group.center, MoveType.ReGroup)
                #
                #     elif move_type == MoveType.PanicRetreat:
                #         self.move_to(actions, group, target, move_type)
                #     else:
                #         self.attack_to(actions, group, enemy_center, move_type)
                #
                # elif enemy_power.is_enough_for(power, 0.75):
                #     own_closest_group = self.closest_group(center, self.own_groups)
                #
                #     if own_closest_group:
                #         self.move_to(actions, group, own_closest_group.center, MoveType.ReGroup)
                #
                # elif move_type == MoveType.PanicRetreat:
                #     self.move_to(actions, group, target, move_type)
                # else:
                #     self.attack_to(actions, group, target, move_type)

        self.tags.clear()