archive by month
Skip to content

Steamhammer status update

Steamhammer 1.1 is in the works. It is currently short 1 major feature, 2 smaller features, and 7 critical bug fixes that I know of, so it is still a ways off. When it does come out, the headline feature will be the ability to transition from one unit mix to another in the middle game. Currently, all transitions are written into the opening book, obviously a severe limitation. The work involves completely rewriting the macro code, and I’m only part way through.

I keep changing my mind about the order of improvements. Here is an outline of what I’m thinking today, so that when I do something completely different, nobody will be surprised.

The basic order of middle game skills should be mutalisk skills, then lurker skills, then drop and runby skills (which are related in a way). For the benefit of people who fork Steamhammer, I want to make sure that all races work and that the bot can play random—it’s theoretically possible today, but I haven’t tested it so expect some bugs. It’s also a priority to upgrade base defense in general and worker defense in particular. In long macro games Steamhammer 1.0 does stuff which is bananasuperbeyond boneheaded, which I’ll have to ameliorate a little at a time. Scouting has got to be worked on and must tie into tactical decisions better. Upgrades need to be more aggressive, and the first hive units should be ultralisks. I really really want to make a start on opponent modeling soon. And I have many other plans that I’ve written down but not put into priority order.

Anyway, here are today’s plans for the headline features of the next few versions. I’m expecting many extra features and fixes in 1.1 and few extras in 1.2 (and beyond that I don’t want to predict).

  • 1.1 - transitions
  • 1.2 - test and fully support random play, like UAlbertaBot
  • 1.3 - mutalisk reign of terror

After starting work on 1.1, I’ve already changed my mind twice about what to do when, and I may rethink again without warning. I shouldn’t try to plan further ahead.

Now I need to put my head back down and return to work.

Steamhammer at 78%

I looked up Steamhammer’s standing on SSCAIT today and was startled to see it at 78% win rate, equal with Bereaver.

standings of Bereaver and Steamhammer

The winning percentages are volatile and I don’t believe for a minute that Steamhammer is as good as Bereaver. But I have never seen it fluctuate up that high, either. Apparently the 1.0 version is substantially stronger. It is definitely better than 0.2, but how much?

Update: I documented Steamhammer 1.0’s configuration file. Because of the new features I added, somebody already expressed interest in forking from Steamhammer rather than directly from UAlbertaBot. Go for it!

Steamhammer and opponent-specific strategies

Some successful bots play in a way that seems to me so unlike sound strategy that I feel morally obligated to beat them—or at least to try. Soundness must be upheld! I do it at the expense of teaching Steamhammer to play well in the general case, but it still feels worthwhile. It’s a quirk of mine, I guess.

As Steamhammer becomes more reactive I’ll remove some of these handmade counters, and when opening learning is in place I’ll drop all of them. But for now I think this is the way.

versus XIMP

The carriers must be crushed! For Steamhammer 0.2 I came up with a three hatch before pool build that puts a lot of hydralisks on the field, in the hope that they would tear down the cannon wall and win, or failing that, would hold off the carriers and bleed XIMP’s money away. I wrote up the first game. It didn’t quite work out; Steamhammer tore down the cannon wall, but with its other weaknesses did not have enough left over to win convincingly.

In later games, I found that Steamhammer 0.2 wins occasionally, but usually loses. It depends partly on the angle at which the hydras approach the cannons. Steamhammer doesn’t know the first thing about good formation, and when the hydras approach around a corner or otherwise in poor formation, they can’t take the cannons. The bot needs to know how to form up.

And it needs other improvements. It can eventually deal with either the cannons or the carriers, but when it tries to deal with both it loses. The tactical decision making is not there. Plus Steamhammer 0.2 has weak macro and doesn’t make as much stuff as it should.

Steamhammer 1.0 has adequate macro. It sometimes lets its minerals run up, but adds enough hatcheries to recover. Its hydra build is improved. The tactical decisions and formation are not improved, so I’m not sure how games will go.

For fun, I added a second three hatch before pool opening that goes mutas. We’ll see whether Steamhammer’s air power can prevail with adequate muta micro and disorganized scourge usage. XIMP goes corsair when it meets air, so I timed the build to produce the first 9 mutas simultaneously and hit hard before XIMP can react.

Versus XIMP, Steamhammer chooses hydra and muta each 50% of the time. Steamhammer already played 1 game versus XIMP with the air build, but it was on Benzene and Steamhammer’s third hatchery drone got lost due to the back door block—the same problem that Bereaver had against XIMP on Heartbreak Ridge, with the same sad result.

versus Iron

The vultures must be repelled! They don’t make sense as a mainstay against zerg. I tried an opening tailored and timed to beat the vultures without having to equal Iron’s superb micro. When I ran my specialized strat against an early December version of Iron, Steamhammer won 13-2. Iron is updated frequently, so as the tournament deadline approached I tested again against the 14 December version of Iron, and Steamhammer scored 8-7; that’s why I said that it had about equal chances. I messed up and my strat didn’t run during the tournament. But later I tried it against the tournament version of Iron, only a few days newer, and Iron won overwhelmingly! All respect to Igor Dimitrijevic, Iron improves at an incredible rate.

