archive by month
Skip to content

Steamhammer-Dragon games

The latest SSCAIT weekly broadcast included a Steamhammer-Dragon game where Steamhammer went up to five hatcheries before it started its spawning pool, a crazy risky build that loses to any early attack. Dragon did not attack early and was hammered into the ground by huge macro. Sonko, narrating the game, rightly concluded that Steamhammer’s opening was the result of learning, though the opening timing idea he mentioned is still on my to-do list. Anyway, five hatches before pool is one of Steamhammer’s favorite builds versus Dragon, but it also plays others, and not always successfully. I thought I’d briefly list a few recent games to show how tricky it can be to choose openings. Even if you know the enemy’s timings, it is still tricky.

7 hatch 6 pool speed, a zergling rush that starts slower than the pool-first rushes but hits harder because of the two hatcheries and the zergling speed research. The opening leaves only 7 drones to power the two hatchery production, so it’s very much all-in. Dragon saw it coming and reacted with a bunker in its main, though for some reason it followed with an expansion CC which it lost without canceling. Even so, Dragon’s defense was better than Steamhammer’s attack, the all-in failed after vultures arrived, and Dragon was in a winning position. But (no doubt due to some bug) terran left only 1 SCV on gas and suffered a severe vespene shortage, and compensated by going mass vultures, not a strong backbone unit for a terran army. The game turned much more exciting than it should have been.

9 pool into 2 hatcheries, with early but not heavy pressure. Again Dragon made a bunker in main and defended easily. Steamhammer droned up well, keeping pace with the terran economy, but could not also make a strong army. Zerg ran into trouble.

5 hatch before pool, like the broadcast game, except this time Dragon got a vulture into the zerg base before defense was quite ready, then followed up with wraiths when defense was not even close to ready. Zerg struggled but finally stabilized, and the game was on. This is the most interesting of the games.

The first two games are fast rushes. One was all-in and the rush failed, but the opponent’s game plan was discomposed by an unforeseeable factor. The other was not all-in and looked successful at first, but did not actually keep up. Even if you recognize the enemy’s tech and attack timings, it’s tricky to choose an opening that exploits them successfully. Starcraft is complicated! The third game is a reminder that the enemy gets a vote, and can change up its timings, or can play its builds sloppily so that the timings vary. At a minimum, you have to take into account the range of timings.

broodling!

Today’s ASL 10 games were excellent. Every game was exciting. There were cool and unusual events, such as turrets placed solely for deception, and 3-base zerg versus 3-base zerg. Recommended.

Meanwhile, to fill the time as I make my second attempt to upgrade Steamhammer to BWAPI 4.4.0, here is another unusual game. The pictures show a queen killing an ultralisk with broodling, something I mentioned by name in the latest change list. See the queen’s energy level and the ultralisk remains. The game is weak on both sides, but as I forecast, Steamhammer was more ready than its opponent for the rare situation.

the queen is ready

scratch one ultralisk

The game was played over a week ago. If Crona is already updated to fix some of the mistakes here, that’s no surprise. Steamhammer has a related improvement.

a bug and its antimatter twin

Steamhammer has a special case reaction in the building manager to ensure that it builds enough macro hatcheries when it is contained: If a drone sent to build an expansion hatchery did not make it there, and zerg suffers from a larva shortage, then the expansion is converted to a macro hatchery instead. A drone is assigned to build the hatchery in base.

The feature seems to have bit-decayed and it is not working reliably. I’ve seen a few games where Steamhammer was contained and desperately kept sending drones to try to expand, while it had a larva shortage and its mineral bank was building up.

At the same time I see the diametrically opposite bug in Steamhammer’s terran play: When terran is contained for a long time, it starts to build “macro command centers” inside its base, which essentially act as oversize 400 mineral supply depots. It doesn’t know how to lift them off and land them elsewhere, and it doesn’t need more SCV production, so it’s pure loss.

What the what?!?

Logically, the bugs must be unrelated. The zerg special case explicitly checks that the building is a zerg hatchery. But it behaves exactly as though it had the races mixed up. If the two bugs annihilated like matter and antimatter, they would create energetic play.

Both bugs are on my list to solve soon. The terran bug is as serious as the zerg one in terms of wasted resources.

learning for tournaments

Most learning bots use a multi-armed bandit algorithm to choose opening builds, such as a UCB variant or an epsilon-greedy algorithm. The algorithms trade off exploration—trying stuff out to find what’s good—versus exploitation—getting wins using the good stuff that it found. If you’re playing on a ladder that always runs, you want an algorithm tuned to keep on exploring. Unless the algorithm hits on a build that wins every game, it will always find some value in occasionally trying another idea that might turn out to be better than what you’ve found so far.

If you’re playing a tournament, it’s different. The tournament will end, and if you’re near the end of the tournament then it won’t help to explore, because if you do find a better strategy you won’t have time to play it and earn wins. The cost of exploring starts to exceed the benefit. In the very last game of the tournament, if you know that it’s the last, the benefit of exploring is exactly zero and you should always play your best idea so far.

It’s an idea I thought of for AIIDE this year, but ended up not implementing in Steamhammer. I don’t know how long the tournament will be, but I can guess that it will probably not be much longer or shorter than last year, which was 100 rounds—100 games against each opponent. I could add a configuration parameter for the expected number of games, and reduce the rate of exploration slowly so that it reaches zero around then.

I may yet do it, it is likely a good idea. Bandit algorithms generally assume that the environment—the opponent—is steady over time, or becomes steady given enough time. Assuming an unchanging opponent, reducing exploration when exploration cannot help is always a gain. In reality the opponent may itself learn, so that bot + opponent form a hard-to-predict dynamic system. Reducing exploration against a learning opponent might make you more predictable so that the opponent’s exploitation works better. But the opponent will have to explore a little to do that exploiting, so... my guess is that the idea is still likely to help.

Does any bot use this technique of reducing exploration as the tournament continues? Do you have data showing how well it works?

Steamhammer’s prepared learning data for AIIDE 2020

What is the best way to prepare initial learning files for a tournament when you have partial knowledge of how your opponents will play? How should you seed your opponent model? Certainly it depends on your learning algorithm. I did not find the answer, but I poked at it and took my best guess for Steamhammer.

I tried an informal experiment on the Starcraft AI Ladder. The ladder is reset to zero once a week—it erases the game records, everybody’s learned data, everything, and makes a fresh start. One week I collected recent full-length data files and set those as Steamhammer’s prepared learning data for use after the weekly reset. (Because of how Steamhammer uses its prepared learning data, the files were not read at all until the reset.) The opponent is reset too, and may not play the same way that the old learning files expect, so it’s not guaranteed that the old learning files are the best seed for new learning. Still, I expected them to provide an advantage over starting from scratch. It makes intuitive sense that if the opponent is relatively constant, such as an opponent carried over in the tournament from a previous year, then keeping your learning files is good. But there may be cases where it’s not true, because both sides learn.

