archive by month
Skip to content

Steamhammer’s documentation is updated

I have updated Steamhammer’s documentation for the first time since version 1.4.2 in May last year. There’s not much to it: One page lists important classes in the code to help people get started, and the other explains the configuration file in great detail.

The documentation is so little used that many people do not seem to realize that it exists. Or maybe it’s the other way around. But now there is no longer an excuse.

Steamhammer 2.4 change list

Steamhammer 2.4 is uploaded. Since I never got around to releasing the source of the previous version, I’ll release source shortly.

This version has 2 points of focus: First, fixing critical bugs that are responsible for many of the losses against weaker opponents, and second, coping with the deadly Styx opening. I wrote 18 new openings, 10 of which are connected to the Styx opening.

configuration

Added the Config::Strategy::HumanOpponent flag for games against humans. It’s false by default, since almost all games are versus bots.

critical bugs

Cancelling mutalisks just before making them is fixed. It happened intermittently in some openings. A spire takes 1800 frames to build, and Steamhammer is configured to conclude that production is jammed if there are 1440 frames without production. In some cases, the opening build might pause production for longer than the limit while saving up for mutalisks; a jam clears the queue and drops out of the opening, so the mutalisks were never made. I fixed it with a special case test, since only this one case was failing.

Gas deadlock is an emergency that happens when Steamhammer needs gas for the next item, and has the extractors for it, but finds itself unable to collect the gas for some reason (for example, the base is under attack so the drones ran away). It clears the queue to try again. The condition for recognizing gas deadlock was too loose, and sometimes declared deadlock falsely. I tightened it up.

Tracking of geysers and refinery buildings seemed to be wrong in some cases. I was not able to pin down any bad behavior it caused, but the code looked confused and I’ll be surprised if nothing is corrected.

Combat sim is more fixed. In the previous version I fixed bugs in setting up the combat sim, related to short-circuit judgments when facing cloaked units. There was still a bug, and I traced it to... checking whether a unit’s air weapon was unequal to BWAPI::UnitTypes::None rather than BWAPI::WeaponTypes::None. Thank you C++ for your “helpful” type checking. This fix will make mutalisks more aggressive, as they should be, in certain situations.

macro

• Restored the setting of 2 workers per mineral patch for terran and protoss. It had been accidentally set to the zerg value of 1.6.

operations

• Against certain stronger enemy units, send more defenders. If an archon is in your base wreaking havoc, 2 marines will not stop it.

• The natural expansion cannot be one of the map’s starting bases. This fixes a problem that came up on the map Baekmagoji.

StrategyBossZerg::enemySeemsToBeDead() works more nearly as intended. There was a minor bug. The enemy is considered to be dead and ready to be buried when all these conditions are met: 1. The enemy starting base has been found (so it can’t happen immediately when the game starts). 2. The enemy has no known surviving bases. 3. The known enemy ground army is not strong enough to threaten to win. 4. The enemy has no known anti-air units or anti-air static defense. When the enemy looks dead, Steamhammer techs to mutas and switches to a unit mix of drone + mutalisk. The mutalisks can efficiently hunt down any hidden or floating buildings.

unit control

The micro system drops positional orders for which the position is “close enough” to the previous order. If code orders a move to (x, y) and then on a later frame a move to (x, y+1), the second order is dropped. The tolerance is a few pixels for short-range moves, larger for long moves. This reduces command spamming and smooths unit flow. In the long run, I ideally want to reduce Steamhammer’s APM to human levels.

• Targeting priority for enemy buildings is factored out and more nearly standardized across unit controllers. Streamhammer should destroy enemy bases a little more purposefully, with fewer cases of zerglings tearing down the spire while mutalisks tackle the spawning pool.

• Enemy observers are a higher priority target for ranged units and scourge, depending on the situation.

zerg

• When in book, if we have no zerglings, do not change a planned zergling into a drone. Steamhammer likes to skip zerglings when it foresees no danger. A similar change was already made for the case when it was out of the opening.

• Queen bug: The queen believed it could infest an unfinished command center. “It has few enough HP, let me fly across the map and take it.” When the building SCV was killed, the queen might sit over the unfinished command center forever. “This infestation sure is taking a long time. Oh well, stick with it!”

• Queen bug: When using broodling, the previous version was intended to be willing to make 2 queens, not the usual 1. After testing the feature, I introduced a typo that prevented it from working. Fixed.

Prevent production freezes related to queen upgrades. Rare but painful.

• Allow air upgrades in any order, using 1 or 2 spires. Formerly, air carapace had to be first (or else production freezes were possible) and Steamhammer could upgrade in only 1 spire. This any-order-is-OK improvement was made earlier for ground upgrades.

openings

ZvZ_Overgas8Pool fills a small gap in the repertoire. A very small gap.

973HydraBust is a precise modern build versus protoss forge expand. The name is because you are supposed to end up with 9 drones in your main, 7 in your natural, and 3 at a third base. Steamhammer does not have the skills to distribute the drones efficiently as intended, but it does get the right total count.

2HatchMutaForever covers a weakness in the zerg strategy boss: There are times when growing the mutalisk flock is best, but the strategy boss doesn’t understand the value of stacking air units and prefers to switch into a different unit mix. The opening doesn’t really make mutalisks indefinitely, only for a long time. It also gets air upgrades.

2HatchFakeHydra and 2HatchFakeMuta are deceptive openings that make both hydralisk den and spire. The fake hydra opening makes a hydralisk den when the enemy scout should see it, chases the scout away, and adds the spire later. The enemy may predict hydra play or lurkers. The fake muta opening is similar but in reverse.

5HatchPool makes 5 hatcheries before spawning pool, an extremely greedy opening for use against opponents that move out late. (See my mention of Locutus in what Steamhammer learned. I’ve seen 6 hatch before pool work against a bot.) ZvP_5HatchPoolHydra is a specialized version that follows up with mass hydralisks. 5HatchPoolLing gets an evolution chamber before the spawning pool, so that when the first zerglings hatch, melee attack +1 is already half finished. The flood of lings is late but massive.

