archive by month
Skip to content

Steamhammer scouting bugs

When I rewrote Steamhammer’s scouting, I tested it widely and thoroughly. I’m disappointed to find out that it still hides bugs, though the bugs only show up in a few games here and there. I’ve seen a couple games where the scouting overlord stops in an empty base, when it should continue to seek the enemy. Plus there is one other bug.

Watch the game Steamhammer-Bryan Weber on the 4 player map Roadrunner, which shows a hard-to-notice but potentially fatal scouting blunder. Bryan Weber played 5 pool while Steamhammer made a hatchery first, which could lead to a build order loss. Bryan Weber’s overlord scouted the correct base first, while Steamhammer’s went in the wrong direction. The situation is bad so far, but Steamhammer’s scouting drone has a chance to make up for it. Watch it leave the base at 2:10 in the game, quickly spot the enemy overlord, and immediately turn around and go home. It looks like the smart inference paid off! The top base was known empty, and Steamhammer calculated that only 1 of the remaining bases was a possible origin for the overlord. The enemy base has been located, so the scout drone doesn’t need to look for it but can get back to mining.

The scout overlord of course wants to see what is in the enemy base. Check its path: At the same moment that the drone turned around, the overlord changed direction from the actual enemy base toward the empty bottom base. Steamhammer drew the wrong conclusion from the enemy overlord’s position. Somehow the “can this overlord have gotten from A to B by this time?” calculation ruled out the actual base A that the overlord came from to reach point B. A minute later, Steamhammer’s zerglings also aimed for the empty base, leaving its own base defenseless.

While this nonsense was going on, Bryan Weber skipped out on a chance to win over breakfast, then a chance to win over lunch, then a chance to win over dinner. It wasn’t hungry at all and chose to wait around instead. Steamhammer won the game despite a build order disadvantage and a scouting bug because the opponent played worse.

Why are there so many bugs? The overlord position inference worked (or correctly drew no inference) in every test I threw at it.

SSCAIT check-in

All players have now reached at least 30 games, so the rating list and crosstable have data for all entrants. That makes today a good time for a check on prospects.

By the way, the 2016 crosstable is missing from its old URL. Did it move, or is it lost? [Update: Last year’s crosstable was and remains here. ]

The elo rating is a better estimate of the eventual ranking than the win rate, because it takes into account whether the bot has played stronger or weaker opponents. On the other hand, the win rate is up-to-date with all games included, while the elo is calculated from older cached data so it may exclude recent games (like CherryPi > McRave, which was just played). Anyway, here are the top 10 by elo.

botelowin%
McRave224592.31%
Marian Devecka
(Killerbot)
224090.57%
tscmoor222394.59%
TyrProtoss221685.71%
Steamhammer221489.13%
Martin Rooijackers
(LetaBot)
221084.09%
Iron220788.57%
Neo Edmund Zerg220682.46%
Tomas Vajda
(XIMP)
220477.78%
Bereaver218291.18%

The first point to strike me is that the rankings are extremely close. There is barely a difference between a rating 0f #9 2204 and #4 2223; 20 elo points is a 53% chance to win for the higher rated opponent. The difference from the top to the bottom of this list gives #1 McRave about 3:2 odds over #10 Bereaver, far from an overwhelming advantage. With little difference measurable between players, the ranking is not stable and the final results could look entirely different in detail.

Bereaver is the bot with the biggest difference between its rank by win rate and its rank by elo. It has played weaker opponents. That probably reduces the accuracy of its ranking.

Iron surprisingly lost 3 games early and fell far back. Since then it has lost only 1 more and climbed back upward.

Steamhammer has been pretty stable over time at rank #4 plus or minus 1 (currently at #5). I predicted that it would finish in place 4 to 8, and so far I haven't seen a reason to doubt my prediction.

The CherryPi-McRave game was sad to watch. CherryPi did its usual thing, with tons of zerglings plus a few mutalisks. McRave made many high templar and idly walked them into the middle of the map to die. Not once in the game did protoss cast a storm or merge an archon. Could this be related to the last-minute binary hot-fix? Against this unit mix, protoss could have gotten away with skipping storm research and merged archons right away. Other protoss mistakes in the game gave me a feeling that McRave is easy to beat if you can just get your basics up to a good enough level.

entertaining Steamhammer game

MadMix protoss lived up to its name and went to 4 bases before its first gateway against Steamhammer. You can’t beat Steamhammer that way, but you may make a very entertaining game!

Actually it would have been a short and boring game if Steamhammer opened with one of its mass zergling openings, as it often does. But Steamhammer went macro style, with 12 hatch 13 pool (squeezing out extra drones early) aiming for hydralisks. Also Steamhammer didn’t understand that the enemy had gone overboard and should be drowned for it (it’s an easy adaptation to code but not needed because Steamhammer wins those games anyway). Zerg thought, logically enough, “That’s a lot of bases, I’d better make a ton of drones to keep up!”

Steamhammer wants more drones

Steamhammer still made enough units to keep the pressure on and repeatedly kill probes. It didn’t take many; 4 bases before gateway is amazingly reckless. Despite concentrating on drone production, zerg was never in trouble.

protoss barely has an army

Finally Steamhammer reached its goal of 75 drones and army production turned on full. The fury of the swarm swept away the fragments of the protoss bases.

fury of the swarm

Against TyrProtoss, Steamhammer played the same hydralisk opening. Despite playing on its worst map and messing up its macro, Steamhammer had (as I expected) an almost adequate army and held a chance to stop the big timing attack. Instead (as I also expected) it decided to move its forces through the enemy army without fighting and lose everything for nothing—the weakness is related to paths on the map. Steamhammer still makes many fatal blunders in big army fights.

Against ZurZurZur, Steamhammer got in trouble but managed to slowly claw ahead with better decisions. This could be an instructive ZvZ to study, with mistakes all around and all through.

a paradox of motivation

It occurs to me that tournaments cause a paradox of motivation. Once the tournament is underway, nothing I do affects it. I want Steamhammer to defeat its strong opponents, giving them losses so Steamhammer can pull in front. If I have to lose some games, I would prefer to lose to the weaker opponents which pose no threat of placing higher.

In development, I don’t ignore the strong opponents by any means, but I have been concentrating on building a firm foundation, getting the basics down solid. Compare: Last year, Steamhammer scored many upsets against stronger players and many losses against the lower ranks. Today it is the other way around; Steamhammer can barely touch Iron or McRave (in last year’s edition it scored an upset over Iron), and it only now and then drops a game to the bottom half. Steamhammer has gone from upset-prone to consistent. I haven’t been trying to beat the top bots, I’ve been trying to play better. I put extra effort into analyzing Steamhammer’s losses against the weakest opponents in AIIDE, for example. It’s the opposite plan from trying to beat the current #1.

Well, I don’t plan to change course. I just thought the paradox of motivation was interesting. As soon as there is nothing I can do, my goals change.

mining gas at full efficiency

How many workers does it take to mine a gas geyser at full efficiency? All bots that I’ve seen, including Steamhammer, assume that the answer is 3. In reality, it depends on the relative positions of the geyser and the resource depot (the command center, nexus, or hatchery that you return resources to). In some base layouts, you only get full gas income with 4 workers. On a professional map, like all the SSCAIT maps, the main bases are designed to mine gas at full efficiency with 3 workers. But expansions may be different. On original Blizzard maps distributed with the game, anything goes.

Also, exceptional situations can come up. It’s fairly common for bots to manner their own gas (meaning partially block it so that workers go around the obstacle). In that case you need more workers to maintain income, unless you’re smart enough to remove the obstacle. If a spider mine is blocking a base position, Krasi0 may offset the command center instead of clearing the mine. There are other reasons to offset a resource depot; maybe you’re trying to hide a base that the enemy won’t scout. If the primary hatchery at a base is destroyed but zerg has another hatchery at the same base, mining can continue. Or you might just be long-distance mining the gas.

How is a bot to judge the number of workers? The details are complicated.

Precompute it. One way is to make a table of relative positions. Go through all the maps and find the relative positions of the gas geysers and the resource depot for each base. On pro maps, I think the total set of relative positions is not large. Or enumerate all the relative positions up to some short distance. For each possible relative position, measure the number of workers needed to fully mine the gas. At runtime, the bot can look up the number of workers to assign in the table. Maybe you can find a rule, or a rule and a small set of exceptions, to make it more compact. It should be simple and fast at runtime, but it’s rigid and it doesn’t account for exceptional situations.

Figure it out on the fly. Assign 3 workers at first. Once they’ve settled into the task, check the geyser to see whether it is idle. I haven’t looked into the details, but the check is something like: There is no worker inside and it’s not in a latency period with a worker entering or leaving. If the geyser has idle time, or has idle time above some limit, assign another worker (at least if you need the gas income). This doesn’t have the advantage of instantly doing the right thing in known cases, but it does adapt to exceptional situations.

Human players do both, of course: They know what common positions need extra workers, and they notice unusual situations that also call for more workers. For Steamhammer, I think I will eventually add the on-the-fly method. It’s not high on my list, though.

I don’t know of any bots that are smart about the number of workers needed to mine gas, but maybe there are some. AILien, for example, will use fewer workers to mine if it is short of workers, but I’ve never known it to add above 3. Can anybody enlighten me?

SSCAIT 2017 early results

How is the tournament going so far? Many games remain to be played, and bots have played different numbers, so all conclusions are tentative. But we can see some trends.

The top leaders at the moment by win rate are Bereaver 15-0, McRave 21-1, Tscmoo Random 17-1, Steamhammer 20-2, and KillAll at 25-3. Bereaver is a genuine candidate for a high finish, but most likely not #1. It has played relatively few games. McRave’s one loss is to Wuli. I think McRave is now the top candidate for #1 finisher. KillAll is the biggest surprise to me.

ICEbot at 13-2 is above expectations, but has also played few games. Iron has unexpectedly lost 3 games already and stands at 16-3. I won’t be surprised if its standing rises after more games. Killerbot by Marian Devecka is at 18-3 and can be expected to finish high. Microwave at 11-3 has a higher rate of losses than I expected. I may have overestimated it, as its author MicroDK said, but it hasn’t played many games yet. Microwave does have a win over Iron thanks to wall-busting skills.

