archive by month
Skip to content

Randomhammer early returns

Steamhammer 1.2 should play zerg a smidgeon stronger than 1.1.1, because of a few fixes. But I doubt the difference is noticeable. I didn’t fix anything important to strength.

After 2 days, Randomhammer’s rating has settled near 2050, a little above the average rating and 200 points below Steamhammer. The bot’s protoss and terran came out far weaker than its zerg. I’ve been looking at the games and thinking about why.

The building placement slowdown bug turns out to be critical for protoss. Randomhammer protoss has reached winning games against tough opponents like LetaBot and Killerbot by Marian Devecka, but tough opponents do not roll over and die, they fight stubbornly. Randomhammer fills up its main with widely-spaced buildings, the building placer slows to a crawl, and the bot busts the time limit and kicks out a loss.

Indecisive army movement is also critical for protoss. It’s harmful for zerg, but deadly for protoss, because the bulky protoss army spreads across the map, and one dragoon or another will happen to see something unimportant that distracts the attention of the whole army. The correct fix is to replace the targeting priority system, a job that needs a lot of detail work. I may try a cheaper fix instead.

Incompetence with terran seems harder to improve. Terran needs a lot of skills to play well, including adaptation skills. I did find the reason behind some strange play when going siege tanks, and fixed it.

Randomhammer beats Steamhammer on average, because Steamhammer’s openings are weaker versus random. When you don’t know what you’ll face, you have to play a general-purpose build. For example, when Randomhammer rolls zerg, it usually plays an optimized anti-zerg opening while Steamhammer is stuck with a tamer 9 pool or overpool. Steamhammer does not have a pro’s ability to play a general-purpose opening as sharply as a specialized one.

As a result, having Randomhammer in the pool of opponents decreases Steamhammer’s equilibrium elo, especially if people think the matchup is interesting and vote for it. Well, difficult opponents make good inspiration—all the better if I can supply the difficult opponent myself.

changes to plans for the next versions

Critical problems are a good excuse to rework my plans. Of course the real reason is that no plan survives contact with the calendar—it has been two days already, it’s time to change it up. The schedule must be rendered meaningless!

I decided to split versions again, so I can make the most important fixes up front and see the results sooner. The fixes now planned for 1.2.1 should delight protoss and leave terran and zerg smiling too. I don’t want to go too deeply into protoss and terran skills, though, because they’ll distract me from my main goals.

  1. 1.2.1 - fix critical bugs, add critical skills
  2. 1.2.2 - further skills
  3. 1.2.3 - other lingering bugs

Steamhammer 1.1.1 retrospective

Now that Steamhammer 1.2 is out, I want to think back over the lessons of version 1.1.1.

Steamhammer 1.1.1 was shockingly successful. The high end of my expectation was that it might reach an elo a little over 2200, and that seemed unlikely. In fact it had a final elo of 2285 and maintained a position as the #3 bot on SSCAIT, behind only Iron and Krasi0. Even when it hit a losing streak (which I helped along by voting for lower-rated opponents that were likely to beat it), it quickly bounced back. What did I accidentally do right?

Compare Steamhammer to AILien. They’re about the same age and both are descended from UAlbertaBot. We’ve helped each other out with bug fixes and ideas. AILien is ahead of Steamhammer in most zerg skills: It has better scouting, better tactical decisions, better building placement, better worker defense, better overlord safety, better cooperation of mobile units with sunkens—I have a lot to do to catch up with it, if I ever can. And yet Steamhammer is stronger by 100 elo, a large difference. What’s going on?

I didn’t expect it and I can’t explain it. Some of the bugs introduced in this version seem devastating, but they turned out to hurt results only against a small number of opponents. All I can do is explain my choices and conclude that somehow they were good choices.

1. Play efficient openings. Steamhammer’s builds are not all perfectly tight, but they’re pretty good and they put pressure on the enemy. I haven’t seen such good builds from any automatic code, whether BOSS or AILien or Steamhammer’s own strategy boss or any other bot. Handmade is still better—so far!

2. Keep the pressure on. Steamhammer plays the full range from fast rushes to economy-heavy openings, but it prefers low-economy pressure builds. I thought: Bots are good at attack and poor at defense, so keep attacking! AILien prefers a strong economy; it’s not a mistake, but it may be less effective at exploiting weaknesses in other bots.