For Steamhammer 1.0 I put in a cheesy exploit strat, not a sound counter strategy. Against the tournament Iron it wins 13-2, losing only on 2-player maps. Iron improves so fast that I’m not sure it will work against the January Iron—and if it does, probably not for long! I have 2 different sound counter strategies in hand, but Steamhammer needs new skills before it will be able to pull them off. Eventually I hope to force Iron to play soundly, and then its amazing ability will be hard to touch.

versus Jakub Trancik

The cannon proxy scares me. If you see the cannons in time, they are no trouble. But what if you don’t see them? Steamhammer is none too sharp at scouting for surprises. In practice Steamhammer 0.2’s 9 pool is successful in stopping the cannons when no bug intervenes.

For Jakub Trancik I went with Steamhammer 1.0’s new “hidden base” skill in a 9 pool expo opening. This is Steamhammer’s only use of a hidden base in a far corner of the map. If the cannons are seen, lings will tear them down. If they are not seen, the zerg main will probably fall sooner or later, but the hidden base will live on. Steamhammer 1.0 is not fully robust, but it can often recover from losing its tech.

Steamhammer 1.0 also plays the 9 pool expo 20% of the time versus random opponents, because why not?

versus GarmBot

Against Aurelien Lermant’s GarmBot, Steamhammer plays its 13 pool opening—an opening that is specialized for play versus terran. By sheer coincidence it is also a strong counter to zerg GarmBot!

about Steamhammer 1.0

Change of plans. Today and tomorrow I’ll download my thoughts about Steamhammer 1.0 before I dive into 1.1 and start to forget which feature came when. After that I’ll return to tournament coverage. Keeping up with real time? I may have heard of that.

Steamhammer’s web page is updated. Get the 1.0 source and binary releases there. Downloading from SSCAIT is another way to get the binary. Don’t miss the config file, the bot needs it to run.

new skills

The configuration file lets you specify more possibilities as part of the opening build orders. One of my goals is to be able to play every opening, and I’m making progress.

  • scout on command: always, or only if necessary, or only to find the enemy
  • build a macro hatchery, or mineral only base, or a gas base, or a “hidden” base
  • stop and restart gas gathering, or gather a specified amount of gas then stop
  • build static defense in the main or natural

For example, you can code “go scout if needed” to send out a worker scout, right then, only if the enemy base location is not already known. Or “go gas until 100” to get 100 gas for zergling speed and then put the drones back on minerals. Or “hatchery @ min only” to start a new base that does not need to have gas. These are items that can go into the production queue to be executed when they come up; the strategy boss uses the same underlying code to communicate its dynamic plans to the production manager.

New openings use all these features. The old openings in Steamhammer have also been reworked extensively. Even when it looks like it’s doing the same thing as the previous version, there are differences. Some openings have fancy optimizations, like stopping and restarting gas more than once to smooth production. It’s easy to edit the config file, so it’s no special effort to try out tricks like that.

The strategy boss copes with emergencies like having no drones and has some basic reactive skills, like queueing up scourge when corsairs are sighted. Overall Steamhammer is much more robust when things go wrong; there are still bugs that can freeze it, but only on cool days.

The strategy boss also improves macro. Steamhammer still sometimes runs its minerals up into the thousands, but it recovers reasonably soon, and in many cases macro is fine from the beginning of the game to the end. Far from perfect, still much better.

random openings

Steamhammer 0.2’s ZvT configuration looks like this. It plays one fixed opening.

		"ZvT" : "ZvT_12Pool",

Steamhammer 1.0’s looks like this.

		"ZvT" :
			{ "StrategyMix" : [
				{ "Weight" :  3, "Strategy" : "4PoolHard" },
				{ "Weight" :  2, "Strategy" : "4PoolSoft" },
				{ "Weight" :  5, "Strategy" : "5Pool" },
				{ "Weight" : 10, "Strategy" : "9PoolSpeed" },
				{ "Weight" : 25, "Strategy" : "ZvT_12Pool" },
				{ "Weight" : 35, "Strategy" : "ZvT_13Pool" },
				{ "Weight" : 10, "Strategy" : "ZvT_2HatchMuta" },
				{ "Weight" : 10, "Strategy" : "ZvT_3HatchMuta" }
			]},

The bot chooses randomly among 8 openings, 4 zergling openings and 4 mutalisk openings. I haven’t worked seriously on lurker skills yet. The weights can be any positive integers, but I chose weights that add up to 100 so that I can interpret them as percentages. The 4 and 5 pool openings are slight variations of the same thing and happen 10% of the time in total. (With better scouting skills and followup, Steamhammer plays these fast rushes more strongly than UAlbertaBot.) The 9 pool overruns surprisingly many terrans and happens another 10% of the time. The 12 pool and 13 pool are similar muta rushes and together happen 60% of the time. Most people won’t notice the difference between the similar openings, but many details vary. The 2 hatch and 3 hatch muta openings are actual genuine honest-to-Betsy true-blue manufacturer-guaranteed mainstream builds with stronger economy, but Steamhammer is not yet adaptive enough to play them safely, so together they happen only 20% of the time. I’m curious to see how well they do in practice—hmm, I predict results will vary!

