archive by month
Skip to content

Randomhammer’s matchups

Here are Randomhammer’s win rates on BASIL. Randomhammer’s race is on the left, opponent race across the top. X means overall. Win rates are good for comparing matchups of a single bot, but because BASIL assigns different mixes of opponents to different bots, they can’t be compared across bots. You could compare across bots by computing elos per matchup.

vTvPvZvX
T31%27%54%39%
P58%51%75%63%
Z73%60%71%69%
X53%45%66%58%

Z is the best race, of course, since zerg is Steamhammer’s main race. The vZ matchups are the best versus any, because I understand better how to play against zerg and because I want Randomhammer to be a good test opponent. But PvZ is above every Z matchup and far above ZvP! No matter what race Randomhammer rolls, vP is its worst matchup.

experience with SCHNAIL

I’ve been keeping an eye on SCHNAIL by Sonko for human-machine play. The interface is not pretty like BASIL, but it works. Few games are played, by comparison with SSCAIT and BASIL; on the days I counted games, between 64 and 111. Humans—it’s shocking but true—are somewhat slower than computers. A game on SCHNAIL can be “practice” or “ranked”, with different rules. Sonko was surprised early on that nearly all games were practice. I guess it makes sense while people are first trying out something new. Today most games are still practice games, but there is a good mix of ranked games too and most bots seem to have properly established ranks which are not very different from their ranks on BASIL. The ratings look different, though, since the midpoint is 1500 instead of 2000—and humans are better, so the bot ratings are mostly below 1500. The ratio of practice to ranked games varies depending on how popular the bot is to practice against: BananaBrain is popular and has 12% ranked games, while tscmoo is not and has 61% ranked. Some bots have few total games and no believable ranking, probably because they don’t work reliably, and probably should be removed from the rankings.

SCHNAIL supports 22 maps, at least notionally: The 15 SSCAIT maps (including Electric Circuit, which is disabled on SSCAIT) plus a handful of newer maps. I was not able to find any successful games on the maps Tres Pass or Core Breach. Perhaps they use features from Broodwar Remastered? Or do so few bots support them that none has succeeded there yet? The bot upload page comes with checkboxes so you can specify which maps the bot can play on. I didn’t realize at first that the checkboxes scrolled; a more rectangular arrangement would be easier to use. Anyway, my uploads are set to play on all maps except the two broken ones and Electric Circuit, where they run into pathing trouble.

In a practice game you choose your opponent; in a ranked game, SCHNAIL makes the match, trying to choose a bot near the human’s strength when it can. I thought there was an element of randomness in the ranked matchmaking, but if so apparently it is not a large element. I often see streaks where the human is matched against the same bot repeatedly. It makes a difference, too; humans learn fast and adapt their play to what they are facing, and I sometimes see the same pattern in ranked games as in practice games, where the human loses several times and then figures out how to win.

Steamhammer has only a handful of games since it was updated; most days it does not play at all. Nevertheless, some of the games are ranked games, and its rating has climbed. In ranked games SCHNAIL is still matching Steamhammer against players below its current strength, and its rank will likely keep climbing for a while.

The weaknesses I see in Steamhammer’s play versus humans are about the same as the ones I see in its games against other bots. But humans pick up on weaknesses more easily, and exploit them more consistently, so the weaknesses look bigger. It’s useful, actually. I have changed some priorities after seeing games. One protoss at first struggled against Steamhammer’s macro, but after a few games realized: Put a little pressure on, and then Steamhammer can’t defend its expansions, hydras don’t think they can get there. A couple more games, and it was: Cannon the expo while zerg can’t respond, then maybe take it for protoss. Bots aren’t that smart!

Randomhammer was indeed a newer version than Steamhammer at first, explaining why it was rated a little higher. Since then I’ve updated them both, of course. I had to ask to be given control of Randomhammer, but it was no trouble. Randomhammer has no games since it was updated. Human players may be different, but BASIL provides the best available forecast: The win rate graph shows protoss not far below zerg, with terran stuck in the mud far behind. I think the big difference must make terran less fun to play against.

Crazyhammer is a just-for-fun Steamhammer zerg configuration that I uploaded to SCHNAIL yesterday. It is set to choose randomly from its library of over 200 zerg openings, paying no attention to the matchup or the map or anything. I set it to practice-only, since it is in no way competitive. Play a game and be surprised; Crazyhammer might accidentally play something sensible, or it might play a protoss build like 4 hatches before lair against your zerg.

Will it be ordinary 2 hatch muta—or queen rush, or 5 hatches before pool, or 7 pool hydra rush, or...? Chooses utterly at random from a huge library of sensible and insane builds. For weirdness!

As a taste, there are 2 builds starting with 4 pool, 3 with 5 pool, 5 with 6 pool, 8 with 7 pool, 4 with 8 pool, and 18 builds with 9 pool. If I counted right. At the opposite end of the macro spectrum, there are 4 builds with 5 hatcheries before pool, 1 with 4 hatcheries before pool, and 11 with the more reasonable 3 hatcheries before pool. The bulk of the options lie between the extremes. Most of the openings counter something and make sense in some situation, however rare, but a few are pure nonsense thrown in for the hell of it. The two-base ultralisk rush has no known use, and the 7 pool mutalisk rush might beat you if you are a sworn pacifist. Some of the ideas I have never seen anywhere, from bot or human. I hope players will enjoy sampling a little of the prodigious variety.

Crazyhammer has been chosen for 1 game so far, a ZvZ where it went with a perfectly sober 10 pool, scouted the wrong way so that it failed to react to the enemy, and lost easily. Not crazy enough.