I was interested in whether the carried-over learning data would be helpful from the start, or would have trouble until it adjusted to the opponent’s reset. I let the ladder run overnight and collected data then. The carried-over data did seem to work well, certainly better than the missing or unmaintained initial data I had been using up to then.

The next week I tried an alternative, preparing minimal initial data. Steamhammer’s learning varies its approach depending on how much data is available, so I expect a difference between full-size and minimal prepared data. I looked through my records of previous weeks—not only one previous week—and selected by hand a small number of sample game records using varied openings that had scored well, never more than 4 games. This is the kind of preparation that makes intuitive sense if you have data on an opponent but you expect that the bot has enjoyed a major update—you want to be ready to exploit known weaknesses, but also to be ready to switch in case the weaknesses are gone. Again I set things up and grabbed the data the next morning. And the minimal data performed better. No opponent had worse numbers.

It was not in any sense a well-controlled experiment. Two weeks of data with the ladder’s small number of opponents is not enough to draw a statistically valid conclusion. Both Steamhammer and other bots were updated during the week between experiments, so the result is more than questionable, not solid but vapor. It’s entirely possible that Steamhammer performed better because I had made an important improvement during the week, and I know that I made improvements. Nevertheless this was the data I had, and I decided that it was more likely to be right than wrong. To my eye, Steamhammer’s performance curve over time looked more convincing with the minimal prepared data—not a scientific conclusion.

So in my AIIDE 2020 submission, I went with minimal prepared learning data. I selected the sample games with more care than in my experiment, trying to take everything into account. I could not prepare for the unknown bots, but I did invent one fictional game for EggBot so that Steamhammer will know it is a cannon bot. I did not prepare for Stardust because nothing has yet worked twice against Stardust. I also didn’t prepare against DaQin because I didn’t have recent data handy; I could have tried harder, but time was short.

We’ll see how it goes!

Surely the best preparation can’t be found by a fixed rule, but depends on the opponent and on what you know about it. And by nature it depends on your bot’s learning algorithm. It’s a question worth thought.

Steamhammer AIIDE 2020 version change list

Steamhammer 3.2.19 (you did memorize the version number as I required, yes?) is uploaded to SSCAIT. Randomhammer too, since a few quick games did not turn up any new bugs in terran or protoss, untested while I worked on zerg. I worked on basic skills (saving my tricks for later), smoothing some of Steamhammer’s long-standing jagged edges, and the bot is appreciably stronger. I’m excited to see how Newfangled Steamhammer copes with the great variety of opponents on SSCAIT and BASIL. Will the anti-cannon procedures work against Krasi0P? I didn’t test it, that opponent is not in the tournament. This Steamhammer has a lot of new fangling, there is sure to be some surprising interplay with other bots.

The SSCAIT upload is the same code and configuration as the AIIDE version. Since the configuration is the same, none of the debug display options is turned on (don’t want that for a tournament), so there’s no interesting drawing on the screen. However, the learning files that I prepared for AIIDE are not carried over to SSCAIT; I’m leaving the existing learning files in place. From experience, I expect that Steamhammer will perform worse on SSCAIT and BASIL for some weeks until the opening learning adjusts to the new behaviors—and to the opponents’ changed reactions to the changed behaviors.

I divide up the changes by the aspect of Steamhammer they affect, as usual. It may be a mistake, because it conceals how teams of changes are coordinated to meet goals. There are teams of changes which work together to help Steamhammer survive cheese, and teams which work together to reduce wasted units during the midgame. The different changes in each team are in different parts of the code, and I write each one up separately, but the important thing is that each team pulls its oars in synchrony.

Today’s list bundles together all the changes I made in versions 3.2 through 3.2.19 (20 versions in all). The test versions had short lifetimes, some of them a day or less. As usual, the more important items are in bold.

Whew, I needed the extra day to have any hope of writing up this, er, nearly endless list by today. I started it on Tuesday, worked on it all day yesterday, and didn’t finish until now.

safe movement

Micro::MoveSafely() is a drop-in alternative to Micro::Move() for use by units which prefer to never come under enemy fire. It follows the simple method of running away from the nearest dangerous enemy, gaining 80% of the benefit of optimized hazard avoidance with 20% of the effort. If you know what to look for it’s easy to see cases where it makes a worse decision than potential fields would, but you have to look.

Overlords use MoveSafely(), except for squad detector overlords which already have their own way to avoid danger. Formerly, one of Steamhammer’s great weaknesses was that it would generously donate overlords to the enemy cause. Sometimes it would try to transfer an overlord to a distant base when an enemy army happened to be on the path, fail, try again.... In the worst cases, overlords would appear to converge from all sides on a group of marines or dragoons as if they were flying ultralisks closing a surround. That is all gone. Overlords are lost at a reasonable rate and live longer, more fruitful lives.

Workers also move safely using some of the same code, though the implementation is more involved than MoveSafely() because of the special needs of workers. Micro has a suite of helper functions. There is one exception: When moving to construct a building, just go there. The scout worker does rely on MoveSafely(), and it has become more adept at surviving to see what is going on. Overall, it’s a clear benefit. When zealots raid, the workers scatter and have to be chased down, at worst causing delay to the enemy and at best surviving to return to mining.

If burrow is researched, workers burrow to avoid danger instead of running away, unless an enemy detector is seen to be in range. This behavior is a delight to watch. Zealots raid, or a reaver lands—and the enemy sees nothing but puffs of dust as the workers disappear under the ground. After the attack is cleared, the workers pop up and instantly return to work. Steamhammer still loves to transfer workers across the middle of the map where the enemy is roaming, but now the workers realize the risk and burrow for safety. The enemy may like to scan when it sees units burrow (Steamhammer terran does that), or may have an observer which was out of range when the workers burrowed but can be brought over, so it’s not entirely safe, but it’s a breakthrough compared to the former behavior of running willy-nilly into the grinder. Also if the enemy moves away a bit the workers may unburrow, try to continue, come too close again and reburrow—which is funny if nothing else.

Overall, safe movement is a huge gain. There is room to make it far better yet, but that will take incremental refinement over time. There are disadvantages in certain situations. For example, when there is only one base and it is raided, then the workers flee or burrow and there is no mining whatsoever to fuel production and defeat the attack. It might have been better to keep mining and accept the loss of workers. Terran could do something like send 1 wraith to each mineral line and stop all mining, and in fact I have seen Steamhammer lose in similar ways.

scouting and overlord assignments

Every overlord is assigned a location to move to and stay at. These parts are unchanged: One overlord is under the control of the scout manager early in the game. Some overlords are assigned to squads to serve as detectors and provide vision. The remaining overlords belong to the Overlord squad. What is different is that the Overlord squad assigns a location to every overlord it controls. Formerly, the Overlord squad assigned locations to some overlords and left the remainder floating wherever they happened to be, which might be in the middle of the map. It was not efficient scouting, and it was not safe for the overlords (but it was easy and I got it done).

