archive by month
Skip to content

an amusing Steamhammer bug

I was testing a macro build on the map Baekmagoji, a 2 player map where macro builds are fitting because each main base has 2 geysers and 18 mineral patches—double the usual. (I routinely test on all kinds of maps.) Early in the game, Steamhammer suddenly panicked and canceled a hatchery to get its spawning pool immediately. What was going on?

The bug, or I should say bugs, turned out to be this: Because the enemy main was so rich in resources, Steamhammer decided “well, it’s a bit far away, but still it’s the best choice for my natural base.” When the scout found enemy buildings (“hey, that’s in my natural”), Steamhammer concluded that it was getting proxied. Panic! That was easy to fix; the chosen natural is not allowed to be a starting base. But wait, why was the first expansion hatchery already started somewhere else, so that it could be canceled? Because the choice of the natural base and the actual first expansion taken are not quite coordinated correctly; in some cases they can be different for no good reason. Ack!

Baekmagoji is a difficult map for bots. Another issue is that some of the mineral patches in the main are not reachable until other patches are mined out. It’s a clever design, but Steamhammer doesn’t understand it and tries to assign drones to minerals that they can’t reach. Well, that’s not important to fix yet. I can’t think of another competitive map that would trigger this bug (though more than a few Blizzard maps do). Also notice the neutral sunken colonies spreading creep, and the blocking temples and blocking minerals. Lots of tricks lying in wait.

AIIDE 2019 - what Steamhammer learned

Today is Steamhammer. With a mid-rank finish and the widest range of builds, plus informative game records, Steamhammer may give us the best insight into how other bots played.

The tournament was 100 rounds, and Steamhammer was configured to remember the previous 100 game records, because in play there is no reason to remember more (earlier records are increasingly discounted). Steamhammer also had pre-learned game records for many opponents, so when the game record count reached 100, new records added caused old pre-learned records to drop away. Not all 100 tournament games happened for each opponent, but the pre-learned games filled in the small gaps so that Steamhammer ended up with exactly 100 game records per opponent in every case.

The “opening” table counts Steamhammer’s opening choices. The “plan” table shows the plan that Steamhammer first predicted that the opponent would play, then recognized that the opponent was playing. Both prediction and recognition can be wrong. The timing table is new this year, an attempt to get a little more information out of Steamhammer’s rich game records. For some events, it gives the count of games in which the event occurred, and the median time, earliest time, and latest time it occurred in those games when it did. The times are given under the assumption that 1 second of game time is exactly 24 frames, a simplification.

gas steal attempt - When Steamhammer sent out the drone to steal gas (if it did).
gas steal success - Whether the gas steal attempt succeeded in taking the opponent’s gas. Steamhammer doesn’t record the time it happens, so this is only a success count.
enemy scout - When the enemy scout first reached Streamhammer’s base.
enemy combat units - When the first enemy combat unit was seen.
enemy air units - When the enemy is first known to have tech for flying units (except overlords).
enemy cloaked units - When the enemy is first known to have tech for cloaked units.


#1 locutus

openinggameswins
11Gas10PoolMuta10%
12Hatch12Pool10%
2.5HatchMuta20%
2HatchHydra10%
2HatchHydraBust40%
2HatchLingAllInSpire10%
3HatchHydraBust50%
3HatchHydraExpo10%
3HatchLateHydras+150%
3HatchLingBust230%
4HatchBeforeGas10%
4HatchBeforeLair50%
5HatchBeforeGas20%
5PoolHard2Player20%
5Scout10%
7PoolSoft10%
8-8HydraRush10%
8Hatch7Pool10%
8Pool10%
9Pool20%
9PoolHatch20%
9PoolSpeedAllIn10%
AntiFact_Overpool9Gas10%
DefilerRush20%
Over10Hatch2Sunk10%
Over10HatchSlowLings10%
Over10PoolMuta10%
OverhatchExpoLing20%
OverhatchExpoMuta20%
Overpool2HatchLurker10%
OverpoolHatch10%
OverpoolHydra120%
OverpoolSpeed40%
OverpoolSunk10%
Overpool_4HatchLing20%
PurpleSwarmBuild10%
Sparkle 1HatchMuta10%
Sparkle 2HatchMuta10%
ZvP_3BaseSpire+Den10%
ZvP_3HatchPoolHydra20%
ZvP_4HatchPoolHydra1421%
ZvT_12PoolMuta20%
ZvZ_12PoolLing10%
ZvZ_12PoolLingB10%
ZvZ_Overpool9Gas10%
45 openings1003%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Heavy rush--44%0%0%0%
Safe expand5656%2%4444%5%43%5%
Turtle4444%5%4545%2%43%9%
Unknown--77%0%0%0%
timing#medianearlylate
gas steal attempt431:290:002:34
gas steal success23---
enemy scout1001:351:116:51
enemy combat units1005:234:107:58
enemy air units712:057:3921:34
enemy cloaked units811:244:3921:34


It looks like Locutus opened forge-expand every game. It worked. Steamhammer desperately tried everything, including ZvZ builds and island builds, and finally squeezed 3 wins with a risky extreme macro opening, 4 hatcheries before spawning pool, which was able to win one game in five. I should add 5 and 6 hatch before pool and see if they help.

Locutus rarely made corsairs or dark templar. I wonder what its criteria are? Maybe it won before it got that far. The scout was usually quite early, and the first combat unit was seen late, as expected for a cannon-first opener.

I played over the 3 wins. They were in rounds 65, 70, and 73; after that, I expect that Locutus found a way to win. In 2 games, Steamhammer pulled ahead in early economy with its greedy opening, then struggled to defend and fell into a losing position. But Locutus got most of its units stuck in its base, and Steamhammer was able to turn it around and win after a hard fight with critical defiler support. In the third win, Locutus chose a zealot-archon unit mix that Steamhammer knows how to cope with, and zerg powered through.


#2 purplewave

openinggameswins
10Pool9Gas10%
11HatchTurtleHydra5044%
11HatchTurtleLurker10%
11HatchTurtleMuta1520%
12Hatch_4HatchLing10%
2HatchLingAllInSpire10%
3HatchHydraExpo10%
3HatchLing10%
3HatchLingExpo10%
4HatchBeforeLair10%
5PoolSoft10%
7Pool12Hatch10%
9PoolBurrow10%
AntiZeal_12Hatch10%
HiveRush10%
Over10Hatch20%
Over10Hatch1Sunk30%
Over10Hatch2Sunk10%
OverhatchLateGas10%
Overpool+110%
OverpoolSpeed10%
OverpoolTurtle20%
ZvP_3HatchPoolHydra10%
ZvT_7Pool10%
ZvZ_Overpool9Gas933%
25 openings10028%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Fast rush--22%0%0%0%
Heavy rush9999%28%9090%24%90%4%
Safe expand--33%100%0%0%
Turtle--11%100%0%0%
Unknown11%0%44%50%0%0%
timing#medianearlylate
gas steal attempt411:131:092:36
gas steal success37---
enemy scout982:131:1915:06
enemy combat units992:352:155:59
enemy air units5113:575:1520:37
enemy cloaked units4814:016:0217:11


PurpleWave in contrast went with mostly 2 gate openings against Steamhammer; that’s what “heavy rush” means for protoss. Steamhammer countered with early sunkens plus hydras or, less successfully, mutalisks (this version had a bug that weakened mutalisk play). There are also 3 wins with a ZvZ fast mutalisk opening. 2 gates should beat that, so protoss either played poorly or chose a different build in those games.


#3 bananabrain

openinggameswins
10HatchHydra10%
11Gas10PoolLurker20%
11Gas10PoolMuta1010%
11HatchTurtleHydra10%
12Hatch_4HatchLing10%
2.5HatchMuta10%
2HatchLingAllInSpire10%
3HatchHydra20%
3HatchHydraBust10%
3HatchHydraExpo10%
3HatchLateHydras10%
3HatchLingExpo911%
5PoolHard10%
6Pool10%
6PoolSpeed10%
7-7HydraLingRush10%
8Gas7PoolLurker B10%
9HatchMain9Pool9Gas10%
9PoolBurrow10%
9PoolSpeed10%
9PoolSpire10%
AntiFact_2Hatch1540%
AntiFact_Overpool9Gas10%
AntiZeal_12Hatch100%
Over10Hatch1Sunk10%
Over10HatchBust2825%
OverpoolSpeed10%
OverpoolTurtle 010%
ZvP_Overpool3Hatch20%
ZvT_3HatchMuta10%
30 openings10015%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Heavy rush7070%14%3232%3%33%39%
Naked expand22%0%11%100%0%50%
Proxy--44%0%0%0%
Safe expand2323%17%1616%31%17%35%
Turtle55%20%1010%20%0%20%
Unknown--3737%16%0%0%
timing#medianearlylate
gas steal attempt501:261:091:38
gas steal success31---
enemy scout1001:561:213:17
enemy combat units1002:562:198:19
enemy air units835:192:5111:41
enemy cloaked units616:263:2714:05


BananaBrain contrasts with both previous opponents in that it played a variety of builds. Steamhammer was unable to predict what was coming. It looks strange that the best reaction was an opening designed to counter terran factory-first builds that include a vulture runby, but in fact it is a mildly specialized 2 hatch mutalisk variant and not so surprising. BananaBrain made corsairs and dark templar in most games.