Steamhammer versus cannon rushes

In its earliest days, Steamhammer had some trouble with cannon rushes due to bugs that you might imagine are unrelated. See Steamhammer’s funniest bug from January 2017, when it was only a month old. Back then it had no learning, and I manually configured it to play 9 pool versus cannon rushers and other cheese bots. Once the basics of scouting and so on were straightened out, it worked fine at the time, except against AIUR by Florian Richoux, which alongside other builds sometimes does sneaky cannon rushes (still among the best cannon rushes by any bot, in my opinion).

When I added learning, Steamhammer became able to recognize the cannon bots and react on its own. No more manual configuration. It still countered with 9 pool, which is simple and reliable. When Juno by Yuanheng Zhu came on the scene, it caused little new trouble. Only AIUR, with its unpredictable builds, occasionally won by cannon rush. The other cannon bots were predictable and easy to stop.

Today it is different. Krasi0P switches between cannon contain to lock you into your base, and defensive cannons. MadMix can execute an impressive variety of offensive cannon builds: In your base, in your natural, outside your natural; containing or directly attacking without trying to contain; with forge in base or forge up front. The 9 pool still stops them all, provided the cannons have been spotted, but since the enemy build is unpredictable, Steamhammer doesn’t know when to play it. Well, it could play 9 pool every game, except that it doesn’t have the skills to adapt its play when it sees that the enemy has done something else. If there were about 16 of me, I might be able to work on everything at once....

The current Steamhammer has many different reactions to help it cope with cannon rushes. And it can still lose.

• If the enemy is predicted to proxy cannons, choose 9 pool or a similar anti-cheese build. That takes care of bots with only 1 build, and bots that play the cannon rush too consistently after it wins.

• Scout the main base and areas near the natural with an overlord. How this happens depends on game events, but typically the second overlord starts the work; it may be replaced by a later overlord if the second is called away to join units. With Steamhammer’s current skills, scouting the cannons early is crucial to reacting well. This scouting may in practice be the most valuable skill on the list—although objectively it’s often better to send the overlord to scout the enemy.

• Recognize all nearby cannons, out to beyond the natural, as rushes. Early Steamhammer versions only noticed cannons in the zerg base, because that was all it faced back then.

• Recognize a forward forge as an incoming cannon rush. There is no other reason to build a forge near the enemy base. (Now we get to see if any bots make a pylon and start the forge when it is in vision, then cancel it, to spoof a cannon rush. Would Steamhammer overreact?)

• If a forge or unfinished cannons are near the mineral line, pull drones to attack. Steamhammer doesn’t pull drones far, though. I haven’t felt inspired to do the calculation of when workers reach the cannons versus when the cannons complete.

• If cannons are scouted before the spawning pool has been placed, start the pool ASAP, canceling stuff if necessary. This is often objectively an overreaction, but with Steamhammer’s skills it’s usually a good decision in practice.

• If a cannon appears near a zerg base, any base at any time during the game, place exactly one sunken to prevent the cannons from pushing closer. All bots that use cannons offensively also like to cannon push—except Steamhammer protoss, which prefers to add a gateway. MadMix can sometimes push cannons around the single sunken and reach a vulnerable point in the zerg base, so the defense is not airtight.

• Send a drone to a hidden base location if possible, and the next time we want to expand, expand to that base. If the scout drone is out scouting, it will be the one assigned. If we’re contained we’ll be able to produce units outside the containment, and if the main base is killed by cannons, we’ll have a distant base that protoss will have to find and deal with separately.

• Don’t assign units to the defense squad to kill cannons, assign units to an attack squad to go kill the enemy base. So far, I have seen no cannon bots defend the main with cannons—and, well, Steamhammer’s hidden base is hidden.

• If the enemy has no known mobile anti-air units, send overlords to watch over vacant bases on the map. This is also an anti-cannon skill! Steamhammer has lost games after killing the enemy main by not noticing that protoss had another base—zerg units gather to kill the cannons, the last known enemy buildings, which may take a long time and let the enemy recover.

• When there are cannons on the map, prefer hydralisks over zerglings. They’re more efficient versus mass cannons. Steamhammer is slow to switch, though, and often overproduces zerglings regardless.

That is a lot of skills! And they work fairly well and win most cannon rush games. How does Steamhammer still lose games? Mainly by blundering into cannons. Drones leaving the base to build don’t notice the cannons and die. Drones trying to transfer to the outside base do notice the cannons and mostly stay out of range, but clog up movement for other units. Safe movement is not perfect and loses some. Attacking is sloppy and loses more. Defense has a horrible bug which sends warriors through the cannons without fighting. I’ve concluded that threat-aware pathfinding is necessary, and that it has to be hooked into production so that Steamhammer doesn’t do things like make more drones in the main than it can support—it has to know whether it can transfer them out before it decides to produce them.

In other words, the losses are due to bugs that you might imagine are unrelated. If only there were 16 of me!

the Steamhammer-Krasi0P match

Yesterday’s loser’s round match KrasioP-Steamhammer ended up with the result I expected, but not in the way I expected. Krasi0P has two builds, cannons in base and proxy cannons. Steamhammer can easily beat either one if it correctly predicts it, but it is poor at predicting. The wins tend to go in streaks, Steamhammer loses a bunch in a row then wins a bunch in a row, because both bots are somewhat slow at reacting when the opponent’s build switches. And Steamhammer’s recent games against Krasi0P, the 2 games in the SSCAIT round robin, were losses. So most likely the losing streak would continue.

1-1 after the first 2 games was good. In the last game, my initial diagnosis was the same as the commentator’s: Steamhammer was going to play 1 hatch muta, an excellent choice that should win. I was suddenly looking forward to a surprise match victory. But when I saw the second hatchery start, I knew something had gone wrong. Steamhammer ended up playing a nonsense build that countered nothing, a sure loss. After seeing the cannons it should have turned a few planned zergling pairs into drones; that part looked OK. I’m not sure what failed, but my best guess is that something caused Steamhammer to break out of its opening build and fall back on the strategy boss, which is buried up to its neck in ZvP weaknesses (it’s Steamhammer’s weakest matchup). Those mistakes look like strategy boss mistakes. But nothing I saw in the game should have caused it to break out of the opening. It may be a bug I haven’t seen before.

In any case, the fixes in version 3.3.6 made Steamhammer substantially stronger against Krasi0P (and many other opponents). Steamhammer will look impressive if it ever gets into a tournament with all the major bugs fixed before instead of after....

Really next, no really, this time I mean it: Steamhammer’s experience versus cannon rushes.

funny fast burrow game

Randomhammer protoss has been rolling up opponents with its dragoon build, thanks to improved macro. Though there’s plenty of room to improve it further. Randomhammer terran looks as erratic as ever, sometimes wiping out zergs with efficient marine attacks but more often goofing around. Overall, a worthwhile update for the short time I spent on it.

I thought this game was funny: Steamhammer-Krasi0 on Empire of the Sun. Krasi0 opened with risky aggressive 2 barracks in the middle. Steamhammer, purely by chance, decided to play a build that it does not understand how to exploit properly, 9 pool speed burrow. Different burrow tricks are possible, but the main idea behind getting burrow so early is to run lings into the enemy main and use them to cause confusion and delay, harassing and then burrowing whenever in danger. This game did not go that way. Burrow finished just as marines entered the zerg main with murder in their eyes, and the rest was inevitable. It looked as if it had been custom crafted.

Steamhammer on SCHNAIL

I have felt fully busy with Steamhammer, with No Time For Anything Else, so I have been ignoring SCHNAIL. Besides, until I updated to BWAPI 4.4.0 I could not upload a new version anyway. Today I apparently felt less busy, because I logged in there for the first time since early days.

I updated Steamhammer on SCHAIL from version 2.4.1 (dating from late 2019) to the current version 3.4.1. The current version is far stronger against other bots, and it should be much stronger against humans too—though I imagine that some of the new danger-avoiding behaviors that are effective against other bots can be exploited by devious humans. The older version already had a HumanOpponent flag which is supposed to be set automatically when running under SCHNAIL. I have never verified that it works as planned. Maybe I should do that soon....

Unsurprisingly, the old Steamhammer ranks much lower versus humans than the current Steamhammer ranks versus bots. What did surprise me is that Randomhammer ranked higher than Steamhammer proper. Ever since Randomhammer was first uploaded to SSCAIT in 2017, I have never seen Randomhammer above Steamhammer. Steamhammer’s zerg is much stronger than its alternate races. It’s hard to believe that humans are worse than bots against random opponents, so maybe this is a newer version of Randomhammer? I’ll check that out too.

I watched a few replays. It was delightful to see some of the bot exploits that people attempted. Especially when they didn’t work.

Still next: Steamhammer’s experience versus cannon rushes.

Steamhammer 3.4.1 uploaded

As promised, I’ve uploaded Steamhammer 3.4.1 which has fixes that primarily benefit terran and protoss. I anticipate that protoss will be significantly stronger, terran a bit stronger, and zerg minutely better. For the debug display this time, I turned on drawing of worker info. Among other things, each worker is drawn with a letter representing its task, M for mining minerals, G for gas, B for constructing a building, and others (11 codes in all; the most obscure is Q for a worker which was posted to a location and tasked to build there).

I wanted to handle one more bug, a longstanding problem with terran addons, but I decided that the fix was too involved. This is enough for now. Next I’ll switch to prep for AIST.

expansions

Expansion timings changed for terran and protoss. There is a hard-coded list of timings to take bases. It bears little resemblance to good play, but I adjusted it to be less ridiculous (you may slightly lower the volume of your laughter). The new list, which is the same for terran and protoss in all matchups even though that’s silly, calls for a faster natural, slower later bases, and more total bases in the late game.

A bug caused terran and protoss to “expand to the main base” when contained, especially by cannons. A command center or nexus, or sometimes more than one, would be built in the main, where it stood for the rest of the game as a monument to the value of wasting resources. It happened often to terran, occasionally to protoss. I fixed one cause. I did not verify that there are no other causes....

• A bit of code requires terran and protoss to take the natural as the second base. I added an exception: If Steamhammer no longer owns its starting base, the constraint is released. This only happens in rare emergencies, but when it does happen, it could make a big difference.

BOSS

BOSS limited refinery buildings to 3, affecting terran and protoss (zerg does not use BOSS for its production). The result was that, if the game went on long, Steamhammer would take 6 bases and only 3 gas, and as the geysers ran dry it would become severely short of vespene and throttle back production, and struggle to win a won game. This game versus Iron is an example. The limit mostly affected protoss, since terran rarely plays well enough to get that far. I changed the limit from 3 to 6. It was a hardcoded constant in DFBB_BuildOrderSmartSearch::calculateSearchSettings(), so this was a one-character change that took me 10 minutes to find. It is as big a change as I am willing to make in BOSS, which is on the jettison list.

3 was probably adequate for UAlbertaBot back in the day. I hope the increase never causes the search to blow up; it was fine in my tests, but I’m not sure I understand the ramifications.