The Overlord squad has gained a general assignment system similar to (but simpler than) what I plan for the deferred Scout Boss. It lists useful overlord destinations in priority order, then assigns the closest available overlord to each destination in order. If there are leftover overlords, as there generally are by the middle of the game, the remainder are sent to the front line of the front base (both “front” ideas are detailed in sections below)—basically, they wait together in a clump near where the enemy is likely to try to attack. It’s a reasonable try because the overlords use MoveSafely() to flee dangers.

• Early in the game, one overlord is assigned to survey the main base for hidden proxies. It uses the new function MapGrid::getLeastExploredNear() to repeatedly find what place inside the starting base has least recently been seen, and goes there. The result is that the overlord flies an irregular, adaptive, hard-to-predict and fairly efficient search pattern (and it takes literally 2 lines of code inside the Overlord squad thanks to the infrastructure). I was inspired to add this by a game versus Ecgberht where the terran built a hidden proxy factory in a far corner of the zerg base, a strategy that has earned it a lot of wins over Steamhammer. Typically Steamhammer has no idea that vultures are appearing in its base because of a proxy and fails to defend effectively, but in this game an overlord accidentally scouted the factory and Steamhammer crushed the proxy brutally. It was a short step to scout on purpose.

• If the enemy has no mobile anti-air units (somewhat uncommon), then an overlord is assigned to watch the enemy natural. Further overlords are assigned to guard our bases against cloaked units, just as formerly. If the enemy has transport and does not have flying overlord hunters, the main base scouting pattern restarts to watch for drops. If the enemy still does not have mobile anti-air units (rare by the point there are enough overlords for it, but possible versus Stone, versus a persistent zealot rush, versus a zerg going zerglings, or very late in the game after the enemy’s army is wiped out) then overlords are assigned to watch every base on the map. As always, if there are flying overlord hunters then overlords congregate at spore colonies instead. There is a lot of room to make strides in overlord deployment; future Steamhammer versions will do things like find overlord perches where they can watch without being seen.

• The scout manager also controls its overlord somewhat differently. If an enemy turret, cannon, or spore colony appears in range of the overlord (generally when it is in the enemy base), then the overlord is immediately released from scouting duty. It is reassigned either to a combat squad or to the Overlord squad, and in either case attempts to safely make its way to a new destination. (I wanted to have it cruise around the edge of the enemy base to keep scouting, but it was too much for now.) Releasing the overlord loses scouting information, but losing the first overlord this early in the game is a severe setback and it was happening too often, so I think it’s the correct trade. If the overlord remains safe in the enemy base, however, it no longer sits still over the enemy resource depot but instead scouts the enemy base in a * pattern: It goes to the depot, then calls MapGrid::getLeastExploredNear() to find another place in the enemy base that it needs to look at, then returns to the depot, etc. That way it regularly revisits the most important spot, but also pokes into the corners of the enemy base so that it sees more.

• Squad overlords, or properly squad detectors since science vessels and observers are handled the same way, are also controlled slightly differently. The flying squad detectors have long had abilities to avoid dangers and seek out cloaked enemies, and they could try to protect themselves from air attackers by seeking friendly units that can shoot air. Now, rounding out their skills, they also try to protect themselves from ground attackers by seeking friendly units that can shoot ground. We’ll see how well it works!

building construction

Critical bug fix: It was possible for the building manager to accept a worker for a construction job while the worker manager believed that the worker was still available for other tasks. Ouchies. The worker was alternately given conflicting commands and achieved nothing. The building it was supposed to construct was hugely delayed or canceled, a game-risking error.

• When choosing a hatchery to morph into a lair, if possible choose a hatchery that is away from enemy units. For example, if there is a scout circling the main, start the lair in the natural where it won’t be seen right away. I wanted this to be a first step in denying and delaying information to the enemy. I wanted to also place other tech buildings out of enemy view when possible and safe (they’re constructed rather than morphed so it takes different code), but I didn’t have time. I did add UnitUtil::IsTechBuildingType() so that Steamhammer can distinguish tech buildings from other buildings (to also eventually be used in prioritizing buildings to destroy in an enemy base).

• Bug fix: When a worker was handed over to production manager or building manager to construct a building, for 1 frame it would be given 2 inconsistent commands, one from worker manager before the reassignment and one from the production manager (to move into position) or building manager (to start construction) after reassignment. I solved it by the simple expedient of running the production manager and building manager before the worker manager, being careful to comment the change so it is not later undone by mistake. The result is that the worker is able to follow its movement or construction command one frame earlier, so the building starts sooner by one Planck time.

• The production manager replaced a worker requisitioned for construction if the worker was locked down, stasised, or maelstrommed before it could be handed off to the building manager. Now that workers often burrow for safety, it also replaces a worker which it finds to be burrowed. The building manager by oversight did not replace a worker which was rendered unable to build (only a worker that was killed). The oversight is fixed; now the building manager also recognizes lockdown and the others. Buildings should construct more reliably in the face of enemy interference.

• The worker manager’s setBuildWorker() no longer takes an unused building type argument. I should have gotten rid of that long ago.

plan recognizer

The plan recognizer work focuses on detecting early shenanigans by the opponent so that Steamhammer can react in time this game, or failing that, choose a safer opening next game.

Recognize an enemy Contain opening plan distinct from the Proxy plan. The details of what counts as Proxy are changed accordingly. The general idea is that a proxy requires an immediate forceful reaction, while a contain should be dealt with more deliberately. This means that the configuration file can include Counter Contain openings which are different from the Counter Proxy openings (see the new openings below). Zerg also reacts somewhat differently in the two cases (see the zerg section).

• The code to recognize a proxy is moved from Bases to OpponentPlan where it belongs, and combined with the code to recognize a contain.

• There was a crashing bug in recognizing a proxy on a map where our starting base had no natural base. Every starting location on every competitive map has a natural, so the bug never occurred. But it’s fixed.

• Do not recognize a gas steal as a proxy. Oops.

• A nearby enemy forge implies that cannons are coming; there is no other reason to build a forge in or near the enemy base. (Well, theoretically it could be part of a wall, but what the wall be for? MadMixP and Steamhammer itself as protoss both do proxy forge into cannons sometimes.) Recognize a proxy forge as a Contain plan. This is not always strictly correct; sometimes the predicted cannons would be better recognized as Proxy. But good enough.

Enemy Fast rush and Worker rush plans are recognized more accurately by using building completion times (see when will that enemy building complete?) and unit travel times (by shortest-distance ground paths—I did mention that Steamhammer has all the parts for pathfinding except actually following paths) to better constrain the true timing of events. I always meant to do this, and now I’ve gotten around to it. The work includes tuning the time limits (“earlier than this is a rush”) based on timing the slowest builds that I want to count as fast rushes, versus the fastest builds that I don’t want to count.

• There was a potential crashing bug in recognizing a rush. I don’t think it ever happened, and now the bug is fixed so it won’t.

Explicitly recognize terran BBS as Fast rush. It was a loophole. Steamhammer might fly its first overlord directly over 2 center barracks... and fail to react, and lose. That won’t happen any more.

Recognize a new Wraith opening plan so that Steamhammer is less often caught off guard by 2-port wraith openings. This gives a chance to react earlier to incoming wraiths and lets you configure Counter Wraith openings. Steamhammer is not reliable at recognizing wraith openings before the wraiths show up, though, because its scouting and plan inference are not good enough. I wanted to improve that, but ran out of time. Steamhammer’s anti-factory hydra-first openings are intended to protect against wraith attack but are not successful in practice because AI-controlled wraiths outmicro the hydras, which don’t have either speed or range yet. A hydralisk needs its range upgrade to equal the weapon range of a wraith.

bases

Always unreserve tiles of a base we failed to take. Formerly, sometimes the base would remain reserved and could never be taken. On the one hand, that was a severe weakness. On the other hand, it created adaptivity in choosing the next base to take; repeatedly failing to take the same base over and over is not a winning plan.

Avoid taking a base where enemy units are thought to be. This is a cheap way to add back some of the adaptivity lost by the previous change. Steamhammer does nevertheless sometimes show perseveration in failing to take a base. The next step, for a future version, is to check the path a worker will take to reach the base, and only accept paths that seem safe.

The “front line” position of each base is smarter. The front line is where static defense is positioned when Steamhammer wants to defend the approaches to the base. (It may also place static defense directly next to the resource depot if it wants to defend the mineral line specifically. It depends on the goal.) The front line is now on the shortest outside ground path toward the base, which I figure is the path an enemy bot is most likely to send its attackers along. Compared to the previous calculation, the new front is much better on some maps (like Benzene and Roadkill) and slightly worse on others (like the top base of Destination, though not the bottom base). It’s a net gain.

A zerg base doesn’t become the “front base” until it completes, because zerg needs creep to build. The front base is where the main approach static defense goes; it is the natural base if the natural is taken. Formerly, Steamhammer might place defenses in the main because there was a hatchery morphing in the natural and the main was where it was able to build—yeesh. For terran and protoss, the natural need only be started.

Don’t try to take an enemy base as a hidden base. If the enemy has not been found yet, and we need to choose an expansion as a hidden base, do not choose any main or natural base (unless that’s all there is), because it might be the enemy’s and that would suck. This is critical if the enemy is following a Contain plan, because then we will try to take a hidden base early without scouting.

• Make a stronger attempt to expand toward the edges, leaving central bases for later. The code proudly flaunts it as a big change, but it is not particularly successful; Steamhammer still likes bases in the open middle on maps like Aztec and Fortress. I probably have to bite the bullet and do the tactical analysis of the ease of approach and the width of the attacking front to figure out how vulnerable a base is.

• Fixed: The global pointer “what is my natural?” and the local pointers “what is the natural of this main base?” might be inconsistent. I don’t know what the effects of that were, but it couldn’t be anything good. As part of correcting it, I simplified and improved the calculation of natural bases. Also, each Base object (each base on the map) now includes a backpointer to its main base if it is the natural of some main (or null if not). It makes some calculations easier.

• Fixed: There was a crashing bug that affected maps on which every base which had minerals was a starting base. That’s very rare, but Crystallis is an example. Though I doubt any bot can play a reasonable game on Crystallis....

squads

Don’t assign base defenders against nearby cannons. This is part of the system to defeat cannon rushes: Combat units should go destroy the enemy base instead, which some of them should be able to do if a zerg hidden base was created as planned. The system doesn’t work perfectly, and sometimes Steamhammer wants to attack the proxy anyway because defenders are still assigned to attack the proxy pylons and any other buildings that may be part of the proxy. But most of the time it works well for a cheap hack.

• The hysteresis in distance for unassigning base defenders is increased. The main visible effect is that an enemy scouting worker has to run farther away before the single zergling assigned to catch it gives up and heads away.

• The Watch squad no longer assigns overlords to watch bases to catch enemy activity. The Overlord squad is responsible for that now; see above.

• I tried adjusting the regroup position (aka retreat point) of Steamhammer units that retreat toward static defense. It didn’t really help.

other infrastructure

• The movement routines in the Micro module check their arguments and drop movement commands for illegal destinations outside the map bounds. After an arduous campaign, I have finally fixed all the diverse callers so that they do not issue those commands in the first place. In long tests, the error checks were never triggered.

InformationManager::getUnitInfo() fetches the UnitInfo for a single unit (recording where and when an enemy was last seen, among other data). I never needed it before; in the past, Steamhammer only wanted to iterate through all unit info records.

• Due to an error in interpreting the configuration file, AbsoluteMaxWorkers always had its default value of 75, ignoring what the config file said. Fixed.

• The code for UnitUtil::GetUncompletedUnitCount() is simplified. Now it simply subtracts the already-computed completed unit count from the already-computed total unit count.

other worker behaviors

When a worker is posted to a location, it remembers not only its macro location as it used to, but its actual map location, and stays there. This is part of the system for taking hidden bases: When you go post worker @ hidden the “hidden” location differs depending on where the enemy base is. When we take a hidden base to counter a Contain plan, we may post the worker before the enemy base is found. If we find the enemy base before starting the hidden hatchery, the map location corresponding to the macro location changes, and at first the drone would waste time and take unnecessary risk moving across the map. Now the worker stays put at the original map location and the hidden base is taken safely and on time.

• When a worker is posted to a location using go post worker @ it first returns any minerals or gas it was carrying. A tiny mining efficiency tweak.

• Steamhammer can mine out blocking mineral patches with non-zero mineral amounts. Not many maps have those, but it was a two-line change that makes more maps playable. The code to mine out the more common zero-amount blocking mineral patches, as seen on Destination and Heartbreak Ridge, has been in there for a while. (There is still no code to break down blocking buildings as on Benzene.)

ranged unit kiting

In my mind this is one change with several parts to the code, but the effects vary depending on the ranged unit. For one thing, air units and ground units kite differently because ground units have to worry about terrain or other units getting in the way. For another, Steamhammer kites what it calls “AlwaysKite” units (not a good name since they don’t in fact always kite) with different code than others. The AlwaysKite unit types are set by Micro::AlwaysKite() and are vultures, wraiths, and mutalisks—fast units with instant acceleration—plus guardians. (By the way, the rate of change of acceleration is called “jerk” so instant acceleration means infinite jerk: those units are infinite jerks.) The AlwaysKite units use “muta dance” kiting code which pays closer attention to timing and latency than the regular kiting code, so that kiting is more precise and takes advantage of the instant acceleration.

• A suite of new routines appeared in the Micro module, for use both in kiting handled inside Micro and by other unit control code as needed. For kiting, the key ones are kiteBack() for kiting regular units, and the more generic fleeEnemy() used for AlwaysKite units.

kiteBack() for regular units considers alternate kiting destinations if the first try doesn’t pan out, according to checks I list below. The effect is that if a unit cannot or should not kite directly backward, it may go diagonally backward or sideways. A unit that is unable to kite away will realize it and keep shooting in place.