#4 daqin

openinggameswins
10HatchHydra10%
10Pool9Hatch10%
11Gas10PoolLurker119%
11Gas10PoolMuta10%
11HatchTurtleLurker10%
12Hatch12Pool10%
12HatchTurtle20%
12Hatch_4HatchLing20%
2HatchHydraBust10%
2HatchLurker10%
3HatchHydra10%
3HatchHydraBust10%
3HatchHydraExpo40%
3HatchLing10%
3HatchLingBust21020%
3HatchLingExpo10%
4HatchBeforeGas30%
4HatchBeforeLair30%
4PoolSoft10%
5HatchBeforeGas20%
5Scout10%
8-8HydraRush10%
8Hatch7Pool10%
8Hatch7PoolSpeed1916%
9GasLair10%
9HatchExpo9Pool9Gas20%
9PoolBurrow10%
9PoolSpeedAllIn10%
AntiFact_2Hatch10%
AntiFactory10%
OverhatchExpoLing30%
OverhatchExpoMuta10%
OverhatchLateGas10%
Overpool+110%
OverpoolSunk10%
ZvP_2HatchMuta10%
ZvP_3BaseSpire+Den110%
ZvZ_12Gas11Pool10%
ZvZ_12HatchMain10%
ZvZ_12Pool10%
40 openings1006%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Heavy rush--44%0%0%0%
Proxy--66%0%0%0%
Safe expand1111%9%2323%13%18%0%
Turtle8989%6%6363%5%62%4%
Unknown--44%0%0%0%
timing#medianearlylate
gas steal attempt431:261:091:58
gas steal success24---
enemy scout991:341:149:35
enemy combat units1005:264:076:58
enemy air units319:478:5416:19
enemy cloaked units369:447:2314:39


DaQin played forge-expand and has similar timings to Locutus, for the same reasons. The fast scout is to allow adjustment of the cannon count and timing, and the late combat units are due to getting a gateway later. Steamhammer couldn’t find any better reaction than to try to bust with zerglings, either early or late, and it was not particularly successful.


#6 zzzkbot

openinggameswins
2.5HatchMuta10%
3HatchLingExpo10%
9HatchExpo9Pool9Gas367%
9PoolLurker933%
9PoolSpeedAllIn10%
9PoolSunkHatch1258%
9PoolSunkSpeed933%
OverpoolSunk1338%
ZvZ_Overgas9Pool1258%
ZvZ_Overpool9Gas3982%
10 openings10059%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Turtle100100%59%7979%71%79%21%
Unknown--2121%14%0%0%
timing#medianearlylate
gas steal attempt261:141:111:37
gas steal success12---
enemy scout992:550:377:23
enemy combat units1004:062:254:43
enemy air units665:295:0310:11
enemy cloaked units0---


ZZZKBot mostly played a turtle-into-mutalisks strategy against Steamhammer, and was somewhat successful. You can read the idea straight out of the tables above. The 2:25 earliest timing but 4:06 median timing for combat units says that ZZZKBot sometimes rushed zerglings, but usually not.


#7 microwave

openinggameswins
11Gas10PoolLurker2843%
11Gas10PoolMuta1520%
2HatchHydra10%
3HatchLing10%
3HatchLingBust210%
5PoolHard10%
6Pool10%
7-7HydraLingRush10%
9GasLair10%
9HatchMain9Pool9Gas10%
9PoolLurker10%
OverhatchLing10%
OverhatchMuta2030%
OverpoolLurker10%
PurpleSwarmBuild10%
Sparkle 1HatchMuta812%
ZvZ_12HatchExpo10%
ZvZ_12HatchMain20%
ZvZ_Overpool11Gas10%
ZvZ_Overpool9Gas10%
ZvZ_OverpoolTurtle1225%
21 openings10025%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Heavy rush77%29%22%50%0%86%
Naked expand8989%26%2323%17%25%73%
Turtle44%0%11%0%0%75%
Unknown--7474%27%0%0%
timing#medianearlylate
gas steal attempt541:300:421:57
gas steal success1---
enemy scout1002:391:373:47
enemy combat units1002:272:143:58
enemy air units396:255:219:19
enemy cloaked units0---


Microwave played a 9 pool speed build into expansion and then spire, which you cannot read out of the plan table because Steamhammer didn’t recognize it accurately. But in the timing table you can see that combat units (zerglings) were early and air units (mutalisks) were not late.

Steamhammer was not able to steal Microwave’s gas. It probably should have stopped trying.


#8 iron

openinggameswins
2.5HatchMuta10%
5HatchBeforeGas10%
5Scout10%
7-7HydraLingRush4384%
8Gas7PoolLurker B10%
AntiFact_13Pool1155%
AntiFactory3964%
OverhatchExpoMuta10%
OverhatchMuta10%
Sparkle 2HatchMuta10%
10 openings10067%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Factory100100%67%9191%70%91%9%
Unknown--99%33%0%0%
timing#medianearlylate
gas steal attempt301:261:252:03
gas steal success0---
enemy scout873:270:3415:09
enemy combat units1002:592:295:27
enemy air units2313:5310:1120:07
enemy cloaked units696:395:3511:47


Look at that huge range of scout timings! 0:34 means that the scout SCV was sent immediately at the start of the game and went directly to the zerg base. 15:09 probably means that no enemy unit got into the base until the end of the game when Steamhammer lost (Steamhammer is on BWAPI 4.1.2 and cannot detect scans). Steamhammer prevented the scout entirely in 13 out of the 100 games by its own count; 15:09 is probably the same. Steamhammer was not able to steal Iron’s gas, and did eventually give up trying.


#9 xiaoyi

openinggameswins
12Hatch13Pool10%
2HatchLingAllInSpire1619%
2HatchLurkerAllIn10%
3HatchLurker10%
3HatchPoolMuta10%
5PoolSoft10%
7-7HydraLingRush3669%
7PoolMid2475%
AntiFact_13Pool933%
AntiFactory10%
AntiFactoryHydra812%
Over10Hatch10%
12 openings10050%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Factory9898%51%7474%41%74%21%
Naked expand--11%100%0%0%
Safe expand--33%33%0%0%
Unknown22%0%2222%82%0%50%
timing#medianearlylate
gas steal attempt461:261:052:08
gas steal success1---
enemy scout922:371:347:29
enemy combat units1002:392:253:22
enemy air units5512:238:5516:30
enemy cloaked units617:395:4217:07


Steamhammer liked 7 pool against XiaoYi, just as Microwave did, but also liked its dawn hydra rush.


#10 mcrave

openinggameswins
2HatchHydraBust580%
3HatchHydraBust667%
9PoolHatch1984%
Over10Hatch2Sunk3288%
Over10Hatch2SunkHard2692%
OverpoolTurtle1283%
6 openings10086%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Heavy rush9797%87%6464%80%63%19%
Safe expand22%100%1111%100%0%0%
Turtle11%0%77%100%0%0%
Unknown--1818%94%0%0%
timing#medianearlylate
gas steal attempt531:281:111:33
gas steal success33---
enemy scout922:211:149:55
enemy combat units982:422:158:51
enemy air units6910:025:0614:18
enemy cloaked units3010:295:0116:39

#11 ualbertabot

openinggameswins
5Scout2875%
Over10Hatch2Sunk10%
OverpoolTurtle7197%
3 openings10090%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Factory55%100%88%100%0%0%
Fast rush44%100%1111%100%0%25%
Heavy rush8686%88%4747%87%48%24%
Naked expand55%100%1010%100%0%40%
Unknown--2424%83%0%0%
timing#medianearlylate
gas steal attempt431:120:001:16
gas steal success23---
enemy scout792:111:194:23
enemy combat units612:431:464:33
enemy air units1014:2012:0216:57
enemy cloaked units1214:252:3816:57


Thanks to pre-learning, I expected Steamhammer to play its overpool turtle build every game. I’m not sure why it didn’t. I also don’t know how it hit on the 5 scout build, which means send out a drone at 5 supply to scout very early, then leave all decisions to the strategy boss. It’s a logical try against a random opponent, especially one that has a single strategy for each race, and it was fairly successful. But it did not appear in the pre-learned data.


#12 aitp

openinggameswins
7-7HydraLingRush1292%
9HatchExpo9Pool9Gas30100%
AntiFact_13Pool22100%
AntiFactory2195%
AntiFactoryHydra1493%
ZvT_3HatchMuta10%
6 openings10096%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Factory8787%97%3030%97%28%62%
Fast rush44%100%44%100%0%50%
Heavy rush44%100%22%100%25%50%
Turtle44%100%55%60%0%25%
Unknown11%0%5959%98%0%0%
timing#medianearlylate
gas steal attempt441:251:121:58
gas steal success3---
enemy scout253:312:4119:11
enemy combat units1003:231:578:09
enemy air units3111:277:4619:34
enemy cloaked units597:385:1916:34


AITP scored zip against both mass zerglings (9HatchExpo9Pool9Gas) and against fast mutalisks (AntiFact_13Pool). And it successfully scouted Steamhammer’s base only 25% of the time. If you don’t scout reliably, it will be hard to withstand rushes.


#13 bunkerboxer