The powerful Styx build. The openings 9PoolHatchSpeed7Drone, 9PoolHatchSpeed7DroneB, 9PoolHatchSpeed, 9PoolHatchSpeedAllIn, 9PoolHatchSpeedAllInB are variations on the Styx build of 9 pool, 3 pairs of zerglings, hatchery, extractor (leaving yourself with 7 drones), zergling speed, and deluge the enemy with zerglings (7 drones are enough). That exact build is 9PoolHatchSpeed7DroneB. The versions without a B have the extractor before the second hatchery, which gets faster zergling speed and a slightly slower hatchery. The versions without 7Drone use the extractor trick to end up with an 8th drone without losing time. The 8th drone does not make the zergling attack stronger, because 7 drones are enough to keep the 2 hatcheries completely busy producing, but it does establish leeway to lose a drone to accidents, make an emergency sunken, or transition into another plan. The plain version 9PoolHatchSpeed makes fewer zerglings and leaves the followup to the strategy boss, which is not too helpful because the strategy boss doesn’t understand the idea.

Anti-Styx openings. If you know your opponent’s exact build order, you can always choose your own build to gain an advantage. (Don’t be predictable!) If the opponent is too greedy, you can clobber them with a rush or a bust before they’re ready. The Styx opening is not greedy; 9 pool is what you play to be safe against cheese. When the opponent is not greedy, you gain an advantage by being greedier, to a calculated extent. AntiStyx_9Pool is the simplest try. It uses the extractor trick for the 8th drone, and turns the drone into a sunken. The zergling wars are about equal, but the sunken at home is safer and allows more freedom of action because there is less need to hang back in defense. At Steamhammer’s level of play, the advantage is slight. However, this anti-Styx build is valuable as a general-purpose anti-cheese build; I configured it for that too. AntiStyx_3Hatch and AntiStyx_Muta are more successful at defending against the Styx opening. They open with overpool rather than 9 pool, gaining a lead in drones. Both make 1 sunken and use the safety it provides to scrape out more drones. The 3 hatch followup adds a third hatchery to eventually win the zergling wars, while the muta followup techs instead. The safe path is narrow; I’m curious to see how well the openings perform in practice.

Turtle openings can also cross the river Styx. Some turtles swim well, and they do not have the same weakness as Achilles. See wins over StyxZ by ZurZurZur, by Simplicity, and by Microwave with its turtle build.

9PoolHatchSpeedSpire and 9PoolHatchSpeedLurker are my try to pre-empt bot authors who may add a recognizer for the dangerous Styx opening so they can counter it. These builds start out with the Styx opening stem but transition into tech.

• I made tweaks to AntiZeal_12Hatch and 12HatchTurtle. They should be a trifle stronger.

Steamhammer 2.4 tomorrow

Steamhammer 2.4 is almost ready. I’ll upload it tomorrow. It has accumulated enough critical bug fixes and changes; it is time to put it on the road and see how it drives.

New are 4 variants of the “Styx” opening (popularized, not invented, by StyxZ—as Ogden Nash said, “Don’t be a discoverer, be a promoter.”). A later post will analyze and compare the variants. And I wrote 3 counter-Styx openings designed to defend and come out ahead.

Steamhammer’s SSCAIT prospects

In 2016, when Steamhammer was brand new, it squeaked into the SSCAIT final playoffs through a tiebreaker match. In 2017 and 2018, it was clear to me ahead of time that Steamhammer would make it into the finals. This year, my life and schedule have been disrupted and I made less progress. Some of the work I put in, like queen skills, was more about having fun than about playing better, because I need some fun. The bottom line is, Steamhammer is failing to keep up with advances. Its rank is sliding.

I think that Steamhammer is still likely to make it into the SSCAIT round of 16, but it may be a close call. There’s a real risk that it may fall short. The fixes in version 2.4 may claw back a rank or two, but not enough to eliminate the risk. It’s possible that I can change Steamhammer’s prospects before then by implementing a killer skill (I have one in mind), but that’s risky in itself, and my past attempts to code killer skills before a deadline have fallen short. But we’ll see.

the HumanOpponent flag

I watched the SCHNAIL video and I’m pleased. Today I added a HumanOpponent flag to Steamhammer’s configuration file, to make the bot more fun for humans to play against. If you set it to true, the flag has 2 effects:

1. It tells the opponent model that the opponent is unpredictable, which the opponent model takes to mean “I’d better be unpredictable too so I can’t be exploited.” It chooses openings more randomly. This is just turning on a standard Steamhammer behavior that already existed.

2. When losing, Steamhammer ggs out much earlier. Steamhammer in the past assumed that its opponent is a bot and may mess up the win, so it surrenders barely one step before it is provably unable to win. (Even so, I’ve seen a couple games over the years when it might have won if it hadn’t given up—when it had no drones and no combat units and no money, but had units in production that could outfight the opponent which was also near death. It’s extremely rare.) Versus a human, that gg timing is way way too late, unacceptably late. When HumanOpponent is turned on, Steamhammer follows a two-part rule: A. The enemy is much stronger than me—my supply is less than half the enemy’s known supply. B. I have been hurt—my supply has fallen below half of its high water mark. The B part ensures that Steamhammer doesn’t give up without a fight merely because it has been grossly outmacroed.

I’m curious to find out how well the gg rule works in real human games. In test games, I thought the gg still came later than a strong human would prefer. But perhaps it is a good fit for human players who deem Steamhammer an interesting opponent. Also, the enemy’s known supply is generally less than the enemy’s true supply, and Steamhammer is weak at scouting so often it is much less. But I will need to improve scouting as part of my strategy adaptation project, and gg timing may improve when I do.

