Ejemplo n.º 1
0
  async def on_step(self, iteration):
    if not self.version_reported:
      self.version_reported = True
      repo = Repo(search_parent_directories=True)
      if not repo.is_dirty():
        sha = repo.head.object.hexsha
        await self.chat_send("ModuBot verified hash: " + sha[0:10])
      await self.chat_send("(glhf)(cake)(sc2)")
    if self.time < 120:
      return
    if self.highest_optimism_reported < 10 and self.shared.optimism > 10:
      self.highest_optimism_reported = 10
      await self.chat_send("-- Enemy contained --")

    if self.highest_optimism_reported < 50 and self.shared.optimism > 50:
      self.highest_optimism_reported = 50
      await self.chat_send("-- Victory confidence 99% --")

    enemy_fighters = self.enemy_units.filter(lambda u: not is_worker(u))
    if enemy_fighters.amount > 10:
      if self.lowest_optimism_reported > 0.3 and self.shared.optimism < 0.3:
        self.lowest_optimism_reported = 0.3
        await self.chat_send("whoa... (scared) ")

      if self.lowest_optimism_reported > 0.15 and self.shared.optimism < 0.15:
        self.lowest_optimism_reported = 0.15
        await self.chat_send("this is not good. (salty)")
Ejemplo n.º 2
0
    async def on_step(self, iteration):
        if self.surrender_declared and self.time - self.surrender_declared > 5:
            await self._client.leave()
            raise SurrenderedException("Surrendered")

        self.shared.optimism = optimism(
            self.units.ready.filter(
                lambda u: not is_worker(u) and not u.is_structure),
            (u for u in self.shared.known_enemy_units.values()
             if not is_worker(u) and not u.is_structure))

        if self.shared.optimism < 0.02 and not self.surrender_declared:
            self.surrender_declared = self.time
            await self.chat_send("(gameheart)(gg)(gameheart)")

        for unit in self.enemy_units:
            self.shared.known_enemy_units[unit.tag] = unit
Ejemplo n.º 3
0
 def minimum_supply(self, enemy_units):
     #everyone...! but no less supply than we know we'll be facing
     return max(
         sum(supply_cost(u) for u in enemy_units),
         sum(
             supply_cost(u)
             for u in (self.units.tags_in(self.allocated) +
                       self.unallocated(urgency=self.urgency).filter(
                           lambda u: not is_worker(u)))))
Ejemplo n.º 4
0
    async def on_step(self, iteration):
        if self.last_camera_move < self.time - 2:
            self.last_camera_move = self.time

            # if we're defending
            if self.shared.threats.amount > 1:
                await self._client.move_camera(
                    self.shared.threats.closest_to(self.shared.threats.center))
                return

            # if we're attacking
            if self.shared.attackers and any(
                    unit.position.is_closer_than(10, enemy)
                    for (unit, enemy) in itertools.product(
                        self.shared.attackers, self.shared.victims)):
                await self._client.move_camera(
                    self.shared.attackers.closest_to(
                        self.shared.victims.center))
                return

            # if we're building a new base
            if self.already_pending(
                    self.shared.new_base) > 0 and self.structures(
                        self.shared.new_base).not_ready.empty:
                await self._client.move_camera(self.shared.next_base_location)
                return

            # if we can see more than half their army
            enemy_army_size = len([
                u for u in self.shared.known_enemy_units.values()
                if not is_worker(u)
            ])
            if self.enemy_units.amount > enemy_army_size / 2:
                await self._client.move_camera(
                    self.enemy_units.closest_to(self.enemy_units.center))
                return

            if self.shared.scouts.exists:
                interesting_scouts = self.shared.scouts.filter(
                    lambda scout: (self.enemy_units + self.enemy_structures
                                   ).closer_than(8, scout.position).amount > 1)

                if interesting_scouts.exists:
                    await self._client.move_camera(
                        interesting_scouts.first.position)
                    return

            def energy_amount(base):
                return base.energy

            await self._client.move_camera(
                self.shared.rally_point if self.shared.rally_point and
                self.units.closer_than(10, self.shared.rally_point).amount > 2
                else max(self.townhalls,
                         key=energy_amount,
                         default=self.start_location))
Ejemplo n.º 5
0
    def __init__(self,
                 bot,
                 unit_priority=[],
                 retreat_while=lambda scout: False,
                 start_when=None):
        if not start_when:
            start_when = lambda: self.units.filter(lambda u: not is_worker(u)
                                                   ).exists

        super().__init__(bot, unit_priority, retreat_while)
        self.static_targets = False