openinggameswins
9PoolExpo42100%
9PoolSunkHatch31100%
9PoolSunkSpeed27100%
3 openings100100%
planpredictedrecognizedaccuracy
countgameswinscountgameswinsgood?
Proxy6666%100%3535%100%36%36%
Unknown--4242%100%0%0%
Worker rush3434%100%2323%100%15%53%
timing#medianearlylate
gas steal attempt401:351:321:37
gas steal success33---
enemy scout912:101:473:47
enemy combat units842:432:093:27
enemy air units0---
enemy cloaked units0---


Steamhammer was not able to judge whether BunkerBoxeR was playing a proxy (with its proxy bunker) or a worker rush (since it sent SCVs in support). But it didn’t matter. The reactions are nearly the same. Since BunkerBoxeR never wants gas, stealing its gas was a waste.


overall

totalZvTZvPZvZZvR
openinggameswinsgameswinsgameswinsgameswinsgameswins
10HatchHydra20% 20%
10Pool9Gas10% 10%
10Pool9Hatch10% 10%
11Gas10PoolLurker4132% 138% 2843%
11Gas10PoolMuta2715% 128% 1520%
11HatchTurtleHydra5143% 5143%
11HatchTurtleLurker20% 20%
11HatchTurtleMuta1520% 1520%
12Hatch12Pool20% 20%
12Hatch13Pool10% 10%
12HatchTurtle20% 20%
12Hatch_4HatchLing40% 40%
2.5HatchMuta50% 10% 30% 10%
2HatchHydra20% 10% 10%
2HatchHydraBust1040% 1040%
2HatchLingAllInSpire1916% 1619% 30%
2HatchLurker10% 10%
2HatchLurkerAllIn10% 10%
3HatchHydra30% 30%
3HatchHydraBust1331% 1331%
3HatchHydraExpo70% 70%
3HatchLateHydras10% 10%
3HatchLateHydras+150% 50%
3HatchLing30% 20% 10%
3HatchLingBust21414% 1315% 10%
3HatchLingExpo128% 119% 10%
3HatchLurker10% 10%
3HatchPoolMuta10% 10%
4HatchBeforeGas40% 40%
4HatchBeforeLair90% 90%
4PoolSoft10% 10%
5HatchBeforeGas50% 10% 40%
5PoolHard20% 10% 10%
5PoolHard2Player20% 20%
5PoolSoft20% 10% 10%
5Scout3168% 10% 20% 2875%
6Pool20% 10% 10%
6PoolSpeed10% 10%
7-7HydraLingRush9377% 9179% 10% 10%
7Pool12Hatch10% 10%
7PoolMid2475% 2475%
7PoolSoft10% 10%
8-8HydraRush20% 20%
8Gas7PoolLurker B20% 10% 10%
8Hatch7Pool20% 20%
8Hatch7PoolSpeed1916% 1916%
8Pool10% 10%
9GasLair20% 10% 10%
9HatchExpo9Pool9Gas3591% 30100% 20% 367%
9HatchMain9Pool9Gas20% 10% 10%
9Pool20% 20%
9PoolBurrow30% 30%
9PoolExpo42100% 42100%
9PoolHatch2176% 2176%
9PoolLurker1030% 1030%
9PoolSpeed10% 10%
9PoolSpeedAllIn30% 20% 10%
9PoolSpire10% 10%
9PoolSunkHatch4388% 31100% 1258%
9PoolSunkSpeed3683% 27100% 933%
AntiFact_13Pool4274% 4274%
AntiFact_2Hatch1638% 1638%
AntiFact_Overpool9Gas20% 20%
AntiFactory6273% 6174% 10%
AntiFactoryHydra2264% 2264%
AntiZeal_12Hatch110% 110%
DefilerRush20% 20%
HiveRush10% 10%
Over10Hatch30% 10% 20%
Over10Hatch1Sunk40% 40%
Over10Hatch2Sunk3580% 3482% 10%
Over10Hatch2SunkHard2692% 2692%
Over10HatchBust2825% 2825%
Over10HatchSlowLings10% 10%
Over10PoolMuta10% 10%
OverhatchExpoLing50% 50%
OverhatchExpoMuta40% 10% 30%
OverhatchLateGas20% 20%
OverhatchLing10% 10%
OverhatchMuta2129% 10% 2030%
Overpool+120% 20%
Overpool2HatchLurker10% 10%
OverpoolHatch10% 10%
OverpoolHydra120% 120%
OverpoolLurker10% 10%
OverpoolSpeed60% 60%
OverpoolSunk1533% 20% 1338%
OverpoolTurtle8593% 1471% 7197%
OverpoolTurtle 010% 10%
Overpool_4HatchLing20% 20%
PurpleSwarmBuild20% 10% 10%
Sparkle 1HatchMuta911% 10% 812%
Sparkle 2HatchMuta20% 10% 10%
ZvP_2HatchMuta10% 10%
ZvP_3BaseSpire+Den120% 120%
ZvP_3HatchPoolHydra30% 30%
ZvP_4HatchPoolHydra1421% 1421%
ZvP_Overpool3Hatch20% 20%
ZvT_12PoolMuta20% 20%
ZvT_3HatchMuta20% 10% 10%
ZvT_7Pool10% 10%
ZvZ_12Gas11Pool10% 10%
ZvZ_12HatchExpo10% 10%
ZvZ_12HatchMain30% 10% 20%
ZvZ_12Pool10% 10%
ZvZ_12PoolLing10% 10%
ZvZ_12PoolLingB10% 10%
ZvZ_Overgas9Pool1258% 1258%
ZvZ_Overpool11Gas10% 10%
ZvZ_Overpool9Gas5070% 1030% 4080%
ZvZ_OverpoolTurtle1225% 1225%
total120052%40078%50028%20042%10090%
openings played1112493293


Steamhammer knows 142 different openings. In the whole tournament, it was only able to try 111 of them! It tried the most openings versus protoss, since it was looking everywhere for an escape from the overwhelming top protoss bots. Most openings were tried only a few times and lost every game, which means that Steamhammer would have performed better without them. That’s expected and even intentional; my plan is to add smarts until it is able to make good guesses about what to try. The work is underway.

Steamhammer 2.3.6 uploaded

I’ve uploaded Steamhammer 2.3.6 to SSCAIT. The main purpose of this point release is to fix a combat simulation bug that I cleverly—nay, brilliantly inserted just before the AIIDE tournament, to ensure that Steamhammer’s results didn’t discourage other bot authors. The bug caused deviations from excellence such as scoring 67% against Iron rather than 95%. The bug had a variety of effects, but the most important is that mutalisks were afraid of enemies that they could not see, even enemies like vultures that could not shoot back. Come into view and die, stay out of sight and live forever.

After AIIDE prep I wanted to do something fun, so I also added queen skills, improved defiler plague, and fixed a bunch of easier bugs and weaknesses, including a few important ones. Important changes are in bold.

combat simulation

Setup of combat simulation is corrected. In the AIIDE version I added code in the CombatSimulation class (which works the details of setting up a combat sim) to bypass the combat sim and return a short-circuit result in certain easy cases where the enemy has undetected cloaked units. FAP does not simulate cloaking and detection, so it was an important improvement. I reversed a condition in an important bit of code, which had the effect that the short-circuit worked correctly in the cases where it was supposed to, but also worked in cases where it was not supposed to. Ouch.

related to bases

An infested command center was misrecorded as belonging to both sides. That was a fun bug! There was a correct record saying it was zerg, and a leftover incorrect record claiming that it was still terran. I didn’t test mind control, but the bug must have affected that too. The most obvious effect was that a squad might be ordered to attack the location of the “enemy base,” after which they would gather around the infested CC and warm their hands (well, claws).

• A lifted command center no longer establishes a base. The code that checked “does somebody own this base?” did not consider whether a command center in the correct location might be in the air. That generally led units to collect underneath the lifted CC until it was either shot down or moved away from the base location. It didn’t cause any losses that I saw, but it did cause bad play.

Workers start transferring to a new base before the base’s resource depot completes. It’s something of a big deal, because Steamhammer zerg deliberately overproduces drones to populate a new base as soon as the hatchery starts, so that the base can become productive as early as possible. But then it didn’t transfer the drones until the hatchery completed. Now it computes the distance and transfers the drones to arrive after the hatchery finishes. It uses the shorter air distance instead of the true ground distance so workers are sent later than they could be, but it’s nevertheless an honorable improvement. Be afraid of the big macro.

queens

For fun, I added broodling and ensnare and made command center infestation more reliable. Steamhammer already had parasite skills. Parasite was more successful than I expected; in recent games I think the queen sometimes paid for itself in information about the enemy. Broodling and ensnare make games more fun when they come up, especially ensnare, and they’re not too costly. There remains a lot of room to improve queen play, especially queen maneuvering and coordination.

Broodling. If Steamhammer sees enough enemy units that want to turn into broodlings (like tanks, or high templar, or ultralisks), it will eventually make 1 or 2 queens and research broodling. Making 2 queens is new behavior. If broodling is researched, then broodling is the queen’s highest priority: The queen will stay home until it has enough energy, then join the army and broodling any enemy that wants it enough. Only if there is extra energy will it consider ensnare or parasite.

Ensnare. If Steamhammer sees a substantial number of enemies that enjoy being ensnared, it will eventually produce a queen, research ensnare, and oblige them. If ensnare is researched, then ensnare has priority over parasite: Steamhammer will only use parasite if the queen has enough energy that a future ensnare could still happen. (Ensnare and parasite both cost 75 energy.) The ensnare code works similarly to plague: It scans around and scores the possible ensnare targets to choose the best. It likes to ensnare fast units, and it likes to reveal cloaked units with ensnare, and of course it likes to goop up as many enemies as possible. Also, I updated FAP to understand that ensnare slows down the movement and firing rate of units. FAP’s understanding of ensnared movement is approximate, but its understanding of firing rate is nearly accurate. That way Steamhammer understands that ensnared units are weaker, and now might be a good time to attack them.

• If ensnare or broodling is researched, eventually also research the queen energy upgrade.

Infest command centers more reliably. Formerly, Steamhammer had no special infestation skill at all. It could infest a command center solely as a side effect of the queen’s behavior of staying with the army; if the army was hitting a command center, then the queen was in infestation range because the army was there. If the queen didn’t have energy for a spell, it stayed home and could not infest. Now the queen wakes up whenever an infestable command center is seen on the map, and moves toward it. Also, formerly the army might destroy the command center before the queen could infest it. Now the army recognizes when a queen is near and stops attacking the command center when it becomes infestable (below 1/2 HP). The army is more efficient, and more command centers turn to the dark side where they belong.

• Change to queen behavior that mainly affects cases where Steamhammer is contained to its natural: If a queen has enough energy to cast a spell, then its fallback retreat position is the front defense point, where it may be able to do some good. Otherwise its fallback retreat is the main base, where it should be relatively safe to sit and gain energy. This can make the queen more useful in a bad situation, but the queen is not likely to help much.

defilers

• There was an awesome extra digit in the constant “how many HP can plague eat up at most?” that Steamhammer uses in its forecast of how much damage a given plague will do. Oh... that is why it insisted on plaguing buildings even as I discounted them more and more—it thought it would do awesome damage! After fixing it, Steamhammer still loves to plague buildings; the practical effect of the fix is limited. But it has shifted its preference somewhat toward enemy units.

• I simplified the plague scoring code and tweaked it. Plague gets a higher score for putting a terran building into the red (so that it burns down if not repaired), and it will plague even a single enemy unit if it seems worth it.

The defiler might retreat to the main base and be useless when Steamhammer was contained to its natural and needed the defiler there to break out. I changed the defiler’s fallback retreat point to be the front defense point, which is also where any sunken colonies are placed. It’s not quite the same as the queen’s fallback retreat behavior. The queen needs a safe place to gather energy, the defiler can consume.

zerg

The finishing unit mix is drone-mutalisk. Formerly, when the opponent looked dead and Steamhammer wanted to chase down its last buildings, it made mutalisks plus whatever ground unit came out of the usual unit mix calculation, usually zerglings. That had rare unfortunate results when Steamhammer made too many ground units and could not get mutalisks. The drone count is capped at 75, so with a drone-mutalisk mix, Steamhammer will not run itself out of supply to make mutalisks and should almost never fail to finish off the opponent.

Ensure that there is at least one zergling or hydralisk in the army at all times after the opening book. Steamhammer scouts the enemy army primarily with its own army. If its army was wiped out in battle, it might sit back behind sunkens and drone up, thinking that the enemy army was also weak, and never learn better because it didn’t have forward units to see the enemy move out. “You mean, if I keep my eyes closed, I’m not safe after all?”

If terran or protoss has too much air, make a defensive spore colony even if Steamhammer also has a spire. Formerly, Steamhammer skipped the spore if it had a spire, because it used to be that scourge was defense enough. But if the enemy has too many air units, scourge is not enough. McRave (after an update this summer) is especially good at massing its corsairs and shooting down scourge. (In ZvZ, Steamhammer follows different rules for making defensive spores.)

• A temporary production freeze happened if Steamhammer wanted to upgrade air carapace... at the same time that it was morphing a greater spire. All production stopped until the greater spire completed. It was surprisingly common, it seemed to happen in most games where Steamhammer got a greater spire. Anyway, fixed now.

openings

• Added a protoss opening GoonObserver to directly counter DT rushes and other cloak rushes. Unfortunately the automatic “oh no, cloaked units, hurry and build cannons” reaction still happens and tends to delay the observers, but it’s still not a bad counter.

Steamhammer can’t finish the game

Finishing off the enemy just means destroying all their buildings. It sounds simple, but it is a sophisticated skill, and there are a lot of ways to go wrong. Steamhammer has a number of special provisions for quickly finding the last enemy remnants, but small loopholes persist and occasionally a game slips through one.

PurpleSpirit-Steamhammer on La Mancha is an example. It’s an entertaining game, thanks to the purple habit of playing all over the map, but I want to focus on the end, after PurpleSpirit has lost, when Steamhammer fails to destroy the floating terran buildings that are right over its head. That part is entertaining too, but not for the same reason.

the beginning of the end

Everything terran on the ground is destroyed, except one command center which was infested instead. The remaining terran force is 2 full-strength battlecruisers, and the remaining terran infrastructure is 2 floating ebays. Steamhammer is maxed and banking resources, but its only anti-air units are 8 scourge, plus a defiler with plague. Notice how much game time is left?

One of Steamhammer’s special game-finishing skills is that it makes mutalisks to chase down the residue of the enemy. The condition is, if the enemy has no known bases and no known anti-air units, then Steamhammer will tech to mutalisks and make mutas its primary unit. The mutas scout faster than ground units, and can find floating buildings and island bases that ground units can’t reach. But here terran still has battlecruisers, so the mutalisk rule does not kick in. First the terran army, such as it is, must be defeated.

swarm all over

Some scourge have hit, and the battlecruisers are no longer at full HP. But Steamhammer has been replacing losses primarily with more zerglings and ultralisks, which are of no use. Oops, the unit mix is wrong. Now there are only 2 scourge, and a battlecruiser can kill a scourge in one shot—2 battlecruisers, if not distracted by other targets, are safe from 2 scourge. The ebays choose to park over the terran natural, and zerg units have congregated there. The battlecruisers seek zerg stuff to shoot, and the defiler responds by blanketing the area in defensive swarm, consuming zerglings like crazy.

some damage has been done

Well, the 2 scourge hit one of the battlecruisers, which was distracted seeking zerg units that strayed from under dark swarm. And Steamhammer is now making 3 new pairs of scourge to replace various losses; if it can keep this up, the battlecruisers will eventually fall. Best of all, the defiler has plagued the terran buildings, despite the zerg units underneath. That will put the ebays into the yellow. One more plague should put them into the red, after which they will burn down.

nothing happens after this

Whew, finally the battlecruisers are shot down by scourge.

But that’s all she wrote. The swarms wore off and there was no need to renew them. The defiler did not plague again because it thought the zerg units underneath were more valuable. Scourge are coded to avoid floating buildings, because it is usually wasteful to spend gas destroying them. The mutalisk rule is engaged, and there is supply to build 1 mutalisk, but Steamhammer happened to choose to spawn zerglings first, and after that there was no supply to make a mutalisk. The game timed out with no more progress.

Finishing off the enemy can be hard. In this case, Steamhammer had the wrong unit mix; to make zerglings and ultralisks when all enemies were in the air was no good. The mutalisk rule should make mutalisks only, not mix them with other units. The scourge might have understood that when only floating buildings are left, they are good targets. Also the zerg ground units that can’t shoot up might have known better than to chase floating buildings (though it can be useful when they track a building trying to escape), and the defiler might have realized that damage to its own units was irrelevant when it could eliminate the enemy. That is a lot of flaws, and yet Steamhammer rarely fails to finish a game!

And fixing all the problems would only narrow the loophole, not eliminate it. In the worst case, Steamhammer would need to be able to destroy some of its own units to clear supply to make mutalisks to finish off the enemy. And that’s a high-end skill that I am in no hurry to add.

Next: The start of CoG 2019 analysis.

Steamhammer’s defiler play

Earlier I claimed that if Steamhammer has defilers out, it is probably winning. It’s true but misleading. Steamhammer’s game plan is such that it doesn’t try to win in the middle game (though it may win accidentally); the midgame is about holding the enemy off, getting upgrades, and growing the economy. When its drone count reaches 75, Steamhammer switches to all army production and its military strength grows rapidly—and that is the same time that defilers come into their own. When it reaches the late game, whether there are defilers or not, Steamhammer will be hitting hard and very likely winning, because if it weren’t winning it would probably have lost already. The late game is Steamhammer’s strongest phase.

Nevertheless, Steamhammer’s defiler usage has grown skillful enough that it definitely contributes to the bot’s strength. It’s an important milestone, because good defiler usage is critical to strong zerg play. Defilers are complicated, and zerg cannot reach its potential without mastering them. Steamhammer is far from mastering defilers, but I think it has become more adept with them than any other bot.

The original description of the defiler implementation is still accurate. Bugs have been fixed and refinements made, but the structure is unchanged.

that laser precision

I picked this game TyrProtoss-Randomhammer because it shows off Steamhammer’s precision and fluidity in defiler spellcasting. The precision was always there; the fluidity was reached by a long road with a year’s worth of bug fixes and other improvements. In the first picture, Steamhammer is about to start its decisive final attack. The attack would have won with or without defiler support. Accurate defiler spells made it effortless.

a slightly weak plague

Steamhammer chooses plague because it looks like the fight will feature zealots versus hydras. The plague is actually a little weak. The defiler (selected and a little hard to see) is hemmed in by friendly units and cannot move forward, and Steamhammer hasn’t seen all the approaching enemies yet, so it plagues only 3 zealots. With a short delay for the opposing armies to close, it could have plagued more enemies, but it is not able to figure that out. Still, the plague helped in the battle.

swarm neutralizes the dragoons

Once the front zealots have died, Steamhammer has a fuller view of the situation, and realizes that the enemy has mostly dragoons left. The defiler (which has the energy upgrade) casts swarm, consume, consume, then a second swarm. The swarms are accurately placed to nullify the dragoons and drive the enemy back, bringing the fight into the natural. In the picture the defiler has just cast the second swarm, and it instantly consumes again.

plague hammers in the final nail

The defiler is again stuck behind friendly units for a time, but protoss is forced back to the ramp. As zerg units spread out to raze the enemy natural, the defiler becomes free to move and drops a perfect plague on the ramp. Every protoss unit on the ramp is hit, and the zerg melee units that are in contact are untouched. No better plague is possible.

Steamhammer is awkward in maneuvering its defiler, and it is unable to foresee better opportunities that will arise in the near future. But when a spell goes down, it is often close to the best that is possible at that moment. It’s plenty good for now.

potential to turn the game

One defiler spell can make the difference between losing and winning. In practice, Steamhammer needs more skills before that will happen often in its games, but the examples here offer a foretaste. The game Steamhammer-McRave I picked to show the brute power of plague.

The first defiler of the game wandered carelessly into the front lines, stood on top of an isolated lurker, and got stormed to death. The defiler didn’t know the best place to go, that’s one weakness, and Steamhammer only makes 1 defiler at a time, that’s another weakness. An alert opponent can pick off the defiler and earn a respite. When the second defiler of the game joined the fray, this happened:

a plague on all your zealots

It’s a fun game, worth watching through. At the time of the picture, Steamhammer had been slowly twisting the situation into its favor from far behind, but McRave was still winning. The game could have gone either way. After this massive plague, turning a whole phalanx of zealots into straw, McRave’s army was broken and it quickly collapsed.

Here’s a picture from a different Steamhammer-McRave game. The red stuff all over the protoss natural is from 3 active plagues cast one after another by one defiler. The defiler just died; it sacrificed itself amidst the zealots (at the white spot of a dragoon hit) to get the third plague off, the one currently spreading over dragoons in the rear. The sacrifice was worth it. The protoss army was hollowed out, giving zerg time to consolidate an economic advantage and win. Without those plagues, McRave would have been able to move out and take the game with its bigger army (though I’m not sure it would have chosen to).

plague of plagues

Here is a third example of a turnaround plague, from Steamhammer-MadMixT. After playing well much of the game, Steamhammer went astray and collapsed under a terran attack. It was about to lose its main and the game when a defiler risked its life to throw a plague over the core of the terran force, reducing the units to eggshells. Plague hurts terran more than protoss, which has shields. It then took only a few zerg units to clear the attack, partly due to terran’s disorganized movement, and with a return to superior play, Steamhammer slowly clawed its way to a win.

eggshell terrans

keeping active

Steamhammer is weak at using defilers in defense. I think it’s the widest remaining gap in defiler play. But it’s pretty good at using defilers in attack. I chose the game Steamhammer-MadMixP to show how, in the best case, Steamhammer can keep its defiler active through a long attacking sequence. The game itself is not very interesting, but watch the finishing attack which starts at around 17:30 from across the bridge to the terran natural.

the finishing attack begins with a plague

It starts with a plague. If I didn’t miss anything, the sequence that follows is consume, consume, swarm, consume, consume, consume, plague, consume, consume, swarm, consume, consume, swarm, consume, consume, consume, swarm, consume, plague, consume, consume, consume, plague, consume, consume, consume, plague, consume, consume—and the last enemy building is destroyed. The defiler was stuck behind friendly units for short stretches, and otherwise busy every moment supporting the raging attack. Even though not all the activity was useful, the ability to keep constantly active is valuable.

blunders

Steamhammer does make mistakes in casting defiler spells, though rarely serious ones. Plague doesn’t account for moving units. It can miss fast-moving enemies altogether, for example trying to plague a group of corsairs and smearing only bare ground. In an active fight it can unintentionally plague its own units, which do not realize that they are moving into a danger zone. (It’s also perfectly willing to intentionally plague its own units, if that lets it splash more enemies. The calculation simply adds damage done to enemies and subtracts damage done to self.)

Dark swarm is thorny. Steamhammer only partially understands it. In Randomhammer-tscmoop2 the defiler cast a swarm that helped the enemy—with hydras on hand versus zealots and a reaver as well as the cannons and dragoons, swarm was a poor idea in the first place, and this swarm placement defends the enemy and does not open a path to attack. Oops. The research tab shows that plague was almost but not quite finished.

swarm protects enemy units

improvements needed

Why is Steamhammer weak with defensive dark swarm? To lay down swarm over lurkers and hold a position, or to force marines back with zerglings under swarm, you have to coordinate the swarm with the combat units. The defiler knows that swarm over lurkers is a great idea, and the combat simulator knows it too, in an approximate way. The lurkers themselves have no inkling; when their targets retreat, the lurkers will pick themselves up and obliviously step out of the swarm and die. Even something as simple as rendering hydralisks invulnerable to air attack is beyond Steamhammer. The hydras pay no attention.

Steamhammer’s squad code is already fragile from having too many skills tacked on, and needs to be rethought and rewritten. I’m reluctant to add complicated coordination skills before tackling that, so this weakness will likely be around for a while. It is a severe weakness, though, because defense is a critical use of defilers. Darn it, but there are times when only invulnerability can save you.

Besides the lack of coordination, there is no planning ahead. Defilers live in the moment and know nothing beyond. With prediction and planning, greater things could be accomplished with fewer resources.

More basically, the tendency of the defiler to get stuck behind friendly units reminds me that Steamhammer needs another fundamental skill: Smooth unit movement. Human players know that the defiler’s position is important, and move other units so that the defiler gets where it needs to be. And more generally, the missing skill shows in things like awkward movement through choke points, and clumsy collisions when squads cross paths.

I have a few simple ideas for how to control multiple defilers at once without blowing out cpu usage or seeing them simultaneously plague the same enemies. I expect I’ll implement that before SSCAIT this year. With 2 or 3 defilers in the Ground squad, defenders won’t have time to draw breath between spells.

Someday I’ll implement defiler drops. Zerglings with adrenal glands upgrade might as well be wrecking balls. Drop a defiler and some zerglings off to one side, swarm, swarm, and pick up the defiler for another go later while the lings rip down buildings. It’s cheap to do and expensive to defend against.

Steamhammer 2.3.5 source released

I finally uploaded the source for Steamhammer 2.3.5; see Steamhammer’s web page. Sorry about the delay. As I’ve mentioned, this is the same code as the AIIDE 2019 competition version, but configured to play all races rather than zerg only.

One of my steps in uploading a new version is to calculate the performance numbers of the previous version. By SSCAIT win rate, Steamhammer 2.3 (from last April) with 69% wins is the most successful version since Steamhammer 1.2 with 70% wins, way back in March 2017. And I’ve seen that the following test versions are stronger yet. This version 2.3.5 (and the tournament version 2.3.4 since it’s identical) has a new combat sim bug which makes it slightly weaker than the previous test version, 2.3.3, but I think it is still stronger than version 2.3. Steamhammer is doing well at the moment.

Before long I plan to release a new point version which fixes the combat sim bug and (just for fun) adds new queen skills. After that I’ll dig into strategy adaptation, which I expect will cause strength to plummet, because that is what major new features do at first. When strength recovers, though, it will recover to a higher level.

Next: A long post about defiler play, with examples and explanations. I also found a few research papers that I want to write up.

Steamhammer plans update

After every new Steamhammer version it’s time to come out with new plans for the following versions—plans that are always updated and sometimes changed beyond recognition. No plan survives contact with further consideration.

Despite my intention to stick to low-risk changes in the latest Steamhammer, I seem to have introduced a severe bug into combat simulation. I’m seeing cases of pointless fear, like ultralisks fearful to attack an assimilator, and Games Are Being Lost, which must not be. I need to make a point release to fix this bug, and possibly a few minor bugs besides.

But I don’t have the energy to fix bugs right now. I want to do something fun instead. I’m adding broodling for queens, and thinking about how to adjust the strategy boss so it can make more than 1 queen at a time without ever going overboard. Hmm. The rest of the code already supports any number of queens, at least in principle, but not the strategy boss. This is, by the way, another change of plans; I was originally intending to implement ensnare before broodling.

Related stuff that’s high on my list: Simple sample configuration file, for people who prefer to ignore the complex default config file with features piled over their heads. Up-to-date documentation. I promised a post on defilers. Oh, and I forgot to release source, I’d better do that next. I’d forget the period at the end of the sentence if it weren’t there on the keyboard to remind me

In the longer term, I need to go to BWAPI 4.4.0 and make progress on strategy adaptation. My thinking at the moment is that I’ll make the most progress by working with timings: The opponent model should record the timings and unit mix of opponent attacks, and compare them against the measured timings of Steamhammer’s openings to figure out how to counter an opponent. That’s only a small part of the full strategy adaptation suite, but it’s critical and it seems like a good piece to do early.