CherryPi at 17-5 may be the bot in the tournament with the most smarts. Sometimes its play looks crisp and precise, with accurate reactions. But CherryPi is also immature, as you can guess from its slightly higher rate of losses. With less experience on SSCAIT, it is not ready for everything. It collapsed in the face of the cannon contain of Juno by Yuanheng Zhu, which the strongest bots all defeat easily. (Juno, I learned, builds a cannon contain not only at its enemy’s natural, but at every enemy expansion it finds. I hadn’t seen that before, though I’ve watched many Juno games from AIIDE.) Other CherryPi losses are to AIlien and to Steamhammer in strategically similar ZvZ games: CherryPi undertook a strategy of a rush-safe opening followed by attempted zergling domination (similar in idea to the ZvZ plan of Killerbot by Marian Devecka but with a less thoroughgoing execution), while its opponents chose less-safe hatchery first openings that in fact let them win the zergling war. Trying to win without risk is risky.

CherryPi showed up with a new version not long before the tournament. It reportedly did not show its strongest builds at first: If true, I take that to be a sign of lacking confidence. If you believe that your team, with its funding and top experts, has produced a better bot than all others, then you should also believe that others will be unable to catch up or to exploit its weaknesses, certainly not in a short time. I get the impression that the CherryPi team understands that their bot is not yet solid and mature.

Hannes Bredberg at 14-5 is impressing me as much improved. It used to scatter its marines to scout then gather them to attack, which was cool but not effective. Now it keeps its marines in formation and punches much harder.

Steamhammer is scoring at the level I predicted; it is now at #4 when I gave it places 4 through 8. The win over XIMP reassures me that I probably fixed the weakness that caused the recent test version to lose to XIMP. One point that worries me is that its losses are to MegaBot2017 which is much lower ranked, and to Neo Edmund Zerg which it should beat nearly 100% of the time. Except for CherryPi and XIMP, Steamhammer has not yet played most of its strongest opposition.

As always, the results will tell us. Now I have to hurry up and post this before the results change on me!

new Steamhammer versus old Iron

I ran a 15 game match of this year’s tournament Steamhammer versus last year’s tournament Iron. This is a true year-over-year comparison. By comparing the 2017 SSCAIT Steamhammer versus the 2016 SSCAIT Iron, we can get a measure of how much Steamhammer has improved.

Over the course of 2017, Iron has consistently stayed well ahead of Steamhammer, fixing weaknesses before Steamhammer was able attack them properly. I think Iron has even pulled ahead a little, which is impressive because Iron is stronger and therefore harder to improve. Last year’s Iron versus last year’s Steamhammer goes to Iron with a few losses, this year’s Iron versus this year’s Steamhammer goes to Iron with maybe a couple losses, maybe none.

It turns out that Steamhammer has more than caught up with last year’s Iron. The score was 10-5, new Steamhammer over old Iron. Steamhammer won both with mutalisks (which Iron at the time thought it was ready for) and with lurkers (which old Iron was not prepared for). 2016 Iron was already tough, so it’s a good result. The result table here is from Steamhammer’s point of view.

mapopeningw/lnotes
BenzeneOverhatchLateGas0A mass zergling opening with slow tech. It can’t touch Iron’s vulture build.
Destination4PoolSoft0Iron has zergling rushes down cold.
Heartbreak Ridge9PoolSpeed1Steamhammer struggled with the map, as it often does, but eventually won with lurkers.
Moon GlaiveZvT_2HatchMuta1Smash.
Tau CrossOverhatchLateGas0Bad luck for this inappropriate opening to come up a second time. Steamhammer plays it in 1% of games.
AndromedaZvT_3HatchMutaExpo1A bit of a struggle, but the mutalisks prevailed.
Circuit Breaker9PoolSpeed1Iron defended too cautiously, pulling excess SCVs, letting Steamhammer draw ahead in macro. Zerg won with lurkers.
Electric CircuitZvT_3HatchMutaExpo1Smash.
Empire of the SunOverpoolSpeed0Steamhammer got lurker tech but decided to make no lurkers. It went hydra and lost after the tank numbers built up.
Fighting SpiritZvT_3HatchMutaExpo1Smash.
Icarus2HatchLurker1Iron was not ready. Spider mines and wraiths eventually cleared the lurkers, but the command center was already lost. Mutalisks finished the game.
JadeZvT_3HatchMutaExpo1The most hard-fought game of the match. Iron held on with good turret repair and its vulture containment, but Steamhammer slid drones past the contain to take the map and eventually win with hive tech.
La ManchaZvT_2HatchMuta1Another hard fight going to hive tech.
Python3HatchLurker1Smash.
RoadrunnerZvT_13Pool0One of Steamhammer’s classic openings, but objectively weaker. The initial pressure looked good but was never enough to tip Iron down the slope.

The games were varied, especially considering that Iron plays a single strategy, and both sides got to show their strengths. Some were one-sided smashes for one player or the other.

Steamhammer was able to prevent too much damage from Iron’s standard 3 vulture runby with zerglings. Iron’s vulture micro at the time was not slick enough to keep the vultures safe from speedlings in the zerg base. Or to say it differently, Steamhammer’s micro has improved enough to nab the vultures when they get stuck on a building or take a wrong turn.

In a number of games, Steamhammer won by getting ahead of Iron in workers. When mutalisks fly in, Iron has turrets ready and works hard to keep them repaired. Steamhammer likes to pick off the repairing SCVs. It’s costly in mutalisks and reduces the immediate pressure, but zerg gets ahead in macro and can win later in the game.

Iron’s forward turrets protecting its vulture contain sometimes confused mutalisks and distracted them from what they should be doing, but I don’t think the effect was decisive in any game. Loss of drones that tried to exit through the vulture contain was a problem, though.

It was striking that old Iron did not scout the map in the middle game. If Steamhammer squeezed a drone past the vulture containment and the game continued long enough, zerg could set up additional bases that remained safe throughout. It happened in both of the hive tech games.

What do the last 2 days’ results mean? In the SSCAIT 2016 round robin phase, Steamhammer 0.2 finished tied for places 16-17, and the latest Steamhammer is stronger than its much-improved successor Steamhammer 1.0. Iron finished 5th with 89% win rate, and the latest Steamhammer is stronger. Steamhammer improved tremendously in 2017, so much that it would have likely have finished in the top 4 last year if we sent it backward in time. Where did I leave that time machine?

We’ll see how it does this year. The tide has risen all around. Still, 2018 had better watch out!

new Steamhammer versus old Steamhammer

To commemorate a year’s progress, I ran a 15 game match of the latest tournament version Steamhammer 1.4a3 versus Steamhammer 1.0, which was released on 28 January 2017. A true year-over-year comparison would have been this year’s tournament Steamhammer versus last year’s tournament version, Steamhammer 0.2, but that would have been a boring blowout. Steamhammer 1.0 is good enough to put up a fight.

The score was 11-4 in favor of the latest Steamhammer. The results below are from the point of view of the new version.

mapw/lreason for loss
Benzene0abdicating the fight for air superiority
Destination1
Heartbreak Ridge1
Moon Glaive1
Tau Cross1
Andromeda0gross tactical blunders
Circuit Breaker0build order
Electric Circuit1
Empire of the Sun1
Fighting Spirit1
Icarus1
Jade1
La Mancha0stupid drone chasing
Python1
Roadrunner1

It’s interesting that there is only one build order loss. In a couple other games where new Steamhammer randomly chose an inferior build order, it managed to hold on and turn the game around with stronger play. New Steamhammer has a wider range of better openings and was more likely to get a build order win. Also interesting is that every loss was for a different reason. It means there is no One Big Flaw to fix. I have handled the worst of them; the rest is a rabble of many lesser weaknesses. It is a sign of growing maturity.

Tomorrow: A different year-over-year match.

SSCAIT 2017 tournament expectations

How will the tournament go? I can’t predict the final results because they come out of an elimination phase, which is unpredictable by nature. It depends on pairings and luck. But I have some insight into the round robin phase. There are 78 participants, much more than the 45 last year, so each will play each other only once, giving the announced 6006 = 78 * 77 games. I haven’t seen it explained, but I suppose that the top 16 will go to the elimination phase, like last year.

How bots do in regular ladder play can be very different from how they will do in the tournament. The voters have a big influence. Steamhammer has been underrated lately on the ladder and will finish high in the round robin.

With Krasi0 choosing to stand out of the picture, the top favorites, of course, are Iron and McRave. Microwave has become steady and reliable and should also finish near the top; it even has a chance to finish #1, because it is not as big a target as Iron and McRave. And there are old standbys like Bereaver and like Killerbot by Marian Devecka.

Tscmoo random is being allowed to play, which I did not expect. As a random bot, it won’t be allowed into the elimination phase, but it will compete in the round robin. It was last updated in October and will probably finish out of the top ranks. But it would have had a good chance to make it into the elimination bracket if that were allowed by the rules.

CherryPi is a hard case to figure out. This version of CherryPi follows what is at heart a simple game plan: It wants to win with masses of zerglings (sometimes it falls back on winning with masses of hydralisks). It seems to have some ability to vary its plan by massing early, or saving up and massing more later. A casual watch of its games gives me the impression that it may be learning how to beat its opponents by varying its timing, but without a close study I’m not sure; maybe it’s something else. In any case, CherryPi’s initial results are mixed, with losses to weaker bots and wins against stronger ones. And in a single round robin, CherryPi won’t have any additional games to learn about opponents; it will have to rely on what it already knows.

Steamhammer I expect to finish out of the top 3 but likely between ranks 4 and 8. It should beat lower-ranked bots consistently and its only sure losses are against Iron and McRave, though of course it will lose some other games too. Microwave will probably win, but not definitely. I give Steamhammer a 75% chance against former nemesis CasiaBot because I hand-coded in a counter to CasiaBot’s hand-coded Steamhammer-countering opening. Steamhammer’s other nemesis TyrProtoss is not participating. The last couple games against Bereaver give the impression that Steamhammer can now go toe-to-toe against the protoss bot in the middle game, which it could not do before (Steamhammer won early or not at all). So the game against Bereaver is likely also a win.

Steamhammer 1.4a3 with last-minute bug fixes

New tournament version with last-minute fixes! I set to work on version 1.4 for release around the end of the tournament, and thought, “Well, what could be a better start than a bug fix?” I ended up fixing 2 bugs that could help in the tournament and have low risk of causing other problems. I changed gears, and now 1.4a3 is uploaded.