About SCHNAIL: Obviously we can’t expect SCHNAIL users to edit Steamhammer’s config file and set the HumanOpponent flag. The file won’t be exposed to them at all; they don’t need to know it exists. I asked Sonko if there will be a way for a bot to tell that it is running under SCHNAIL. Whatever the final arrangement ends up being, I will help Steamhammer fit into it so the bot does sensible things in human games.

an amusing Steamhammer bug

I was testing a macro build on the map Baekmagoji, a 2 player map where macro builds are fitting because each main base has 2 geysers and 18 mineral patches—double the usual. (I routinely test on all kinds of maps.) Early in the game, Steamhammer suddenly panicked and canceled a hatchery to get its spawning pool immediately. What was going on?

The bug, or I should say bugs, turned out to be this: Because the enemy main was so rich in resources, Steamhammer decided “well, it’s a bit far away, but still it’s the best choice for my natural base.” When the scout found enemy buildings (“hey, that’s in my natural”), Steamhammer concluded that it was getting proxied. Panic! That was easy to fix; the chosen natural is not allowed to be a starting base. But wait, why was the first expansion hatchery already started somewhere else, so that it could be canceled? Because the choice of the natural base and the actual first expansion taken are not quite coordinated correctly; in some cases they can be different for no good reason. Ack!

Baekmagoji is a difficult map for bots. Another issue is that some of the mineral patches in the main are not reachable until other patches are mined out. It’s a clever design, but Steamhammer doesn’t understand it and tries to assign drones to minerals that they can’t reach. Well, that’s not important to fix yet. I can’t think of another competitive map that would trigger this bug (though more than a few Blizzard maps do). Also notice the neutral sunken colonies spreading creep, and the blocking temples and blocking minerals. Lots of tricks lying in wait.

AIIDE 2019 - looking into AITP

AITP follows an “aggressive defense” game plan, similar to SAIDA, where it builds up a strong ground army, then sets up tank lines in forward positions to constrict the enemy like a boa (preferably a snake, sometimes a feather boa). Its overall skill is far less, though; it finished second to last in AIIDE 2019. Overall, after reading some of the key code, I am not impressed (maybe you shouldn’t expect me to have been). The plans are ambitious but the work looks hasty, as if the authors underestimated it and had to rush to make the tournament. Still, the plans are ambitious, and that makes it somewhat interesting.

tactics

One of AITP’s first steps is to calculate map positions for a wall (supplyPoint barracksPoint bunkerPoint), defensive locations (chokePoint1 through chokePoint4) and offensive tank lines (frontLine1 through frontLine3). How does it calculate them? They are hardcoded for every starting base on every map in InformationManager::initializePosition(). That must be part of why AITP did not want to participate in the unknown map tournament. These positions seem to be the foundation on which all the tactical decisions are laid.

Spider mines are placed in neat diagonal double lines at locations offset from the defense line calculated by CombatCommander::updateDefenseLine(), which looks mostly at the supply and the previous defense line and sets the current defense line to chokePoint2 (the natural choke) or to one of the precalculated frontLine values. It’s simple and primitive, and there is not much examination of the game situation, a good starting try but nothing you expect to be strong. It’s silly sometimes; the defense line may be in front of an empty base that is away from the fight. CombatCommander::updateSpiderSquads() sets up spiderSquad1 and spiderSquad2—and also lays mines itself, calculating the offset steps and checking every vulture itself rather than leaving it to the squads. The intended separation of functions is not observed. Micro::LaySpiderMine() is unused.

StrategyManager::shouldBuildTurret() decides how many turrets should go where. Some turrets go to occupied choke points 1 and 2, some next to command centers, and some at the front lines computed above depending on certain “squad positions.” These so-called squad positions come from CombatCommander::getSquadPosition(std::string squadID), which takes a string that is called squad ID but is actually a 2-digit code that identifies a location rather than a squad. The location is usually an offset from the current defense line, but there are exceptions. The ID seems to choose one of a hardcoded set of offsets for the final position.

Units, of course, also go to the current defense line: That is the tank line, soon furnished with mines and turrets, that is meant to restrict the enemy. At some point CombatCommander::updateAttackEnemyBase() becomes true and sets _aimEnemyBase to the location of an enemy base to destroy. When this happens depends on what the current defense line is, but it’s another set of simple calculations using the closest friendly unit to various enemy bases.

what to build

I outlined the build order and unit mix decisions in the post how AITP played. There are game stages A, B and C and “modules” A1, A2 and so on for each game stage.

A1 is the antirush module that starts a barracks at 5, whose play was described in that post. It switches to the next module when there is a bunker and 4 marines and the engineering bay is started. One of AITP’s strategies was A1-B1-B2-C2. B1 makes SCVs up to 20, barracks up to 5, academy and medics, moves out at 10 marines, and switches to the next module after 10 minutes game time. B2 makes a bunker under certain conditions—but only if the previous module was A4. The modules are not in fact modular but know about each other. Then it makes SCVs and marines up to a smaller limit than B1, makes a factory and gets the upgrades and expansion. It switches when there are 2 command centers or the supply reaches 100 (really 100, not 50: int supplyUsed = BWAPI::Broodwar->self()->supplyUsed() / 2;). Module C2 is the middlegame: It makes SCVs to the limit, adds factories, throws bunkers into the middle of the map, gets armory upgrades, and never switches.

Here’s an extract showing the strange over-specificity of AITP’s code, from StrategyManager::doSwitchModule() which switches from the current module to the next one. The code does not simply parse out the strategy module names from the StrategyName string, it handles each as a special case, sometimes taking extra actions that I would say should be factored out.

	if (_currentModule == "A1")
	{
		if (Config::Strategy::StrategyName == "A1-B1-B2-C2")
		{
			_currentModule = "B1";
			CombatCommander::Instance().clearSquad("bunkerSquad2");
		}
		else if (Config::Strategy::StrategyName == "A1-B3-C2")
		{
			_currentModule = "B3";
			CombatCommander::Instance().clearSquad("bunkerSquad2");
		}
	}