If you look closely at the source—you know, the source I forgot to release—you’ll find an unfinished and unused class BOSimulator which is a start on another essential part of strategy adaptation. I need to rename it, the name is confusingly similar to Dave Churchill’s BOSS.

Steamhammer’s strategy boss debug display

For this upload of Steamhammer to SSCAIT, I turned on display of the strategy boss information. It’s kind of cryptic, so I thought I’d explain.

strategy boss debug info drawn on the screen

The top section, with all yellow labels from “bases” to “build”, describes the game situation and some automatic reactions that can happen at any time, including during the opening. The top section displays all game long. Then comes a slight break, and the bottom section, with multi-color labels from “eco” to the end, describes the strategy boss’s plans and conclusions after the opening is over. The bottom section only appears after exit from the opening book.

The strategy boss also cares about the game’s mineral count, gas count, and supply count. That’s why I draw the strategy boss info directly underneath Starcraft’s info.

top section of the info

bases 3/12 Steamhammer owns 3 of the 12 bases on the map.

patches 20 These 3 bases have 20 mineral patches total. This determines the upper limit of how fast it is possible to mine minerals.

geysers 2+0 Steamhammer has taken 2 gas geysers, and no more are available. If a geyser is in the process of being taken—the extractor is morphing—then it doesn’t count on either side. With 3 bases and 2 geysers, it could be that Steamhammer has 2 gas bases and a mineral only, or 3 gas bases and the final geyser is in the process of being taken.

drones 27/39 Steamhammer has 27 drones, including drones that are in the egg and haven’t hatched yet. It will spawn up to 39 drones; it believes that, taking into account the mineral patches and geysers, 39 drones are as many as it is reasonable to make.

mins 23 23 of the drones are mining minerals.

gas 0 None of the drones are mining gas. That leaves 4 drones on neither minerals or gas; they may be still in the egg, or may be carrying out other business, like building or scouting. But in any case, gas collection is turned off at the moment so that Steamhammer can collect minerals faster.

react +16 Based on what we’ve seen the opponent do, aim for 16 drones more than what we would normally build in this situation; they are “reactive drones.” A number as large as +16 usually means that the opponent is playing very defensively with many cannons, so that we can safely make extra drones to get ahead in economy.

larvas 0 There are no larvas available to spawn more units. Steamhammer takes a shortage of larvas as evidence that it may need more hatcheries (other factors count too). That might be why gas is turned off: To collect minerals faster to make a macro hatchery ASAP. (Though it might have concluded only that 911 gas is more than it needs for now.)

build +0g +0h This describes a complex strategy reaction that can occur in the opening book, and cannot occur later in the game. It connects with the “react” item above, the count of reactive drones. If there are too many reactive drones in the opening, they will bring in excess minerals, so Steamhammer takes actions to use resources more efficiently and prevent the excess minerals from building up unused. The actions are that it can take extra geysers—“g”—or make extra hatcheries—“h”. The extra geysers bring in extra gas so that income is balanced, and the extra hatcheries bring extra larvas for faster production. The result is that the unplanned resources can be spent efficiently and Steamhammer runs through its opening line faster, entering the middle game in a stronger position. In this game, it did not add anything extra in the opening; most of the +16 reactive drones must have been decided after the book line was over.

bottom section of the info

eco 0.35 5/43 describes plans for economic growth. 0.35 is the proportion of larvas planned to be made into drones on average over the long run. Actual moment-to-moment drone production can vary from all drones to all combat units, depending on circumstances, but Steamhammer aims for a given ratio. 5/43 is the actual ratio of drone production: It made 5 drones out of the last 43 larvas morphed, a ratio of about 0.11—Steamhammer is behind on planned drone production. Reactive drones are implemented behind the scenes by manipulating the ratio.

army 24 40 bad gives army sizes: Steamhammer’s army size is 24 (in an arbitrary measure), including static defense, and the enemy’s army size is 40, counting only mobile units. This is “bad” in red because it means that Steamhammer may be overrun. When the army size is “bad” Steamhammer makes combat units to defend itself; that explains why it is behind on drone production.

The 7 orange unit types lings, hydras, lurkers, mutas, guardians, devourers, ultras, are the candidate units for Steamhammer’s main unit mix. Overlords, queens, and defilers are support units that are made on the side and do not count toward the main unit mix. The number after each unit type is the strategy boss’s score for how important the unit type is in the current situation. The scores are used for two purposes: First, to decide on the combat unit mix. Second, to decide on the tech target, the next unit type that the bot should aim for.

The starred unit types are those that Steamhammer has the tech for. They are candidates for the unit mix. The starred unit with the highest score will be part of the unit mix. The rest of the unit types are candidates for the tech target.

Zergling Hydralisk 1 Lurker is the combat unit mix. Hydras had the highest score, so they are part of the unit mix. The full rules for choosing the unit mix are complex. Lurkers had the next highest score, but the strategy boss decided that it is enough to have only 1 lurker for now (which really means at least 1 lurker; if there happen to already be more, that is OK). Minerals not spent on hydras or the 1 lurker (or on drones or whatever else) will be spent on zerglings.

plan Mutas gives the tech target: A tech switch to mutalisks is planned. Mutas are a candidate for the tech target because they have a higher score than any of the starred units that Steamhammer already has the tech for. Guardians and ultras have higher scores yet, but Steamhammer doesn’t have a hive so mutalisks can be gotten much faster. If mutas did not score higher than hydras, the strategy boss would have picked guardians as the tech target.

Steamhammer 2.3.5 uploaded

I have uploaded Steamhammer 2.3.5 to SSCAIT. It is the same code as the AIIDE 2019 tournament version 2.3.4. The main difference is that it is configured to play all races. I did a little work on the openings, since that’s autonomic and proceeds without volition. Also I didn’t include pre-learned data files; they’re not helpful for SSCAIT and BASIL.

Source release soon.

change list

• Fixed the protoss ForgeExpand opening. At some point it was edited incorrectly and started to place the cannons in the main, where they were nicely protected since the enemy tore down the natural first.

• Added a protoss 10-12ForwardGateExpo opening. It puts gateways in the natural and tries to scare the enemy with some zealots before expanding. Whether the gateways successfully fit in the natural may vary by map....

• Added a zerg UltraRush opening. It’s not useful as written, unless maybe some opponent is extremely passive and at the same time highly skilled in stopping defilers. But I left it in.

Steamhammer 2.3.4 change list

The change list is longer than I originally predicted! This is the Steamhammer version that I submitted to the AIIDE 2019 tournament. The list includes changes from unreleased versions 2.3.1, 2.3.2, and 2.3.3 that played on SSCAIT for testing, as well as final changes in version 2.3.4 that never played on SSCAIT.

This version is configured to play zerg only, and all changes affect zerg play. A few of them should also improve play by terran and protoss. As usual, the most important changes are in bold.

opponent model

Support pre-learned data files. If Steamhammer does not find a learning file for a given opponent in the read directory, it looks next in a “static” directory to see if there is a data file for the opponent there. The config variable Config::IO::StaticDirectory points to the static directory, and is set to bwapi-data/AI/om/ in the release version (“om” stands for “opponent model”). After the game, it proceeds as usual: It writes the pre-learned game records, followed by the game record for the current game, into the write directory; after write is copied to read, there is no reason to refer back to the static directory. Locutus does it essentially the same way.

The AIIDE version of Steamhammer includes pre-learned opponent model files for 12 of the registered bots. Most of these files don’t have much in them beyond a few sample strategies that have won in the past, so that Steamhammer doesn’t have to cast about blindly to find a likely build. Best play against Iron is more complicated—Steamhammer knows 3 very different successful openings with varying win rates depending on the map—so the pre-learned file for Iron includes 50 games to give Steamhammer an excellent winning rate right from the start. All the game records were originally extracted from Steamhammer’s learning files on BASIL.

operations

Squad targeting: In deciding what enemy base to attack, count defenders in a smaller radius, unless the enemy is terran and has siege mode (then we need the wide radius to include any tanks that may be sieged). This helps Steamhammer more accurately choose the least-defended enemy base to attack next.

• There was a copy-paste error in the code to detect whether the enemy has siege mode. The siege mode information was returned correctly, but it mistakenly set the flag that means “the enemy has static air defense,” so Steamhammer would believe there were turrets whether there were or not.

• Squad targeting: Don’t order a squad to attack an addon. I changed ranged units to never attack addons, to avoid wasting time when they should be attacking something else. (Melee units will, though, because it may be the closest thing.) That unexpectedly caused difficulties in finishing off games versus terran, when units might collect around an enemy addon and never attack it, rather than attacking a known building that was perhaps farther away.

• Squad targeting: If no enemy buildings are known, seek enemy units which may still be findable. This can help Steamhammer finish off winning games faster.

A terrific bug caused enemy unit counts to be horribly wrong in many cases. Steamhammer sometimes believed that the enemy had a negative number of units of some type. The broken unit counts were not used by many decisions—the most important decisions use the player snapshot unit counts, which are accurate—but decisions that did use them could be completely wrong.