Ejemplo n.º 6
0
    def allocate(self):
        may_proceed = False
        enemy_units = self.enemies
        minimum_supply = int(self.minimum_supply(enemy_units))
        optimum_supply = int(self.optimum_supply(enemy_units))
        allocated_supply = int(
            sum(supply_cost(u) for u in self.units.tags_in(self.allocated)))

        if minimum_supply <= allocated_supply:
            may_proceed = True

        still_needed = minimum_supply - allocated_supply
        still_wanted = max(optimum_supply - allocated_supply, still_needed)
        usable_units = self.unallocated(
            urgency=self.urgency).filter(lambda u: not is_worker(u))
        if enemy_units.filter(lambda e: not e.is_flying).empty:
            usable_units = usable_units.filter(lambda u: u.can_attack_air)
        preferred_units = usable_units.filter(
            lambda u: u.can_attack_both
        ) if usable_units.exists else usable_units
        adding_units = set()

        if sum(supply_cost(u) for u in preferred_units) >= still_needed:
            # still_wanted is actually supply, not units, so this will over-select for protoss and under-select for zerg
            adding_units = set(unit.tag
                               for unit in preferred_units.closest_n_units(
                                   self.target.position, still_wanted))
        elif sum(supply_cost(u) for u in usable_units) >= still_needed:
            adding_units = set(preferred_units)
            adding_units.update((unit.tag
                                 for unit in usable_units.closest_n_units(
                                     self.target.position, still_wanted)))

        self.deallocate(adding_units)
        self.allocated = self.allocated.union(adding_units)

        if sum(supply_cost(u)
               for u in self.units.tags_in(self.allocated)) >= minimum_supply:
            may_proceed = True

        if may_proceed:
            if self.status == ObjectiveStatus.ALLOCATING:
                self.status = ObjectiveStatus.STAGING
                self.status_since = self.time

            elif self.status == ObjectiveStatus.RETREATING and \
              self.shared.optimism > 1.5 and \
              self.units.exists and \
              self.units.closer_than(15, median_position([u.position for u in self.units])).amount > self.units.amount / 2:
                self.status = ObjectiveStatus.STAGING
                self.status_since = self.time

        self.units = self.bot.units.tags_in(self.allocated)

        if len(adding_units) > 0:
            self.log.debug({
                "message": "Allocating units",
                "quantity": len(adding_units),
                "now_allocated": len(self.allocated),
            })
        # noisy, but possibly informative
        # self.log.info(f"{self.units.amount} units allocated for {self.enemies.amount} known enemies")
        return
Ejemplo n.º 7
0
 def optimum_supply(self, enemy_units):
     return sum(
         supply_cost(unit) for unit in self.bot.units.filter(
             lambda u: u.ground_dps + u.air_dps > 5 and not is_worker(u)))
Ejemplo n.º 8
0
 def optimum_supply(self, enemy_units):
     return sum(
         supply_cost(u)
         for u in self.units.filter(lambda u: not is_worker(u)))
Ejemplo n.º 9
0
 def unallocated(self, unit_types=None, urgency=Urgency.NONE):
   units = self.units.ready(unit_types) if unit_types else self.units.ready.filter(lambda u: not is_worker(u))
   return units.tags_not_in(list_flatten([
     list(module.allocated) if module.urgency >= urgency
     else []
     for module in self.modules
   ]))
Ejemplo n.º 10
0
    def maybe_expand(self, nodes, gas_structs):
        requests = []
        # this does not have to happen very often
        if not self.shared.next_base_location or self.time - self.last_base_check > 11:
            self.last_base_check = self.time
            if (not self.shared.next_base_location or any(
                    base.position.is_closer_than(
                        1, self.shared.next_base_location)
                    for base in self.townhalls +
                    self.enemy_structures(BaseStructures))):
                self.shared.next_base_location = self.find_next_base()

        if not self.shared.next_base_location:
            return requests

        destructables = self.destructables.filter(
            lambda d: d.position.is_closer_than(1.0, self.shared.
                                                next_base_location))
        if destructables.exists:
            for unit in self.units.filter(lambda u: not is_worker(u)).idle:
                self.do(unit.attack(destructables.first))
        for unit in self.units.closer_than(5, self.shared.next_base_location):
            # apparently, when a probe warps in a building, they become idle *before* the building has started warping
            if unit.is_idle and unit.type_id != self.shared.common_worker:
                self.do(
                    unit.move(
                        self.shared.next_base_location.towards(
                            self.game_info.map_center, 10)))
        base_urgency = Urgency.NONE
        mineable = self.sum_mineral_contents(nodes)

        if not self.already_pending(self.shared.new_base):
            # don't count bases at start locations, because we know they have one, whether we've seen it or not
            enemy_bases = self.enemy_structures(BaseStructures).filter(
                lambda base: base.position not in self.enemy_start_locations)
            # if they're out-expanding us
            base_urgency = 1 + enemy_bases.amount - self.townhalls.amount

            total_desired_harvesters = len(nodes) * 2 + gas_structs.filter(
                lambda a: a.vespene_contents > 0).amount * 3

            if self.race == Race.Zerg:
                base_urgency += 1

            if self.shared.optimism > 1.1:
                base_urgency += 1

            # if the enemy has any bases apart from the main... we got this
            if enemy_bases.amount > 0:
                base_urgency += 1

            # if we're really running out of things to do
            if self.workers.amount >= total_desired_harvesters - 3:
                base_urgency += 1

            # if we're down to about one base
            if len(nodes) < 10:
                base_urgency += 1

            # if we're running out of minerals
            if mineable < 4000:
                base_urgency += 1

            if self.townhalls.amount == 1 and self.fast_expand:
                base_urgency += 4

            requests.append(
                BuildRequest(self.shared.new_base,
                             urgency=base_urgency,
                             force_target=self.shared.next_base_location))

        return requests