Skip to content

Instantly share code, notes, and snippets.

@DrekkSama
Last active October 2, 2025 03:26
Show Gist options
  • Select an option

  • Save DrekkSama/320aae5169d625128182510fc595e260 to your computer and use it in GitHub Desktop.

Select an option

Save DrekkSama/320aae5169d625128182510fc595e260 to your computer and use it in GitHub Desktop.
Expansion Logic Example
"""
Intelligent Expansion System for StarCraft 2 Bot
Based on professional player decision-making patterns
"""
from sc2.bot_ai import BotAI
from sc2.ids.unit_typeid import UnitTypeId
class SmartExpansionBot(BotAI):
async def on_step(self, iteration: int):
"""Main game loop"""
if self.should_expand():
await self.expand_now()
def should_expand(self) -> bool:
"""
Decide when to expand based on two core factors:
1. Resource starvation (want to produce but can't afford)
2. Base depletion (mineral patches running low)
Safety-gated: Only expand if army is strong enough
"""
# Gate: Safety first - don't expand if unsafe
if not self.is_safe_to_expand():
return False
# Core logic: Expand if resource-starved OR bases depleting
return self.is_resource_starved() or self.are_bases_depleting()
def is_resource_starved(self) -> bool:
"""
Detect if we want to produce but lack income.
Signal: Production buildings idle + low minerals + some income
"""
idle_production = self.state.score.idle_production_time
current_minerals = self.minerals
income_rate = self.state.score.collection_rate_minerals
return (
idle_production > 30.0 # 30+ seconds of idle production
and current_minerals < 500 # Low mineral bank
and income_rate > 0 # But we have some income
)
def are_bases_depleting(self) -> bool:
"""
Detect if mineral patches are running low.
Check actual mineral contents of patches.
"""
depleted_bases = 0
for townhall in self.townhalls:
nearby_minerals = self.mineral_field.closer_than(10, townhall)
if nearby_minerals:
# Count patches with less than 300 minerals
low_patches = [m for m in nearby_minerals
if m.mineral_contents < 300]
# Base is depleted if >50% of patches are low
if len(low_patches) / len(nearby_minerals) > 0.5:
depleted_bases += 1
return depleted_bases > 0
def is_safe_to_expand(self) -> bool:
"""
Simple army safety check.
Don't expand if enemy army is much stronger.
"""
# Count army supply
own_army_supply = sum(unit.supply_cost for unit in self.units
if unit.type_id not in {UnitTypeId.PROBE,
UnitTypeId.OBSERVER})
# Simple heuristic: need at least some army
min_army_supply = 20 if self.time > 5 * 60 else 10
return own_army_supply >= min_army_supply
# Example decision flow
"""
Time: 06:30
Army Supply: 35 ✓ (safe to expand)
Idle Production: 45 seconds
Current Bank: 250 minerals
Income Rate: 850 minerals/min
Decision: EXPAND
Reason: Resource starved (45s idle + low bank)
---
Time: 08:15
Army Supply: 42 ✓ (safe to expand)
Idle Production: 12 seconds (not starved)
Base 1: 6/8 patches below 300 minerals (75% depleted)
Base 2: 2/8 patches below 300 minerals
Decision: EXPAND
Reason: Base 1 is depleting
---
Time: 04:20
Army Supply: 8 ✗ (not safe)
Idle Production: 35 seconds
Current Bank: 180 minerals
Decision: DO NOT EXPAND
Reason: Army not safe (8 < 10 minimum)
---
Time: 07:00
Army Supply: 28 ✓ (safe to expand)
Idle Production: 8 seconds (not starved)
Base 1: 2/8 patches below 300 minerals (25%)
Base 2: 1/8 patches below 300 minerals (12%)
Decision: DO NOT EXPAND
Reason: Not resource starved AND bases not depleting
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment