archive by month
Skip to content

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.

Korean visitors

In the last couple days there have been a lot of Koreans on the SSCAIT stream chat. The total number of viewers zoomed up. I guess SSCAIT suddenly got publicity in South Korea.

My impression is that since the AlphaGo shock, AI is hot in Korea. I get the idea that it’s at both the grassroots level, “hey, this is cool,” and at corporate and government decision levels, “we need a strategy so we don’t fall behind in the tech race.”

So I hope that we get some new Korean bots this year! Of course a strong player community is very different from a strong bot community, but still, doesn’t it seem that there should be some feedthrough? In any case, I think the interest is there, and that’s what counts.

Update: As LetaBot mentions in comments, some spectators were brought in on Friday by a post on the Factorio game site (scroll down).

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.