micro

Improved behavior for units that refuse to retreat. When a cluster of friendly units is predicted to lose a battle and ordered to retreat, there are a few special cases where units keep attacking anyway. One is broodlings; a broodling does not want to waste its brief life. A more important case is a dark templar when no DTs have yet been killed; the DT is probably undetected and in any case has been safe so far, so it does not benefit from retreating.

Formerly, the non-retreat was implemented by giving the non-retreating unit the order to attack move to its own location, so that it could find a nearby enemy and keep up the attack. That caused micro bobbles when the unit stopped what it was doing, thought about it for a moment, then possibly chose a new target, or possibly went into a long reverie. I changed it so that if the unit already had an order to attack a given enemy, it kept the order, and otherwise it was given a new order to attack move to the squad order location. As a result, an initial attack by dark templar is far more incisive than before—it is night and day, formerly the DTs might vibrate uselessly as their “attack where you are” orders kept switching to new locations every time they tried to advance. This is the most important fix in this Steamhammer update.

• I added an experimental change to the dark templar exception: A dark templar will also refuse to retreat whenever it believes itself undetected. It’s experimental because it will cause misbehavior when a non-retreating DT advances into detection range, and perhaps takes hits, before retreating again, and then repeats the behavior. I’m hoping it will be a net win.

terran

• Tanks no longer falsely believe that they can target undetected units. Oops.

• I refactored the tank micro code for clarity and efficiency. Instead of taking a negligible amount of cpu time, it takes a less than negligible amount.

• Terran is limited to 1 starport at most, by a special case check in the production manager. Pointy-haired BOSS enjoys ordering unnecessary production buildings. The change saves a little gas, but mostly saves room in the main base so that buildings are less likely to spill across the map. Limits for barracks and factories would have been more valuable but trickier.

protoss

• Limit gateways a little more flexibly. BOSS loves gateways above all other buildings and will not stop adding more. Formerly, Steamhammer artificially limited itself to 10 gateways, a workaround originally borrowed from Locutus. An improvement, but it built too many gateways, then grew its economy, then had too few. I changed it to allow up to 4 gateways per base with an upper limit of 12 gateways. In my tests it is usually better, never worse, and still crude and wrong. It should hold until I can fire BOSS.

Try to use all the gateways, at least in the “dragoons” opening group. This is the more important fix. If there are more gateways, request more production. Formerly, protoss would often use only 6 of its 10 gateways. No evil is more heinous.

• It turns out that a unit mix of dark templar and dragoons is gas-heavy and may leave minerals unused. Who knew? I added zealots to production in the “dark templar” opening group, again trying to use all gateways.

zerg

• The scourge limit wasn’t working as intended because I changed the wrong number. Fixed.

• I made a change in production that I hope will reduce cases where a creep colony is left unmorphed to a sunken. Later I’ll leave creeps deliberately unmorphed until they are needed, but I still want the current case to work.

next for Steamhammer

I’ll be making another release soon, to fix a few of the most irritating of the longstanding bugs that affect terran and protoss. After that I’ll prepare for AIST S4. I want to have fun implementing secret new skills, and I have thought of a suite of them. By AIST submission time, BASIL should have collected a moderate amount of opening data for me (as I write, it has collected a total of only 112 records, covering a small fraction of Steamhammer’s openings). I’ll be able to compare the wild BASIL data with my tame systematically-collected local data. What happens next depends on how that looks, but I may release another data collection version to fill in spots without enough data; that could harm elo, but it’s in a good cause.

This should be a productive year.

Next: Steamhammer’s experience fighting cannon rushes.

Steamhammer’s opening data

As promised, more on the opening timing data. Here’s the data I decided to collect. I hope I chose the most important data, because I expect that it will take a long time to collect a full set and I’d rather not have to redo it from scratch. I will have to update it over time as Steamhammer evolves, though.

I plan to play local games to systematically collect complete data, but that can’t be the only approach. Steamhammer needs real world experience with games against all kinds of opponents, so it can see the ways that its openings break down under stress. I think that will be key for playing well. That’s why I uploaded this data collection version of Steamhammer. I’ll see how it goes, but I may later upload a version that (heedless of its rank) chooses little-played openings to fill out the dataset.

By the way, this sounds like a lot of data when I describe it here. But it’s only a few lines of numbers. It’s not much.

• Opening timings: For each game, info about opening events, on Steamhammer’s side only. Ten numbers giving key info about the results of the build as of the time the opening line ends, plus the frame of completion of each tech building, each upgrade, and each tech researched. The completion times are recorded until 1500 frames after the end of the build, to give opening stuff time to finish and to see some events from the start of the middle game.

number of the first frame out of book
the number of workers alivehow strong is the economy?
mineral cost of all combat units producedhow strong is the army?
gas cost of all combat units produced
unspent mineralsdid the opening build use resources efficiently?
unspent gas
count of barracks, or gateways, or hatcheries/lairs/hiveswhat is the production capacity?
count of factories, or robo facilities, or 0 for zerg
count of starports, or stargates, or 0 for zerg
the number of bases, including incomplete bases

The 10 numbers outline the strategic state of the game at the end of the book line, and the completion times say what our tech is and when we got it. The idea is to save info about how the opening actually went, rather than how the book said it was supposed to go. Events will vary depending on the map, our reactions to the enemy strategy, the effects of fighting, random bobbles, and who knows what. My plan is to collect all the records for each opening (across all opponents), and reduce them to summaries for each matchup that show how the opening typically goes and the range of variation. The summaries can be stored in a static file read at initialization time. Add in win rates for each build and matchup, and Steamhammer will have a sound basis to choose openings against unfamiliar opponents. Choosing based on data will surely be better than choosing based on numbers I made up and typed into the config file.