Steamhammer also chooses randomly in the other matchups, including versus random. You have to scout it to know what it is doing.

other stuff

The configuration file includes the version number: Steamhammer_1.0.json. That way I can conveniently run more than one version from the same directory.

I blogged about the fixes for original UAlbertaBot bugs. There were 10 in total, and only a couple were already in version 0.2. Stream viewers may not notice, but Steamhammer makes slightly fewer absurd blunders.

There are many small improvements to tactics and targeting, which together make a noticeable difference. The bunker obsession is reduced but still claims its toll. The bot is less eager to send out drones for emergency defense, but doesn’t run them away when they are under attack (“keep working, you cowards!”). And Steamhammer now has basic overlord vision skills thanks to hints from AIL, so it makes more informed engagement decisions and can fight cloaked units like dark templar.

And that’s about it. All other changes are minor.

future plans

Alongside further work on adaptivity in the strategy boss, next I want to improve the defense against worker harassment. Aggressive harassers like Iron and Bereaver often kill 2 or more drones, a grave setback (very like being set back in the grave). After that, I want to finally fix the mutalisk tactics and put those terrans in their place. When the mutas meet a strongpoint they should not call a dance party, they should turn aside (“you’re no fun!”) and fly around it. After comparing ideas and thinking ahead to how I want to integrate it someday with machine learning, I’m leaning toward Berkeley Overmind-style convex hull analysis rather than Overkill-style pathing analysis or ZerGreenBot-style reactive movement. But we’ll see.

One thing at a time. Mutalisk skills first, then lurker skills, then drop skills. Once I have all those, opponents will need real smarts to foresee what is going to happen to them.

Tomorrow: Some of Steamhammer’s opponent-specific openings.

Steamhammer 1.0 uploaded

Steamhammer 1.0 is uploaded. I had 2 essential bugs to fix; I fixed 1 and the other turned out to be transient or intermittent so it was not essential after all. After that, testing turned up 3 more bugs in the new adaptation code, and they affected how openings played out so they were essential too. Whew, all fixed, it took until now! The web page is not updated yet. I’ll also write it up here. I just... need some... time.

By the way, 3 brand new bots have also appeared, and old standards have been updated. This is a fun time.

Update: In a comment, AIL offers a video of his new bot AILien playing 3 games.

Steamhammer’s greatest misses

All bots have bugs, even strong bots. Watching a game Krasi0 vs Iron today, I saw that Iron had built many academies, some in rows like subsidized housing. Sadly, its devotion to education did not help it win. Krasi0, by the way, has a similar bug with turrets. It’s a kind of symmetry.

Here are some of Steamhammer 0.2’s most dramatic bugs.

drone defense aka suicide

Steamhammer loves to defend with drones. You can almost hear it jumping up and down, “Can I send out the drones yet? Can I send out the drones?” When it works, it looks brilliant—how did it kill all those zerglings and only lose 1 drone? When it fails, it looks ridiculous. Here the drones are blocking the bot’s own zerglings and the game is about to be a massacre.

I sent out the drones!

suicide aka drone non-defense

Despite its love of drone defense, Steamhammer sucks at defending its drones from early harassment. Its system of chasing the enemy scout with one drone is adequate against weaker bots, but often loses 1 or more drones against strong opponents. Here Bereaver’s probe already has 2 kills, and the newly-hatched zerglings are speeding past ignoring it. Not their job.

probe victorious

gas > life

Many bots share this play bug. Steamhammer 0.2 believes that vespine gas is more precious than life itself.

If you kill a gas drone, the bot will replace it. If you kill all but a few drones, it will put the survivors on gas and mine no minerals. If you kill a hatchery and leave the extractor, it will send drones to long-distance mine the extractor, and if you kill those, it will send more. Leave a few units in the destroyed base and Steamhammer 0.2 will ship over its entire mineral-mining population 3 at a time to be exterminated. Gas is more precious than life.

This bug is related to strategy, so it is mostly fixed. Steamhammer dev version has skills to start and stop collecting gas at sensible times. Tonight I’ll fix a bug in the interaction between automatically turning off excess gas collection and gas limits specified in the opening book. Later I’ll fix the one last corner case that I know of: If you kill an expansion hatchery while its extractor is still morphing, the bot will still do the extermination train when the extractor finishes.

expand to the enemy base

Some have wondered why, in longer games, Steamhammer sometimes sends a drone or two to the enemy base to die. That’s simple. It wants to expand there. What’s to stop it?

this looks like a good place to build

UAlbertaBot’s native “where’s the next expansion?” routine does not take into account where the enemy is. It only checks whether the spot is blocked by a known building, and I suspect that the check is not correct. The dev version tries to expand away from the enemy, only sets its sights on untaken bases, and is reluctant to take a base in the same region as any known enemy building (but it still will try, in a pinch).

scouting by mistake

But expanding to an enemy base is not so bad if you didn’t realize. After the early game, Steamhammer does not scout again until all known enemy buildings are destroyed. If you build where Steamhammer does not want to attack, there’s a good chance that you won’t be discovered until late game. It usually finds enemy expansions eventually, though, because it likes to expand across the map.

Scouting is high on my list, which means I should get to it sometime in February.

detection? what’s that?

Who would even try a straight dark templar rush against zerg, with no attempt to chase away overlords? Well, MegaBot would. It worked, too. Here the drones are trying to help out in a fight against invisible assassins that can kill them in one blow. Sure, you can send in the drones, stop jumping.

dark templar destroy a base

I’ll take this base twice—no, three times!

If you watch Steamhammer games, sooner or later the camera will move to a new base with a hatchery, one or two idle drones, and nothing else. The nothing else is because the bot does not try to balance its drones among bases; it only transfers as old bases saturate or mine out. The idle drones are because Steamhammer tried to take the same base more than once at the same time. The production queue had 2 or 3 hatcheries in a row, and the building placer decided to put them in the same spot. Often 2 drones arrive simultaneously and repeatedly prevent each other from starting the building—no need for an enemy, Steamhammer can harass itself. Eventually one succeeds, and then the other drones are despondent and go idle.

Nice one, right? It turns out that the building placer was missing a check, “don’t place a hatchery in a spot already reserved for another.” I added the check, but it still behaves the same; either the check is wrong (which I suspect), or else there’s another mistake. Steamhammer dev version at least puts the idle drones back to work.

So little to do, so much time! How will I alleviate the boredom?

Steamhammer vs LetaBot, SSCAIT round of 16

Steamhammer’s round of 16 game in the SSCAIT was entertaining. It was played on Moon Glaive against Martin Rooijackers, the latest LetaBot. Steamhammer has played a bunch of games against this version of LetaBot, so I can roughly estimate by eye (without counting the games to be sure) that Steamhammer wins maybe 1/4 of the time or so. LetaBot is clearly stronger, but there is a chance of an upset. The round of 16 is single elimination, so the winner moves on and the loser is out.

Steamhammer 0.2 opened with its 2 hatch muta rush and LetaBot went rax-expand. The video doesn’t show it, but Steamhammer’s first 4 zerglings got 3 SCV kills between them. They sniped the SCV building the natural command center and 2 more that came to replace it before marines chased them off. That set terran back, though not decisively. Here the zerglings are escaping from marines that you can see on the minimap, and LetaBot is about to resume construction.

the 4 zerglings escape

LetaBot built 2 bunkers in front of its natural for safety. Unfortunately for Steamhammer, the map positions meant that the bunkers were on the straight line flying path between bases, so Steamhammer’s bunker OCD meant that zerg could not harass. The mutalisks stopped and stared at the bunkers in a standoff. Nepeta in the video politely called it “containing” the terran, but since zerg played a rush opening and terran played an economic opening, zerg was falling behind with every passing second. The rush must do damage to win.

mutalisks stare at the bunkers

LetaBot already had a winning game when terran moved out. If the terran ball had stayed compact, the terran forces would have punched through all opposition and won on the spot. But LetaBot let its forces string out, and the mutalisks were—just barely—able to defeat the army in detail. (Watch Carsten Nielsen play. The protoss bot may be the champion of maintaining good formation with its zealots while attacking. Few bots can do it at all.)

LetaBot lets its forces string out

I selected a mutalisk so you can see the zerg resources and supply. Steamhammer 0.2’s poor macro is showing; it expands too late and does not know how to build macro hatcheries, and it did not have enough hatcheries to spend all its income. Terran was economically far ahead and zerg was failing to keep up production, so it hardly needs saying that the next attack brought victory to LetaBot. (Macro is much improved in the current development version, though still not good enough. The current version would have crushed the attack with forces to spare, and would have still been in the game.)

An entertaining game, though more one-sided than it may look!

backing up is hard to do

If you want to beat Steamhammer without really trying, I have a suggestion. All you have to do is maneuver your army to the other side of Steamhammer’s and put yourself on the path between Steamhammer and its base. You leave your base wide open, but you’ll probably win. It works versus ground units and versus air units.

At some point Steamhammer will want to retreat. Even when winning, it sometimes retreats for no apparent reason (I haven’t looked into why yet). It pays no attention to its surroundings when it decides to retreat, so if you are on the path between Steamhammer and its base, it will retreat through your army. And Steamhammer does not fight when it retreats—the units are on move command.

Here Steamhammer forced its way into Carsten Nielsen’s base, started in on the probes, then got scared for no good reason and left, giving the zealots free kills. If more zealots had been near the ramp, all the zerglings could have been caught.

Steamhammer loses zerglings

The next one is even more infuriating. Sometimes, Steamhammer retreats from a threat but does not retreat out of weapons range. It seems unpredictable when. It’s most glaring with mutalisks and goliaths: Mutalisks approach, take hits, retreat without firing, turn around before escaping goliath range and approach again, continue to take hits, retreat without firing... it doesn’t go on long, soon they’re all dead with nothing accomplished.

Here Steamhammer’s mutalisks are moving back and forth in goliath range, offering free lunch. The mutas did eventually escape, only to get caught again.

Steamhammer loses mutalisks

It also happens sometimes with mutalisks and bunkers, zerglings and bunkers, and zerglings and tanks. And probably other unit combinations. But it doesn’t happen every time, only sometimes.

I don’t have immediate plans to fix either of these weaknesses.

Later: I’ll have at least one more post about bugs and weaknesses in Steamhammer 0.2.

Steamhammer’s bunker obsession

The #2 most frustrating weakness in the play of Steamhammer 0.2 is its insane obsession with bunkers.

Here’s the kind of strongpoint Icebot builds when it sees Steamhammer’s mutalisks coming: A bunker, surrounded by turrets, with SCVs to repair, placed out in front where it can’t be overlooked. Objectively, it’s a stupid move, because the rest of the terran base is barely defended. Against an opponent that knows how to bypass strongpoints, like Overkill, Icebot collapses.

Icebot's strongpoint

But against Steamhammer, Icebot holds and usually wins. Steamhammer sees that bunker and can’t take its eyes away. Steamhammer measures the air defense and realizes it can’t attack, so it pulls back a little, waits, collects some more mutalisks, pokes in to take another look, still doesn’t have enough, waits some more... soon Icebot has goliaths and valkyries and it is too late. Steamhammer’s opening is a low-econ rush, and the last thing it can afford is to wait.

It’s frustrating for two reasons. One, it’s intolerably foolish and must be fixed. And two, it’s not a simple bug that can be set right with an hour of coding. It’s an ingrained behavior with both tactical and micro aspects—it’s the result of a design attitude, and it has more than one cause.

I already fixed one cause in moving from Steamhammer 0.1 to the tournament 0.2 version. In 0.1, the mutalisks were grouped with zerglings in the same squad and followed the same path, so the mutas were constrained to ground paths and could not avoid front bunkers. In 0.2 the mutas are in their own squad and can fly as they will, so in some cases they fly a straight line path far from any bunker and ravage the terran. It helps noticeably, but not enough.

Another cause is targeting priorities. Steamhammer 0.2 believes that a bunker is more important to attack than a marine or a turret. When it collects enough mutalisks to fight, it should pick off turrets until the bunker is laid bare—the turrets are easier to destroy. Instead it ignores the turrets and goes straight for the bunker, which of course terran repairs. The development version of Steamhammer gets the priorities mostly right, after about 3 rounds of tinkering, so this cause is fixed too (well, fixed enough for now). New Steamhammer plays clearly better around bunkers.

But improved Steamhammer still shows obsessive tendencies. Given an unguarded command center and a bunker, instead of winning the game without risk it will too often divert to fight the bunker, depending on what happens to catch its attention.

The most fundamental cause is that the tactical system is not conceived with guerilla warfare in mind. I think many bots share this weakness, maybe most bots. Steamhammer, like its parent UAlbertaBot, draws a line from its base to the enemy’s and wants to progress down the line: Defeat the units in front of me, move forward, defeat the units in front of me, etc. It’s a super-simplified tactical framework. And for the guerilla warfare of air units, it is exactly backwards. The guerilla wants to bypass the units in front and hit wherever the defenders aren’t.

The simplification shows in how the combat simulator SparCraft works. SparCraft wargames out a battle under the assumption that both sides stand and fight, and predicts who will win: The side that is not annihilated. But in the fight of mutalisks versus terran base, only the terrans want to stand and fight. The mutalisks are happy to hit and run, as long as they don’t suffer too much. The mutalisks would prefer to ask SparCraft the question, “can I kill something—anything—and get away without any mutas dying?”

Anyway, I’m not going to fix this fundamental cause soon. Someday I hope to work on SparCraft and teach it to answer more questions. But that is at the tactics level, and I’m doing strategy first.

Tomorrow: The #1 most frustrating weakness: Retreating is hard to do.

picking the opening randomly

Why does random UAlbertaBot score so well? Its 5 pool rush is easy to counter. Its marine rush is weak and easy to counter. Its zealot rush is strong, but it can be stopped too. I think the secret is: What opening counters all 3? Well, overpool works, but you have to play it very differently depending on what race UAlbertaBot turns out to be. Bots struggle to adapt. Randomness has value in itself, because it forces the opponent first, to choose openings carefully, and second, to scout and adapt.

Steamhammer’s new strategy boss is not far along; it can only respond to a few basic emergencies, like having no drones. (Steamhammer 0.2 freezes; the development version orders up a drone and can play on if it has 50 minerals.) But yesterday I decided it would be more fun to switch the order of improvements around and do randomized openings before getting the strategy basics down.

I was right, the variety is a lot more fun. I don’t know in advance what Steamhammer is going to do; I have to watch and see.

Today I played a long ZvZ match versus Zia to make sure that the random openings don’t hurt performance. Steamhammer played 5 different openings. One of the openings dominates Zia, but Zia has answers to the other 4—if it can find the answers with its opening learning. Does mixing in the weaker openings give Zia a chance to find the answers, or does the randomness wipe out any learning signal and make life even harder for Zia?

Answer: After 45 games, giving Zia time to learn, Steamhammer scored 40-5. Zia won 4 games by accidentally hitting on a counter and 1 by playing better tactically. At worst, the weaker openings do not hurt. They were chosen to have different counters, and Zia’s implicit assumption that there should be One Best Counter is wrong.

Lesson: Opening learning is not enough, at least not this kind. As difficult as it may be, you have to recognize what the opponent is doing and adapt to it.

On the downside, to earn the full advantage from random openings I have to implement more openings and make sure that Steamhammer plays all of them well enough. At the moment it only has enough variety in ZvZ. But someday, with both random openings and opening learning, Steamhammer will turn fearsome.

Update: I should have added a couple points. 1. Random openings make it hard for other bot authors to hand-code counters to your strategy. This change to Steamhammer should defeat Chris Coxe’s plan of countering specific opponents. 2. Random openings are more fun for humans to play against.

Tomorrow: The curséd bunker obsession. After that: Retreating is hard to do.

Steamhammer’s funniest bug

Here is Steamhammer’s most hilarious bug. When facing Jakub Trancik’s cannon bot, Steamhammer opens with 9 pool, a sunken, and then an expansion. The idea is that 9 pool counters the cannon rush; zerglings should be out before any cannons finish. If that somehow fails, the sunken prevents cannons from completely destroying the base, and the expansion gives zerg a foothold on the other side of the cannons; Steamhammer should be able to go destroy the protoss main. I hadn’t tested it, but with 3 separate counters to proxy cannons I felt confident. I was wrong, though. As it turned out, Steamhammer went 1-1 versus Jakub Trancik in the round robin phase of SSCAIT 2016.

In the losing game, here’s the probe trying to cannon up the zerg base. The probe took 1 sunken hit, escaped and started a pylon, then the probe and pylon immediately died. The defensive plan worked exactly as intended.

Jakub Trancik’s probe about to die

So how did Steamhammer lose? In the minimap, you can see Steamhammer’s overlord headed toward the northwest and drone scouting the southwest. The protoss main hadn’t been seen yet. When it saw a pylon warping in its base, Steamhammer applied a heuristic: I see an enemy building in this base location, so—this must be the enemy base! The scouting probe immediately returned home and starting running loops around the home base, because it was the enemy base too, and the scout never saw the enemy’s real base. It’s not entirely foolish behavior if your enemy likes to proxy! Zerglings explored around and found “another” enemy base filling up with cannons, and started to build up numbers in preparation for an eventual attack. The mistake didn’t look too bad so far.

Then Steamhammer built an extractor on its gas. Since the extractor was in enemy territory, it was obviously a gas steal, so the bot did not collect any gas. The drones will die in the enemy base, right? The zerg build was not able to progress, Steamhammer stopped building anything, and Jakub Trancik eventually did its zealot switch and won, gg.

Here is the unused “gas steal” extractor. That drone moving up the right is the scouting drone, still circling the “enemy” base. The minimap shows zerglings out exploring, looking for the “last remnants” of the protoss. You can see 2 zerg expansions; Steamhammer 0.2 is slow at it, but it set about methodically building up.

Steamhammer is about to freeze up

All those consequences from 1 flaky heuristic! I’m still laughing over it—I get to laugh because the fix is a 1-liner and I already made it in December. The heuristic and the bug are inherited from UAlbertaBot, but I have never seen the bug in UAlbertaBot’s play. I’ve also never seen the heuristic fail any other way, although it can. On the one hand, it’s a critical bug that can cause losses; on the other hand, it’s not that important to fix because it’s rare. Bugs are weird that way.

Next: More bugs and weaknesses (they won’t all get such a thorough writeup, though).

Steamhammer versus Zia for the SSCAIT round of 16

Steamhammer and Zia tied for 16-17th place in the round robin phase of SSCAIT 2016, and played a best-of-3 tiebreaker match to decide who would move on to the round of 16. The video is out with commentary, and here are the games. They’re all somewhat entertaining, if you can tolerate weak bot ZvZ. The caster seemed unfamiliar with bot play, so I’ll explain the reasons behind some of the events.

Game 1 was on Destination. Zia had learned from past games that its most successful opening was an aggressive 9 pool, and that’s how Zia opened. This version of Steamhammer follows a fixed 12 pool build, which is riskier on this 2 player map. When Zia’s initial 6 zerglings arrived at its base, Steamhammer was just about to produce its first 4 zerglings, so Steamhammer pulled drones to defend. With drones and 4 zerglings, Steamhammer should have defended safely. But Steamhammer tends to be overeager with its drone defense and pulls its drones too far out; it should defend in the mineral line, or at least on the creep, but it pulled drones most of the way to the ramp. (This is one of its most severe weaknesses, one step behind the absolutely-must-fix problems.) When Steamhammer’s zerglings followed the drones moments later, the drones got in their way, and too many drones were lost. Zia was far ahead, cautiously built up, and won easily.

Game 2 was on Circuit Breaker, a 4-player map where the aggressive 9 pool is less likely to work. Also, the players spawned in cross positions, so the rush distance was longer. Nevertheless, Zia had learned that it worked, so Zia played the aggressive opening. And sure enough, Zia arrived with more zerglings and Steamhammer again defended poorly, frittering away its lings against a larger force instead of massing for a short time before engaging. Zia was tearing down the natural hatchery while safely expanding itself, and the game seemed to be decided. Then Zia’s remaining zerglings settled on the wrong targets, one attacking an egg and another a larva. The hatchery was deep in the red and would have died if attacked by those 2 lings. Instead Steamhammer’s next wave cleared the invaders and the hatchery survived with 34 hit points, a sliver of red on its health bar. Then Steamhammer had both economic and tech advantages and went on to win. Steamhammer does not make the same targeting mistake, so you could say it was a deserved win, but it was no less a lucky win.

Game 3 was on Fighting Spirit. Zia’s learning algorithm said “uh oh, that didn’t work, better try another opening” and picked a defensive 9 pool instead. Zia massed its zerglings but held them on its ramp for safety. Steamhammer’s opening gave it more larvae, a stronger economy, and a faster tech path, all at the cost of fewer and later zerglings, so Zia’s choice to stay home was poor. Then Zia made another mistake when it wanted to expand to its natural. It should have swept its ling force out to secure the natural, but instead pulled back to the main hatchery to let the expansion drone out. Only after Steamhammer sniped a few expansion drones did Zia change its mind and attack across the map. Steamhammer defended with its characteristic incompetence, overeagerly pulling all drones and losing every one, but mutalisks were out and cleaned up.

Zia has a sneaky fallback when it repeatedly fails to take its natural: It takes a hidden base instead. This time it took the center base on Fighting Spirit. Zia is capable of rebuilding from a hidden base and the cash for a drone or two, but of course it takes a long time. Steamhammer’s mutalisks abolished Zia’s main and then set out across the map to find remaining buildings. Steamhammer’s search behavior (inherited from UAlbertaBot) is inefficient and looks strange, and the caster was understandably confused about it. The algorithm is simple. Steamhammer keeps track of when it explores each square of its map grid, and picks one of the squares that it has least recently explored as the next destination. It’s good enough.

Steamhammer will play LetaBot in the round of 16. The pairings are 1-16, 2-15 and so on, the arrangement with the least likelihood of upsets for the top finishers. Nevertheless, Steamhammer does defeat LetaBot occasionally and has a small chance to move on to the round of 8. If Steamhammer pulls off the upset, it will almost surely lose in the round of 8—it loses 100% against Wuli’s 9-9 gate zealot rush, and nearly as often against Overkill by Sijia Xu. I’ll borrow the bracket image.

SSCAIT 2016 finals bracket

Steamhammer and software development

I’m going to make a post about bugs and flaws in Steamhammer, with pictures. Some are hilarious, some are to weep over. But there are so, so many that I’m too busy fixing them to write about them! So far, my change log for the next version shows 22 new features and bug fixes worth mentioning, and yet the issues marked DONE are thin on the ground.

On my first day of development on Steamhammer, December 2 or 3 I think, I started tracking issues to deal with. Within a day the list was large enough to need organizing. I divided it into topics: Macro issues, build order issues, targeting issues, code issues.... After a while that grew to become unwieldy too, so I also prioritized the issues to concentrate on the critical absolutely-must-fix ones. Today I ran test matches against various opponents and found serious bugs, and now the absolutely-must-fix issues are more than I can keep an easy overview of. I’m overwhelmed, and it’s harming my ability to solve problems in the right order.

This is why it takes a long development period before a new bot can threaten the top ranks. Well, I knew I was in for it. One step at a time. I will eventually get to the good part.

Not that the test matches went poorly. The development version of Steamhammer with new skills and a new ZvZ opening scored 26-4 against Zia, a huge improvement. Zia tried all its openings and could not find an answer. The 4 losses were all due to play bugs that I hope to fix soon—if they don’t get swamped by other bugs. Steamhammer also finally has a non-awful ZvRandom opening.

Steamhammer and the SSCAIT finals

The round robin phase of SSCAIT 2016 has just finished. Seconds ago, Matej Istenik beat OpprimoBot in the last remaining game. Did Steamhammer make it into the round of 16?