• Regular units, air or ground, don’t kite into enemy static defense range. If they’re already in range, they don’t kite deeper into enemy static defense range—the check counts the number of attacks on a prospective kiting destination and rejects it if the prospective count is higher than the current count. It’s relatively rare to fail this check; units are not often backed up against enemy static defense.

• Regular ground units do not kite into terrain.

• Regular ground units do not kite into a tile occupied by any other ground unit, whether a mobile unit or a building. The check is conservative: You might be able to squeeze in there if it fails, but if it succeeds you can definitely go there.

For zerg, the changes primarily affect hydralisks. Hydras used to kite into terrain or into each other as an everyday matter, with the result that they would turn away from the enemy, fail to move because they were blocked, fail to shoot because they were trying to move, and generally be useless and die in vain. To me it was a raging unmissable micro blunder that left hydralisk potential bleeding on the ground. Sideways kiting helps hydras keep moving and spread out so that more of them can fire. Hydras still often get backed up to where they can’t kite, but now they know that they can’t kite and they keep shooting. Hydras do more firing and less dying in battles of every scale, for battles in which kiting happens (Steamhammer units kite only when they expect a benefit). To me it is particularly obvious in small-scale hydra versus zealot fights, which are visibly more efficient.

• The AlwaysKite units don’t do the above checks, but call fleeEnemy() which unconditionally moves away, making sure only that it stays within the map bounds. Slightly complicated unimportant details follow. The muta dance code inherited from UAlbertaBot figures where to kite back to using a function called GetKiteVector() which starts with a point to move away from and calculates the destination by trigonometry. It returns an offset from the kiting unit; add the offset to the kiting unit’s position to get the destination. At some point I apparently mistook the offset for an absolute position and clipped the offset to the map bounds, a teeny-tiny gargantuan boo-boo (the effects on kiting were not severe in practice). More recently, Steamhammer added a function DistanceAndDirection() which, though I didn’t notice it at the time, does the same calculation by the mathematically equivalent method of normalizing the offset vector to length 1 then multiplying it by a scalar. Though it doesn’t make a practical difference in games, the vector math runs much faster than the trig functions, so here is an example of the optimization technique of strength reduction. In working on kiting I noticed the overlap. After undoing the mistaken clipping, I verified by test that the two routines returned identical results to the pixel. Following the motto that strength reduction makes you stronger, I removed GetKiteVector() in favor of fleeEnemy() with the same behavior and less code. By the way, it could be that kiteBack() would be more effective, especially for vultures. It does support air units. I didn’t try it yet.

zerg

Place a sunken to stop a cannon push. If photon cannons are dangerously near one of our bases, place exactly one sunken to prevent them from creeping closer; set it as close as possible outside the range of already completed cannons. This stops most approaching cannon pushes in their tracks. It may be possible for the cannons to circle around outside the sunken’s range and push in regardless, but I’ve only seen that once. The calculation of the cannon’s range is not exact, and on rare occasions the sunken is placed too close, which leads to suicidal placing of the same sunken over and over.

Place a sunken to combat a bunker attempt. If the enemy has built a bunker near a base of ours, try to set a sunken where it can hit the bunker and the bunker cannot hit it. Again, the calculation is not exact and occasionally the sunken is too close (it’s usually good, and I’ve never seen it too far to hit). Also, by the time the sunken is up generally the terran has marines on site, and with good play the marines may kill the drone, or may kill the sunken before it can finish. It won’t just happen; terran has to play well, and zerg should smash clumsy bunker attempts. If the sunken does finish, the bunker play will normally fail and terran will be behind; even if terran kills the natural hatchery, zerg will be comfortably ahead because of the cost of the early barracks plus bunker. (Seriously! I’ve seen it repeatedly versus Halo by Hao Pan.) I concluded that the old school sunken is Steamhammer’s best defense for now, though it’s not the best possible defense. The modern standard way to defeat an early offensive bunker is to pull drones to prevent the bunker from finishing, or prevent marines from getting in. Steamhammer doesn’t have the micro skills yet.

• When placing its one-sunken-per-base to defend against raids by vultures or dark templar, Steamhammer normally places the sunken next to the hatchery to defend the mineral line. In a change, if the base is the natural of some main base, it places the sunken at the front line position instead. That way the sunken provides some protection to both the natural and the main behind it, and if later sunkens are placed then they will also be at the front line and reinforce each other.

Hide a drone on the map versus Contain or Proxy plans by the enemy, and when it is next time to make a hatchery, let it be a hatchery at a hidden base. This is a reaction to a recognized plan: The openings for Counter Contain make a hidden base while the openings for Counter Proxy do not, but the reactions to both call for a hidden base. If there is a scout drone out at the time, then it abandons its scouting mission and hides on the map; otherwise a fresh drone is sent out (which is riskier because it may be caught by, say, containing cannons). Versus Contain, Steamhammer continues its planned opening; versus Proxy it breaks out of the opening unless an early pool is already queued, so that it can react decisively. There remains a weakness versus early bunkers: If Steamhammer scouts the barracks first, it may recognize the plan as a fast rush, in which case it will not update the recognized plan after the bunker starts, and will react differently than intended.

Scourge no longer attack floating buildings. This is a fix for a regression. Wasting gas to set a floating ebay afire is an effective way to suffer.

• If an enemy Wraith plan is recognized, make an evolution chamber right away. Before the Wraith plan was added, Steamhammer waited until it actually saw a wraith. Now it at least has a chance to react in time to 2-port wraiths.

• Unit mix adjustments: If the enemy cannoned us in, favor hydras much more. Vultures more strongly contraindicate zerglings. Versus protoss, favor mutas more; Steamhammer was barely making any after the opening, sometimes building a spire and never using it. Protoss air units more strongly discourage guardians; it was too common to see the guardians countered by corsairs.

• Unit mix in the cleanup phase of the game: If all enemy buildings are unreachable by ground, prefer air units. This could mean the enemy has an island base, or it dropped buildings on a plateau, or its buildings are floating over water. This rule doesn’t outright require air units, because the enemy may still have an army in play.

• Be slightly slower in some cases to take the second gas. It’s a tiny step.

• A regression prevented Spawn Broodlings from being researched, so the skill was never used. Fixed. Tanks or high templar may find themselves abruptly dead.

• In a rare ZvZ where the enemy has lurkers or ultralisks, be quicker with broodling research and prefer a higher number of queens. Queens versus ultralisks = advantage queens. It’s fun to be ready with a correct reaction to a rare situation. Steamhammer has played some successful and entertaining games by being more ready than its opponents for unusual events like hive-tech ZvZ.

• If the enemy is attacking on the ground and you happen to have extra minerals and larvas on hand, then maybe, just maybe, you should make zerglings instead of drones. In fact, I insist on it. You probably didn’t scout the full size of the enemy army. Make zerglings, dammit!

• If we’re in the opening and we have reacted to the enemy’s build by adding more drones than planned, and we’re nevertheless in a situation where there is a mineral shortage and a gas excess, then do not spend one of the extra drones to make an extra extractor. That normal Steamhammer reaction does not make sense in context. This improvement may prevent only a few mistakes over the course of the tournament, but some mistakes are too ridiculous and have to be prevented.

• Steamhammer zerg normally breaks out of its opening if it faces a fast rush that the chosen opening does not already counter. Steamhammer now considers that its 7- and 8-drone dawn hydra rushes counter an enemy fast rush. The change has saved games in test versions.

• If there aren’t “enough” drones, then when adding static defense Steamhammer zerg replaces each drone as it is used up. It’s necessary to prevent emergency defenses from wiping out the economy. I decreased the limit of “enough drones” so that Steamhammer can bring up defenses faster in some midgame situations.

• When looking around a base to see whether it is adequately defended by sunkens, the radius is decreased for considering a sunken as defending the base. It’s a tweak.

• Steamhammer is slightly more cautious about morphing a sunken that will be weak when it is finished. Another tweak.

• The code to place a sunken to defend against vulture or DT raids forgot to check whether we have a spawning pool. Fixed. Other checks in the code would have prevented the error from causing incorrect commands if it ever came up, but it could have caused inefficient play during an emergency.

openings

I made 3 Counter Contain builds to defeat cannon contains and other early containment attempts. They work by starting a hidden base elsewhere on the map, so that units can be produced outside the contain: 6PoolHide 9PoolHide OverpoolHide. Contains still cause Steamhammer to misbehave because it assumes that units can safely walk past (they can’t fight their way past, but walking is different), so the openings don’t work perfectly. But combat units produced outside do usually prefer to find and attack the enemy main first, so it’s a great advance over former behavior.

• The openings I hoped would have a chance against Stardust are 10HatchLing+1, Over10Hatch+1, and Over10HatchHydra. They are all-in builds. The few Steamhammer wins over Stardust so far are due to zergling attacks after Stardust messes up, so I made 2 zergling openings with what I guessed to be good timing. Every Steamhammer win so far has been by a different opening, and neither of these was able to score—they might be as good as anything. The hydra build is one suggested by Jealous in an SSCAIT weekly broadcast. I didn’t really expect it to work and it didn’t, but it was worth a try, and besides, the opening has value for other purposes.

AntiWraith_2Hatch is configured as a Counter Wraith build. It makes an evolution chamber in time to get spores, and goes 2 hatch muta.

AntiFact_Overpool11Hatch is an additional anti-factory mutalisk opening. By opening with overpool it hopes to intimidate the terran into playing too defensively against possible early zerglings. In fact, it makes few lings and aims for 2 hatch muta.

2.5HatchMutaExpo is a variation of the existing 2.5 hatch muta build (2 hatch muta plus a later third hatchery), which adds the third hatchery at an expansion rather than in the main. The original version stuck to 2 bases because it struggled to place the third base on the 2-player SSCAIT maps. That weakness is mostly solved, so it’s time to play the build right.

• Steamhammer doesn’t defeat ZZZKBot as consistently as it should, because Steamhammer is weak at defense. (Microwave is good at defense and wipes the floor with ZZZKBot. “You are my mop!”) Falling back on a quick fix, I tried writing openings. 9PoolHatchSpeedSpire2 as written is too slow to beat the 4 pool. 9PoolHatchSpire is good and should beat all ZZZKBot builds, but Steamhammer still isn’t consistent, only getting about 80% wins in the latest test. A quick fix is not enough, Steamhammer needs the actual skills.

debugging

• Clarified the wording in the building manager’s debug display. The construction status strings were kind of cryptic.

• A meaningless yellow square is no longer drawn in the upper left of the map. It was a leftover code snippet from old debugging. It took me a couple searches through the code to find it.

Next: About Steamhammer’s tournament prep learning files.

Steamhammer is submitted

I submitted Steamhammer to AIIDE 2020, a day ahead of the deadline. I don’t believe in working right up to the limit and risking last-minute bugs, better to turn out a stable version. As it was I did suffer a late bug introduced by an attempted fix, but fortunately it was easy to detect: I knew something was wrong when I noticed 3 spawning pools and 2 spires in the base. It was caused by a tricky race condition, but when I looked back at my change, my familiarity with the code let me see the problem immediately, and I knew how to correct it. I ran long tests after that and found nothing more. The new behaviors have zero known bugs (so I expect to learn something!), though of course they have limitations.

I’m feeling a little paranoid because in double- and triple-checking I discovered a couple mistakes in my submission zip and had to correct them. One was carried over from last year—I had a wrong filename in one line of the README instructions. Luckily for last year, the instructions were clear enough anyway. Actually, triple-checking is an understatement. Some points I verified four times. I ought to feel secure that I got it right.

The version is 3.2.19. Everyone memorize that version number, there will be a quiz. The next step for me is to prepare the change list so I can post it on 1 October. It may take me that long to write it up.

Steamhammer prep for AIIDE

With a couple days left to the deadline, I’m making final preparations for Steamhammer in AIIDE 2020. All the new behaviors are coded and tuned, as best possible. Mostly I’m making final tests and fixing remaining bugs. New code was written to have low risk of bad side effects, has been carefully tested, and seems to have few bugs. I have identified a couple of existing bugs, formerly unseen or unimportant, that are awakened by the changes.

I always wish I could have done more, but I’m happy enough with the improvements. I worked much harder than I have in the past year, when I was distracted by other business. Many long-time weaknesses are finally addressed. Ridicubad midgame play is slashed (and maybe I can do something about the remaining horrors before SSCAIT). Win rates are strongly up against some opponents (though Stardust remains out of reach). Microwave had pulled ahead of Steamhammer lately after months of Steamhammer dominance, but now I see them neck-and-neck rivals. Either might finish ahead in the tournament.

Expect upload to SSCAIT on 1 October, followed shortly by source release. The change list is long. I ran through about 20 test versions.

new bot EggBot

I was surprised to see AIIDE entrant EggBot by Nathan MacNeil make its debut on SSCAIT rather than waiting a few days for the AIIDE deadline. It makes sense, though: For a new bot that can make big progress in a short time, earning some experience to make that progress is way more important than holding your secrets in hope of surprise wins.

EggBot describes itself as “a (not great) cannon rush bot built from scratch that follows up with a gateway and zealots.” And in fact its play has the air of a typical beginner’s bot. On SSCAIT it seems affected by a bug and struggles to place cannons at all. On BASIL it seems to play more nearly as intended, and has scored 7-19 for a rating of 1901 elo with zero crashes, which is not bad at all for a first cut.

EggBot places its cannons near the enemy’s base entrance in containing position. It doesn’t creep the cannons forward to win; only outlying enemy buildings are likely to come under cannon fire. Occasionally it places the cannons somewhere outside the natural instead; so far I’ve seen that happen only when the enemy base location is known before the base is seen, and not usually then. It follows up with 1 gateway and makes zealots to win.