UnitInfo projects when enemy buildings will complete, based on their HP when last seen. It’s not entirely accurate; the calculation leaves out some factor that I haven’t figured out yet. To see the calculated times on the screen, turn on the config option Debug::DrawEnemyUnitInfo. In code, the call getEnemyBuildingTiming() is one way to get the information. This data could make plan recognition more accurate, but is not used for that yet; it is used only to check the enemy spire timing in ZvZ.

tactics

Calculate map tiles in range of enemy static defense and keep the data available. There are separate grids of ground danger zones and air danger zones. A few uses of the data are implemented; many more are possible. Steamhammer will not place buildings in a ground danger zone; this is a vital skill to survive cannon rushes, and has saved games for Steamhammer against AIUR by Florian Richoux. The information also feeds into unit targeting decisions. Steamhammer’s units prefer to fight outside enemy static defense range when possible; Steamhammer has a stronger preference to pick off undefended targets.

Squad detectors avoid danger and seek cloaked enemies. Formerly, detectors stayed with their squads and otherwise ignored the world around them. Steamhammer lost overlords freely, a major weakness. Now they retreat out of range of enemies that could shoot them down, and move toward cloaked enemies that need to be detected. Science vessels and observers benefit too. It’s usually a big improvement, but there are cases where enemy ranged units zone out the overlords, or enemy cloaked units distract them from where they need to be. Overlords that are not acting as squad detectors (some act as base detectors and some are left idle) are as carefree as ever and can still be lost at a high rate.

• A squad detector is supposed to move back home when it finds itself abandoned—when the squad it was detecting for is gone. I don’t think this feature works, or at least, detectors still make all sorts of illogical movements.

Better combat sim results against cloaked enemies. If all enemies in the area are undetected and they can hit us, retreat without further calculation. If some enemies are detected, do the sim to see whether to fight or run. The change makes play vastly stronger in certain situations.

• FAP accounts for cost of scarabs and interceptors, and the full cost of zerg morphed stuff. It doesn’t make a big difference, but combat sim scores are a little more accurate.

• Ranged units are better at ignoring enemy zerg larvas when moving somewhere else. They’ll get distracted less often.

micro

Issue at most 1 move command per 3 frames in the micro system. Zerglings get stuck less often. I still see it happen from time to time, but I think most watchers will see zergling movement as smooth. The underlying code can send move commands to the micro system every frame if it likes, but the micro system will skip or delay some of the commands if they are too closely spaced.

MoveNear() had a potential crashing bug. It never happened as far as I saw, but a unit being given its first command ever could execute invalid code and crash.

• Use MoveNear() rather than Move() in more cases, to reduce unnecessary commanding. MoveNear() ignores commands that “don’t make a difference”—it says, “eh, we’ll end up close enough, don’t bother.” It’s for use when precision doesn’t matter, which is a lot of the time.

• Builder workers were being issued an unnecessary move command on the same frame that they were told to start construction. In the worst case, which was not frequent, building construction might be delayed by 1 frame. Still, it’s fixed.

• Steamhammer’s melee units can be configured to retreat when low on health, to regenerate health (by zerg regeneration or terran medic healing or protoss shield regeneration). The change is, this no longer happens if the unit is irradiated. Net regeneration will not happen, and since it’s a melee unit it’s likely to be right next to the enemy, exposing enemies to the radiation. This mainly helps ultralisks.

• Clip the result of DistanceAndDirection() to the map boundaries, instead of returning a bad result for the caller to deal with. In practice, the effect is that in some situations a unit will move to the edge of the map rather than not moving at all. I’m not sure it’s an improvement in play terms, but the code is safer.

zerg defilers

An outrageous bug could put a defiler into both the defiler controller and the melee unit controller, meaning that defilers were issued zergling commands intermixed with their defiler commands. “Now AttackUnit() that building!” I was floored. The error was in code that was “so simple it could not have a bug,” and the bug was caught by an error check in the micro system, far away from the underlying problem. At least it was easy to fix.

Cast dark swarm over enemy ranged units, not only over enemy buildings. Formerly, Steamhammer could not use swarm against, say, marines on the open field; it had to reach the enemy base before the conditions for the spell were triggered. It was a severe limitation (justified by Steamhammer’s poor swarm skills at the time).

Choose the nearest zerglings as defiler food, not the first zerglings that happen to come up in looping through units. Defilers consume sooner and cast swarm and plague at a higher rate. A defiler generally arrives at the front line already charged up with energy, so even if it is irradiated instantly it is still likely to get a swarm or plague off.

• A typo prevented research of Metasynaptic Node, the defiler energy upgrade. I fixed it and adjusted the conditions to be safer.

• Slightly loosen the conditions for making a defiler in the first place. They work better now, make ‘em sooner.

Swarm and plague scoring adjusted for better effect. The thresholds are reduced, so that the spells can be cast in more situations. Swarm over lurkers counts double. Plague counts more on carrier interceptors, less on buildings. Various other tweaks.

• Fixed a bug in avoiding the overlap of dark swarms. Swarms less often overlap wastefully (though it still happens, for at least 3 reasons).

• FAP bugs in understanding dark swarm are fixed (I added dark swarm to FAP, so all the bugs are my doing). There was an error in recognizing melee units that can hit under dark swarm because of a confusion between range and squared range (I renamed stuff and added comments to make it clearer). FAP also now realizes that a worker cannot do damage under dark swarm, while a reaver can. The effect of the fixes is that units under dark swarm make more accurate decisions about whether to keep attacking.

• A rare bug could allow multiple defiler mounds.

zerg scourge

Do not target an enemy that is covered by enemy static air defense. Steamhammer used to throw scourge away by the ton to cannons or turrets; this solves the issue. Scourge will chase the enemy, but turn around for home if the enemy reaches a defended area. (Mobile enemies might still shoot down the scourge; retreating in that case is decided by combat sim and the regular advance/retreat logic.)

Do not target overlords or interceptors. Shooting down those targets is usually a waste of gas. Neither the scourge squad nor the scourge units will seek overlords or interceptors. This solves another serious issue.

Predict the target’s movement. This helps scourge hit the target directly, instead of doing that weird little loop before suiciding. It also means that scourge cut corners in a turn, but only a hair.

• There was a bug in choosing scourge squad targets that were goneFromLastPosition, that is, known to no longer be where they were last seen. It caused wasteful scourge movement.

• In choosing a scourge unit target, pay less attention to target priority (“the science vessel is more important to destroy than the wraith”) and more attention to target distance (“it’s right here, just hit it!”). That wraith is now less likely to shoot the scourge down while the scourge chases a more distant science vessel.

• If we have lurkers, then enemy observers are higher priority to destroy.

• Further limit scourge production. I tuned it down repeatedly, but Steamhammer was still sometimes spending too much gas on scourge, leaving too little for everything else.

other zerg skills

Sometimes make 1 queen, use parasite, infest command centers. The queen likes to parasite expensive units like carriers and arbiters, and it also likes shuttles and dropships. It will parasite something else if it has excess energy or gets irradiated. As I expected, few enemies understand what to do when they get parasited. A common outcome is that the parasited unit gets scourged at the first opportunity. If the parasited unit stays in a safe place instead, it’s often a valuable spy. The infested command centers don’t do anything but sit there and get in the way; I haven’t yet seen this cause Steamhammer any problems in game, but it could happen. If the queen dies, which happens a lot because it plays recklessly, the strategy boss waits 3 game minutes and makes another queen.

There was a critical crashing bug affecting spellcasters in the late game. Fixed, whew.

In an emergency, set the drone production rate to 0.15 rather than the previous 0.10—that is, make a drone instead of a combat unit 15% of the time. This helps Steamhammer build up its economy even while under heavy pressure, without falling to the pressure. It increases the win rate against zealot rushers and other opponents that press attacks over a long period, like Gaoyuan Chen.

Prefer to make units at hatcheries with more larvas. Steamhammer used to often lose production capacity by using up all the larvas at one hatchery before moving to the next hatchery. A hatchery with 3 larvas will not produce more larvas, so that meant the total rate of larva production was lower, and more total hatcheries were needed to cover the next surge of zergling or drone production (cheap units that call for a lot of larvas).

• Prefer to make drones at undersaturated bases. It is a smaller improvement than it may sound. Formerly, Steamhammer used a cheap but effective trick: It preferred to make drones at the base farthest from the main base. It was the right choice most of the time, but could go wrong if the main was attacked and lost drones. The new method balances workers well in all cases, not only the common case.

• Steamhammer tries to make fewer macro hatcheries before expanding beyond its first and second bases. I saw games where it made as many as 4 hatcheries in its main before taking the natural—it might be OK if the bot is contained, but not the other 6 days of the week.

• Delay the second gas a little. Steamhammer consistently took the second geyser too soon. I think it’s still usually too soon, but the loss is reduced.

• Dark templar more strongly indicate the need for static defense. They hit hard.

• Make a defensive spire in reaction to enemy drop or certain air units. Formerly, only overlord hunters like corsairs would trigger a defensive spire.

• In ZvZ, prefer to counter hydras and especially lurkers with mutas, not lings only. Steamhammer usually did the right thing, but in a few games made a severe strategy mistake.

• In ZvZ, Steamhammer formerly made an evolution chamber if it saw an enemy spire, no matter the state of its own spire. That’s a mistake; the evo is often unneeded, and in ZvZ the drone to make the building is valuable. Now Steamhammer attempts to time the enemy spire and make the evo only if needed. I don’t find it particularly accurate, but it is an improvement.