• Why does Steamhammer sometimes make a hydralisk den versus zerg, when it is explicitly coded to never make hydralisks in ZvZ? Once I realized that it only happens when the opponent went random and rolled zerg, I was able to trace the bug. It turned out that the actions are out of order: Steamhammer first makes its strategy decisions, then checks to see if the enemy race is still Unknown. So in the strategy boss’s first production round after it finds out the enemy’s race (which is usually the first round out of book), it thinks it still doesn’t know. “Hmm, better be ready for anything.” Facepalm!

• In a test game after fixing the above bug, Steamhammer skipped lair tech (in ZvZ!) and rushed to hive for ultralisks. I’ve seen that misbehavior before. It hurts badly when it happens, and the fix turned out to be trivial. A condition was miswritten with && instead of ||.

There must be dozens of play bugs that are hard to trace or even to notice because their effects are rare or subtle....

Steamhammer 1.4a2, tournament version

I’ve uploaded the SSCAIT 2017 tournament version of Steamhammer, which is version 1.4a2. The reason for the strange version number: I promised that release version 1.4 would have a full-up opponent model, and even if I break every other promise, I can keep that one!

Randomhammer is disabled for the tournament (it took me a minute to figure out how to create an empty zip file, since zip refuses to do it directly...). For Steamhammer, I found a number of low-cost low-risk improvements that are enough to make a difference. The new version already has a win against McRave, for the first time in a long time, so I can’t have messed up too much.

• Fixed a crashing bug in assigning units to the Recon squad after losses in the main army require the Recon squad to be downsized. The bug only affected terran, and was related to medics.

• Ranged units target arbiters with a higher priority. By the way, in the strange world according to Steamhammer, scourge are ranged units.

• Fixed a bug in recognizing worker rushes. On one map, enemy workers busy mining could be recognized as “rushing”. Still a strange world.

• A few changes to zerg to be more careful in collecting gas. Turning gas off because there’s a gas excess compared to minerals now happens using the current minerals, not current minerals minus minerals reserved for buildings, so it is more conservative. If there are idle drones, always turn gas on (might as well put them to work). If short of gas, Steamhammer adds extractors faster—it always has, but now it is a little more eager.

• Account for gas usage in planned spending. Together with the gas changes above, this improves the midgame unit mix and army size. Watchers may not notice, but to me the difference is visible.

• Be more thorough in using all larvas. Steamhammer has long had a fallback rule to make zerglings with any spare larvas. I loosened the conditions, and had it also make drones if the army is “big enough” according to an arbitrary criterion. The rule usually fires later in the game, when there are plenty of hatcheries and Steamhammer wants to make more gas units than it has gas for. The result is a bigger army, and again, I can see the difference.

• Tweaks to make guardians less often. I think Steamhammer still makes guardians too often, but it should be closer to right.

Hao Pan

Two posts today. They’re short.

Hao Pan is a new terran bot. (“Hao Pan” is apparently a person’s name; the bot is named Halo.) I watched some games to see what it was like. Watching the first game, I thought “Wow, it can build a wall, knows how to defend it, and knows how to open and close it, and that micro looks nice.” It seemed to have excellent skills for a new bot. Watching more games, I thought “Wait, this looks a lot like Iron, except it’s losing instead of winning.” Sure enough, the description says it is derived from Iron. And the AIIDE 2017 version of Iron comes with a license that says it’s OK.

It looks as though the macro is messed up, which could explain how a bot starting from such a strong base is doing poorly so far. My feeling about Iron is that its strong play depends on fine tuning of details relative to each other. If that’s true, then Iron may be a difficult point to start from; it may be easier to make it play worse than play better. But still, the allure of starting from Iron!

Randomhammer crash!

Randomhammer crashed in a game! It’s the first crash since May, except for the untraceable crash. Now I know exactly what to do next.

The crash was in an interesting TvP game against cannon-bot Jakub Trancik. It’s a shame not to see how it continued. Randomhammer went with marines and Jakub Trancik decided to build its proxy cannons below the ramp, so Randomhammer (seeing the pylon with its scout) didn’t pull SCVs but waited for combat units. The first marines were not quite able to stop the cannons, and retreated out of sight up the ramp. Terran and protoss have very few strategic reactions (unlike zerg), but there is one when the bot is making infantry and meets dragoons, tanks, lurkers, or static defense: It adds tanks. It was the correct move; the unit control is clumsy and loses stuff unnecessarily, but the tanks were sieging down cannons and I was starting to think that the play was good enough.

Then CRASH! The crash is in CombatCommander::updateReconSquad() which decides what units are in the Recon squad. It is complicated for terran because there may be medics in the squad, depending on size and composition, so it’s no big surprise that there’s a bug.

To work!

Steamhammer tournament plans

Today I went for a walk in the snowy woods, setting the first footprints on some of the paths. It’s kind of how I feel about working on Steamhammer: At some points I may leave the first prints, but the path was already there. And I feel as though I still have a lot of paths to walk before I can reach wilderness.

For the tournament, I have changed my plans. Trying to hit a deadline makes my code worse and messes with my motivation. Some people thrive on deadlines; I go wrong. So instead of turning on the next opponent model feature as I had been thinking, I’ll do whatever smaller fixes and features seem likely to help. I’ll have to comment out some stuff I’ve just done, but whatever. The tournament version will be 1.4a2 (anyone who’s not confused by the version numbers needs to get back to their real work), and hopefully not long after I’ll put out release version 1.4 with opening selection controlled by the opponent model. I expect that later 1.4.x releases will add more opponent model features, because the opponent model can do many things.

