Creating a Zerg Rush Bot in Python From Scratch


soO_Bot is down 0-1 in the Finals against Cure_Bot in ProBots.
The crowd is buzzing. soO_Bot needs to pull off something bold to stay in the match. There’s no time to play it safe—the best chance for a comeback is to go all-in with some perfectly executed 12 Pool Zerg Rush. Can you help soO_Bot even the score?


Objective:

Help soO_Bot Spawn Zerglings and Launch a Rush to the Enemy Base after 12 Supply!


Instructions:

  1. Download the starter template to begin.
  2. Add your code to the on_step function to execute the Zerg Rush strategy. This function is called every game loop.
from sc2.bot_ai import BotAI, Race
from sc2.data import Result
from sc2.ids.unit_typeid import UnitTypeId  # References StarCraft II unit types

class CompetitiveBot(BotAI):
    NAME: str = "CompetitiveBot"
    RACE: Race = Race.Zerg

    async def on_start(self):
        print("Game started")

    async def on_step(self, iteration: int):
        # Add logic here
        pass

Resources:


Stuck?

Hint 1:

How can your bot know when it’s at 12 supply to start building a Spawning Pool? Explore the bot’s attributes related to “supply” in the Python-SC2 documentation.

Nudge: Look into self.supply_used to check the current supply. Once you reach 12 supply, use a worker unit (Drone) to construct a building at a specific location. The build() function might help.

Hint 2:

How can your bot train Zerglings after the Spawning Pool is complete? What unit is responsible for spawning Zerglings?

Nudge: Use UnitTypeId.LARVA to find Larvae and command them to train Zerglings. After Zerglings are ready, use self.enemy_start_locations to identify where they should attack.

Solution (if you're truly stuck)
from sc2.bot_ai import BotAI, Race
from sc2.data import Result
from sc2.ids.unit_typeid import UnitTypeId

class CompetitiveBot(BotAI):
    NAME: str = "CompetitiveBot"
    RACE: Race = Race.Zerg

    async def on_start(self):
        print("Game started")

    async def on_step(self, iteration: int):
        if self.supply_used >= 12:
            if (
                self.structures(UnitTypeId.SPAWNINGPOOL).amount
                + self.already_pending(UnitTypeId.SPAWNINGPOOL) == 0
            ):
                if self.can_afford(UnitTypeId.SPAWNINGPOOL):
                    await self.build(UnitTypeId.SPAWNINGPOOL, near=self.townhalls.first)

        if self.structures(UnitTypeId.SPAWNINGPOOL).ready and self.larva:
            if self.can_afford(UnitTypeId.ZERGLING):
                self.train(UnitTypeId.ZERGLING, self.larva.amount)

        if self.units(UnitTypeId.ZERGLING).ready:
            for zergling in self.units(UnitTypeId.ZERGLING):
                zergling.attack(self.enemy_start_locations[0])

Extra:

Discussion for this lab, feedback or questions about it welcomed!