The cannons are often in plain sight, so an enemy that reacts in time will have good chances. Even an old bot like Tomas Cere can pull workers to stop the attack (in this game, EggBot placed one cannon defensively in its base). An opponent that has no defensive reactions is likely to lose hopelessly (in this game, EggBot seemed to hit a bug and did not follow up with zealots, but it still won on points).

EggBot is not efficient at spending its money and tends to let its mineral bank grow out of control. Besides bug fixes, that’s what I would work to improve if I were tuning it for AIIDE: Get each cannon down as soon as resources allow, then make the right number of gateways to grow the zealot count as fast as possible.

Steamhammer island plans

Among many other aspirations, I’ve always wanted Steamhammer to be able to take island bases. It’s not quite time yet, but getting closer. Here is my outline plan, with steps in order:

• BWAPI 4.4.0 helps make drop research practical. BWAPI 4.1.2 has a bug that prevents research in a hive.

• Pathfinding. Pathfinding is... on the critical path, according to my plan. The current release version of Steamhammer already has all the parts needed for pathfinding, except the final step of actually following paths.

• Nydus canals—with pathfinding support, because nydus is useless without. By hive tech time when nydus becomes available, nydus is cheap and valuable. If nothing else, Steamhammer would benefit hugely from transferring drones between distant bases without sending them through the center. In fact, if you have a hive and have drones to transfer far away, it’s normally better to hold the drones until you can get a nydus up. They are likely to get there just as soon, and more safely.

• Take island bases after hive, and nydus them up. Transferring units to and from islands by nydus is far simpler than transporting them by overlord. Given pathfinding, the regular base defense squads can defend islands with no extra code. The only drawback is that if the nydus is lost and the hive is destroyed so that the nydus can’t be replaced, then units will be stranded. But then, if the hive is gone we’re probably losing anyway.

It’s also possible to take an island before hive, and nydus it up later. The island will drone itself up slowly and struggle to defend itself before nydus, and drones will have nowhere to run from an attack, but if the enemy has no air units it may be worth it.

Many current bots do not scout islands. I’ve seen that in Ecgberht games; it can build island bases, though it doesn’t mine them efficiently (at least that I’ve seen)—it may lose a game on points with only an island surviving. A bot that’s good at islands might force other bots to adapt.

At some time in the more distant future I’ll add general overlord transport skills, so that Steamhammer can do mass drops, bypass contains, and fight with ground units on island maps.

RPS analyzer redux

In January I wrote about the idea of an RPS analyzer that tries to predict the opponent’s strategy rock-paper-scissors style, picking up patterns in the sequence of opening tries. For example, many bots never vary a winning build until it loses, and some of those cycle through their choices in a fixed order. If successful, an RPS analyzer could improve the odds of predicting the opponent’s strategy from the get-go, so that Steamhammer could start its counter before it got scouting information to verify. At the time, I wasn’t sure whether an RPS analyzer would be a good idea.

I still think that an RPS analyzer is useless in the limit of very strong bots: PerfectBot will follow game theory and have exactly the right amount of randomness in its choices, and a pattern detector will detect nothing helpful. But as I prepare Steamhammer for AIIDE 2020 I have been playing over many games, and I’ve become convinced that most current learning bots follow predictable or partially predictable patterns that can be exploited.

The current release version of Steamhammer pays limited attention to its predictions, which are accurate only in simple cases. It deliberately shifts its attention over time from openings that counter the specific predicted enemy play toward openings which counter the opponent’s range of play. The changes to make it pay close attention to accurate predictions are easy, though. And there are easy-to-implement algorithms to detect patterns and return a prediction with its confidence level. Do you think it can be ready in time for the AIIDE deadline at the end of the month?

new bot ExampleClient

A new bot ExampleClient by Dan Gant has appeared on the Starcraft AI Ladder. It hasn’t been uploaded to SSCAIT or BASIL, so I imagine it is on the Ladder primarily as a robustness test (it did crash a few times and is currently inactive). Another possible reason that it is not on SSCAIT is that its strategy might break some older bots; see below. The name “ExampleClient” suggests that perhaps it is intended as a starting point bot for new authors.

ExampleClient is terran, and it plays a strategy similar to the current version of Stone: It makes one SCV with its initial 50 minerals, and sends all 5 SCVs to the enemy base, where they try to destroy buildings. But there is a cute twist: It lifts off its command center and flies it out of sight. It seeks a location on the map that is not reachable by ground and not visible to ground units, and leaves the command center floating there. When there is such a location, only air units can find and destroy the CC. When there is no such location on the map (as on Circuit Breaker), it sends the command center to the extreme lower left—the location is hidden by the minimap, so the CC is virtually invisible when watching the replay. The enemy will scout every starting base and see ExampleClient at none of them. See my post breaking scouting assumptions from 2017 for similar ideas.

Most of the bots on the Ladder seem unconcerned that they cannot find ExampleClient’s starting base. Steamhammer, for example, once it has defeated the worker rush, takes the situation in stride as end-game cleanup where the enemy owns no bases, makes mutalisks, and hunts down the floating CC. That is possible in part because it distinguishes “I inferred the location of the enemy base by seeing all the other bases” from “I know the location of the enemy base because I have seen it.” BananaBrain is higher ranked but does not seem to draw that distinction: I have seen it take all bases on the map except the one where it “knows” the enemy must be, even as observers fly over the empty base location, and hold its forces back as if it were afraid to attack the vacuum. In some games, BananaBrain does not make air units and never finds the CC, so that it only wins the game on points. Some bots are fooled, though they still win!

There are a lot of other cute ideas that I have never seen a bot try.

a few items

I am working furiously on Steamhammer, not leaving myself much time for posting. The version I submit for AIIDE should be substantially stronger than the current release version, with visible changes that close observers will notice.

I doubt it will have much chance versus Stardust, though. After watching games where Stardust lost, I wrote 3 new openings to try to exploit its weaknesses, to at least make a dent. One was the hydra opening that Jealous suggested in a cast. But no, a rubber ball does not make a dent in a concrete wall.

A new bot EggBot appeared on the AIIDE 2020 participant list at some point after I wrote up the participants. I guess it must have been omitted by mistake. It is by Nathan MacNeil of the Memorial University of Newfoundland (Dave Churchill’s institution), who is apparently a graduate student. A grad student should have an interesting project in mind, so I have hopes for EggBot—weak or strong, I hope it will be interesting.

I still want to post about encouraging new bot authors, but you can tell it’s not my actual priority because I’m spending my time on coding and testing instead. Still, it’s an important discussion. The addition of S A B C D E F ranks on the BASIL rankings could be a good step if it encourages new authors to make progress: “I want to move up to D!”

AIIDE 2020 participants

The AIIDE 2020 registration deadline was yesterday, and today the list of participants is out (though as I write I don’t see an update to the web site yet). I wrote up the new map pool earlier.

First, the familiar names.