The switch is partly inspired by watching Steamhammer’s 2 recent losses to XIMP by Tomas Vajda. The loss on Heartbreak Ridge I can swallow, because Steamhammer has always played particularly poorly on that map. The loss on Icarus seems to show that Steamhammer is playing worse against the carriers (though it was a long, hard-fought game and many carriers blew up). Apparently delaying the hive, though often good, in this case left Steamhammer unable to batter down bases with ultralisks, because it used all its gas making scourge. Looking closely, I see that it was short of gas in part because it turned off gas for a full minute before seeing the carriers, seemingly due to a bug. Outside of emergencies, zerg should turn off gas only if gas piles up to at least 3 times the mineral count, and here it turned off gas with 1700 minerals and 300 gas. That should be possible only if the building manager reserved a huge pile of minerals to make buildings, and didn’t reserve any gas... it seems barely possible. This is something that can be fixed by a deadline.

Steamhammer 1.4a1 - the rest of the changes

Yesterday I wrote up Steamhammer’s scouting improvements. Today is the rest of the change list.

stuff affecting squads and combat

• Added a parameter setting to each squad: For combat simulation, include either all known enemy units in the area (including remembered units that are out of sight), or include only visible enemy units plus known static defense. For most squads, it is useful to include all known enemy units, so that you don’t attack a superior force when you momentarily can’t see all of it. It’s especially useful for a squad of zerglings, which have a short sight range. The Recon squad is set to fear visible units only, because its purpose is to see what is there.

• The combat simulation radius is also a parameter setting for each squad. The primary combat squads have a large radius so they can try to understand the ultimate outcome of a battle (though it’s questionable whether this is a good idea). The Recon squad has a small radius, so that it does not fear distant units that it is out of range of. That lets it come closer and see more.

• If we can see the last known location of a remembered unit (its lastPosition) and the unit is not there, we flag it as goneFromLastPosition. We keep the lastPosition and know when it was set, so we can narrow down where the unit is now (which is not done yet, but someday). This is a feature from the when the enemy unit is out of sight post. Units which are goneFromLastPosition are skipped in combat simulation, which makes Steamhammer more aggressive. Of course the unit might still be nearby, so Steamhammer is taking a risk, but it seems better than fearing ghosts.

• Squads no longer single-mindedly attack the enemy main. The combat commander prefers to issue orders to attack the enemy base with the least static defense. It’s still not very smart, but the tactical play is much more interesting and varied. There are other tweaks.

• A bug in tactics calculation prevented the combat commander from issuing orders to a squad to attack enemy units, which it will do if there are no enemy bases the squad can attack. Fixed.

• Valkyries, corsairs, and devourers now play much better. Since they are unable to attack bases, the bug fix above to send them to attack units was critical. A new unit micro controller, MicroAirToAir, helps the flying squad make better use of these units. Steamhammer no longer sucks with devourers and protoss corsair openings are stronger.

• Ranged units like to hit air targets that have acid spores on them. Get full value from those devourers.

• Queens, defilers, and dark archons are recognized as combat units and assigned to squads. Steamhammer can’t use any of these spellcasters (yet), but there’s no reason to ignore them.

• Due to mis-nested conditions, if you asked a squad whether it had any air or ground units, flying detectors were counted as ground units. Fixed.

UnitUtil::GetWeapon() makes the simplifying assumption that a bunker has marines in it. It used to ignore bunkers. Someday Steamhammer will attempt to keep track of whether a bunker is loaded, but not yet.

InformationManager::getNearbyForce() includes enemy medics. They were mistakenly excluded by a weapons range check. It was a serious bug.

InformationManager::getNearbyForce() checks enemy attack ranges more accurately. It makes little difference in practice.

InformationManager::getNearbyForce() no longer returns detectors. It is used to feed the combat simulator, and FAP does not support detectors, so it was no help.

• In FAP, added N00byEdge’s September patches: A scarab is a suicide unit, medics heal less.

other

• Recognize some enemy opening plans. This is part of the opponent model. For now, only zerg takes advantage. The plans Steamhammer tries to recognize are named Proxy, WorkerRush, FastRush, HeavyRush, and SafeExpand (which means natural with cannons or bunker). It doesn’t always recognize them successfully, but when it does I find that it is rarely wrong.

• Added the macro act command "go nonadaptive" for zerg, affecting drone production. Zerg normally adjusts its drone production depending on the situation, even if it is playing a book opening. For example, if the book says “make zerglings” but the opponent has cannons, Steamhammer may decide to make a drone instead (it has even more freedom out of book, of course). The "go nonadaptive" command means to turn off this adjustment process for the entire game and trust that the opening book has the situation covered. The new command is used in openings which counter forge fast expand. This version doesn’t play any of those openings, though!

• Steamhammer’s event-driven base tracking system sometimes gets out of sync with reality. Past versions made corrections in some cases. Now all incorrect stored base information is corrected as soon as possible.

MapInfo::getNextExpansion() skips bases without enough resources to be worth it. It should fix occasional cases where Steamhammer re-expanded to a base that was mined out.

MacroAct::mineralPrice() and gasPrice() are now correct for upgrades beyond level 1. See upgrade prices in Steamhammer.