Also keep data about enemy play, so that Steamhammer can choose openings based on data about the current opponent. This info is specific to the opponent, so it doesn’t need to be summarized into a separate file but lives on in the game records.

• Record the frame that each enemy unit type was first spotted, for the entire game. This summarizes a fair amount of the scouting info. It doesn’t tell how many production facilities of each type the enemy has when, but Steamhammer can’t scout that properly anyway. Info about proxies and contains is already kept in another field of the game records.

• Record the first two “significant” battles of the game. I modified the combat sim to save a count of the number of enemy units of each type for the largest battle that it has been asked to resolve so far. The first significant battle is one with at least 8 supply of enemy units. Since BWAPI doubles the supply, that means 4 marines, 2 zealots, or 8 zerglings, or the equivalent. Static defense takes 0 supply and is not counted, which may be a mistake. The second significant battle is one with at least 20 supply of enemy units. When we first notice a significant battle, we don’t record it right away, but wait 3 seconds to see if more enemy units appear. (3 seconds may be too low. Maybe 5 to 10 would be better.) Since the combat sim remembers the biggest battle, no information can be lost.

For each of the 2 battles, we keep the frame the battle started (saved by the combat simulator; it’s the actual frame, not 3 seconds delayed), and the distance of the center of the battle from our starting base in tiles, and the same distance from the enemy base (or -1 if the enemy base is not located). And we keep the count of unit types. Since these are very early battles, usually there are only 1 or 2 enemy unit types present. If the enemy is overrun without putting up much fight, then only one battle or no battle may be recorded.

The unit type timings tell is when we have to be ready for each enemy capability to come online, if the enemy repeats the same strategy. And the battles tell us something about how the enemy behaves, including whether the first fights were near our base or the enemy’s. To choose openings against a familiar opponent, we can check the timings of enemy play from the game records against the timings of our openings from the summary file for the matchup. If we can’t predict the enemy’s strategy, then we can check the range of play and hopefully find safe options. If we can predict, maybe we can find a direct counter.

Info about enemy timings is useful for reactions throughout the game, not only for choosing the opening. “XIMP’s carriers should be arriving around frame x, start the ranged attack upgrade in time to answer that.” And it can be used to automatically develop new opening lines to counter specific enemy builds. That feature is probably far in the future, but I’m looking forward to it.

In overview, the idea is to compare a model of our actual play against a model of the enemy’s actual play to figure out what is likely to work. That means understanding the game, at least for a limited value of “understanding”. It should be way more effective than trying stuff at random until you hit a winner.

Steamhammer 3.4 uploaded

Steamhammer 3.4 is uploaded. The previous version was uploaded only 6 days ago, so changes are few. Nothing here should have any big effect on playing strength. Most of the work went to opening data, but I also made some other tweaks, mostly affecting queens. I turned on the zerg strategy boss info display for stream watchers.

opening timing data

Steamhammer records in its files data useful for choosing openings, in a way similar to my original post. In later games it parses the saved data into a form that the rest of the program can use, but nothing uses the data yet. I have to collect enough first. I’ll post details later.

New skill “battles” added using the skill kit. It records summary info about the first 2 “significant” battles of the game, by its own definition.

New skill “opening timing” added using the skill kit. It records summary info about the results of the opening played.

• The “unit timings” skill, which records scouting data about the enemy, is updated slightly to mark enemy buildings whose completion time is known, because the building was seen under construction. Most buildings are scouted after completion, so it can only record the scouting time. Known times are negated; the minus sign is the flag.

scouting

• As I predicted, I have further relaxed the condition to release the scout worker early. The location of the enemy base need no longer be known. If the worker still sticks around at the front beyond when it will see anything new, I may loosen the condition one last time.

• An early game overlord—usually the second one—now scouts the main and natural, instead of only the main. Steamhammer should notice cannon contains and some proxies earlier, at least on average.

queens

• Steamhammer formerly limited its queen count until queen research was started, either ensnare or broodling. I was afraid that it might spawn a bunch of queens and then change its mind and have no use for them.

• I dropped the mechanism that used to leave a time gap (30 seconds) before remaking queens when all of them were destroyed. I decided that if it overmakes queens and needs to learn better, then I’d prefer a more general mechanism.

• Be more willing to get ensnare versus protoss.

• If terran doesn’t have any bases left, don’t make a queen in hopes of infesting a command center. It looked silly.

• Steamhammer is slower to research queen energy. I thought it was spending on that too often. It now insists on either having at least 4 queens, or having a target of at least 4 queens. I doubt it’s worth it even then. I’ve seen analyses which try to figure out the number of queens before it is economically worthwhile to buy +50 queen energy, and they came up with 8 to 12 as the minimum.

• The strategy boss debug display shows Steamhammer’s target queen counts for each purpose, parasite, ensnare, and broodling. If queens are desired, the line that used to say something like “0/1 queen” (zero queens made of a target of one queen) now says “0/1 queen (1 0 0)”, with the three numbers in parentheses. The overall target number of queens is the maximum of those three numbers. Steamhammer will try to research both ensnare and broodling if it wants queens for both purposes.

SSCAIT Steamhammer-PurpleWave games

Those who saw today’s stream of the second half of the SSCAIT round of 16 in the elimination bracket may be wondering why Steamhammer played the same losing opening three times in a row against PurpleWave. It’s easy to explain.

