Ejemplo n.º 1
0
    def evaluate_engagement(self,
                            own_units: Units,
                            enemy_units: Units,
                            bias=1):
        own_ranged: Units = own_units.filter(lambda u: u.ground_range > 3)
        own_melee: Units = own_units.tags_not_in(own_ranged.tags)
        enemy_ranged: Units = enemy_units.filter(lambda u: u.ground_range > 3)

        try:
            own_ranged_value = bias * self.bot.calculate_combat_value(
                own_ranged)
        except:
            own_ranged_value = 0
        try:
            enemy_ranged_value = self.bot.calculate_combat_value(enemy_ranged)
        except:
            enemy_ranged_value = 0

        corrected_own_value = bias * self.bot.calculate_combat_value(own_units)

        if own_ranged_value < enemy_ranged_value and own_units.exists:
            perimeter = self.get_enemy_perimeter(
                enemy_units.not_structure, self.bot.known_enemy_structures,
                own_units.center)
            if own_melee.exists:
                own_melee_value = bias * self.bot.calculate_combat_value(
                    Units(own_melee.take(perimeter * 2, require_all=False),
                          self.bot._game_data))
            else:
                own_melee_value = 0
            corrected_own_value = own_melee_value + own_ranged_value
        evaluation = corrected_own_value - self.bot.calculate_combat_value(
            enemy_units)
        return evaluation
Ejemplo n.º 2
0
 def group_solve_combat(self, units: Units, current_command: Action) -> Action:
     beaming_phoenixes = units.filter(lambda p: p.orders and p.orders[0].ability.id == AbilityId.GRAVITONBEAM_GRAVITONBEAM)
     if beaming_phoenixes and len(beaming_phoenixes) > len(units) * 0.5:
         self.allow_lift = False
     else:
         self.allow_lift = True
     return current_command
Ejemplo n.º 3
0
    def __init__(self, knowledge: Knowledge, close_enemies: Units, unit: Unit, our_units: Units, our_median: Point2):
        self.ai = knowledge.ai
        self.our_units = our_units
        self.our_median = our_median

        self.close_enemies = close_enemies
        self.my_height = self.ai.get_terrain_height(unit)
        self.enemy_power = ExtendedPower(knowledge.unit_values)
        self.our_power = ExtendedPower(knowledge.unit_values)

        for unit in our_units: # type: Unit
            self.our_power.add_unit(unit)

        self.worker_only = False

        if self.close_enemies.exists:
            self.enemy_center = close_enemies.center
            # Can be empty!
            self.powered_enemies = close_enemies.filter(lambda x: knowledge.unit_values.power(x) > 0.1)

            if self.powered_enemies.exists:
                self.closest = unit.position.closest(self.powered_enemies)
                self.worker_only = True
                for enemy in self.powered_enemies: # type: Unit
                    if not knowledge.unit_values.is_worker(enemy):
                        self.worker_only = False
                    self.enemy_power.add_unit(enemy)
            else:
                self.closest = unit.position.closest(self.close_enemies)

            self.enemy_center_height = self.ai.get_terrain_height(self.enemy_center)
            self.closest_height = self.ai.get_terrain_height(self.closest)
        else:
            self.powered_enemies = Units([], self.ai) # empty list
Ejemplo n.º 4
0
    def enemy_in_range(self, position: Point2, range: Union[int, float], only_targetable = True) -> Units:
        units = Units([], self.ai)
        if self.enemy_tree is None:
            return units

        for index in self.enemy_tree.query_ball_point(np.array([position.x, position.y]), range):
            units.append(self.knowledge.known_enemy_units[index])

        if only_targetable:
            return units.filter(lambda x: x.can_be_attacked or x.is_snapshot)
        return units
Ejemplo n.º 5
0
 def calculate_combat_value(self, units: Units):
     value = 0
     for unit in units.filter(lambda u: u.can_attack_ground):
         if unit.type_id == DRONE or unit.type_id == UnitTypeId.PROBE or unit.type_id == UnitTypeId.SCV:
             resources = (10, 0)
         elif unit.type_id == UnitTypeId.BUNKER:
             resources = (300, 0)
         else:
             resources = self.get_resource_value(unit.type_id)
         minerals = resources[0]
         vespene = resources[1]
         value += (minerals + vespene)
     return value
Ejemplo n.º 6
0
    def in_attack_range_of(
        self, unit: Unit, enemies: Units, bonus_distance: Union[int, float] = 0
    ) -> Optional[Units]:
        """
        Get enemies in attack range of a given unit

        @param unit:
        @param enemies:
        @param bonus_distance:
        @return:
        """
        if not unit or not enemies:
            return None

        return enemies.filter(
            lambda e: self.target_in_range(unit, e, bonus_distance=bonus_distance)
        )
Ejemplo n.º 7
0
 async def defender_base(self, iteration, units: Units):
     for nexus in self.townhalls:
         enemysNear = (self.enemy_units | self.enemy_structures
                       ).filter(lambda unit: unit.can_be_attacked and unit.
                                is_attacking).closer_than(15, nexus)
         if enemysNear.amount > 0:
             ownUnitsNear = units.filter(
                 lambda unit: unit.can_attack).closer_than(20, nexus)
             print("atacando para defender")
             if ownUnitsNear.amount >= enemysNear.amount * 0.6:
                 print("atacando para defender")
                 for unit in ownUnitsNear:
                     unit.attack(enemysNear.closest_to(unit))
             else:
                 print("Foge para defender")
                 nexusAux = self.townhalls
                 nexusAux.remove(nexus)
                 for unit in ownUnitsNear:
                     unit.move(nexusAux.closest_to(nexus))