• The configuration file has new flags Config::IO::ReadOpponentModel and WriteOpponentModel. In this version the flags don’t do anything (the file I/O is turned off in code), but in the release version 1.4 they will work. Separate control of reading and writing the files is handy for debugging.

terran and protoss

• Terran and protoss turn off gas collection when there is too much gas, as zerg has always done. “Too much gas” is defined conservatively as 1. over 400 gas, and 2. over 4 times as much gas as minerals, and 3. more gas than is needed to fill all the orders in the production queue. I think the biggest benefit is that the bot can survive after many workers have been killed, when collecting gas causes mineral mining to slow or stop. Gas production starts again when the bot has a use for the gas.

• Adjusted the terran ratio of marines:medics to 5:1. It used to be 6:1, not enough medics. Some people prefer 4:1.

• Added a terran siege-expand opening. Steamhammer doesn’t adapt well enough to play the opening safely in many cases, but I think it should be adequate for TvT.

zerg

• In case of a recognized Proxy, WorkerRush, or FastRush enemy opening plan, possibly break out of the opening and react appropriately. If the opening is already doing something that looks sensible, let it. I did not follow IMP’s advice to not distinguish between plans with the same reaction, because I expect that the reaction will not always be the same (especially for forks).

• In case of a recognized HeavyRush, maybe build a sunken. It is a wimpy reaction, but may help sometimes. This Steamhammer version does not react to SafeExpand, but I hope that the tournament version will.

• Recognize corsairs, scouts, and carriers as countering guardians. What a blunder! That is why Steamhammer kept making guardians against XIMP.

• Recognize goliaths as countering zerglings. Properly, only enough goliaths counter zerglings; their long range makes them deadly in groups. Steamhammer is too primitive to understand that, so far.

• Also what-counters-what tweaks in ZvZ.

• In ZvT, prefer to get lurkers after mutalisks in the standard way. Steamhammer classically rushed to hive, crazy zerg style. I’m not sure whether this adjustment works as intended.

• Always get overlord speed before hive, except versus zerg. This is a concession to the BWAPI 4.1.2 bug that you can’t get overlord speed after hive.

• Prefer to make unit types that already have their upgrades. It’s not a strong preference, though.

• A new “do I have enough units to get away with this?” check to decide when it is safe to tech. For example, if the enemy has air and we don’t, delay less important spending.

• Added a bunch of openings to counter protoss forge expand. This version doesn’t play them, though. I hope the tournament version will.

• Added an overgas 9 pool opening for ZvZ, mostly because it’s fun but also because it’s a good opening.

• Added an OverpoolHydra opening similar to ZZZKBot’s 1 hatch hydra build that it used to defeat Iron in AIIDE 2017. It is a weak build, and I don’t know if it has any other use than to defeat that version of Iron.

• Lurkers can change targets away from a building. See fixing a lurker micro bug.

• Lurkers are little more eager to target a protoss observatory or robotics facility.

• At some point a bug crept in that made it impossible to research lurker aspect if you had a hive. Fixed.

• In ZvZ, get queen’s nest and hive only once you have at least 12 mutalisks. Steamhammer was losing games by teching at an insane rate.

• Other minor strategy changes to mildly encourage making more combat units.

• Never have more than 9 devourers at a time. See too many devourers.

• A new feature is supposed to prevent zerg from stopping gas collection if that will cause drones to go idle. If you have excess drones, you might as well collect gas whether you need it or not. Unfortunately, the feature doesn’t seem to be working, though I can’t find a bug.

code changes with no effect on play

• Renamed the MainAttack squad to Ground. MainAttack used to be a good name, because all the squad wanted to do was attack the enemy main, but now it has wider ambitions. The 3 combat squads are now named Ground, Flying, and Recon.

• The capitalization of MapGrid::getUnits() was nonstandard. Fixed.

• Removed the unused MapTools::_units instance variable.

• Renamed RegroupRadius in the config file, also known as Config::Micro::CombatRegroupRadius in the code, to CombatSimRadius, since that is what it is. A unit that can fire into this radius around the combat simulation center point is included in the combat simulation. Also it doesn’t hurt for the names to be consistent.

• Rewrote UnitData::updateUnit() to be slightly simpler.

• There was still a redundant mention of SparCraft in the VS settings. As far as I can see it caused no harm, but it’s gone now.

• Map-related data structures use short ints to push less other stuff out of cache. I cleaned up the typing of short ints so that the compiler understands that the type conversions are safe, though they were already.

• In FAP, I initialize the closestDist local variables in 3 routines, solely to avoid compiler warnings when warnings are set to a high level. The code was correct, but the compiler is not smart enough to tell.

• All the debug configuration “Draw...” options can be set manually during the game using /set. It can save time in debugging. I had added some options without adding corresponding commands.

• I renamed all the Micro::SmartX routines to Micro:X to reduce noise in the code text. It doesn’t need to brag. For example, Micro::SmartMove is now Micro::Move.

Steamhammer’s new scouting skills

I decided to write up Steamhammer’s changes in parts. Scouting today, more stuff tomorrow. I wrote briefly about scouting improvements in September; here are the details. The scouting changes affect all races, though of course only zerg has an overlord to help. The overall effect of the changes is that Steamhammer collects more information sooner and makes better decisions, so it was worth the effort.

