Skip to main content

6.2 - Micro-management - Controlling Units in Combat

If macro-management is about building a bigger army, micro-management ("micro") is about making that army fight smarter. It is the fine-grained, real-time control of individual units in combat to maximize their value, minimize losses, and ultimately win battles against superior numbers.

Effective micro is the difference between a clumsy mob of units and a coordinated, intelligent fighting force. It is where a bot's "skill" truly shines.

The Micro-management System

Micro logic is a continuous, rapid decision-making loop that runs for each unit during combat.

(For each unit in a fight...)
|
v
.---- 1. ASSESS THREAT --------.
| - Who is the biggest danger? |
| - Am I in a bad position? |
`------------------------------`
|
v
.--- 2. ASSESS SELF ----.
| - Is my health low? |
| - Is my weapon ready? |
`-----------------------`
|
v
.---- 3. DECIDE & ACT --------.
| - Retreat? |
| - Reposition? |
| - Attack a priority target? |
`-----------------------------`

This loop runs inside your on_step method, evaluating the state of each unit and issuing precise commands to optimize its performance.


Core Micro Techniques: A Tactical Overview

TechniqueGoalHow It WorksKey python-sc2 Tool
Focus FiringEliminate threats quickly.Command all your units to attack the same high-value enemy target (e.g., a Siege Tank or High Templar).Units.closest_to()
army.attack(target)
Kiting (Stutter-Step)Maximize damage, minimize risk.For ranged units: move away from the enemy while your weapon is on cooldown, then stop to fire as soon as it's ready.unit.weapon_cooldown
Retreating Damaged UnitsPreserve your army.Pull individual, low-health units out of the fight to save them for later. A surviving unit is better than a dead one.unit.health_percentage
unit.move(safe_location)
SplittingMitigate splash damage.Move units away from each other to reduce the number hit by a single enemy area-of-effect attack (e.g., from a Baneling).unit.move()

A Developer's Checklist for Micro Logic

When implementing micro for a group of units, this is your plan:

  • 1. Define a Threat. Identify what constitutes a "dangerous" situation (e.g., enemy units are within a certain range).
  • 2. Select a Priority Target. Find the single most important enemy unit for the entire group to focus on.
  • 3. Loop Through Your Units. For each unit in your army:
    • Check its individual condition (health, cooldowns).
    • Issue Commands Directly. Decide on its best action (attack the priority target, retreat, or reposition) and call the appropriate method (e.g., unit.attack(target)). The library will automatically queue and execute these at the end of the step.

Code Example: The "Skirmisher" Bot

This bot demonstrates two fundamental micro techniques: focus firing and retreating damaged units. It builds a force of Marines and, when it engages the enemy, it will intelligently focus fire and pull back weakened units to preserve its army.

# skirmisher_bot.py

from sc2 import maps
from sc2.bot_ai import BotAI
from sc2.data import Difficulty, Race
from sc2.main import run_game
from sc2.player import Bot, Computer
from sc2.ids.unit_typeid import UnitTypeId
from sc2.units import Units

class SkirmisherBot(BotAI):
"""A bot that demonstrates focus firing and retreating damaged units."""

async def on_step(self, iteration: int):
# We need an army to command.
await self.build_army()

army: Units = self.units(UnitTypeId.MARINE)
if not army.exists:
return

# If there are no enemies, attack-move towards their base.
if not self.enemy_units.exists:
for unit in army.idle:
unit.attack(self.enemy_start_locations[0])
return

# --- Micro Logic Begins ---
# 1. Select a Priority Target for the entire army.
# We'll target the enemy unit with the lowest health to eliminate it quickly.
priority_target = self.enemy_units.sorted(lambda u: u.health).first

# 2. Define a safe retreat position.
retreat_position = self.start_location.towards(self.game_info.map_center, 15)

# 3. Loop through our units and issue a command for each.
for marine in army:
# If the marine is badly damaged, retreat it.
if marine.health_percentage < 0.4:
marine.move(retreat_position)
# Otherwise, command it to attack the priority target.
else:
marine.attack(priority_target)


async def build_army(self):
"""A simple helper method to produce units for the demo."""
if self.supply_left < 2 and not self.already_pending(UnitTypeId.SUPPLYDEPOT):
if self.can_afford(UnitTypeId.SUPPLYDEPOT):
await self.build(UnitTypeId.SUPPLYDEPOT, near=self.start_location.towards(self.game_info.map_center, 5))

if not self.structures(UnitTypeId.BARRACKS).exists and not self.already_pending(UnitTypeId.BARRACKS):
if self.can_afford(UnitTypeId.BARRACKS):
await self.build(UnitTypeId.BARRACKS, near=self.start_location.towards(self.game_info.map_center, 8))

if self.structures(UnitTypeId.BARRACKS).ready.idle.exists and self.can_afford(UnitTypeId.MARINE):
self.train(UnitTypeId.MARINE)


if __name__ == "__main__":
run_game(
maps.get("GresvanAIE"),
[
Bot(Race.Terran, SkirmisherBot()),
Computer(Race.Zerg, Difficulty.Medium)
],
realtime=True,
)