• In ZvZ, enemy scourge more strongly discourages Steamhammer from making guardians and devourers. See the game I posted last time, where Steamhammer scourged Microwave’s devourers. Devourers and guardians have little ability to defend themselves against scourge; they can only survive with the help of escorts.

• Limit devourers further. Devourers are support units, so try to keep more mutalisks than devourers.

• A lost defiler mound could cause a production freeze. It was rare, but a production freeze can be a game-losing bug. It’s frustrating, but there remain rare production freezes that I have not traced.

• Emergency reactions: When there are 0 drones, Steamhammer can cancel upgrades and more building types. Formerly it could cancel only units and a few building types.

• Emergency reactions: Correctly account for the gain of canceling a building (you get 3/4 of the cost back). It helps in making the right cancelation decisions.

• Emergency reactions: A bug could allow a planned hatchery to be dropped even though it was the only hatchery.

• ZvZ mutalisk target selection adjusted in a few cases.

Lurkers prefer the most distant target. It helps visibly.

• Fixed lurker vibration: Sometimes lurkers would move back and forth, achieving nothing, instead of advancing on the enemy.

• Attackers can no longer permanently drive overlords away from the spore colonies where they are sheltering. This was a bug introduced in a recent version.

zerg openings

3HatchLingBust2 makes the minimum number of drones and goes all-in on the bust. This version is now configured in place of the original 3HatchLingBust as one counter to protoss forge-expand builds.

12Hatch_4HatchLing makes the right number of drones for continuous zergling production from 4 hatcheries. It’s similar to 3HatchLingBust2.

2HatchMutaPure and 3HatchMutaPure each make only 1 pair of zerglings, and instead get as many drones as possible without delaying the mutalisks. The 2 hatchery one is especially elegant. These are for use against opponents that sit back and defend for a time before moving out.

Overpool2HatchLurker and 3GasMuta similarly are more effective against opponents that are late to attack.

DefilerRush rushes for defilers to support highly-upgraded zerglings. I used it mostly in testing defilers, but there are opponents it could be strong against. The defiler rush is similar to the existing HiveRush build, but better optimized (and of course it also makes a defiler).

12PoolHydra is configured as one counter to terran factory-first openings. 12PoolLurker fills a gap in the lineup of lurker openings. ZvZ_12PoolLingB is a minor variant of ZvZ_12PoolLing. ZvZ_12Gas11Pool is a gas-first stem that fills a gap.

Overpool_3HatchSpeed, Overpool_3HatchLing, and Overpool_4HatchLing try to combine the early zerglings of overpool, which can keep the opponent in the dark and defensive, with a mass zergling followup. Overpool_4HatchLing is configured to be played 1% of the time in ZvZ versus an unknown opponent—it’s risky but can also be hard for the opponent to understand and counter (it makes a third base that the opponent is not likely to scout in time).

10Pool9Gas and 10Pool9Hatch fill small gaps in the ZvZ opening repertoire.

7Pool6GasMuta is derived from one of my 7 pool 6 gas dawn lurker rush builds. It’s quite easy to defeat, even without air defense, with an early attack. I suspect it is useful mainly against opponents which want to defend and fail to figure out how to defend so early.

• Minor tweak to 2HatchHydra. Bigger adjustments to OverpoolTurtle so that it can more consistently beat those (weak) opponents it is intended to beat.

Next: Expect Steamhammer 2.3.5, which again plays all races, on Tuesday or Wednesday.

Steamhammer submitted to AIIDE

I have submitted Steamhammer 2.3.4 for AIIDE 2019, a day ahead of the deadline. The latest changes help in specific situations: Better decisions against dark templar, less time wasted when the defiler wants to consume, more accurate strategy choices in ZvZ when the opponent goes hydras, that kind of thing.

Overall, I’m pleased with this version. It is far more solid than any previous tournament version of Steamhammer. There are a couple of game-losing bugs that I did not solve, but they are rare. There are rough edges, but fewer than before. In last year’s AIIDE, Steamhammer was version 2.0, with many new features including unit clustering and defilers—and they were buggy. This year it is version 2.3.4, and the version number is deserved: The strength improvements over 2.0 are due to bug fixes and refinements, not new features.

This means, of course, that it is time to get back to work on version 3.0, with new strategy adaptation features. Add bugs for victory!

Before long I’ll either upload version 2.3.4 on SSCAIT as zerg only, or I’ll come out with version 2.3.5 that can play as any race.

By the way, I counted the number of zerg openings. There are now 142.

Steamhammer-Microwave rivalry

Microwave was forked from an early version of Steamhammer, and the two have been struggling against each other ever since.

• AIIDE 2017 - Microwave 70.86%, Steamhammer 64.14%
• SSCAIT 2017 - Steamhammer 83.12%, Microwave 79.87%
• AIIDE 2018 - Steamhammer 54.97%, Microwave 54.16%
• SSCAIT 2018 - Microwave 74.65%, Steamhammer 72.54%

The two bots have different strengths, but most results have been close. Which will edge out the other this time? On BASIL, Steamhammer and Microwave have been trading the top zerg position back and forth. Microwave has an advantage in head-to-head fights, but I think Steamhammer has a slight edge overall. We’ll see how the tournament goes!

Randomhammer (Z)-Microwave is a ZvZ with devourers and defilers. Microwave wins the majority of games, but Steamhammer has better hive tech skills.

Steamhammer for non-programmers

A comment to Undermind Episode 31, which mentions non-programmers entering build orders into Steamhammer. I tried to comment directly at Making Computer Do Things, but WordPress thought I was a bot... which was kind of ironic. So I expanded and posted here instead.

There is documentation for the Steamhammer configuration file. It is not up to date, but it is complete except for newer features. It should be plenty for a non-programmer to enter build orders. Telling Steamhammer to play the build order will look difficult if you only read the config file, because the default config is complex, but if you read the documentation you’ll see it’s trivial. Other tricky parts: Steamhammer doesn’t always play build orders literally; queue reordering will be really confusing for beginners. The unforgiving JSON syntax plus uninformative error message might cause trouble (one misplaced comma and it’s “ha ha, it didn’t work, and I won’t tell you why!”).

Thanks, good discussion! I have new ideas about how to make it easier for people to get started. At some point I’ll try to do them.

• Add a simple sample configuration file for people who don’t feel like being overwhelmed by the performance config.

• Add documentation for non-programmers, that concentrates on the most useful features for them.

• Smooth out some of Steamhammer’s in-game behaviors so they are more intuitive. Somehow. They are there because they help sometimes, but they add complexity and can trip me up too.

defiler bugs to the horizon

I wasn’t planning to work more on defiler play for the time being, but then I discovered two more sets of bugs affecting defiler play. Since defilers are bugs, does it follow that you can’t have defilers without bugs? First, my additions to FAP to understand dark swarm had multiple errors in determining which units can hit under swarm. That could cause Steamhammer to cast swarm over its units, then needlessly retreat from under it. Second, there was an unbelievable bug which assigned defilers not only to the defiler controller, but to the melee unit controller at the same time. In between their regular orders, defilers were being interrupted with nonsense orders to act like zerglings. How did defilers ever work? Because in the buggy live version, defiler play is, somehow, already valuable.

Rule of thumb for the upcoming tournament version: If Steamhammer survives to the late game and has defilers out, it is probably winning.

Steamhammer 2.3.3 test version

I’ve uploaded tournament test version Steamhammer 2.3.3 to SSCAIT, zerg only as usual. This version has critical bug fixes, and changes to make defilers more active. The bug fixes are the important part, but it’s a delight to see Steamhammer swarm cannons with alacrity. At least sometimes!

I expect that the final tournament version will be 2.3.4, and that I won’t much benefit from another test version. I have an idea for one new feature that is low risk but should significantly improve the strength.

Next: New bot BetaStar.

Steamhammer 2.3.2 with bug fix

The test paid for itself! Version 2.3.1 has a crashing bug that can strike replacement defilers. I got two crashes on SSCAIT, though strangely none on BASIL. I’ve uploaded Steamhammer 2.3.2, which fixes the bug—I hope it’s the only new defiler bug. Also in the new version are a micro improvement for smoother maneuvering, plus tweaks to plague usage.

The tournament test versions are configured to play zerg only.

I’ve seen a few games with queens and some parasites cast, but Steamhammer hasn’t infested a command center in public yet. I’m sure it will before long. It leaves the infested command center sitting there, blocking the base. I’m curious to find out whether that causes more problems for the opponent, or for itself.

Steamhammer 2.3.1 uploaded

I’ve uploaded Steamhammer 2.3.1 to SSCAIT. It is a test version to smoke out any major new bugs before AIIDE. Opponents that tune against Steamhammer will be able to test against a near-final version, but if I catch an important bug that will more than make up for it.

This version sometimes makes one queen, and knows how to parasite and infest. That’s the only difference that a casual watcher will notice. (In the stream you’ll be able to see the extra vision from parasited enemy units, but the OpenBW player does not show fog of war.) I put in a wide variety of smaller bug fixes and improvements, though unless you watch closely you may not detect them. The improvements tend to make Steamhammer’s behavior more complex, and I foresee a high chance of surprises.

No detailed change list until after tournament submission. It’s not all that short.