AITP’s modules are not easy to read. I think Steamhammer’s explicit build orders plus zerg strategy rules are more perspicuous and no less expressive—but then I would say that, wouldn’t I?

new bot Crona

New bot Crona is, as it says in its description, BananaBrain playing zerg. It was uploaded today and has started out well. The name “Crona” is after an anime villain.

Sp far, I have only seen Crona play with zerglings and mutalisks, no other units. Here are the names of Crona’s openings, extracted from the binary. “Main Muta/Hydra/Ling” looks like an unrelated string that sneaked into the list, but maybe it’s an opening too.

ZvZ_2hatchling
ZvZ_5pool
ZvT_2hatchling
ZvT_4pool
ZvT_2hatchmuta_12pool
ZvT_2hatchmuta_12hatch
ZvP_2hatchling
ZvP_5pool
ZvP_4pool
ZvP_2hatchmuta
Main Muta/Hydra/Ling
ZvU_2hatchling

The build ZvZ_2hatchling is the “Styx build” of 9 pool, 3 pairs of zerglings, second hatchery, extractor, research zergling speed and produce zerglings for a long, long time. (Note 1: One of the rules of naming is that the origin of a thing cannot be the name; you have to pick something later. Note 2: I’ve tested both variants, and I’m pretty sure that the PurpleSwarm variant with extractor before the second hatchery is better.) Likely the other 2hatchling openings are too.

When playing 4 pool, and presumably other builds, Crona sticks with 1 hatchery and 3 drones for a while, then transitions to 2 hatcheries and 7 drones, then later to 3 hatcheries. I assume the sequence continues. My impression is that the expansions are on a timer: I’ve done this long enough, time for another hatchery. It’s a simple way to slowly increase pressure on the opponent.

Crona’s zerg play is good—see its results—but still looks a little rough to me. It doesn’t scout with its overlord. It has a glitch where, at a certain point in the opening, all the drones move away from the minerals for a second before returning. Crona seems a little confused about drone transfers in general. These things should not be hard to fix, though.

I see terran openings in the binary too. Can anybody guess what the terran BananaBrain will be called?

immediate plans

My time and energy are still limited. Well, my plans always outrun my execution anyway. Here are things I hope to get to soon:

• Write up a confused Steamhammer-McRave game.
• Look into AITP’s code.
• I forgot to release source for Steamhammer 2.3.6. I should do that.
• Look more closely at ZZZKBot’s wide swing in AIIDE results.
• Analyze CoG and the AIIDE unknown maps competitions to some degree.

For Steamhammer, I’m constantly torn between the need for immediate repairs of glaring weaknesses and the need to make long-term progress on strategy adaptation and infrastructure rework. The long run is what counts, but there are always lost games and upcoming tournaments to urge me to make quick fixes.

I will do both. For the upcoming SSCAIT, it looks like I will make another point release, Steamhammer 2.4, in which the visible changes will be more on the quick fix side. It will have work (it already has work) on strategy adaptation, but little or none that will be active yet. I don’t have the energy to put my head down and bring off a substantial subproject.

old bot Styx

Old zerg bot StyxZ has been getting updates recently, and I have been watching it steadily climb the rankings. Today Styx became the top zerg on BASIL, at least for the moment, so clearly it is time to write about it!

To give an impression of how far Styx has climbed, its lifetime win rate on SSCAIT is about 34%. In the last 24 hours on BASIL, I count 5 losses and 35 wins, an 88% win rate. On the BASIL crosstable its row is almost all red and stands out sharply in its new green environment. The degree of improvement is astounding.

Styx is distributed as a JAR file, so I unpacked it and took a look. I found that Styx is written in Kotlin, a recent language. That makes me wonder: Is this Styx version a complete rewrite, new code that replaces the older version? That would fit in with the quantum leap in results. But I also see both of the map analysis libraries BWTA and BWEM, which gives the impression that Styx is in the process of transitioning to BWEM, though perhaps it is using both to take advantage of different features. Also in there is the jts geometry library, which seems potentially useful for map-related calculations. The jts version is 1.16.1, officially released this past February (I love that it is the same as our Starcraft version number).

Also in the object code I see the ASS combat simulator, a project started only last year. I see the jsoniter JSON parser, which suggests that Styx is reading data files of some kind, whether static initialization and configuration or dynamic learning files.

The feeling I get is that work on Styx was restarted sometime this year, and a substantial amount of new work has been done. It’s hard to say exactly what, though, since I didn’t save an old version to compare.

What specifically makes Styx stronger? The most obvious improvement is a new build, much sharper than what Styx used to play: It is 9 pool, second hatchery, then zergling speed, and don’t waste time making extra drones but keep up zergling production with a 7 drone economy, which enough for constant production from the 2 hatcheries. The mass lings overrun opponents of every race, including solid defenders like McRave. The purple zerg PurpleSwarm has been playing a similar build for a while, also with success.

The new build is great, but it does make me wonder how much the other changes to Styx contribute.

new bot adias

Adias is a new terran bot, and starting off strongly. The first thing I noticed about it is that its name is SAIDA spelled backward. Does that mean it is like SAIDA, or the opposite of SAIDA? The second thing I noticed, after unpacking the binary from SSCAIT, is a machine learning folder with files caffe2.dll, torch.dll, and a couple of learned models with the .pt suffix. It is the signature of a project using PyTorch for deep learning. It’s not TorchCraft, so not directly related to CherryPi. It also does not seem to be based on SAIDA_RL; strings I checked from SAIDA_RL do not appear in adias.

The third thing I noticed, peering into the .exe, is that it looks to be derived from SAIDA. It’s clear that the two share a lot of code, at least. That’s surprising; based on SAIDA and using RL but not based on SAIDA_RL? Close similarities to SAIDA are visible in the game play. For example, adias shares SAIDA’s way of grouping supply depots and tech buildings together, and SAIDA’s predilection for walls composed of barracks plus engineering bay. Both habits appear in the game adias-Tomas Cere on Benzene. There are a lot more similarities; the building placement and opening build orders look identical to me, and adias shares the skill to set up tank lines where the opponent will be compelled to engage at a disadvantage.

