Programming Policies

A policy is an ASL program that declares what the game state should look like at each point in time. The compiler plans the build order. The runtime executes it. You iterate by editing the policy and reloading.

Each tutorial below shows the ASL source, the asctl compile output, and the terminal output from running the game.

Tutorial 1: Zergling Rush

A Zerg rush uses a single state with a tight deadline. You declare the army you want and when you need it — the compiler handles everything else.

zergling_rush.asl
strategy "Zergling Rush" for Zerg on patch 4.10.0 {
    trajectory {
        state "rush" by 4:00 {
            have Zergling: 12
            workers >= 13
            attack enemy.main priority [army, supply, workers]
        }
    }
}
$ asctl compile zergling_rush.asl
Zergling Rush | Zerg | patch 4.10.0
──────────────────────────────────────

Segment #0: "rush" (deadline 4:00)
 #  Action                 EST
──────────────────────────────────────
 1  Build SpawningPool     0:12
 2  Train Overlord         0:21
 3  Train Worker           0:39
 4  Train Zergling x2      0:58
 5  Train Zergling x2      1:15
 6  Train Zergling x2      1:32
 7  Train Zergling x2      1:49
 8  Train Zergling x2      2:06
 9  Train Zergling x2      2:23
10  Attack enemy main       —
    priority [army, supply, workers]

Expected: 13 workers | 19/22 supply
  Zergling x12

What the compiler did: It added an Overlord for supply and scheduled 6 pairs of Zerglings (Zerglings always train in pairs). The Drone that morphs into the SpawningPool is consumed — Zerg workers sacrifice themselves to become buildings. Because the attack is in the same state as production, Zerglings attack as soon as they hatch — a continuous stream of pressure while more eggs are hatching back home.

Tutorial 2: Bio Push

A Terran timing attack uses two states — first build infrastructure, then army. The second state inherits everything from the first and only plans the delta.

bio_push.asl
strategy "Bio Push" for Terran on patch 4.10.0 {
    trajectory {
        state "opener" by 3:30 {
            have Barracks: 2
            workers >= 16
        }
        state "push" by 8:00 {
            have Marine: 8
            have Marauder: 2
            upgrade Stimpack
            attack enemy.main priority [army, workers]
        }
    }
}
$ asctl compile bio_push.asl
Bio Push | Terran | patch 4.10.0
──────────────────────────────────────

Segment #0: "opener" (deadline 3:30)
 #  Action                 EST
──────────────────────────────────────
 1  Build Supply           0:04
 2  Train Worker           0:08
 3  Build Barracks         0:25
 4  Build Barracks         0:30
 5  Train Worker           0:38
 6  Train Worker           0:50
 7  Train Worker           1:02

Expected: 16 workers | 16/23 supply
  Barracks x2

Segment #1: "push" (deadline 8:00)
 #  Action                 EST
──────────────────────────────────────
 1  Build Gas              1:16
 2  Train Marine           1:16
 3  Train Marine           1:16
 4  Train Marine           1:35
 5  Train Marine           1:35
 6  Train Marine           1:53
 7  Train Marine           1:53
 8  Assign 3 gas workers   2:11
 9  Train Marine           2:11
10  Build Supply           2:11
11  Train Marine           2:32
12  Train Marauder         2:40
13  Train Marauder         2:50
14  Research Stimpack      3:25
15  Attack enemy main       —
    priority [army, workers]

Expected: 16 workers | 28/31 supply
  Marine x8, Marauder x2
  Stimpack

What the compiler did: Segment 1 inherits the 2 Barracks from segment 0 — it only trains the delta. The compiler added a Refinery for gas (needed for Marauders and Stimpack) and scheduled Marines first while gas accumulates. The attack goal tells the runtime to send the army to the enemy main once combat units are ready, targeting army first, then workers.

Tutorial 3: Stalker-Colossus

A Protoss tech build uses three states — opener, tech transition, and power spike. Each state inherits from the last; counts are absolute targets, not deltas.

