示例#1
0
    async def on_building_construction_complete(self, bot: sc2.BotAI,
                                                unit: Unit):
        unit_id: UnitTypeId = unit.type_id
        if unit_id == ASSIMILATOR:
            diff = -unit.surplus_harvesters
            if diff < 0:
                print("ASSIMILATOR WHEN BUILT HAS 4 OR MORE ASSIGNED ALREADY")
            # add three workers to it
            local_minerals_tags = {
                mineral.tag
                for mineral in bot.mineral_field
                if mineral.distance_to(unit.position) <= 8
            }
            n_closest_workers = bot.workers.filter(
                lambda worker: worker.order_target in local_minerals_tags or
                worker.is_carrying_minerals).n_closest_to_distance(
                    unit.position, 20, diff)
            if n_closest_workers == None:
                # no workers close to the new built assimilator, do nothing
                pass
            for worker in n_closest_workers:
                bot.do(worker.gather(unit))

        elif unit_id == NEXUS:
            # do stuff here also
            pass
示例#2
0
    def __init__(self, ai: sc2.BotAI, knowledge: 'Knowledge', x: int, y: int,
                 x2: int, y2: int):
        self.ai = ai
        self.knowledge = knowledge
        self.cache: UnitCacheManager = self.knowledge.unit_cache
        self.bottom_left_x = x
        self.bottom_left_y = y
        self.top_right_x = x2
        self.top_right_y = y2
        self.center = Point2(((x + x2) / 2.0, (y + y2) / 2.0))
        self._x, self._y = self.center.rounded
        self.zone: Optional['Zone'] = None
        self.heat: float = 0
        self.stealth_heat: float = 0
        self.last_enemy_power = ExtendedPower(knowledge.unit_values)

        d2 = 15
        for zone in knowledge.expansion_zones:
            if zone.center_location.distance_to(self.center) < d2:
                if ai.get_terrain_height(
                        zone.center_location) == ai.get_terrain_height(
                            self.center):
                    # if zone == self.knowledge.own_main_zone:
                    #     print("MAIN ZONE")
                    self.zone = zone
示例#3
0
async def chronoboost_building(bot: BotAI, nexus, building=None):
    if not building:
        building = bot.units(WARPGATE).ready.random_or(
            bot.units(GATEWAY).ready.random_or(
                bot.units(ROBOTICSFACILITY).ready.random_or(
                    bot.townhalls.ready.random)))
    chronoboost = AbilityId.EFFECT_CHRONOBOOSTENERGYCOST
    await bot.do(nexus(chronoboost, building))
示例#4
0
 async def __build_supplydepot(self, bot: sc2.BotAI):
     # build supply depot
     if bot.supply_left < (2 if bot.units(UnitTypeId.BARRACKS).amount < 3
                           else 4):
         if bot.can_afford(UnitTypeId.SUPPLYDEPOT) and bot.already_pending(
                 UnitTypeId.SUPPLYDEPOT) < 2:
             await bot.build(UnitTypeId.SUPPLYDEPOT,
                             near=bot.cc.position.random_on_distance(5))
示例#5
0
    def assign_closest_gas(self, bot: sc2.BotAI, unit: Unit):
        gas_buildings = bot.gas_buildings.ready.sorted_by_distance_to(
            unit.position)

        for mining_place in gas_buildings:
            if mining_place.has_vespene and mining_place.surplus_harvesters < 0:
                bot.do(unit.gather(mining_place))
                return True
        return False
示例#6
0
 async def __train_marines(self, bot: sc2.BotAI):
     # train marines
     if bot.units(UnitTypeId.MARINE).amount < 10 or bot.units(
             UnitTypeId.MARINE).amount < bot.units(
                 UnitTypeId.REAPER).amount * 5:
         for rax in bot.units(UnitTypeId.BARRACKS).ready.noqueue:
             if not bot.can_afford(UnitTypeId.MARINE):
                 break
             await bot.do(rax.train(UnitTypeId.MARINE))
示例#7
0
    async def __group_idle_units(self, bot: sc2.BotAI):
        if bot.time > 480:
            idle_units = bot.units(UnitTypeId.MARINE).idle | bot.units(
                UnitTypeId.REAPER).idle

            if not bot.cc:
                idle_units = idle_units | bot.workers

            if idle_units.amount > 20:
                self.attack_groups.add(ControlGroup(idle_units))