The combination of traits reminds me of something else: Stormbreaker, the bot which was disqualified from AIIDE 2019 for being SAIDA with cosmetic changes and a neural network whose result was not used. Is adias only Stormbreaker under a different name?

Well, I don’t know, but I’m guessing not. Though SAIDA and adias look more similar than not, I went back and watched old SAIDA games and I think I see differences too. The difference most salient to me is that adias likes to send an SCV to scout around inside and near its base early in the game, seeming to check for proxies. The only other bot I’ve seen with that style of anti-proxy scouting is tscmoo. Did tscmoo have a hand in adias?

I expect we’ll learn more as we get to see more games. Krasi0 was eventually updated to defeat SAIDA. Will Krasi0 quickly learn to beat adias too, or will Krasi0 have to be updated again to keep up?

AIIDE 2019 - how AITP played

I think AITP is the only AIIDE 2019 bot whose game play deserves its own post. Most others can be watched at SSCAIT and BASIL, and BunkerBoxeR is severely buggy. AITP finished second to last, but it is complex and interesting. In this post, the game links are links to replays; you’ll have to drop them into the OpenBW player yourself.

AITP is derived from Steamhammer and shares some of the same habits. For example, it places supply depots and other buildings of the same size preferentially at the edge of the map, like Steamhammer terran. As explained in what AITP learned, the bot has an interesting abstract strategy system that is different from any other Steamhammer derivative.

AITP does not have strategy work only. It knows how to make a wall at the ramp, how to lift the barracks to open the wall, and how to land the barracks nearby to leave the wall open. It also knows how to lift the barracks back and restore the wall in case of danger. It researches spider mines and lays mines in neat diagonal lines in places like the approach to its natural. Later in the game, when it has a dangerous tank ball, it moves out and sieges to cover movement routes, like SAIDA but with less understanding of where the important places are, and builds turrets there. It has an excessive desire to build bunkers in the middle of the map, which it then doesn’t use properly.

Defensive setup with spider mines.

It has also lost important skills that it inherited. It seems to have lost the emergency reaction of taking SCVs off gas when mineral mining is more important because of a large gas excess. Marines may stand away from a bunker that they should jump into, a new and critical misplay. AITP often moves its army away from the action toward a distant empty base, as in this game versus XiaoYi on Fortress (possibly a bug in deciding on the squad target).

Overall, I judge AITP as promising but not mature. I imagine that the tournament came up too early in its development. Some of its skills are impressive, others look incomplete or broken. It needs work to fix bugs (223 crashes during the tournament), polish skills, and add strategy modules to cover more cases. If it gets that work, I think it could become very strong.

Here are my observations of how AITP played when following each of its 5 declared openings. I correlated its learning files with the detailed tournament results to find games with each strategy. Later I’ll read the code and decipher the strategy modules more fully. All strategies involve initial buildings placed at the base entrance. On the map Aztec, where the main base is on low ground below a ramp, it smartly builds at the entrance to the natural instead of the entrance to the main. Few bots know to do that; even Locutus got in some trouble by not doing that.

Every one of these strategies is defensive, as you might expect with buildings at the entrance. I think AITP has good vulture micro and would benefit from having the option of more aggressive vulture play. Also none of the openings is honed to a fine edge; they are all a little rough.

A1-B1-B2-C2 Make a very fast barracks at 5 supply, placed at the base entrance, then finish the wall with a bunker and supply depot. This is the build labeled AntiRush. Later add more barracks and get medics (though no marine upgrades) and move out. I initially guessed that AITP played factory unit mixes every game, but this is a barracks unit mix. This plan scored wins only against random UAlbertaBot, which of course favors rushes. Here is a win on Heartbreak Ridge versus protoss zealots.

A1-B3-C2 Make a very fast barracks at 5 supply, placed at the base entrance, then finish the wall with a bunker and supply depot (this part must be A1). Follow up with factory and ebay and turret up the base. Get vultures with speed first, then expand. Eventually switch into a tank-goliath unit mix (I’m guessing this is C2, which if true means that I didn’t see a game with the anti-rush A1-B1-B2-C2 strategy which got as far as stage C). This was AITP’s most successful strategy by far, in fact I would call it the only successful strategy. It was a top choice against ZZZKBot, Microwave, McRave, UAlbertaBot, and BunkerBoxeR. Here is one of AITP’s 7 wins against Microwave on Python where Microwave played a 9 pool and followed up unambitiously.

A3-B5-C1 Narrow the base entrance with supply depot then barracks, and start a factory before the first marine. Get vultures with mines first and remain defensive. Start a command center in the base, and keep making vultures. When the command center is done, float it into the natural, keep defending with the vultures, and finally add tanks before moving out. This strategy scored zero against every opponent except BunkerBoxeR, which played broken builds. In the first game versus Iron on Benzene, AITP put up a creditable fight.

A3-B7-C1 Narrow the base entrance with supply depot then barracks, and start a factory before the first marine. Get vultures with mines first and remain defensive (up to here must be A3). Then get tanks and start a command center in the base. Not a suitable opening against aggressive play. When there are 2 tanks (no siege mode), lift the finished command center toward the natural. This plan did not show good success against any opponent, but worked better than A3-B5-C1 above. Here is a game versus McRave on Destination.

A4-B2-C1 Wall the base entrance with barracks, depot, bunker, in that order. Make marines and vultures and a fast ebay for turrets. When there are 5 marines, push out, bunker the natural, and expand. The strategy does not impress me; it is not greedy enough to gain an advantage against a cautious opponent (DaQin), and as implemented not safe enough to survive an aggressive opponent (Microwave). Watch how effortlessly PurpleWave wins with 2 dragoons and straightforward play when the 5 marines move out; AITP is missing the defensive skills to make it work.