stalker_colossus.asl
strategy "Stalker-Colossus" for Protoss on patch 4.10.0 {
    trajectory {
        state "opener" by 3:30 {
            have Gateway: 1
            have CyberneticsCore: 1
            have Stalker: 2
            workers >= 16
        }
        state "tech" by 6:00 {
            have RoboticsFacility: 1
            have Gateway: 2
            have Stalker: 4
            workers >= 22
        }
        state "power" by 9:00 {
            have RoboticsBay: 1
            have Colossus: 2
            have Stalker: 6
            upgrade ExtendedThermalLance
            workers >= 28
            attack enemy.main
        }
    }
}
$ asctl compile stalker_colossus.asl
Stalker-Colossus | Protoss | 4.10.0
──────────────────────────────────────

Segment #0: "opener" (deadline 3:30)
 #  Action                 EST
──────────────────────────────────────
 1  Build Supply           0:04
 2  Build Gas              0:10
 3  Build Gateway          0:22
 4  Train Worker           0:26
 5  Assign 3 gas workers   0:31
 6  Train Worker           0:38
 7  Train Worker           0:50
 8  Train Worker           1:02
 9  Build CyberneticsCore  1:08
10  Train Stalker          1:44
11  Train Stalker          2:14

Expected: 16 workers | 20/23 supply
  Stalker x2

Segment #1: "tech" (deadline 6:00)
 ...11 actions

Segment #2: "power" (deadline 9:00)
 ...16 actions

Expected: 28 workers | 52/55 supply
  Colossus x2, Stalker x6
  ExtendedThermalLance

What the compiler did: Three segments, each inheriting from the last. Segment 1 already has the Gateway and CyberneticsCore — it only builds the delta. Protoss Probes warp buildings and return immediately to mining. The attack goal in the final segment sends the deathball to the enemy main once both Colossi are out.

Shaping Strategy

Influencing priorities within a state

Each state only needs to declare what you care about. The planner infers prerequisites and fills in the rest — you don't need to specify every building and unit explicitly. The more specific you are, the more you influence how the planner reaches the end state.

Worker count shapes the balance between economy and production. A high target like workers >= 22 tells the planner to invest in economy early. Omitting a worker count frees the planner to minimize workers and rush army instead.

Compare the tutorials above: the Zergling Rush specifies workers >= 13 (just one more than starting), so the planner cuts workers to flood Zerglings. The Stalker-Colossus build specifies increasing worker targets (16 → 22 → 28), producing a steady macro game.

Attacking

The attack requirement tells the runtime to send combat units to a location. An optional priority list controls targeting: army, workers, supply, production, base, buildings.

Where you place the attack changes when it fires. An attack in the same state as production activates immediately — the army attacks while production continues. An attack in a separate subsequent state waits for the previous segment to complete first, then hits with the full force.

Adaptive play with branches

For runtime adaptation, use branch with situations. The compiler pre-plans every branch; the runtime picks at the branch point based on the game state.

adaptive.asl
strategy "Adaptive Opener" for Protoss on patch 4.10.0 {
    trajectory {
        state "opener" by 3:30 {
            have Gateway: 1
            have CyberneticsCore: 1
            have Stalker: 2
            workers >= 16
        }
        branch {
            when early_pressure -> {
                state "defense" by 6:00 {
                    have Gateway: 3
                    have Stalker: 6
                    have ShieldBattery: 1
                }
            }
            otherwise -> {
                state "expand" by 7:00 {
                    have RoboticsFacility: 1
                    have Gateway: 2
                    have Stalker: 4
                    workers >= 22
                }
            }
        }
    }
    situations {
        early_pressure = army_supply > 10 and time < 4:00
    }
}

How it works: The compiler plans both branches from the opener's end state. At runtime, if early_pressure is true (enemy has >10 army supply before 4:00), it follows the defensive branch. Otherwise, it expands.

Deep Dives

  • ASL Reference — complete grammar, all sections, full compilable example
  • Build Reference — CPA build order output, segment structure, critical path analysis
← Back to home