Before the tournament, PurpleWave was playing forge expand game after game against Steamhammer. Steamhammer experimented and found that it could win with 9 gas 9 pool, which is a strong ZvZ one-hatch mutalisk build. It is not a strong ZvP build, but before the tournament, the fast mutas scored 13-0 against the fast expands, not a single loss. PurpleWave was not ready to defend against air.

In the round robin phase, PurpleWave again opened the first game with forge expand, and lost to the one-hatch mutas. The score was 14-0. But PurpleWave had been updated for the tournament, and forgot whatever bug or other fixation had caused it to stick to the same strategy. In the second game, protoss varied, and the score went to 14-1. PurpleWave is ranked higher than Steamhammer and usually wins. 14-1 was statistically far and away the best available opening, so Steamhammer stuck with it. It saw during play that it had gotten into trouble and tried desperately to save itself, but the mischief came in the early opening and there was nothing for it; at best it could have lost more slowly.

An RPS analyzer that better predicts the enemy’s opening plan could have helped. Steamhammer would also have to pay more attention to the enemy’s predicted strategy; it deliberately ignores the prediction against long-familiar opponents. The only general way that I know for a bot to be sure that it’s time to switch plans is for it to model the game events and understand why it lost (“oh yeah, you can beat that every time”), which is much more powerful than comparing statistics. I hope to do that eventually, but it’s beyond the state of the art for now. Anyway, opening timing is first, and that feeds in too.

stealth bugs

Early on in Steamhammer’s history, one version introduced a bug that caused small delays in starting the construction of buildings. You couldn’t really tell by watching games unless you knew what to look for, but results were worse and it was clear that something was wrong. It was a stealth bug: The visible symptom was that play was worse, and the cause was hard to discern. I was only able to narrow it down and solve it by knowing what I had changed recently.

Another version had a problem with zergling micro that dragged down results for months. I did not see the cause. I had to watch a great many games to train my eyes to see that zerglings were not as effective as they had been earlier, to tell which fights were going the wrong way, and then I could finally ferret it out. Zerglings are numerous; I remember focusing on the actions of a few specific lings in a fight and being satisfied, but it was an illusion that didn’t hold up when I learned to better follow the movement of the whole fight.

Most recently the latency compensation issue that caused Steamhammer to try to re-use larvas was hard to notice. I noted that Steamhammer was opening with 11 hatchery strangely often, but it can do that so I didn’t smell a bug. And the BASIL ranking was a little disappointing, but that might be because of Monster and other improving opponents. It was only when I was writing a new opening and watching production closely that I saw the blip and could start tracing it. After the fix and its friends were uploaded, Steamhammer’s ranking quickly climbed back to the range I had originally expected.

How many stealth bugs have I never noticed? I have no shortage of known bugs and severe weaknesses on my to-do list, so in a way it doesn’t matter. And yet surely I could do better if I knew more.

What is a stealth bug to one person might be an obvious problem to another. A game has more going on than a mere human can absorb in one viewing, and people pay attention to different aspects. (Flash is presumably not a mere human.) I remember a lurker target-fixation bug that Steamhammer shared with Microwave. I thought the bug was noticeable, since I pay attention to lurker micro, while Microwave’s author MicroDK had not realized it was happening.

In the end I guess there’s no moral to the story, other than to test rigorously, vigorously, and variously, which is standard software advice anyway. Pay attention to performance regressions and dig up their roots. It can never hurt to run tournaments at home.

12 gas 11 pool build orders

I counted Steamhammer’s zerg openings, and found 222. Most of those I wrote as variations of standard builds, or when inspired to copy somebody else’s build ideas, or to systematically fill out a range of possibilities. A few are novel ideas that I had myself. Steamhammer’s new 12 gas 11 pool builds I have not seen elsewhere, though Steamhammer did already have a build named ZvZ_12Gas11Pool which is similar (it was an example of filling out a range of possibilities).

Why did I write over 200 opening builds? It’s obvious that Steamhammer can’t effectively use that many, because it doesn’t know how to choose between them without trying each one repeatedly. Against a difficult opponent, Steamhammer would have to play thousands of games to be likely to make the best choices, and even then it would risk being wrong—the opponent is learning too. I wrote them all anyway, because I have been planning from the beginning to make learning smarter. If the opening timing project works as well as I hope, the bot will be able to quickly zero in on promising builds from its large library, perhaps turning up surprising but effective tries. Compare my post Precomputing a catalog of build orders from April 2016, before I started work on Steamhammer.

11 gas 10 spawning pool is a standard zerg opening stem. It continues into fast one-hatchery mutalisks for ZvZ (implemented in Steamhammer in version 1.0 in January 2017 and for a long time Steamhammer’s favorite ZvZ build), or into one-hatchery lurkers for other matchups (mainly useful against terran). The timings have a good feeling, because when the spawning pool finishes, you can start your lair immediately and simultaneously start zerglings. You’re spending a lot to get fast tech, so the second hatchery comes much later.

go to 11 drones
extractor
spawning pool
2 more drones
when the pool finishes:
lair
3 pairs of zerglings
(continue with spire or lurkers)

I noticed that if you squeeze in a couple drones and drop one of the zergling pairs, you can get a second hatchery right after without delaying your tech. The only delay is in getting one extra drone before the extractor (you do have to wait a bit for the larva to spawn); after that, the build is every bit as smooth as the classic version. For the cost of that delay plus a lower number of zerglings, you get a stronger economy and a second hatchery, with a much wider selection of follow-up plans.

go to 12 drones
extractor
spawning pool
3 more drones
when the pool finishes:
lair
2 pairs of zerglings
hatchery
(continue with spire or lurkers)