AIIDE 2019 - what Microwave did

Here’s data from Microwave’s history files, using the same script as for BananaBrain with a little customization. Unlike Microwave’s learning files, which deliberately omit data and include information from pre-learning, the history files tell what Microwave actually did during the games. Microwave didn’t record information about the opponent’s strategy, so that table is left out. That made it look a little sparse, so I added columns giving the first and last games when the opening was tried, where the first game in the history file is game 0. We can see things like when a winning opening was found, and whether it kept winning. If there are fewer than 100 games recorded for an opponent because Microwave crashed, then the game numbers generally do not align with the tournament round numbers.

Against difficult opponents, Microwave experimented widely. Against some opponents that Microwave pre-trained against, it played whatever came out of pre-training. So I don’t have much to say about opponents in the top half of the post. But toward the bottom I’ve made some comments. Especially see the note to AITP.


#1 locutus

openinggameswinsfirstlast
10Hatch9Pool9gas812%152
2HatchHydra70%053
2HatchLurker729%8389
2HatchLurkerAllIn20%6390
2HatchMuta1225%356
3HatchHydraBust30%1057
3HatchLingBust30%3891
3HatchPoolHydra50%1692
4HatchBeforeGas40%2793
4PoolHard30%1558
4PoolSoft40%2159
5Pool20%3660
5PoolSpeed30%4194
6Pool30%4295
6PoolSpeed30%4396
7Pool20%3761
8Pool30%4497
9Pool922%4578
9PoolLurker20%4679
9PoolSpeed30%1162
9PoolSpeedLing20%4780
ZvP_10Hatch9Pool40%1781
ZvZ_Overpool11Gas40%1882
23 openings988%

#2 purplewave

openinggameswinsfirstlast
10Hatch9Pool9gas119%2093
2HatchHydra60%1487
2HatchMuta50%3594
3HatchHydraBust90%395
3HatchLingBust147%074
4PoolHard10%8080
4PoolSoft714%3075
5Pool812%1590
5PoolSpeed10%8181
6Pool10%8282
6PoolSpeed10%8383
7Pool80%1776
8Pool40%4291
9Pool10%8484
9PoolSpeed30%5292
9PoolSpeedLing1421%477
ZvP_10Hatch9Pool10%8585
ZvZ_Overpool11Gas10%8686
18 openings967%

#3 bananabrain

openinggameswinsfirstlast
10Hatch9Pool9gas10%5454
2HatchHydra10%5151
2HatchMuta10%5252
3HatchLingBust3749%092
4PoolHard30%2963
4PoolSoft40%2867
5Pool1145%2276
5PoolSpeed729%1978
6Pool10%6262
6PoolSpeed520%2068
7Pool10%5555
8Pool30%2469
9Pool743%5670
9PoolSpeed10%5353
9PoolSpeedLing30%2571
ZvZ_Overgas9Pool40%2677
ZvZ_Overpool11Gas30%3579
17 openings9331%

#4 daqin

openinggameswinsfirstlast
10Hatch9Pool9gas1118%277
2HatchHydra40%1878
2HatchLurker40%2379
2HatchMuta1323%1789
3HatchHydraBust30%2051
3HatchLingBust3139%1676
3HatchPoolHydra30%2552
4PoolSoft30%653
5Pool30%754
7Pool30%1155
9Pool30%156
9PoolSpeed30%1057
9PoolSpeedLing30%058
ZvP_10Hatch9Pool30%559
14 openings9019%

#5 steamhammer

openinggameswinsfirstlast
9PoolSpeed10075%099
1 openings10075%

#6 zzzkbot

openinggameswinsfirstlast
9PoolHatch10%00
ZvZ_Overgas11Pool7080%170
2 openings7179%


Why are only 71 games recorded? According to the official results, Microwave crashed in 56 games throughout the tournament, and 29 of those crashes happened against ZZZKBot. Microwave recorded every game in which it did not crash. It’s a debugging opportunity. :-/


#8 iron

openinggameswinsfirstlast
10Hatch9Pool9gas20%5382
2HatchHydra10%8383
2HatchLurkerAllIn20%6388
2HatchMuta119%072
3HatchHydraBust1533%577
3HatchHydraExpo10%8484
3HatchPoolHydra10%8585
4HatchBeforeGas40%1889
4PoolHard60%1378
4PoolSoft714%1171
5Pool10%8686
5PoolSpeed60%1479
6Pool20%5487
6PoolSpeed520%3592
7Pool1030%1968
8Pool714%1780
9Pool812%195
9PoolSpeedLing40%2196
OverpoolTurtle40%2281
19 openings9713%

#9 xiaoyi

openinggameswinsfirstlast
10Hatch9Pool9gas20%4247
2HatchLurker10%4848
2HatchMuta20%4546
4PoolSoft3863%138
5Pool250%039
7Pool5176%4999
9Pool250%4041
9PoolSpeedLing20%4344
8 openings10065%


As soon as Microwave found that 7 pool worked, it played 7 pool exclusively.


#10 mcrave

openinggameswinsfirstlast
2HatchMuta4062%079
3HatchHydraBust1392%8698
4PoolHard10%8080
4PoolSoft4062%140
9Pool10%8585
ZvZ_Overgas11Pool450%8184
6 openings9965%


Microwave was late to discover the success of the hydra bust opening. That’s why it was played so little. The example shows the importance of finding good ideas as early as possible. I am adding smarts to Steamhammer to make it better at finding the good tries fast.

It’s interesting that 2HatchMuta and 4PoolSoft have the same numbers, but were given up on at different times.


#11 ualbertabot

openinggameswinsfirstlast
4PoolSoft10082%099
1 openings10082%


The choice against UAlbertaBot was determined by pre-training. From scratch, I expect Microwave would have tried a wider variety.


#12 aitp

openinggameswinsfirstlast
9PoolSpeedLing10093%099
1 openings10093%