3. Stay strategically crisp. Zerg larva management means that zerg can switch its unit mix suddenly to push the opponent off balance. I took the attitude: Don’t adapt to the situation, drive the situation so that the opponent has to adapt. That’s why Steamhammer makes explicit unit mix and tech target decisions. I directly coded in bias and hysteresis, so that it doesn’t change its mind lightly:

bool StrategyBossZerg::vProtossDenOverSpire()
{
	// Bias.
	int denScore   = 3;
	int spireScore = 0;

	// Hysteresis. Make it bigger than the bias.
	if (_techTarget == TechTarget::Hydralisks) { denScore   += 13; };
	if (_techTarget == TechTarget::Mutalisks)  { spireScore +=  9; };
	...

4. Fix bugs and stay resilient. As it stands, at least half of Steamhammer’s lost games show severe bugs—maybe not game-losing bugs, but deeply harmful bugs that destroy resilience and take away opportunities to come back. The bugs I fixed between version 1.0 and 1.1.1 likely made a big contribution to Steamhammer’s strength.

Are these the real reasons? Well, I already said that I don’t know. If you’ve watched the games, what do you think?

Tomorrow: Early returns from Randomhammer.

Steamhammer 1.2 and Randomhammer

Steamhammer 1.2 is out. Headline feature: It plays random (like UAlbertaBot). Steamhammer continues to play as zerg, and Randomhammer is the same code playing random. In its first game, thanks to the voting system, Randomhammer played Steamhammer. Randomhammer rolled protoss, opened 10-12 gate, and won easily.

Randomhammer’s elo is likely to end up lower, since zerg is way more polished. But the protoss is not bad, and it will be a good test. Terran and protoss hit bugs more often than zerg.

The change list is not long.

  • In the configuration file, you specify the target number of workers per mineral patch separately for each race, as a floating point number. I set it to 1.8 for zerg, down from 2.
  • New middle game production code, with longer tech paths than UAlbertaBot.
  • Openings.
    • 4 terran openings and 7 protoss openings, with random choice.
    • Terran and protoss openings use the OpeningGroup feature to share middle game production code.
    • Fixed a bug that prevented “2 x dark templar” from working due to the space character in “dark templar”.
    • Zerg’s 9 pool speed opening is updated to fix a mistake introduced in 1.1.1.
  • Worker defense: Attack stuck as well as non-moving enemies. (An unnoticeable tweak—for now.)
  • Emergency cloaked unit defense: Fixed a bug that caused the queue to explode.
  • Terran resumes construction after a building SCV is lost. (UAlbertaBot leaves the incomplete building there forever.)
  • Small updates to the zerg strategy boss.
    • Fixed a potential crashing bug.
    • Fixed a bug that could explode the queue when there were fewer than 3 drones.
    • Fixed a bug that could cause double ultralisk caverns.
    • Minor adjustments to the heuristics.

It was not hard to get protoss to play a decent game, but terran is tough. In my tests, Steamhammer 1.2 terran scores much worse than zerg or protoss. In a random-on-random test with a development version versus UAlbertaBot, Steamhammer protoss scored 8-1 and terran scored 1-7 (there were no mirror matchups). Another example: Against Stone, Steamhammer protoss survived on the first try. Terran did not, because Stone gangs up on building SCVs. Resuming buildings which lose their building SCVs was a necessary skill to give Steamhammer terran any chance at all; it can survive Stone occasionally. Terrans that beat Stone reliably have 2 other skills that I did not implement, replacing the building SCV when it gets hurt and pulling SCVs to drive the attackers off.

UAlbertaBot’s building placer started to show problems in longer games. UAlbertaBot plays rushes and doesn’t see many long games. The building placer wants to build everything in the main; when the main fills up, placement slows down drastically and may overstep the time limit.

I made a forge fast expand opening for protoss, but I have reservations because of other limitations of the building placer. In Steamhammer, you can ask for buildings to be made in the natural, and it works. The building placer knows to leave the nexus spot open. But it doesn’t know the plan, and may place the pylon in a spot without room for a forge, 2 cannons, and a gateway. If there’s no room, the build freezes and the bot will lose. I worked around it for now by inefficiently building extra pylons in the main for the gateway and everything after. Even so, it fails sometimes on SSCAIT maps when it can’t place the forge. Someday I’ll drop the building placer for a building planner, but that will probably be a long time from now.

version 1.2.1

I didn’t get everything done that I wanted, so I’m changing my plans for future versions. 1.2.1 will be mainly a feature version. Here are the features I hope to add, in order of priority.

  1. loading and unloading for terran bunkers
  2. simple measures so zerg can better survive vulture attacks
  3. basic drop skills for terran and protoss
  4. reavers
  5. psionic storm
  6. stim for marines
  7. mixed strategies versus specific opponents when playing random
  8. generalize certain zerg smarts so that terran and protoss can benefit

It seems to me the best tradeoff between getting key skills and getting finished. I’m leaving out a bunch of other basic skills: Overlord hunting (needed for wraith and corsair play versus zerg), mine laying, keeping medics close to marines, carriers, picking up dropped units....

There are also critical problems I want to fix. Others are likely to come up.

  • the bot falsely believes that mining SCVs block the comsat from being added
  • aimless play when the army gets distracted by units all around

version 1.2.2

Then the following version, 1.2.2, becomes the cleanup bugfix version. There are 2 bugs that pass invalid parameters to Micro::SmartMove(), at least 3 bugs that cause expansions to fail to be made, and 2 bugs that cause workers to go idle unnecessarily. I hope to stomp at least 5 of those 7, plus of course anything that turns up from playing random on the server.

version 1.3

Version 1.3 will be my start on mutalisk skills.

Steamhammer 1.2 to be followed by 1.2.1

Steamhammer 1.2 is taking longer than I expected. It may end up being a few days later than promised. It’s not as fun to work on protoss and terran, and I’ve been putting less effort in.

I have given it a workable set of a half-dozen protoss openings to play in a different mix versus each race. There are still a couple of critical bugs (why can’t it make a photon cannon?). The terran openings are giving me more trouble. UAlbertaBot turns out to be short of terran skills. It doesn’t know how to stim marines, so bio builds are weak, and it doesn’t know where to lay spider mines, so mech builds are weak. (There’s a routine to lay mines, but it is never called.) And I’m not excited about adding the skills. The terran openings will not keep up with the other races.

BOSS truly does work much better for protoss than for zerg. Steamhammer’s protoss play using BOSS with simple goals shows better macro than Steamhammer’s old BOSS versions did with carefully-chosen goals.

UAlbertaBot does include a protoss drop skill, which in a test almost worked. It built a shuttle and flew it in a cautious path along the edge of the map to the enemy base—all it forgot was to load zealots first. If I don’t run into any surprise trouble, I’ll get it working for protoss and terran and include a drop opening or two. With XelnagaII disabled, no bot currently plays dark templar drop, and that’s a shame.

Also, Steamhammer 1.1.1 is showing some severe bugs that sabotage its play, especially in long games. So before I get into the 1.3 series, I’m planning a bug fix version 1.2.1 that fixes the worst bugs and restores good macro in long games. That includes protoss and terran bugs that may come up in version 1.2.

Steamhammer’s unbelievable winning streak

OK, this is officially Too Much. Steamhammer hit a string of good luck and its elo went over 2300—it should be about as high as this version gets. After its first loss to Steamhammer, Krasi0’s opening learning is still struggling to find the answer (which is: go back to the default build and win almost all games). After many losses against Iron, Steamhammer scored back-to-back wins, which can only be called luck. The wins came with opposite opening styles. One game was 9 pool speed. Steamhammer transitioned to mutalisks, which fought well enough to stop serious drone loss from the vultures. Iron built mass turrets but was unable to cope on the open map, and ultralisks eventually put in the final word. The other was 3 hatch muta. In the second game, the mutalisks were early and numerous and cut down Iron where it stood. A bunker and a couple rings of turrets are not enough; this mainstream opening is a flat-out counter to Iron’s build. If zerg took a little more care in defense, Iron would stand no chance against the 3 hatchery mutalisks.

Steamhammer also scored two fluke wins over LetaBot versions when LetaBot crashed while far ahead. Skynet by Andrew Smith finally put an end to the incredible winning streak—with a dark templar rush! Ha ha! Skynet played it well, killing spotting overlords with a dragoon and taking full advantage of Steamhammer’s blindness to its build.

GHOST solver

I want to draw attention to GHOST, a constrained optimization solver from 2014 that claims to be good for a wide variety of RTS problems. The lead is Florian Richoux, author of the protoss bot AIUR which was a strong contender in its day.

According to the description, GHOST should be good for Starcraft problems like designing a wall, placing static defense, choosing where to siege your tanks, planning build orders, optimizing your army composition, prioritizing targets to shoot at—a huge variety of things, actually. It claims to give answers not too far from optimal and to be fast enough to run within a single frame (though it will depend on what problem you’re solving).

I haven’t tried GHOST and I don’t intend to, because it is under a GPL license, which rubs me the wrong way. But if is as good as the paper says, it could be a superb way to solve a lot of different Starcraft problems.

Steamhammer 1.2 OpeningGroup feature

For the upcoming Steamhammer 1.2, I added a feature today to simplify the coding of similar middle game production for different openings. In older versions of Steamhammer, StrategyManager checked the name of the opening build order to decide what to build. There were a bunch of zergling openings, so I coded in: If the opening is this, or this, or this... build zerglings. If the opening is that, or that, or that... build mutalisks. It was bulky and hard to maintain, but I let it stand because I knew I was throwing the code away when the new strategy boss was ready (and I did).

I don’t want to write a new strategy boss for protoss and terran, so BOSS will be the way. BOSS works better for protoss and terran than for zerg, anyway. To solve the maintenance problem, you can add an optional OpeningGroup string to each opening, and check the OpeningGroup in the code instead of the opening name. If OpeningGroup is zealots, make zealots, and so on. It doesn’t matter how many zealot openings you write, StrategyManager doesn’t need to be updated. Of course nothing stops you from using the opening name too, if you want to fine-tune, but then keeping it in sync is up to you.

Here is the start of UAlbertaBot’s zealot rush:

"Protoss_ZealotRush" : { "Race" : "Protoss", "OpeningBuildOrder" : ["Probe", "Probe", "Probe", "Probe", "Pylon", "Probe", "Gateway", "Gateway", ...

Here is the same part of the identical opening in Steamhammer 1.2 development version. There is also a “10-12Gate” opening in the zealots OpeningGroup. Liquipedia lists other two gate zealot openings if you want to code them in yourself.

"9-9Gate" : { "Race" : "Protoss", "OpeningGroup" : "zealots", "OpeningBuildOrder" :
    ["4 x probe", "pylon", "go scout location", "probe", "2 x gateway", ...

I made a couple of simple and necessary improvements to the followup, too. When it transitions to dragoons, Steamhammer (unlike UAlbertaBot) gets dragoon range and eventually zealot legs. If given the same openings, Steamhammer will play them better than UAlbertaBot does. I intend to give it random openings that are a little different, though.

a win and a loss against Krasi0

Steamhammer got its first win against Krasi0 after many many tries. The map was Python, where starting positions are important, and the two bots got neighboring positions. Steamhammer went 9 pool speed, as it does 10% of the time versus terran, and Krasi0 was unlucky and scouted the wrong way around the map. Zerglings ran past the scouting SCV before it could reach the zerg base. The bunker in the terran natural was late and never finished (a bunker in the main could still have saved the game). Once zergling speed completed there was no hope for terran.

That apparently used up Steamhammer’s supply of luck, because it was immediately tied up in a string of losses. The loss against XIMP showed a bug I hadn’t seen, where Steamhammer repeatedly tried to take the third base that is a crucial part of its build order, but each time the drone lost interest and went home. Some weird macro bugs are lurking.

The most informative loss was another game against Krasi0, where Steamhammer first gained a winning advantage, then lined up its bugs and limitations in a row and held a parade. This time Steamhammer opened 12 hatch into 2 hatch muta. The bunker was again late, this time without excuse (is it a newly-introduced error?). The initial 6 zerglings got SCV kills that they did not fully deserve and, more importantly, slowed mining for a time as SCVs were pulled. With more smarts they could have stayed in the terran base and marauded for a time.

When the mutalisks came out, Steamhammer’s eyes lit up with crazed aggression. It flew over the bunker to kill every SCV that came near while ignoring the bunker itself and probably laughing maniacally. If it knew to fly to the mineral lines instead it could have won on the spot, but as it was the loss of workers set terran far back for the middle game. It was a decisive advantage and would have been a sure win with good followup.

Krasi0 countered the mutas with goliaths, which Steamhammer countered with hydralisks, which Krasi0 countered with tanks. That’s how you play the game. Steamhammer went up to 4 bases and brought out ultralisks while Krasi0 was still on 2 bases. Here you can see that Steamhammer has a larger army and more workers, and the production tab shows that zerg is outproducing terran even though minerals are accumulating. The terran 3rd command center is under construction in the lower left natural.

zerg is way ahead

In the later game, Steamhammer, showing the other side of its mad streak, made 3 deadly mistakes and a bunch of smaller mistakes. Avoiding any of the 3 deadly mistakes might have been enough to win.

1. Steamhammer chose the unit mix hydra-ultra and became pinched for gas and unable to spend all its minerals. I overlooked a couple of important factors in the calculation. Hydra-ultra is useful in rare situations, and especially in situations nothing like this one. With zerglings instead, the zerg army would have been larger and deadlier and there was likely nothing Krasi0 could have done to hold it off.

2. Due to a bug, zerg was unable to take a 5th base. This bug I’ve seen before; it is not the same one as against XIMP. Getting the 5th gas would have made hydra-ultra more playable.

3. Zerg never scouted the terran 3rd base. It’s a limitation; I haven’t gotten around to middle game scouting yet though it’s a basic skill. See the expansion attempt, kick it down before it starts with a few units, starve out the terran. The hydra-ultra army should have been enough to keep the terran army bottled up if a few zerglings spotted expansion attempts.

scourge turn aside

Here’s another weakness: This is the 4th pair of scourge to chase this dropship, and the scourge is veering away for no reason. The 5th pair finally caught it. Suicide missions are hard to recruit for. Steamhammer showed hesitation with scourge and in shutting down vulture harass. In this picture, Krasi0 has turned it around and is winning by a mile.

Steamhammer, documentation and next version

documentation

1. I uploaded documentation for Steamhammer 1.1.1’s configuration file.

2. Next I’ll write a short document “getting oriented to the code”.

3. In future versions I’ll update the existing documents to that version and slowly add new documents. Documentation links for each version will be alongside the download links on the bottom of Steamhammer’s web page.

Steamhammer 1.2

Steamhammer 1.2 will be tested to play any race. I have promised it will be ready by the Ides of March, as a bad omen for everybody else. I will have it play random on SSCAIT as a test.

So far, my initial prediction is holding up: Terran and protoss play seem to show a small number of bugs. I will fix those and also add a small number of features to better support random play. There will also be a small number of other bug fixes and minor features, and that will be all.

small numbers speak small

Curious fact: Steamhammer versions 1.1 and 1.1.1 are currently 3-0 versus Bereaver and 0-3 versus Killerbot by Marian Devecka. I don’t think it deserves either of those numbers.

The wins over Bereaver are exploiting a weakness. Early in the game, Bereaver techs too hard and doesn’t defend itself adequately, and some of Steamhammer’s openings mass-produce zerglings at a timing that exploits the weakness. I don’t expect all the openings to win; Steamhammer got lucky so far.

The losses to Killerbot are due to scouting wrong (in the most recent game) or taking poor tactical engagements (in the other two). Against Killerbot, these Steamhammer versions play a more solid counter to Killerbot’s overpool +1 opening. Steamhammer now goes overpool with an early second hatchery to outproduce Killerbot in zerglings for a while, occasionally winning outright but usually buying time to transition into spire, which Killerbot can’t defend. I think Steamhammer’s strategy advantage at least equals Killerbot’s skill advantage in tactics and crisis management. Steamhammer’s long term score versus Killerbot should be 50% or more.

You can’t tell how two bots fare against each other from a few games. You especially can’t tell how Steamhammer fares, because the bot plays so many different openings. I propose new wording for the law of small numbers: Small numbers speak small.

coping with map blocks

On 2-player maps, some games of Steamhammer against strong bio terrans, LetaBot and Tyr by Simon Prins, have gone like this: Steamhammer opens with mutalisks and, seeing defenses at the front and not knowing how to fly around them, falls into a standoff. Both sides build up for a while. The terran moves out with an infantry force. That’s a head-to-head fight that the zerg flyers understand, and they clean up the terrans before serious damage is done to zerg bases—not without losses, of course. Meanwhile, Steamhammer has long since sent out a drone to take a 3rd base, but the drone was confused by the blocking buildings on Benzene, or the blocking minerals on Destination or Heartbreak Ridge, and is still wandering back and forth looking for the way. Steamhammer has a mineral excess but does not make macro hatcheries because it is waiting for the new base to start. Zerg can’t keep up in production and loses to the next attack.

Map blocks are causing too many losses. I have to do something soon. Most bots stronger than Steamhammer already take measures (I think only Bereaver still suffers losses to map block issues). What are the options?

  1. Fix pathing: Go around the blocks.
    1. Goal monitoring: Detect units which seem stuck and reroute them.
    2. Detect that paths may go through blocks and (somehow) take extra care.
    3. Switch to BWEM. I want to, but maybe later?
  2. Clear the blocks.
    1. Clear blocks near our bases unconditionally. I think some bots do.
    2. Clear blocks which are adjacent to the main, or to an expansion we want.
    3. Goal monitoring: Clear blocks near stuck units. The units themselves can often do it.
    4. Hypothetical path analysis: Clear a block if it makes a path that we want to take shorter.
    5. Strategic analysis: Open paths which are more valuable to us than to the enemy.
  3. Work around it in some cheesy way.
    1. Take bases in an order that doesn’t run into map blocks.
    2. Hardcode, or add to the config file, a list of maps with blocks and what to do about them.
    3. Get vision of the base first, and then mineral walk to it, passing through blocks.

Obviously the ideal is to both fix pathing and clear the blocks, as in 1C plus 2E. Goal monitoring has some value, but not much value if the goals hardly fail.

To analyze from general principles whether it’s a good idea to clear a given block, you need hypothetical reasoning: If I clear this block, then that path opens, or that shorter route becomes available. I don’t notice direct support for hypothetical reasoning in either BWTA2 or BWEM. It doesn’t seem all too difficult to cobble something together if you can find out what choke each blocking mineral/building blocks and the choke-to-choke distances.

For now I don’t want an ideal solution, I want something simple that solves enough of the problem. I expect I’ll start with 2B and adjust as needed.

What do others do? Are there tricks or pitfalls?

Update: I should have talked about mineral walking. Quite a few competitive maps are designed with small mineral patches on one or both sides of a block. A worker at the block can see the minerals on the other side, right-click on them, and pass through the block, but another kind of unit cannot. Electric Circuit in the SSCAIT map pool has the feature, but the map is not used, because too many bots get units trapped behind the blocks. Of course, as long as the map is not used there is no incentive to fix the bugs....

And that suggests an idea for zerg bots: First send an overlord to any base that you want to take. With vision of the minerals, you can mineral walk the expansion drone to the base. Having vision also gives some assurance that the base is safe and worth taking, and it lets you deal with spider mines. I’ve added the idea to the post as 3C. I hadn’t thought of it before, but now I’m seriously considering it.

Steamhammer 1.1.1 source is available

Steamhammer’s web page is updated through version 1.1.1. Download source there. I’ll write two bits of documentation, one for the configuration file in this version and one “getting oriented to the code.” Stand by; it may take a few days.

By the way, version 1.0 scored 151-82 (65%) over its active lifetime. Version 1.1 scored 8-14 (35%) in the one day before the bugfix version 1.1.1. Version 1.1.1 has scored 11-5 (68%) so far. I let a big big bug slip in!

Steamhammer bugfix version 1.1.1

Steamhammer 1.1.1 is uploaded with a fix to the infinite creep colony bug. I also added a new opening, because it had been nearly a whole day and I have to keep up my self-respect. The 9PoolHatch opening counters zergling rushers more sharply than 9PoolExpo. And I tweaked ZvT to make more drones, because it seemed a little lean.

The bug, by the way, was a hard-to-see typo in a part of the code that has no direct connection with making creep colonies. It took some finding.

I’ll update Steamhammer’s web page tomorrow.

about Steamhammer 1.1

stand by for bug fix version 1.1.1

Steamhammer 1.1 is losing game after game to the infinite creep colony bug. Apparently I ran the wrong test games to see it. There will be a 1.1.1 release to fix the bug.

version 1.1

Steamhammer 1.1 had a shorter development period (compared to the previous version) than 1.0 did, but it includes at least as many changes.

The primary goal of 1.1 is not to play better, it is to raise the ceiling on potential performance by playing more flexibly. Every time you add flexibility you run the risk of playing worse: The bot could misuse its flexibility. Flexibility makes more mistakes possible.

1.1 includes enough strength improvements that I think it probably does play better overall, or at least fixed version 1.1.1 should. Its rating went down at first, partly due to losses to Neo Edmund Zerg (which seems to be by the same author as Newbie Zerg, 5 Rax Newbie, and 5 Pool—what is it with all this coming and going? [it is partly explained in a comment]). Over time, I expect its rating to wobble over a range offset slightly upward from 1.0 (whose final elo of 2163 was above its average).

strategy boss

The headline feature of Steamhammer 1.1 is new macro code in the zerg strategy boss. It looks at the game situation and decides on a unit mix to produce now and a tech goal to work toward. It’s not very extensive; the possible tech goals are hydras, mutas, and ultralisks. Units allowed in unit mixes include those three plus zerglings. A unit mix is specific: It always includes one mineral-heavy unit and optionally includes one gas-heavy unit, and that’s all. The units are combined as resources allow. Some of the unit mixes, like hydra-ultra, are designed for rare circumstances, and I’ll be watching to see whether they ever appear in real games.

The strategy boss has a lot of tiny smartness improvements, mostly to avoid mistakes. Overlord timing is better. It copes more successfully with a wider range of emergencies (oops, lost the main? I’ll call this base my new main). When the enemy army looks big, it may build sunkens. There are no more random unused buildings (buildings may still go unused, but they are always made for a purpose). It no longer goes overboard on scourge (that was a bug). Few situations cause production freezes, though there are still some. It can upgrade in 2 evo chambers at once. It has fine control over the economic growth rate, though it doesn’t make much use of the ability.

All these improvements have surprisingly little effect on skill. They are weaknesses that need to be fixed, but not bottleneck weaknesses that lose many games.

tactical improvements

One big improvement is the worker harass defense as suggested by AIL. Steamhammer beats Stone. This defense skill helped 1.1 to a win over Bereaver in its first SSCAIT game, losing 0 drones where 1.0 often lost 2 or more.

Another big improvement is that Steamhammer is more cautious about the range of enemy units. It understands the range advantage given by a bunker, and assumes that enemy units have their range upgrades. Units less often suicide by dawdling under enemy fire. Steamhammer was able to play longer against Krasi0 before losing due to other weaknesses.

There are a bunch of other improvements, but they’re minor by comparison. Targeting is further improved. Zerglings and scourge are slightly less stupid. Stuff like that.

One improvement behind the scenes is used only by the strategy boss for a minor purpose, but should be valuable in the future: InformationManager tracks when its data about each enemy unit was last updated. You can tell if the data is fresh or stale.

the configuration file

You can specify repeated units in a build order: “4 x drone” gets you 4 drones. Or at the end of a rush build, “50 x zergling”. The openings become shorter and easier to read and edit. 1.1’s configuration file is less than 3/4 the size of 1.0’s, even though the bot plays more openings.

openings

The new strategy boss bring changes to openings. Since the bot can now adapt to the situation, a bunch of openings have been shortened to get out of the opening sooner and start adapting. A few openings have been lengthened because the boss was likely to do the wrong thing.

The opening selection changed. In earlier versions I rejected overpool openings for ZvP (even though they’re the top ZvP openings in human play) because they require adaptation to play well. Also the ZvZ overpool openings I tried were unconvincing. 1.1 plays 2 different ZvP overpool openings, and 3 ZvZ overpool openings plus an overgas opening.

Openings are still chosen randomly with weights. The number of openings per matchup:

matchup1.01.1
ZvT89
ZvP66
ZvZ711
ZvRandom34

I dropped the ZvP 3HatchHydra opening altogether. I wasn’t satisfied with the version in 0.2 and reworked it for 1.0, but I did a thoughtless job and the 1.0 version is worse. The bad opening is responsible for more than its share of losses. Now all ZvP openings stop at zerglings and let the strategy boss decide whether to go for hydras or mutas next. In my tests it makes mostly good choices.

I also fixed tuning mistakes in the ZvT 2HatchMuta opening; it hits harder. A number of the other openings are not quite optimized and could use tuning up.

Steamhammer 1.1

Steamhammer 1.1 is uploaded. Headline feature: New macro code which knows how to bring new tech online and transition to new unit mixes. “Traditionally” I draw no debug info on the screen in release versions, but for this version I tossed up a tiny bit of info in the upper left for spectators: While in the opening book, the name of the opening; after that, the current unit mix and next tech goal.

Details and stuff tomorrow. I need some rest.

I made strenuous efforts to eliminate all production freezes and critical bugs, but I failed. There turn out to be a tremendous number of ways for production to seize up, and I couldn’t eliminate all of them. There’s also a particularly amusing bug that causes the bot to send all its drones to its main base to build creep colonies. I’ve only seen that bug in 2 test games out of dozens, and it resists finding so far. It will be hilarious to see it happen on the server.

spiral development

When I started Steamhammer, one of my first additions was macro code so the bot could build units appropriate to the openings I had coded in.

Now I have tossed that macro code and completely replaced it. The new macro code is better in many ways: It reacts faster to changes, adapts to a wider range of circumstances, survives more emergencies, knows how to transition to a new unit mix and how to pick a new tech goal, and is generally more capable and less buggy.

And I am planning to toss it and replace it again. Its transitions feel mushy and imprecise, as if it weren’t quite sure what it was aiming for. It’s similar to other bots: It is making decisions based on low-level heuristics rather than on an understanding of the situation.

The central zerg macro skill is knowing when to make drones. Steamhammer 1.1 makes drones because it vaguely believes that more drones are better. Strong players don’t do that. A player at ICCup B level understands that the right drone count depends on what you want them for, and makes drones with specific purposes in mind. Making a purposeless drone means that your army is smaller and you are putting less pressure on the enemy; it is a mistake.

For another example, watch AILien tech up (Steamhammer 1.1’s play is not altogether different). When it has teched up to a new unit, you commonly see a few mutalisks or a few ultralisks join the army. If those are successful, more may join in. Pro games don’t go that way; at some point the observer will center on the zerg rally zone and you’ll see a dozen ultralisks as if out of nowhere. The pro is reacting to the future, not the past. No pro would spend on ultra tech to make a few and see how they turned out.

abstraction saves your bacon

So at some point I will rewrite the macro code again, to give it a deeper understanding of goals and constraints. How can I do it?

I keep seeing people complain, or point out by way of excuse, that the state space is too big for machine learning to work. I don’t accept it.

Take the zerg macro problem. You start out knowing part of the game state and part of its past: Where your units are, where enemy units were last seen, and all the other details. Your problem is to use this information to decide what to make next: a drone, a zergling, a hatchery, a creep colony....

If you frame the problem that way, the state space may truly be intractable. “I have a hydralisk with n hit points at position (x, y)” informs the decision, but not much! If you try to train a neural network (or whatever) with that input and output, you may struggle to make progress. And you absolutely will need a huge quantity of data that will be difficult to gather (even with OpenBW tools, which aim to make the data easier to gather).

You need an understanding of the situation, not a list of the details of the situation. I frame the problem as the interaction of goals and constraints. Goals are “I want this current unit mix,” “I want to aim for this set of upgrades,” “I want to add this tech.” Constraints are rooted in the game rules, “it takes x frames to make a y” and “my income is x minerals per second.” Constraints let you calculate or estimate useful information: “How long will it take me to make upgraded ultras?” and “How many ultras will I able to include in my unit mix by then?” and “How many if I expand first to get more gas?”

“What should my current unit mix be?” is a more tractable problem to solve than “what unit should I make next?” and yet in practice it answers the same question. It abstracts away the detail of “what next?” leaving only “what?” The detail of exactly which is next may not matter, and if it does, it can be solved as a separate problem. Also the unit mix question can be answered partly by constraints: Knowing your mineral and gas income and rate of larva production constrains what your unit mix can be, even when it doesn’t constrain what your next unit is. Constraints can be calculated; they should be included in or reflected in the input to the learning algorithm, not treated as something to learn. Don’t do everything bottom up; top down has its place.

Similarly for other goals like “what tech should I seek?”

Abstraction also helps on the input side. I want the input to be not “here is what is known of the game state” directly from InformationManager, but “here is the abstract tactical situation,” the tactical sitrep, maintained by a tactics boss which does not exist yet. I want the strategy boss to realize “it’s too dangerous to expand in this situation, and I have enough drones to support this unit mix, so no more drones for now.” Further in the future, I want it to be able to say “this enemy mineral line has a back door, so morph these nearby hydras to lurkers.” Or something with the same effect.

With an abstract output and a much smaller abstract input, the learning problem should be fully tractable. “The state space is too big” is a flag, and the flag flies over the territory of abstraction. Deep learning copes with large state spaces by learning abstraction using huge amounts of data; I don’t expect to be able to get huge amounts, so I must supply abstraction from outside.

spiral development

Steamhammer’s original macro code was needed so that the bot could play a complete game—otherwise I couldn’t make progress on the basic features. In 1.0 the basic features were finished enough, so next I replaced the macro code to add flexibility; the bot has greater ability to react and adapt. That flexibility is needed for the next step, a smarter tactical boss that keeps track of tactical goals and maintains a picture of the tactical situation. And that tactical picture is the foundation I need to throw away the macro code again and rebuild it.

I’m still concentrating on strategy first. But strategy needs tactical understanding; the levels are not independent.