botauthor
BananaBrainJohan de Jong
DragonVegard Mella
EcgberhtFrancisco Javier Sacido
McRaveChristian McCrave
MicrowaveMicky Holdorf
PurpleWaveDan Gant
StardustBruce Nielsen
SteamhammerJay Scott
WillyTNico Klausner
ZZZKBotChris Coxe

Stardust crushed CoG and is at the head of the BASIL ladder; it is of course the favorite to win #1. McRave is playing zerg again, as in CoG. I’m hoping that Dragon will show us something new. For the other bots, I feel that I know more or less what to expect.

Then the new entrants that have not competed in AIIDE before.

botauthor
DanDanBotKim TaeYoung
RandofooEdgar Yajure
TaijWang Bin

I think “Kim Tae-Young” is a more standard way to anglicize the Korean name. DanDanBot registered last year too, but ended up not competing. The name “Wang Bin” also looks somehow familiar, though I don’t see a past mention related to Starcraft. It is possible that the second author of this recent paper Triple-GAIL: A Multi-Modal Imitation Learning Framework with Generative Adversarial Nets is the same person, but the name is common (at least as anglicized), so I can’t be sure.

Unknown bots are unknown. Let’s hope some of them are fun!

Plus 2 holdovers from last year.

botauthor
DaQinLion GIS
UAlbertaBotDave Churchill

DaQin first competed in AIIDE in 2018. UAlbertaBot is of course the perennial benchmark, though it risks landing in last place (last year it finished third to last, ahead of newcomers AITP and BunkerBoxeR).

I count 15 participants in total, 4 terran, 6 protoss, 4 zerg, 1 random. That’s a relatively even balance; protoss domination is not showing much. It is “traditional” for some participants to drop out before the tournament gets under way, so we’ll see how that goes. Last year half of AIIDE dropped out. Let’s hope there is no such trouble this year.

CoG 2020 - breakdown by map

These tables show, for each bot, its win rate against each opponent, broken down by map. For example, the first table is for Stardust, and shows Stardust’s win percentages by opponent and map. The tournament played 200 round robins rotating between 5 maps, so each table cell shows the result of 200/5 = 40 games between the two opponents on that map, or slightly less than 40 if some games were not counted due to problems.

See looking forward to CoG 2020 for a general discussion of the maps. As a reminder, the maps are:

  • (2)Blue Storm
  • (3)Alchemist
  • (3)Great Barrier Reef
  • (4)Andromeda
  • (4)Luna the Final
StardustoverallBlueStAlchemGreatBAndromLunaTh
PurpleWave86%62%92%88%92%95%
BananaBrain63%55%62%72%65%62%
BetaStar76%100%55%80%72%75%
Microwave96%95%100%95%95%98%
XIAOYI95%98%100%98%90%90%
McRave96%100%95%92%95%100%
MetaBot99%100%100%100%100%98%
overall87.61%87%86%89%87%88%

Aha, details count! Stardust’s overall results look even across maps, but there are differences for the top protoss opponents. It had some trouble on Blue Storm against PurpleWave and BananaBrain, and on Alchemist versus BetaStar.

PurpleWaveoverallBlueStAlchemGreatBAndromLunaTh
Stardust14%38%8%12%8%5%
BananaBrain42%40%38%45%38%48%
BetaStar70%85%68%75%70%52%
Microwave84%82%80%90%85%82%
XIAOYI100%100%98%100%100%100%
McRave88%92%88%85%90%88%
MetaBot98%100%100%98%92%100%
overall70.82%77%68%72%69%68%

Again, differences show mainly against top opponents, where PurpleWave favored Blue Storm and struggled on Luna against Stardust and BetaStar (though it liked the map against BananaBrain). Luna is a classic macro map. Maybe PurpleWave is not as skilled at the brute force just-make-more-units-and-win style.

BananaBrainoverallBlueStAlchemGreatBAndromLunaTh
Stardust37%45%38%28%35%38%
PurpleWave58%60%62%55%62%52%
BetaStar67%82%68%60%62%62%
Microwave74%72%57%80%85%75%
XIAOYI98%100%95%100%98%95%
McRave64%48%90%65%68%50%
MetaBot91%100%88%89%89%87%
overall69.71%72%71%68%71%66%

BananaBrain by contrast shows differences versus many opponents, most notably McRave where it dominated on Alchemist and suffered on Blue Storm and Luna. A big disparity like that must mean something.

BetaStaroverallBlueStAlchemGreatBAndromLunaTh
Stardust24%0%45%20%28%25%
PurpleWave30%15%32%25%30%48%
BananaBrain33%18%32%40%38%38%
Microwave71%92%25%65%98%75%
XIAOYI46%25%30%80%32%65%
McRave70%100%20%80%90%62%
MetaBot90%92%100%85%91%81%
overall51.73%49%41%56%57%56%

A checkerboard table. The middling overall percentages are averages of big wins and big losses. BetaStar comes across as strong but brittle.

MicrowaveoverallBlueStAlchemGreatBAndromLunaTh
Stardust4%5%0%5%5%2%
PurpleWave16%18%20%10%15%18%
BananaBrain26%28%42%20%15%25%
BetaStar29%8%75%35%2%25%
XIAOYI82%88%80%90%78%72%
McRave42%28%60%32%48%40%
MetaBot86%95%82%98%75%82%
overall40.57%38%51%41%34%38%

Also with dramatic variations, especially against BetaStar. Was there map-specific preparation, and if so, why did it not work on Andromeda, which is traditionally considered a zerg-favored map? There was an incorrect announcement of maps followed by a correction, but Andromeda appears on both lists, and in any case the map announcements are dated before the submission deadline.

XIAOYIoverallBlueStAlchemGreatBAndromLunaTh
Stardust5%2%0%2%10%10%
PurpleWave0%0%2%0%0%0%
BananaBrain2%0%5%0%2%5%
BetaStar54%75%70%20%68%35%
Microwave18%12%20%10%22%28%
McRave100%100%100%98%100%100%
MetaBot76%95%92%98%57%40%
overall36.57%41%41%32%37%31%

McRaveoverallBlueStAlchemGreatBAndromLunaTh
Stardust4%0%5%8%5%0%
PurpleWave12%8%12%15%10%12%
BananaBrain36%52%10%35%32%50%
BetaStar30%0%80%20%10%38%
Microwave58%72%40%68%52%60%
XIAOYI0%0%0%2%0%0%
MetaBot82%98%85%78%78%72%
overall31.64%33%33%32%27%33%

MetaBotoverallBlueStAlchemGreatBAndromLunaTh
Stardust1%0%0%0%0%2%
PurpleWave2%0%0%2%8%0%
BananaBrain9%0%12%11%11%13%
BetaStar10%8%0%15%9%19%
Microwave14%5%18%2%25%18%
XIAOYI24%5%8%2%42%60%
McRave18%2%15%22%22%28%
overall11.02%3%8%8%17%20%

Upsetting XiaoYi on even one map is not bad.