If the first try wins, keep it up. What if Microwave had an opening that would have won more than 93%? The theory is that, above some winning rate, the risk of losing by trying alternatives is higher than the risk of losing by sticking with a known good opening. But what winning rate is high enough to stick with? It depends on how much you respect your opponents. If you expect to win nearly every game, like Locutus, maybe you should switch to an alternative as soon as you lose a single game. If you expect to finish near the bottom, maybe you should stick with a strategy that wins 50%.

But more: How much do you respect each opponent? Maybe bots should have a “contempt factor” like chess programs may use to decide whether to aim for a draw: Accept a low winning rate strategy against Locutus, but demand 95% wins against the unknown who you’ve decided is a weak newbie. I would rather call it a respect factor! In a UCB algorithm, a level of respect is implicitly encoded in the exploration rate constant. Does any bot already have a respect factor for specific opponents?


#13 bunkerboxer

openinggameswinsfirstlast
5Pool10099%099
1 openings10099%


Apparently the initial choice against an unknown is random.

AIIDE 2019 - what BananaBrain learned

I wrote a script to analyze BananaBrain’s game history files, which record its experience with each opponent. For now, I had the script summarize the strategies played and the enemy strategies recognized. The history files also record the map and a value that represents the game duration. History files are rich with information, and there are many ways to summarize it. It would be interesting to see how strategy usage and win rate vary by map, among other possibilities.

The same script should work with minor changes to summarize Microwave’s history files.

BananaBrain had prepared history files for the opponents #1 Locutus, #2 PurpleWave, #5 Steamhammer, #6 ZZZKBot, #7 Microwave, and #8 Iron. Data from the prepared history files was not copied into the write directory. That is different from how Steamhammer and Locutus keep their game records, and it has the nice effect that the tables show exactly what happened in the tournament, from BananaBrain’s point of view.

For each opponent, the left table is BananaBrain’s choice. The right table is BananaBrain’s idea of what the opponent did. All the win rates are from BananaBrain’s point of view, so that, for example, when Locutus played P_1gatecore, BananaBrain won 5% of the time. Of course, the opponent’s view of its own strategy is likely to be more fine-grained than BananaBrain’s. To take the extreme case, Steamhammer played 30 different openings against BananaBrain, and BananaBrain recognized them in 8 categories.


#1 locutus

openinggameswins
PvP_10/12gate617%
PvP_12nexus1136%
PvP_2gatedt100%
PvP_2gatedtexpo90%
PvP_3gaterobo50%
PvP_3gatespeedzeal825%
PvP_4gategoon60%
PvP_9/9gate128%
PvP_9/9proxygate90%
PvP_nzcore812%
PvP_zcore40%
PvP_zcorez60%
PvP_zzcore617%
13 openings10010%
enemygameswins
P_1gatecore205%
P_cannonrush297%
P_fastexpand10%
P_ffe1921%
P_unknown3110%
5 openings10010%


As you might expect against Locutus, the best choice was a fast expansion.

Is the single game of enemy P_fastexpand a misrecognition? I suspect that Locutus played otherwise, and BananaBrain didn’t see everything and wasn’t able to draw the right conclusion. Or maybe it’s a bug somewhere. PurpleWave and McRave also show a single P_fastexpand game.


#2 purplewave

openinggameswins
PvP_10/12gate2370%
PvP_12nexus20%
PvP_2gatedt617%
PvP_2gatedtexpo333%
PvP_3gaterobo20%
PvP_3gatespeedzeal10%
PvP_4gategoon838%
PvP_9/9gate2688%
PvP_9/9proxygate1362%
PvP_nzcore30%
PvP_zcore425%
PvP_zcorez540%
PvP_zzcore425%
13 openings10056%
enemygameswins
P_1gatecore5456%
P_2gate2560%
P_2gatefast633%
P_fastexpand10%
P_ffe250%
P_unknown1267%
6 openings10056%


Against PurpleWave, different zealot rushes worked best. Maybe it is because zealot rushes depend for their success more on execution than on the enemy’s strategic reaction. PurpleWave is particularly good at reacting to the enemy strategy, and BananaBrain is good at execution.


#4 daqin

openinggameswins
PvP_10/12gate862%
PvP_12nexus633%
PvP_2gatedt617%
PvP_2gatedtexpo1283%
PvP_3gaterobo714%
PvP_3gatespeedzeal633%
PvP_4gategoon50%
PvP_9/9gate1493%
PvP_9/9proxygate967%
PvP_nzcore743%
PvP_zcore633%
PvP_zcorez743%
PvP_zzcore743%
13 openings10051%
enemygameswins
P_1gatecore8250%
P_unknown1856%
2 openings10051%


BananaBrain made quite a variety of tries, and was most successful with... zealot rush and dark templars, which are kind of different. BananaBrain’s varied opening choice is a strength.


#5 steamhammer

openinggameswins
PvZ_10/12gate15100%
PvZ_1basespeedzeal888%
PvZ_2basespeedzeal1182%
PvZ_4gate2archon757%
PvZ_5gategoon786%
PvZ_9/9gate1292%
PvZ_9/9proxygate15100%
PvZ_bisu475%
PvZ_neobisu250%
PvZ_sairdt7100%
PvZ_sairgoon20%
PvZ_stove1070%
12 openings10085%
enemygameswins
Z_10hatch3876%
Z_12hatch3184%
Z_12pool1191%
Z_4/5pool3100%
Z_9pool1100%
Z_9poolspeed4100%
Z_overpool2100%
Z_unknown10100%
8 openings10085%


2 gate zealot openings work well against Steamhammer—but only when played by PurpleWave or BananaBrain. Steamhammer can usually defend versus a lesser protoss.


#6 zzzkbot