示例#8
0
    async def __collect_with_scv(self, bot: sc2.BotAI):
        # collect with SCV
        for scv in bot.units(UnitTypeId.SCV).idle:
            await bot.do(scv.gather(bot.state.mineral_field.closest_to(bot.cc))
                         )

        for a in bot.units(UnitTypeId.REFINERY):
            if a.assigned_harvesters < a.ideal_harvesters:
                w = bot.workers.closer_than(20, a)
                if w.exists:
                    await bot.do(w.random.gather(a))
示例#9
0
async def upgrade_zergling_speed(bot: BotAI):
    spawning_pool = bot.units(UnitTypeId.SPAWNINGPOOL).ready
    if not spawning_pool.exists:
        return False
    spawning_pool = spawning_pool.first
    metabolic_boost = AbilityId.RESEARCH_ZERGLINGMETABOLICBOOST
    if bot.can_afford(metabolic_boost):
        available_abilities = await bot.get_available_abilities(spawning_pool)
        if metabolic_boost in available_abilities:
            bot_logger.log_action(bot, 'upgrading metabolic boost')
            await bot.do(spawning_pool(metabolic_boost))
            return True
    return False
示例#10
0
    async def __build_refinery(self, bot: sc2.BotAI):
        if bot.units(UnitTypeId.REFINERY).amount < 2:
            if bot.can_afford(UnitTypeId.REFINERY):
                vgs = bot.state.vespene_geyser.closer_than(20.0, bot.cc)
                for vg in vgs:
                    if bot.units(UnitTypeId.REFINERY).closer_than(1.0,
                                                                  vg).exists:
                        break

                    worker = bot.select_build_worker(vg.position)
                    if worker is None:
                        break

                    await bot.do(worker.build(UnitTypeId.REFINERY, vg))
                    break
示例#11
0
    def assign_probe(self, bot: sc2.BotAI, unit: Unit, prio_gas: bool):
        """
        Assigns the unit (PROBE) to either the closes gas or mineral patch depending
        on prio_gas
        """
        if prio_gas:
            if not self.assign_closest_gas(
                    bot, unit) and not self.assign_closest_mineral(bot, unit):
                closest_mineral = bot.mineral_field.closest_to(unit)
                bot.do(unit.gather(closest_mineral))

        else:
            if not self.assign_closest_mineral(
                    bot, unit) and not self.assign_closest_gas(bot, unit):
                closest_mineral = bot.mineral_field.closest_to(unit)
                bot.do(unit.gather(closest_mineral))
示例#12
0
async def build_building_once(bot: BotAI,
                              building: UnitTypeId,
                              location: Union[Point2, Point3, Unit],
                              max_distance: int = 20,
                              unit: Optional[Unit] = None,
                              random_alternative: bool = True,
                              placement_step: int = 2):
    if not bot.units(building).ready.exists and not bot.already_pending(
            building) and bot.can_afford(building):
        bot_logger.log_action(bot,
                              "building {} at {}".format(building, location))
        return await bot.build(building,
                               near=location,
                               max_distance=max_distance,
                               unit=unit,
                               random_alternative=random_alternative,
                               placement_step=placement_step)
示例#13
0
def test_empty():
    queue = ExpenseQueue(BotAI())
    assert_(queue.is_empty())                   # queue is initially empty

    queue.put(lambda item: None)
    assert_(not queue.is_empty())               # there is an action enqueued

    queue.get()
    assert_(queue.is_empty())                   # and now it should be gone
示例#14
0
 def assign_closest_mineral(self, bot: sc2.BotAI, unit: Unit) -> bool:
     """
     Assigns unit to the closest mineral field that is not utilized
     """
     bases = bot.townhalls.ready.sorted_by_distance_to(unit.position)
     for mining_place in bases:
         if mining_place.surplus_harvesters < 0:
             local_minerals = {
                 mineral for mineral \
                     in bot.mineral_field if mineral.distance_to(mining_place) <= 8
             }
             target_mineral = max(
                 local_minerals,
                 key=lambda mineral: mineral.mineral_contents,
                 default=None)
             bot.do(unit.gather(target_mineral))
             return True
     return False