The build shares ideas with 12 pool builds, where you use the high number of early drones to get a second hatchery, but gets the lair before the second hatch. It also shares ideas with 2.5 hatch muta builds, where you get your tech first and add the extra hatchery along the way. You could think of it is as a 1.5 hatchery lurker/muta build.

I prefer the lurker version. Steamhammer wins a lot of games versus terran with 1 hatch lurker builds, but it is not skilled at using its lings along with the fast lurkers. And many terrans stay safe at home anyway, so that lings have little value before lurkers; all they can do is keep an eye on the front line. Getting an extra hatchery and stronger economy seems like a good tradeoff.

Here are the timings of some of Steamhammer’s lurker builds. The lurker column is the number of lurkers made in the first wave, for an initial attack (Steamhammer’s lurkers always attack). The time given is the frame that the first lurker hatches from its egg, median of 3 runs.

buildsecond hatchlurkersframe
11 gas 10 pool lurkerafter lurkers3 then 1 more7405
12 gas 11 pool lurkerafter lair4 at once7551
12 pool lurkerbefore lair5, as gas allows7785
12 hatch lurkerbefore pool5 at once8513

Steamhammer 3.3.7 fixes crashing bug

Oops, yesterday’s upload included a crashing bug in the changes to base defense, ignoring proxy pylons when appropriate but not ignoring all the side effects of ignoring pylons. I’ve uploaded a new version 3.3.7 to fix the bug. Let’s see if there are any more... occasionally I have whole strings of new crashing bugs.

Steamhammer 3.3.6 uploaded

Steamhammer 3.3.6 is uploaded, along with matching Randomhammer. It is primarily a bug-fix release, and many of the bugs are noted here. It includes some work on opening timing, but nothing finished, so no writeup yet.

plan recognition

• I instrumented the code that incorrectly decided that Wuli was doing a “Fast rush”, and did not find a logic error. It behaved as designed. I tightened up the thresholds so that a rush has to be faster to be recognized as “fast”.

tactical analysis

Don’t assign defenders to destroy proxy pylons, or proxy supply depots, or proxy engineering bays, unless there are no other enemies to defend against. As an example, if there’s a pylon and a zealot, call in 4 zerglings to defeat the zealot, and ignore the pylon for the moment. (Formerly, Steamhammer called in 6 zerglings.) If there is a pylon and no other enemy, call in 1 zergling to destroy the pylon. This more frugal defense is also an important improvement to cannon rush defense: Steamhammer does not assign defenders to defeat the cannons, but relies on its anti-cannon sunken to hold them at bay, so that mobile units can instead go attack the enemy base. (Units made outside any cannon containment should have a clear path to the enemy, and another part of cannon rush defense is to build an outside base, diverting the scout drone if necessary.) This change means that Steamhammer also does not assign defenders to defeat the pylons powering the cannons, which was allowing the enemy base to survive too often. To be sure, blunders in unit movement count more.

• The base defense hysteresis is slightly increased, and the in-zone defense radius is increased significantly. This should ameliorate some chasing misbehaviors, such as when mutalisks seem to forget that vultures are in the base.

base->inOverlordDanger() added: Any overlords at a given base are at risk. Used in deciding where to spawn fresh overlords (see below).

base->inWorkerDanger() tightened up. The enemy must be 2 tiles closer before the workers are considered to be in danger. Workers have been panicking too early, losing too much mining time. More improvements are needed, but this simple tweak should help.

production

Bug of trying to morph the same larva twice is fixed. This is a big one. Steamhammer now does its own tracking of orders to morph, bypassing BWAPI. The fix brought a side effect bug of making it impossible to morph a lair into a hive, because the lair remembered its previous morph order from hatchery to lair and refused to repeat it to become a hive. I fixed that by clearing morph orders of buildings when they complete. (Morph orders of units change immediately after they complete, because units are given orders right away.)

Selecting which larva to morph is smarter. The routine had to be rewritten anyway to solve the morph-twice bug. Formerly, Steamhammer did an ad hoc analysis of the main hatchery of each base when deciding where to make drones, so it could make drones at a base which needed them, and otherwise preferred to spawn units at whatever hatchery had the most larvas (a hatchery with 3 larvas cannot spawn more, so you want to use those first). Now it follows a more general 2-step procedure. First, it decides what bases are best for the production, sorting them into priority order. Second, it scores every larva for nearness to a priority base, and for hatchery larva count. A larva that does not belong to any hatchery (because its hatchery was destroyed) gets a higher score (because it is not likely to live long), provided the enemy is not near. The enemy just destroyed the hatchery, they’ll hit any stray units too.

Base priority is implemented for drones and overlords. For drones, all base hatcheries are considered, not only the main hatchery, and a base that is under attack is avoided when possible. This is a small improvement over the former behavior, and will become more important when Steamhammer distributes hatcheries better, as I plan. For overlords, if the enemy has wraiths or corsairs or other overlord hunters and we have spores to defend, bases with a spore colony get priority. A base under active attack by anti-air units is avoided when possible. This is a substantial improvement and will save games.

micro

Drones do not burrow in reaction to cannons, or a nearby bunker or sunken colony. It was an oversight in the original implementation. The drones would burrow just out of range and remain burrowed unless and until the enemy static defense was destroyed, not a useful behavior.

• Fixed a bug causing double commanding of overlords.

• Fixed bugs causing double commanding of drones to burrow or unburrow. It’s not harmful, the commanding infrastructure swallows the extra safely, but I fixed it anyway. Though I didn’t entirely fix it, because I see double commanding to unburrow can still happen.

scouting