openinggameswins
PvZ_10/12gate17100%
PvZ_1basespeedzeal1191%
PvZ_2basespeedzeal425%
PvZ_4gate2archon450%
PvZ_5gategoon667%
PvZ_9/9gate15100%
PvZ_9/9proxygate367%
PvZ_bisu560%
PvZ_neobisu425%
PvZ_sairdt12100%
PvZ_sairgoon650%
PvZ_stove13100%
12 openings10083%
enemygameswins
Z_4/5pool3385%
Z_9pool17100%
Z_9poolspeed2100%
Z_overpool2365%
Z_unknown2584%
5 openings10083%


I like that BananaBrain varies its opening choice even when several openings win 100%. (Steamhammer does too; if more than one opening has scored 100% so far, Steamhammer chooses randomly among them.) Playing a strong opening gives the opponent one problem to solve (“how do I survive this?”). Unpredictably playing one of several strong openings sets the opponent two problems (“what is this fiend doing, and then how do I live through it?”) which must both be solved, more than twice as difficult.


#7 microwave

openinggameswins
PvZ_10/12gate2090%
PvZ_1basespeedzeal1173%
PvZ_2basespeedzeal333%
PvZ_4gate2archon650%
PvZ_5gategoon875%
PvZ_9/9gate1788%
PvZ_9/9proxygate875%
PvZ_bisu1060%
PvZ_neobisu333%
PvZ_sairdt450%
PvZ_sairgoon20%
PvZ_stove862%
12 openings10071%
enemygameswins
Z_10hatch888%
Z_12hatch3855%
Z_12pool2100%
Z_4/5pool2871%
Z_9pool967%
Z_9poolspeed7100%
Z_overpool3100%
Z_unknown5100%
8 openings10071%

#8 iron

openinggameswins
PvT_10/12gate667%
PvT_10/15gate30%
PvT_12nexus425%
PvT_1gatedtexpo2584%
PvT_2gatedt1060%
PvT_9/9gate1060%
PvT_9/9proxygate475%
PvT_bulldog10%
PvT_dtdrop1464%
PvT_nzcore540%
PvT_proxydt20%
PvT_stove425%
PvT_zcore540%
PvT_zzcore743%
14 openings10058%
enemygameswins
T_1fac3063%
T_2fac10%
T_fastexpand2948%
T_unknown4062%
4 openings10058%


Bulldog! That involves protoss dropping zealots, typically on cliff tanks, with a simultaneous attack by ground. When successful, a bulldog can abruptly break a terran defense that is sound against any purely ground attack. I don’t think I’ve seen BananaBrain play that; I should watch more games versus terran. Can anybody point out an example?


#9 xiaoyi

openinggameswins
PvT_10/12gate1090%
PvT_10/15gate743%
PvT_12nexus520%
PvT_1gatedtexpo11100%
PvT_2gatedt757%
PvT_9/9gate633%
PvT_9/9proxygate617%
PvT_bulldog50%
PvT_dtdrop989%
PvT_nzcore617%
PvT_proxydt771%
PvT_stove875%
PvT_zcore633%
PvT_zzcore757%
14 openings10057%
enemygameswins
T_1fac3757%
T_fastexpand2065%
T_unknown4353%
3 openings10057%


The Stove worked against XiaoYi? Again, XiaoYi shows weakness against tricks. The Stove involves making scouts to harass while teching to dark templar. It should not be hard for a good terran to defend against; notice that Iron dealt with it well enough.


#10 mcrave

openinggameswins
PvP_10/12gate771%
PvP_12nexus650%
PvP_2gatedt667%
PvP_2gatedtexpo850%
PvP_3gaterobo978%
PvP_3gatespeedzeal862%
PvP_4gategoon757%
PvP_9/9gate875%
PvP_9/9proxygate633%
PvP_nzcore1090%
PvP_zcore757%
PvP_zcorez1090%
PvP_zzcore888%
13 openings10069%
enemygameswins
P_1gatecore3474%
P_2gate2665%
P_2gatefast2969%
P_fastexpand10%
P_proxygate4100%
P_unknown650%
6 openings10069%


It looks like most openings performed similarly against McRave, and BananaBrain struggled to identify what worked. I imagine a fierce learning battle, both trying to keep one step ahead.


#11 ualbertabot

openinggameswins
PvU_10/12gate1794%
PvU_9/9gate17100%
PvU_9/9proxygate1385%
PvU_flex1267%
PvU_nzcore1164%
PvU_zcore1688%
PvU_zzcore1377%
7 openings9984%
enemygameswins
P_1gatecore8100%
P_2gate683%
P_2gatefast2171%
P_unknown333%
T_1fac5100%
T_2fac7100%
T_2rax1090%
T_fastexpand3100%
T_unknown5100%
Z_10hatch2100%
Z_12hatch8100%
Z_4/5pool1771%
Z_unknown475%
13 openings9984%

#12 aitp

openinggameswins
PvT_10/12gate7100%
PvT_10/15gate8100%
PvT_12nexus6100%
PvT_1gatedtexpo8100%
PvT_2gatedt7100%
PvT_9/9gate6100%
PvT_9/9proxygate7100%
PvT_bulldog9100%
PvT_dtdrop7100%
PvT_nzcore7100%
PvT_proxydt7100%
PvT_stove9100%
PvT_zcore6100%
PvT_zzcore6100%
14 openings100100%
enemygameswins
T_1fac4100%
T_2fac12100%
T_fastexpand24100%
T_unknown60100%
4 openings100100%

#13 bunkerboxer

openinggameswins
PvT_10/12gate7100%
PvT_10/15gate7100%
PvT_12nexus7100%
PvT_1gatedtexpo7100%
PvT_2gatedt7100%
PvT_9/9gate6100%
PvT_9/9proxygate7100%
PvT_bulldog8100%
PvT_dtdrop7100%
PvT_nzcore6100%
PvT_proxydt8100%
PvT_stove8100%
PvT_zcore7100%
PvT_zzcore8100%
14 openings100100%
enemygameswins
T_unknown100100%
1 openings100100%


BananaBrain apparently does not have a bunker rush recognizer.