示例#15
0
 def draw_influence_in_game(self, bot: BotAI, grid: np.ndarray,
                            lower_threshold: int, upper_threshold: int,
                            color: Tuple[int, int, int], size: int) -> None:
     height: float = bot.get_terrain_z_height(bot.start_location)
     for x, y in zip(*np.where((grid > lower_threshold)
                               & (grid < upper_threshold))):
         pos: Point3 = Point3((x, y, height))
         if grid[x, y] == np.inf:
             val: int = 9999
         else:
             val: int = int(grid[x, y])
         bot.client.debug_text_world(str(val), pos, color, size)
示例#16
0
 def is_base_full(self, bot: sc2.BotAI, base: Unit) -> bool:
     """
     Returns True if all 'numbers' are full over a nexus and its assimilators
     """
     # find the assimilators close to this base
     assimilators = bot.structures(ASSIMILATOR).closer_than(
         8,
         base.position).filter(lambda assimilator: assimilator.has_vespene)
     count = sum(
         map(lambda assimilator: assimilator.assigned_harvesters,
             assimilators))
     count += base.assigned_harvesters
     return count >= (base.ideal_harvesters + 3 * assimilators.amount)
示例#17
0
async def micro_zealots(bot: BotAI):
    zealots = bot.units(ZEALOT).ready
    actions = []
    for zealot in zealots:
        if bot.known_enemy_units.exists:
            actions.append(
                zealot.attack(bot.known_enemy_units.closest_to(
                    zealot.position)))
        else:
            target = bot.known_enemy_structures.random_or(
                bot.known_enemy_units.random_or(bot.enemy_start_locations[0]))
            actions.append(zealot.attack(target))
    await bot.do_actions(actions)
示例#18
0
async def depots_required(bot: sc2.BotAI, ) -> int:
    """
    Returns the number of supply depots needed based on bot's production structures
    """
    growth_speed = 0
    townhall_count = bot.structures({
        UnitTypeId.COMMANDCENTER, UnitTypeId.PLANETARYFORTRESS,
        UnitTypeId.ORBITALCOMMAND
    }).ready.amount

    rax_count = bot.structures(UnitTypeId.BARRACKS).ready.amount
    rax_count += bot.structures(UnitTypeId.BARRACKSREACTOR).ready.amount

    factory_count = bot.structures(UnitTypeId.FACTORY).ready.amount
    factory_count += bot.structures(UnitTypeId.FACTORYREACTOR).ready.amount
    starport_count = bot.structures(UnitTypeId.STARPORT).ready.amount
    starport_count += bot.structures(UnitTypeId.STARPORTREACTOR).ready.amount

    # Probes/scv take 12 seconds to build
    # https://liquipedia.net/starcraft2/Nexus_(Legacy_of_the_Void)
    growth_speed += townhall_count / 12.0

    # https://liquipedia.net/starcraft2/Barracks_(Legacy_of_the_Void)
    # fastest usage is marauder supply with 2 supply and train 21 seconds
    growth_speed += rax_count * 2 / 21.0

    # https://liquipedia.net/starcraft2/Factory_(Legacy_of_the_Void)
    # fastest usage is helliom with 2 supply and build time of 21 seconds
    growth_speed += factory_count * 2 / 21.0

    # https://liquipedia.net/starcraft2/Starport_(Legacy_of_the_Void)
    # We'll use viking timing here
    growth_speed += starport_count * 2 / 30.0

    growth_speed *= 1.2  # Just a little bit of margin of error
    build_time = 21  # depot build time
    # build_time += min(self.ai.time / 60, 5) # probe walk time

    predicted_supply = min(200, bot.supply_used + build_time * growth_speed)
    current_depots = bot.structures({
        UnitTypeId.SUPPLYDEPOT, UnitTypeId.SUPPLYDEPOTLOWERED,
        UnitTypeId.SUPPLYDEPOTDROP
    }).ready.amount

    if bot.supply_cap == 200:
        return current_depots

    return ceil((predicted_supply - bot.supply_cap) / 8) + current_depots