• In the last version I added a feature to release the scouting worker under tight conditions that ensured that the scout was only released if it was unlikely to be able to scout anything more. A drone stalled from getting into the enemy base by cannons would be released when zerglings arrived to keep watch, for example. I always expected that the conditions would turn out to be too tight, and I was right. I dropped the condition on the distance to the enemy base, so that (for example) a drone chased across the map by enemies could be released if zerglings showed up to save it. I will probably loosen the conditions further in the future.

zerg

Fix to ZvZ emergency spores due to an integer overflow bug.

• In an emergency, build sunken colonies or spore colonies even if the drone count is low. Keeping the last 5 drones alive is more important than making another drone because you only have 6.

Don’t break out of the opening versus cannons unless it is necessary to make a faster spawning pool (to make a sunk to hold the cannons at bay). This is a bug fix. It was always intended to work that way.

Place any anti-cannon sunken colony near the ramp to the main when possible. If the base has a corresponding main base (it is the natural of some main), then prefer sunken positions near the entrance to the main. This is another advance in cannon rush defense. It will be harder for the cannons to creep past the natural and into the main, as MadMixP and Juno both like to do, and it is generally good to defend the ramp anyway. Steamhammer’s cannon rush defense has grown complex, with many necessary skills that add resilience, and yet is still easy to overcome. I should post about that.

• Limit scourge production more tightly yet. I’ve improved this over and over, and it still makes trouble.

• Tune down the scourge priority for valuable targets, except for helpless guardians and cocoons. Scourge were too often trying to fly past the corsairs to reach the carriers, and not making it.

• Spawn all desired queens at once, instead of waiting to order them until resources are available. Rules are sorted so that more than 2 queens were almost never made, even when more were on order. This should make broodling more viable, but it’s mostly for fun.

openings

• I added new openings 12Gas11PoolLurker and 12Gas11PoolMuta. They’re more interesting than you probably guess, so I’ll post separately about them.

Steamhammer’s new bugs

From watching tournament games, I wrote down about 20 to-do items. A couple are ideas to try, but most are bugs, and 8 are critical bugs that I want to fix fast. I thought I had left Steamhammer in a more reliable state. :-(

Steamhammer lost its tournament record of no losses due to crippling bugs when it lost both games to Wuli. In both games, it misdiagnosed the protoss opening as “Fast rush” instead of “Heavy rush” and broke out of an opening that would have been strong, reacting as though it were facing a surprise 6 gate rather than 9-9 gates. You can’t survive a blunder like that against an aggressive opponent. I don’t see the error in the code, but I’ll work it until I find it.

Two winning games were even worse, against cannon bot Juno by Yuanheng Zhu. Steamhammer started out playing a build that had been 100% successful forever, then panicked and broke out of the opening when it saw the cannons. I think that somehow a bug got into the code that decides whether the current build is good for the situation and should not be interrupted. Having broken out of the opening, Steamhammer relied on the strategy boss, which made choices much inferior to the planned opening. In one of the 2 games it played well enough to eventually bust the cannons and win, but the other game, on Python, was plagued by further severe bugs. If you know Starcraft at all, this game will offend your sense of esthetics, and possibly your sense of ethics; it is so bad it is immoral. Steamhammer smuggled a drone to a hidden expansion, one of few successful actions in the game. It built the expansion after a long delay—there is probably another bug there—then sent nearly every drone made at the outside hatchery back to the main so that it died to the containing cannons—definitely a bug, and not one I’ve seen before. Steamhammer also burrowed drones that came near cannons, so that it eventually stopped mining (even gas mining) because every surviving drone was burrowed. And other bugs. So many bugs. :-( Zerg won the game on points because it mined less and because Juno had its own misbehavior, repeatedly building cannons in sunken range where they died instantly.

The rich player usually loses if the game times out, because the rich player made more stuff and it died. And you want to be the rich player. So win your winning games, don’t let them time out!

Steamhammer won its games versus XIMP by Tomas Vajda with its usual seeming ease, but there was a bug there too. This bug I’d seen before, but I only realized the cause in watching the tournament. Steamhammer had a partial production freeze, where it built nothing but scourge and zerglings for a period, losing ground compared to its regular production. The cause is that the reactive behavior of building scourge and the fallback behavior of adding zerglings when the situation allows were jointly blocking the regular behavior of refilling the production queue. Only special case units were being made, not regular units.

The bugs above are severe, but only affected a few games each. Together, they may have cost Steamhammer one rank in the tournament, if that much. I think the latency compensation bug is more severe, even though I can’t point to a game that Steamhammer definitely lost due to it. It affects far more games, and one of the effects is to drop one drone in 12 pool or 12 hatchery builds. Being one drone short of plan, starting early in the opening, is a serious handicap. It also sometimes drops planned zerglings or other units. Many openings have their timing disrupted, so that research is not accomplished or unit counts are reached late, causing further misplays.

I fixed the latency compensation bug yesterday. To do it I had to completely rewrite the routine that chooses which larva to morph into the next unit, so I took extra time and added features. Now it is more general: It is divided into one step that decides which bases are better locations for the next unit, and second step which tries to find a larva near one of those bases. The old version already knew that it’s better to make a drone at a base which needs more drones. I taught it in addition that if there are corsairs or wraiths flying about, and we have spores to defend, it’s better to make overlords at a base with a spore.

As mentioned here, I plan to release a bugfix version Steamhammer 3.3.6 first, then get back to work on my real project of 3.4. I’m often wrong in strength estimates, but even so, if I can fix the critical bugs I think 3.3.6 should be stronger by 50 elo points.