Steamhammer has suffered its usual ratings crash in the new version. I think the voters have the journalistic instinct to comfort the afflicted and afflict the comfortable, and top bots and new versions of well-known opponents count as comfortable. They say to themselves, “Let’s vote in a good challenge,” and in Steamhammer’s case succeed.

Even so, I’m satisfied with early results. I see plenty of familiar misbehaviors, and no surprise bugs. And play improvements are showing. For example, Microwave has opening learning, and learned that 5 pool usually beats Steamhammer’s default ZvZ opening mix. In Steamhammer-Microwave, Steamhammer played a gas-first opening that formerly would have lost instantly to the rush, but this time saw it coming and built a sunken in time to stay alive. It became a good game instead of a smash.

early game scouting

Classic Steamhammer scouting, from December 2016: Pick a base on the map, and send both the first overlord and the scouting drone to that base. It was a hack. The overlord waits there for the rest of its life whether the enemy is there or not, and the scouting drone keeps looking if necessary.

Good scouting: Send the overlord and drone to different bases. Redirect one or both depending on what is seen. Send later overlords to good locations to collect further information.

Steamhammer’s current scouting is in between. It uses only the first overlord and the scouting drone, and against terran doesn’t send the overlord because it still doesn’t understand how to keep it safe from marines. The overlord and drone go to different bases, so that the enemy is often found sooner. When the enemy base is located, the overlord changes its path if necessary to go there, so there is often a better view of the enemy’s play for a long time. If the overlord finds the base first, the drone either goes home or stops by to visit the base, depending on its orders.

I added only one clever feature, inference of the enemy zerg’s location from seeing its overlord. When Steamhammer sees an enemy overlord early in the game and the enemy base has not been located, it considers “what bases have I not yet scouted?” It calculates which of those bases the overlord might have come from, based on its position and top speed. If that narrows it down to one base, then “Bingo! Found you!” This doesn’t quite extract all the available information; it’s possible that seeing the overlord could eliminate one base and leave two possibilities, and Steamhammer doesn’t realize that. But that’s a rare case, and in practice the overlord sighting speeds up scouting fairly often. The feature was definitely worth adding, and it helps terran and protoss too.

I want a more general scout manager instead of the current one that is able to scout with one worker and one overlord. It should be: Dump whatever units you feel are free into the scout manager, and it will figure out how to employ them. I decided it was too much for now, but I’ll probably do it later.

middle game scouting

Most bots, I have noticed, scout only to see what’s up. Even Zia, which scouts in the middle game with a zergling, only sends the zergling to see stuff and doesn’t attack with it.

Purely out of orneriness, I decided to do middle game scouting differently. Steamhammer’s middle game scouting is reconnaissance in force.

When there are “enough” ground combat units for the main ground squad, Steamhammer redirects a small number of them into a squad named Recon. The choice of units depends on race, of course, but only certain ground unit types are considered suitable for Recon. The terran Recon squad can include medics, and there are actually remaining bugs in that. If the main squad loses too many units, Recon may be disbanded to join it.

Recon is another combat squad, and it gets orders to attack bases where the enemy is not known to be. Usually it discovers that the enemy is still not there, and it gets new attack orders. But if it sees enemy presence, then its orders remain the same; the combat simulator decides whether to attack or hold ground. Stray enemy units and naked expansions are at risk. If Recon holds ground too long, then its orders time out and it is given a new location to attack.

I added a couple parameters to squad behavior so that Recon can do its job better, while the main combat squad does its job as always. I’ll write that up tomorrow.

Recon usually moves around pretty fast and travels over most of the map, though it does get stuck sometimes holding ground. The effect of the Recon squad is that Steamhammer finds enemy expansions quickly and has much more vision of enemy army movement. It occasionally prevents expansions or catches enemy scouts or tears down misplaced buildings in the middle of the map, but my feeling is that that is less important. I’m curious to see how Recon copes with terrans that sow the map with spider mines. Recon does get dedicated detection when it is available, but the detector often lags behind. I may need to make changes if it struggles against spider mines.

other scouting-related stuff

• A new feature controls the damage of scouting misses, when the scout worker is lost before finding the enemy base. In past versions, that caused disastrously bad play when the early combat units came out: They scoured the map indiscriminately looking for enemy presence in unlikely corners, and were often out of position when the enemy came knocking. Now Steamhammer recognizes that is is likely to find the enemy in a starting base location, and looks there first. The enemy is found much sooner and the combat squad is out of position for a short time or not at all. It is more aggressive than Killerbot’s approach of leaving the combat units at home until the enemy is found.

• The gas steal works, though this version doesn’t use it. You can configure "go steal gas" and Steamhammer will find the enemy base and try to steal the geyser. Or "go scout" and "go steal gas", and the scout will steal gas and, if it still exists, continue to circle the enemy base. And some other combinations. Getting the gas steal to work for all races and cases was time consuming; the number of bugs was incredible.

• The previous Steamhammer version has a misbehavior when the scouting worker is on its way home: It stops to attack anything stationary that it runs across. It is the standard worker self-defense behavior popping up at an inappropriate time. Fixed.

• When doing worker harass on a map with other than 1 geyser in each main, there was a potential crash. It never happened, but I fixed it.