示例#19
0
async def micro_sentries(bot: BotAI):
    sentries = bot.units(SENTRY).ready
    actions = []
    for sentry in sentries:
        if bot.known_enemy_units.exists:
            closest_known_enemy = bot.known_enemy_units.closest_to(
                sentry.position)
            if sentry.target_in_range(closest_known_enemy):
                guardian_shield = AbilityId.GUARDIANSHIELD_GUARDIANSHIELD
                can_cast = await bot.can_cast(sentry, guardian_shield)
                if can_cast:
                    actions.append(sentry(guardian_shield))
            actions.append(sentry.attack(closest_known_enemy))
        else:
            target = bot.known_enemy_structures.random_or(
                bot.known_enemy_units.random_or(bot.enemy_start_locations[0]))
            actions.append(sentry.attack(target))
    await bot.do_actions(actions)
示例#20
0
async def micro_stalkers(bot: BotAI):
    stalkers = bot.units(STALKER).ready
    actions = []
    for stalker in stalkers:
        enemy_threats_close = bot.known_enemy_units.filter(
            lambda x: x.can_attack_ground).closer_than(
                15, stalker)  # threats that can attack
        if enemy_threats_close.exists:
            closest_enemy = enemy_threats_close.sorted_by_distance_to(
                stalker).first
            if stalker.weapon_cooldown == 0:
                actions.append(stalker.attack(closest_enemy))
            elif not bot.known_enemy_units.filter(
                    lambda x: x.can_attack_ground).closer_than(3,
                                                               stalker).exists:
                actions.append(stalker.move(closest_enemy.position))
        else:
            target = bot.known_enemy_structures.random_or(
                bot.known_enemy_units.random_or(bot.enemy_start_locations[0]))
            actions.append(stalker.attack(target))
    await bot.do_actions(actions)
示例#21
0
async def micro_immortals(bot: BotAI):
    immortals = bot.units(IMMORTAL).ready
    actions = []
    for immortal in immortals:
        enemy_threats_close = bot.known_enemy_units.filter(
            lambda x: x.can_attack_ground).closer_than(
                15, immortal)  # threats that can attack
        if enemy_threats_close.exists:
            closest_enemy = enemy_threats_close.sorted_by_distance_to(
                immortal).first
            if immortal.weapon_cooldown == 0:
                actions.append(immortal.attack(closest_enemy))
            elif not bot.known_enemy_units.filter(
                    lambda x: x.can_attack_ground).closer_than(
                        5, immortal).exists:
                actions.append(immortal.move(closest_enemy.position))
        else:
            target = bot.known_enemy_structures.random_or(
                bot.known_enemy_units.random_or(bot.enemy_start_locations[0]))
            actions.append(immortal.attack(target))
    await bot.do_actions(actions)
示例#22
0
    async def on_step(self, bot: sc2.BotAI, iteration):
        ramp_pos = bot.main_base_ramp.protoss_wall_warpin
        if self.state == "DEFENCE":
            if len(self.army) >= self.squad_size:
                self.squads.append(self.army.copy())
                self.army.clear()
            for unit in self.army:
                bot.do(unit.attack(ramp_pos))

        # select all enemy units, filter out invis units
        targets = (
            bot.enemy_units
            | bot.enemy_structures).filter(lambda unit: unit.can_be_attacked)
        for squad in self.squads:
            for unit in squad:
                if targets:
                    target = targets.closest_to(unit)
                    bot.do(unit.attack(target))
                else:
                    bot.do(unit.attack(bot.enemy_start_locations[0]))
示例#23
0
def get_random_larva(bot: BotAI) -> Union[Unit, None]:
    larva = bot.units(UnitTypeId.LARVA).ready
    return larva.exists and larva.random
示例#24
0
async def build_overlord(bot: BotAI, larva):
    if bot.can_afford(UnitTypeId.OVERLORD):
        unit = larva if larva else get_random_larva(bot)
        if unit:
            bot_logger.log_action(bot, "building overlord")
            return await bot.do(unit.train(UnitTypeId.OVERLORD))
示例#25
0
async def build_zergling(bot: BotAI, larva):
    unit = larva if larva else get_random_larva(bot)
    if unit and bot.can_afford(UnitTypeId.ZERGLING) and bot.units(UnitTypeId.SPAWNINGPOOL).ready.exists:
        bot_logger.log_action(bot, "building zergling")
        return await bot.do(unit.train(UnitTypeId.ZERGLING))