It was a nailbiter! Only fiction gives us closer decisions. As the end approached, Steamhammer and Zia were tied for 16-17th places, each with 1 game remaining to be played. One would be in and one out! As the last dozen or so games came up, Zia was scheduled to play MegaBot, and after 2 intervening games—just enough time to enjoy the tension—Steamhammer to play Tscmoo protoss.

Zia had beaten MegaBot in their previous game, and easily won again. In the previous Steamhammer-Tscmoo game, Tscmoo had opened forge expand; Steamhammer did not know how to adapt its build and lost. (That is why Steamhammer opens three hatch before pool against XIMP and ZerGreenBot.) Tscmoo is unpredictable.... I thought the odds were poor, but I knew anything was possible. This game Tscmoo opened 14 nexus and then gas before gateway, a crazy greedy opening, and went down like a house of cards. What a way to deflate expectations of an exciting decision!

Steamhammer and Zia finished in a tie for 16-17th places. I don’t know how tiebreaking will work. Their result against each other was (I’m sure you already guessed this) 1-1, so that doesn’t help. Maybe they’ll have a playoff game. Either way, I’ll enjoy watching the finals and I’m happy that my bot performed so well after such a short development time. Watch out for the next version!

Next: Some of the bugs that came up in the round robin phase.

don’t lose that scout

Wow, it’s down to the wire on whether Steamhammer will make it into the final 16. Steamhammer has been scoring a little lower in the final third of the tournament, and as I write it is standing on the edge at rank 16. With 10 games left, I look at the opponents and expect 4 losses and 6 wins, probably not enough to hold rank 16.

But we don’t know until we know. In an unexpected loss to PeregrineBot (which it easily beat in their first game), Steamhammer suffered at least 2 different play bugs, including one caused by losing its initial scout before finding the enemy base. Gotta fix more bugs. Then it followed up with an unexpected win against Bereaver; the protoss had easily won the first game. Bereaver was careless with its early probe scout and lost it before zerglings spawned, and Steamhammer’s aggressive play caught it off guard. Without information on what zerg was doing, Bereaver did not make enough zealots to hold. Moral: That scout is important!

We’ll see what happens! Steamhammer plays sharply and is prone to upsets in both directions.

Steamhammer versus IceBot

Steamhammer defeated IceBot 2-0 in SSCAIT 2016, but the numbers are deceiving. In the first game, IceBot built its strongpoint defense with a bunker surrounded by turrets, Steamhammer became obsessed with the bunker but was barely able to attack it, and IceBot countered the mutalisks in good time with goliaths and valkyries. Steamhammer was falling behind, but took more bases. IceBot moved out with an unstoppable army and crushed the zerg natural and main; Steamhammer was still able to stop dropship harassment with its remaining army, but zerg was dead. Then IceBot crashed.

The only good news is that I taught Steamhammer 0.2 that dropships are critical targets and must be eliminated. IceBot’s drop attempts were shut down hard and only hurt terran. In every other way, IceBot played better.

The second game was exciting. IceBot again built its strongpoint defense and Steamhammer again became obsessed with the bunker. But for some reason IceBot did not raise the mutalisk defense flag, and instead kept pushing columns of marines out beyond turret range to die. Steamhammer took more bases, its mutalisk flock was growing, and it was upgrading air carapace. It even made some dents in the strongpoint, destroying the first bunker. IceBot also took two side bases, and Steamhammer did not scout them, much less attack. IceBot finally switched to goliaths and valkyries, but by then the mutalisks were so strong that they could fight on even terms. IceBot made its big tank push, but the push was defeated. Steamhammer had most of the map and IceBot could not expand any more, but terran tried to stay in the game with drops and vulture harassment and long distance mining. In the end IceBot mined out and Steamhammer was still going, the terran army wore away to nothing, and the strongpoint finally fell like the gate to a fortress. Good game.

Steamhammer showed a lot of weaknesses, but the key one was the obsession with that bunker. It turns out that there are multiple causes. One cause is that bunkers were given high priority as targets, so that mutalisks would attack an empty bunker surrounded by turrets and ignore the turrets and other enemies. I made a quick fix for that in the next version. Another cause has to do with the way squad orders are computed. It turns out that squad orders made based on early scouting tend to direct play for the rest of the game. I’m still thinking about that one; my first attempt to fix it is no good. A third cause is the way it calculates whether a bunker can be successfully attacked. SparCraft does not support bunkers, but bunkers can’t be ignored. Dave Churchill’s workaround was to pretend that a bunker is actually 5 marines with hitpoints pro-rated based on the bunker’s health! It’s an ingenious idea, but it’s also a poor approximation. The damage rate is wrong, the health is wrong, and the 5 imaginary marines can be shot down one by one. SparCraft will need some work.

At some point I’ll study SparCraft closely and improve it. It seems reasonably accurate, but it’s not all the way there. On the one hand, SparCraft doesn’t support every unit. On the other, SparCraft does seem to support medic healing and unit upgrades, but UAlbertaBot does not take advantage of the support. Well, one step at a time. It’s not a priority yet.