Ejemplo n.º 8
0
 def add_workers(self, new_workers: Units):
     try:
         # Only add the units to the workers list if all of them are workers and aren't already in the list
         if new_workers.amount == new_workers(UnitTypeId.PROBE).amount:
             # Only add the units to the workers list if none them already is in the list
             if new_workers.filter(lambda w: w in self.workers).empty:
                 self.workers.extend(new_workers)
             else:
                 raise WorkerManagementException
         else:
             raise UnitTypeException
     except UnitTypeException:
         print(
             f"Only workers can be added to a workers list: {nw.type_id for nw in new_workers}"
         )
         print()
     except WorkerManagementException:
         print(
             f"Some of the workers are already associated to the base: {nw.tag for nw in new_workers} | {w.tag for w in self.workers}"
         )
         print()
Ejemplo n.º 9
0
async def pickup_micro(bot: sc2.BotAI,
                       marines: Units = None,
                       medivacs: Units = None,
                       endangered_marines_tags: Set[int] = set(),
                       target: Point2 = None,
                       retreat_point: Point2 = None):
    """
    Pickup micro on medivacs and marines.
     - Marines a move to enemy main.
     - Medivacs heal lowest marines.
     - Stim when in range of an enemy unit. Marines less than EMPATHY_STIM_RANGE away from a stimmed marine will stim themselves.
     - Marines are picked up when at or below MARINE_PICKUP_THRESHOLD, and dropped off at a safe location.
    """
    MARINE_PICKUP_THRESHOLD = 10
    EMPATHY_STIM_RANGE = 10

    marines: Units = marines
    medivacs: Units = medivacs
    target: Point2 = target or bot.enemy_start_locations[0]
    retreat_point: Point2 = bot.start_location

    energy_medivacs: Units = medivacs.filter(
        lambda m: m.energy_percentage >= 0.1)
    for marine in marines:
        endangered_marines_nearby = marines.filter(
            lambda u: u.type_id == UnitTypeId.MARINE and u.tag != marine.tag
            and u.tag in endangered_marines_tags and u.distance_to(
                marine) <= EMPATHY_STIM_RANGE)

        marine_endangered = marine.tag in endangered_marines_tags
        if (marine_endangered and marine.health <= MARINE_PICKUP_THRESHOLD
                and medivacs):
            closest_medivac = medivacs.filter(
                lambda m: m.cargo_left > 0).sorted(
                    key=lambda m: m.distance_to(marine))
            marine.smart(closest_medivac.first)
        elif ((marine_endangered or endangered_marines_nearby)
              and not marine.has_buff(BuffId.STIMPACK) and energy_medivacs):
            marine(AbilityId.EFFECT_STIM_MARINE)
        else:
            marine.attack(target)

    sorted_marines = marines.sorted(key=lambda m: m.health)
    sorted_marines_iter = iter(sorted_marines)

    endangered_marines = sorted_marines.filter(
        lambda m: m.tag in endangered_marines_tags)
    endangered_marines_iter = iter(endangered_marines)

    for medivac in medivacs:
        if medivac.has_cargo:
            # drop off at closest safe position
            enemies_in_range = bot.enemy_units.filter(
                lambda e: e.ground_range >= e.distance_to(medivac)).sorted(
                    lambda e: e.distance_to(medivac))
            if (not enemies_in_range
                    and ((await bot.can_place(UnitTypeId.SENSORTOWER,
                                              [medivac.position]))[0] or
                         (await bot.can_place(UnitTypeId.CREEPTUMOR,
                                              [medivac.position]))[0])):
                # TODO: make sure location valid, and within expo radius
                medivac(AbilityId.UNLOADALLAT_MEDIVAC, medivac)
                if medivac.is_moving:
                    medivac.hold_position()
            elif enemies_in_range:
                # TODO: helper method to determine "direction" of battle
                first_enemy = enemies_in_range.first.position
                enemy_vector = (first_enemy.x - medivac.position.x,
                                first_enemy.y - medivac.position.y)
                safe_point = (medivac.position.x - enemy_vector[0],
                              medivac.position.y - enemy_vector[1])

                medivac.move(medivac.position.towards(Point2(safe_point), 3))
            else:
                medivac.move(retreat_point)
        elif not (len(medivac.orders) > 0
                  and medivac.orders[0].ability.id == AbilityId.LOAD_MEDIVAC):
            next_endangered_marine = next(endangered_marines_iter, None)
            if next_endangered_marine:
                if not medivac.has_buff(
                        BuffId.MEDIVACSPEEDBOOST) and await bot.can_cast(
                            medivac,
                            AbilityId.EFFECT_MEDIVACIGNITEAFTERBURNERS):
                    medivac(AbilityId.EFFECT_MEDIVACIGNITEAFTERBURNERS)
                elif next_endangered_marine.health <= MARINE_PICKUP_THRESHOLD:
                    # move and load
                    medivac(AbilityId.LOAD_MEDIVAC, next_endangered_marine)
                else:
                    medivac(AbilityId.MEDIVACHEAL_HEAL, next_endangered_marine)
            elif marines:
                next_marine = next(sorted_marines_iter,
                                   sorted_marines.random_or(None))
                if next_marine:
                    medivac.attack(next_marine.position)
            else:
                # no marines
                medivac.move(retreat_point)