示例#26
0
 async def __train_scv(self, bot: sc2.BotAI):
     # train SCVs
     if bot.can_afford(
             UnitTypeId.SCV) and bot.workers.amount < 20 and bot.cc.noqueue:
         await bot.do(bot.cc.train(UnitTypeId.SCV))
示例#27
0
def mock_ai() -> BotAI:
    ai = BotAI()
    ai.unit_command_uses_self_do = True
    ai._initialize_variables()
    # ai = mock.Mock(bot_object)
    ai._distances_override_functions(0)
    ai.actions = []
    ai.config = {"general": mock.Mock(), "debug_log": mock.Mock()}
    ai.config["general"].getboolean = lambda x: False
    ai.config["debug_log"].getboolean = lambda x, fallback: False
    ai.my_race = Race.Protoss
    ai.enemy_race = Race.Protoss

    ai.state = mock.Mock()
    ai.state.effects = []
    ai.state.visibility.__getitem__ = lambda s, x: 2

    ai._client = mock.Mock()

    ai._game_info = mock.Mock()
    ai._game_info.player_start_location = MAIN_POINT
    ai._game_info.start_locations = [ENEMY_MAIN_POINT]
    ai._game_info.placement_grid.height = 100
    ai._game_info.placement_grid.width = 100
    ai._game_info.map_center = Point2((50, 50))
    ai._game_info.map_name = "Mock"
    ai._game_info.terrain_height.__getitem__ = lambda s, x: 0
    ai._game_info.terrain_height.data_numpy = [0]
    ai._game_info.map_ramps = []

    ai._game_data = mock.Mock()
    ai._game_data.unit_types = {}
    ai._game_data.units = {
        UnitTypeId.MINERALFIELD.value: mock.Mock(),
        UnitTypeId.PROBE.value: mock.Mock(),
    }

    ai._game_data.units[UnitTypeId.MINERALFIELD.value].has_minerals = True
    ai._game_data.units[UnitTypeId.MINERALFIELD.value].attributes = {}
    ai._game_data.units[UnitTypeId.PROBE.value].attributes = {}
    ai._game_data.abilities = {AbilityId.HARVEST_GATHER.value: mock.Mock()}
    ai._game_data.abilities[
        AbilityId.HARVEST_GATHER.value].id = AbilityId.HARVEST_GATHER

    for typedata in BUILDING_IDS:
        ai._game_data.units[typedata.value] = mock.Mock()
        ai._game_data.units[typedata.value].attributes = {IS_STRUCTURE}

    ai._game_data.units[UnitTypeId.ASSIMILATOR.value].has_vespene = True
    ai._game_data.units[UnitTypeId.ASSIMILATORRICH.value].has_vespene = True

    mineral = create_mineral(ai, Point2((16, 10)))
    mineral2 = create_mineral(ai, Point2((16, 60)))

    ai._expansion_positions_list = [
        MAIN_POINT, NATURAL_POINT, ENEMY_MAIN_POINT, ENEMY_NATURAL_POINT
    ]
    ai._resource_location_to_expansion_position_dict = {
        mineral.position: MAIN_POINT,
        mineral2.position: NATURAL_POINT
    }

    return ai
示例#28
0
 async def __train_siegetank(self, bot: sc2.BotAI):
     for fact in bot.units(UnitTypeId.FACTORY).ready.noqueue:
         if not bot.can_afford(UnitTypeId.SIEGETANK):
             break
         await bot.do(fact.train(UnitTypeId.SIEGETANK))
示例#29
0
 async def __train_reapers(self, bot: sc2.BotAI):
     for rax in bot.units(UnitTypeId.BARRACKS).ready.noqueue:
         if not bot.can_afford(UnitTypeId.REAPER):
             break
         await bot.do(rax.train(UnitTypeId.REAPER))
示例#30
0
def get_closest_pylon_to_enemy_base(bot: BotAI):
    proxy_pylon = bot.units(PYLON).closest_to(bot.enemy_start_locations[0])
    return proxy_pylon