archive by month
Skip to content

the story of a trapped drone

In a game Steamhammer - McRaveZ on La Mancha, McRave pulled drones to try to survive.

unsupported drone

But what happened to that one drone that seems to be leaning over the chasm? It collided with other units and was pushed across unwalkable terrain to a new position where it was trapped.

zerglings can’t reach the drone

Steamhammer’s zerglings desperately want to get at that drone, but they can’t... quite... reach it. The zerglings were nearly useless for the rest of the game, distracted by the stuck drone every time they reached the enemy base. Steamhammer floundered until it finally remembered that mutalisks are also a unit it can make.

Here is the walkability map. Steamhammer actually checks that it can reach the drone target, but the check is incorrect in this case: There is a narrow corridor, one walk tile or 8 pixels across, leading to the little platform where the drone waits. No unit is narrow enough to walk there (even a ghost is 15 pixels wide), but Steamhammer doesn’t know that.

8x8 walk tiles

The imprisoned drone illustrates a flaw in the map design: Accidents should not push units into places where they will be permanently trapped. Freakling would never allow such a blunder! Of course it also illustrates a bug in Steamhammer. The bug makes a regular appearance on a few maps, like Fortress, but this is the first time I’ve seen it affect play on a regular SSCAIT map.

Next: Steamhammer status. Soon: Some of Steamhammer’s best recent games.

the strange question of reaching a refinery

You’ve located an enemy refinery building and you want to know whether your ground units can walk there to attack it. Is it on ground that they can reach, or on an island? For other buildings, Steamhammer solves the reachability problem with a partition map: Areas reachable by ground from each other are in the same partition, and 2 simple lookups tell it whether one point is reachable from another.

Refineries are trickier. First of all, a geyser is not walkable ground, so properly speaking it doesn’t belong to any partition. The same for a refinery built on it; every other building is built on ground that can be walked over after the building is destroyed. This actually causes a rare bug in Steamhammer, where the ground squad understands that it cannot attack an island—except for any refinery that may be on the island, it may attempt to attack that! It knows that a refinery building is a special case, but it doesn’t understand the special case correctly.

Of course, the problem can be solved by filling in the partition map for the refinery with the partition that the geyser is in. “Of course”? No, actually it can’t: The geyser itself might be part of the unwalkable terrain between partitions. Imagine a wall on the left and a wall on the right, and a geyser plugging the gap between them. North of the geyser is one partition, south might be a different partition, and there is no way to walk from one to the other. The geyser, and any refinery you build on it, is adjacent to 2 partitions but doesn’t belong to either.

This actually happens in an even more complicated way on maps like Gold Rush and a number of others, where two assimilators form a gate. An assimilator is smaller than a geyser (protoss space warp tech, no doubt), so if you destroy the eggs between the assimilators, units can pass through. But if you destroy the assimilators the gap disappears and the bare geysers block passage. A bot needs sophisticated knowledge of the game to understand the effects.

assimilator gate

I haven’t chosen a way to fix it yet. But it’s clear that geysers and refineries have to be treated with special care.

resource tracking progress and thoughts

Today I put in the workaround for yesterday’s visible vespene BWAPI bug. Steamhammer now considers the gas reserves of an enemy refinery to be inaccessible. At the same time I fixed a rare bug that could briefly give a gas supply of 0, handled mineral and gas amounts of 0 in a more informative way, added features to improve the debug display, and made unnecessary efficiency improvements (“the cost is negligible—but—but—look how much I can reduce it!”). It added up to refactoring most of the code, but there’s not much of it so it wasn’t long.

Some later day I’ll add tracking of the bot’s own mining. Any minerals or gas missing from the map that Steamhammer did not mine were mined by the enemy, putting one lower limit on the enemy’s total resource gathering. Another lower limit comes from counting enemy units. The first use of enemy mining information will be for scouting: Overlord thinks, “these minerals have been mined, I don’t need to fly any farther to know that the base has been taken.” Look at the map Python. An overlord moving from the base at 3 to the base at 12 will encounter the mineral patches first, and can see that they have been mined before it comes into the sight range of any worker doing the mining. Identifying the enemy base even seconds earlier is an advantage worth taking.

The enemy’s resources will be valuable for strategy calculations. The same overlord on Python can judge whether the enemy is playing a low-econ strategy even before it gets close enough to count the enemy workers. The total resources mined by the enemy, as long as we have it, tells us about the enemy plan. It’s possible to find a hard upper limit too, but it seems complicated to get an upper limit that’s tight enough to be useful. Workers can be made this fast, bases can be taken this fast, a mineral patch can be mined this fast, it’s not as simple as counting stuff on the map.

In the long run, I envision an enemy resource usage estimator that takes visible resource amounts as only one source of information. Saved game records in the opponent model would be another, and a library of known strategies might be another. It feeds to an opponent plan recognizer, which feeds to a strategy planner. In my mind, resource tracking is a step along the path to smart strategy adaptation.

Stepping back to take a wider view, there are two ways to be smart: You can learn stuff like CherryPi with its neural networks, or you can calculate stuff like FAP—you can use knowledge or you can use search. I think you should ideally use both, like AlphaZero, because they support each other. Calculated limits on the unknown value of the game state are good inputs to help a machine learning algorithm.

the joy of inferring tech buildings

The picture is from a test game against the built-in AI. The columns on the right are a new debug display. The game was played to test an unrelated new debug display, which is not showing. Because of a newly-introduced bug (success! I’m introducing new bugs as planned!) Steamhammer had trouble against the built-in AI and did not win until late.

test game screencap

The green unit types on the right are Steamhammer’s units. White is the count of completed units, yellow is the count of uncompleted units. Hmm, 19 uncompleted zerglings, an odd number? That is because 2 zerglings in an egg may not hatch at exactly the same time.

The orange unit types are the enemy units. The white numbers count enemies that have been seen, and the red numbers are inferred enemy buildings. For example, Steamhammer has seen observers, so it knows that there must be a robo fac and an observatory. But wait, why are there a hatchery, a hydra den, and a spawning pool among the inferred enemy buildings?

Ha ha, protoss mind controlled a lurker! It’s there on the list of enemy units. Bug 1: The building inference code doesn’t know about mind control. Bug 2: The code also does not know that lurker research implies a lair.

Bug 1 takes effort to fix in full generality, because you have to remember what units the enemy has mind controlled, and Steamhammer doesn’t track that (or need to for now, it’s rarely important). If enemy protoss mind controlled your carrier, you can’t infer from that carrier that the enemy has a stargate and fleet beacon. If enemy protoss mind controlled an SCV and never mind controlled a marine, then you would like to infer a barracks from seeing a marine. For now I put in a simple workaround: Require an inferred building to belong to the same race as the enemy. That will reduce the errors, at least.

Mind control is a very sharp corner case, it can cut.

Bug 2 I decided also to leave unfixed for now, because there is another bug hiding behind it, related to zerg. Inferring buildings from tech adds complexity. If you have seen 1 enemy hatchery and later see a lurker, implying a lair, does that imply that the enemy now has 1 hatchery and 1 lair? No, the hatchery might have morphed into a lair. In effect, a lair is a hatchery and a hive is a lair, but not the reverse. Similarly if you see a guardian, implying a greater spire. Most tricky.

Steamhammer skill kit

As a teaser, here is a code snippet from the Steamhammer 3.0 development version.

void SkillKit::update()
{
    for (Skill * skill : skills)
    {
        if (skill->nextUpdate() <= the.now())
        {
            skill->update();
            if (skill->feasible() && skill->good())
            {
                skill->execute();
            }
        }
    }
}

(the.now() is short for BWAPI::Broodwar->getFrameCount(), the current frame number.)

The skill kit doesn’t actually add skills as such, it adds control of skills; to “execute” a skill means to set flags or post goals or otherwise send orders to the rest of the program to carry out the skill as directed. The skill controller can run every frame if it likes and change its orders at any time. There are two main features. 1. The skill kit is extensible: It is easy to write your own skill controllers as subclasses of Skill and drop them in. This is good for modularity and especially good for people who fork Steamhammer. 2. The skill kit provides an easy interface to the persistent opponent model files. A Skill can include one method to write its data to a string, and one method to parse a string that it wrote back into data, and the skill kit takes care of the I/O plumbing.

As I use the skill kit for more things, Steamhammer will become much more flexible in adapting to its opponents.

Soon: Tournament design is hard.

Steamhammer and bugs

I’m pleased with Steamhammer’s reliability this tournament. I watched all 88 games, and for the first time ever I saw no losses caused by crippling bugs. There were 2 games with terrible play due to bugs, but in both cases Steamhammer recovered and won anyway. There was also a bug that occasionally caused multiple drones to be sent to fail to scout the enemy: Lose one, send another, repeat. That would lose games for sure against an even opponent, but in practice it occurs in games that Steamhammer will lose no matter what. I think I know the cause, and it will be fixed soon.

I surmise that Steamhammer is especially prone to reliability problems because it aspires to do everything. It plays over 150 opening builds of all kinds; failing to adapt to all the misadventures of the opening causes a lot of snags. I count only 3 zerg abilities yet to be implemented: Nydus canals, infested terrans, and lifting off an infested command center, all on my list for coming months. (Drop is technically implemented even though not yet used by zerg. I guess overlord sight range is not implemented either, but it’s trivial if I ever want it.) More features means more bugs; fixing bugs in defiler play was a big time sink last year.

Another source of reliability hitches is my habit of swapping in new plans as fast as I can make them. A number of Steamhammer’s internal modules are half-rewritten, stuck in the middle of a transition from an old design that is not flexible enough to a new design that is not finished enough. It would be more efficient to complete one task before moving on to the next. But then I would be making progress on only one front at a time, and it wouldn’t be as much fun. I like the variety.

Anyway, after burnishing the 2.x versions for over a year, I’ve remedied almost all of the worst bugs. It is past time to get back to major features and structural work, so that I can add a new round of bugs. To symbolize that, I’ll be calling the next version 3.0 even though it doesn’t in reality have any new feature worthy of a major version number. It will in time.

Steamhammer in the SSCAIT elimination phase

As I write, the SSCAIT round robin phase is close to its end, and though the top 2 places are undecided, most of the top 16 ranks are either mathematically fixed or highly unlikely to change. I am able to forecast part of Steamhammer’s path through the final elimination phase with only moderate risk of error.

Steamhammer will finish #11, the same as last year. It’s the middle of the range #10-#12 that I predicted on 29 December.

BananaBrain and Iron are tied for #5-#6. I don’t know how the tie will be broken for pairing purposes, because they scored 1-1 against each other. Perhaps it will be broken randomly. It matters for Steamhammer, because if the pairings work the same as last year, #11 Steamhammer will be paired against #6.

suppose #6 Iron

A stroke of luck. #11 Steamhammer 3-0 #6 Iron in the first round, or at worst 3-1, the same round 1 result as last year. In the second round, Steamhammer should face #3 BetaStar, which will win crushingly, still the same result, pushing Steamhammer into loser’s bracket round 2. There, Steamhammer is likely to face #16 TyrProtoss, which will be a close match that I can’t call. In the last two weeks on BASIL, the score is Steamhammer 13-11 TyrProtoss. In the SSCAIT round robin, the score is Steamhammer 1-1 TyrProtoss. Last year, this is that match that eliminated Steamhammer. If Steamhammer does win, surviving longer than last year, its next opponent in the loser’s round 3 is harder to forecast, and the match could again go either way—though I think Steamhammer is more likely to drop out here than to go on. It’s funny that this path is so nearly the same as last year, and maybe longer even though Steamhammer is probably relatively weaker.

suppose #6 BananaBrain

Though Steamhammer 2-0 BananaBrain in the round robin thanks to my preparation and/or luck, BananaBrain is likely to win this match. BASIL shows Steamhammer 2-14 BananaBrain. In this case, Steamhammer is likely kicked out at once.

Yeah, elimination tournaments are very sensitive to pairings and lucky results. Which means that something entirely different could yet happen.

experience with Steamhammer’s burrowed zerglings

Steamhammer’s ostensible Killer Feature or tournament surprise was burrowed zerglings to block the opponent from taking nearby bases. The lings are assigned to Watch squads to watch the bases, and burrow there as soon as burrow is researched. How did it work out? Do the Watch squads contribute to Steamhammer’s strength?

My conclusion: Yes. The cost is the expense of researching Burrowing (100/100) plus the assignment of up to 4 zerglings to watch enemy bases, taking them from other duties. It’s reasonably low. To pay that back, burrowed zerglings have to gain intelligence or delay enemy expansions. A few opponents, like Tscmoo, know what to do about burrowed zerglings and send detection and force. Even so, the intended expansion is delayed, and Tscmoo then starts the base immediately so that the zergling’s residual vision sees it and Steamhammer can react instantly. It’s already worth the cost. Other opponents treat a burrowed zergling the same as a spider mine, which is not always astute. XIMP sends a zealot to “trigger the mine” with no effect; the burrowed zergling continues to block the base until carriers fly over with an observer. It’s no better when terran scans and tries to kill the “mine” with an SCV. Some opponents don’t react and can’t deliberately expand at all; they are stuck until the zergling is removed by mischance. In many cases, I think Steamhammer would benefit by researching burrow earlier. There is virtually no effect against zerg, because by default the strategy boss researches burrow when Steamhammer has 3 bases, and that is late game in a ZvZ.

A couple issues limit effectiveness. First, the zergling unburrows when it knows that it is detected—and then it forgets and reburrows at once, going into a loop. The intention was to stand up and fight or flee when necessary, but there was a bug. Second, in an emergency when all other zerglings are killed, the last watching zergling unburrows and races home to join in the defense. But one zergling running in from afar barely affects the fight, and the enemy becomes free to expand without hindrance. After seeing games, I concluded that it will be more effective to leave the last watcher in place. Both issues are fixed in the development version. Overall, this is a low rate of errors compared to other new features I’ve made; care in testing paid off.

Against some opponents, the Watch squads do little good and represent mostly cost. The best example is Tyr protoss, which against Steamhammer plays one-base cannon defense into timing attack. When the attack comes, it includes an observer and the oncoming steamroller incidentally rolls up the zergling burrowed in the natural. Steamhammer pays the cost, and Tyr bypasses it with no effort. Blocking later bases sometimes helps, though. Another example is Iron, which likes to build turrets before it starts the command center. The burrowed zergling at most gets to see a turret or two. At some point I will put the Watch squads into the upcoming opponent model skill system and have Steamhammer collect data on how well they work. That will help Steamhammer research burrow at the right timing, as late as possible while effective against this opponent, and never if it is never effective.

I have more uses in mind for burrow. In particular, I want to use it to protect drones from some attacks. Reaver drops usually don’t include an observer, so when the reaver lands, the drones should poof out of sight before they can be targeted. When the reaver is picked up, the drones casually reappear and continue work. That will be funny to watch.

Steamhammer’s opponent model

In the tournament, the ranks are starting to resolve. Outside the collapse of McRave, I don’t see any big surprises. Locutus has played fewer games than other bots, so the top position is less clear than others. Steamhammer is likely to finish around rank #10-#12, in the range of past performances, so it is safely in despite my worries.

In development, resource tracking was soon working. When destroying an enemy base you normally get to see the resource counts, so used bases should be evaluated accurately.

I started writing a scout boss, then I got distracted by another project. I am refactoring gas steal into one skill in a skill system that retains data in the game records of the opponent model. You subclass a Skill object, fill in around 8 virtual methods of which most are simple, and you get opponent modeling that estimates when the skill is useful against whoever you’re playing now. Since it’s implemented in code, it’s highly flexible. You can choose what data to record, including measurements of how successful a skill was in the current game, and how to interpret the data.

The immediate effect I hope for is better gas steal decisions. Steamhammer’s new queen skills are also good candidates, because queens vary from useful to wasteful. Will a queen be good? How many queens? Will ensnare be good? Even tactical decisions like “play defensively until time t” should be possible, with t adjusted in real time as the opponent model watches the game unfold. I like the idea of learning to adapt tactical play to the opponent.

The game record file format will change. The format has to change soon anyway, because it doesn’t record all the information needed for some important strategy decisions. I designed it so that I can add new format game records without having to discard old ones.

Steamhammer 2.4.2 change list

Steamhammer 2.4.2 is available as source from Steamhammer’s web page. The documentation is updated too. As far as game play goes, it is identical to version 2.4.1 in the SSCAIT annual tournament. The main difference is that Steamhammer can automatically recognize when it is running under SCHNAIL and treat its opponent as a human.

I hope SCHNAIL testers will let me know how it goes, so I can adjust the behavior against human players.

Here is what’s new.

configuration

  "Skills" :
  {
    "SCHNAILMeansHuman"       : true,
    "HumanOpponent"           : false,
    "SurrenderWhenHopeIsLost" : true,

    "ScoutHarassEnemy"   : false,
    "AutoGasSteal"       : true,
    "RandomGasStealRate" : 0.0,

    "Burrow"             : true,
    "MaxQueens"          : 1,
    "MaxInfestedTerrans" : 0
  },

• The SurrenderWhenHopeIsLost, ScoutHarassEnemy, AutoGasSteal and RandomGasStealRate items are moved from the Strategy section to the Skills section of the configuration file.

• An internal flag Config::Skills::UnderSCHNAIL is added. It does not appear in the configuration file but is set by code. It is true when Steamhammer detects SCHNAIL’s schnail.env file in the read directory. Code can use this to do something different when running under SCHNAIL; it may be useful someday.

• A flag SCHNAILMeansHuman is added. If UnderSCHNAIL and SCHNAILMeansHuman are both true, then Steamhammer overrides the configured value of the HumanOpponent flag and sets it to true.

In other words, if you set SCHNAILMeansHuman to true, then whenever Steamhammer is running under SCHNAIL, it will assume that its opponent is a human. That should almost always be what you want. If it’s not what you want, you can turn off SCHNAILMeansHuman and set the HumanOpponent flag by hand.

• Steamhammer messages “gl hf” at the start of the game if it thinks the opponent is human. It actually wishes the human to have bad luck and suffer torment (BLAST), but it doesn’t mind lying. The real purpose of the message is so you can tell whether the HumanOpponent flag is turned on when it should be.

• The game message was formerly messed up. I think I finally fixed it.

• In the IO section of the config file, I separated Config::IO::PreparedDataDirectory (bwapi-data/AI/om/ for prepared opponent model files) from Config::IO::StaticDirectory (bwapi-data/AI/) for reasons of what I prefer to call clarity. The change doesn’t affect anything but a name in the code.

Steamhammer 2.4.1 change list

Steamhammer 2.4.1 is the version for the SSCAIT 2019 tournament. Version 2.4.2 with source release should follow shortly with only one significant change, SCHNAIL recognition.

For the tournament, I replaced the SSCAIT learning data with data from BASIL, because BASIL has more games that are recent. There are downsides; it could be that it was a mistake. I made a small number of hand edits to the learning data. For example, for StyxZ, I deleted games from before Styx was updated and suddenly became strong. I edited data for 7 opponents in total, usually just altering one game record.

First an explanation of my supposed Killer Feature, then the change list proper.

the Killer Feature

The “Killer Feature,” which is no more deadly than your average killer app, is to burrow zerglings at bases that the opponent is likely to want to take soon. CherryPi did this a couple of years ago, and I was surprised that bots which know how to cope with spider mines laid to block base locations were often unprepared for burrowed zerglings doing the same thing. Two years later, bots which remain unprepared may get into trouble. Burrow has many many uses, and Steamhammer will take advantage of more of them in the future; in choosing a burrow skill, I am looking ahead. There are 3 parts to the system.

The strategy boss by default researches burrow after Steamhammer takes its third base. If the opening build takes three or more bases, it starts the research shortly after the opening. This is late enough in the game that the research is not a major expense, but it does lose the opportunity to exploit burrow early on.

The 9PoolHatchBurrow opening researches burrow much earlier. It is for use against opponents which may be vulnerable. 9PoolHatchBurrow is a variant of the Styx opening which collects 200 gas instead of 100 and researches burrow immediately after zergling speed, trading some of the zergling punch for the burrow ability. The two upgrades finish at almost the same time, because burrow (1200 frames) doesn’t take as long as speed (1500 frames). The aim is to get burrow early while pressuring with zerglings, and try to burrow a zergling in the enemy’s natural to delay or displace the expansion and mess up the enemy’s build. Burrow normally finishes before the enemy has scan or observers, so even an opponent which knows how to react may be delayed.

I tweaked the learning data so that this build will be given a try against a few opponents.

The Watch squads are for scouting and base denial. The design attempts to gain the most impact with the least investment. The combat commander creates from 0 to 4 Watch squads (depending on Steamhammer’s ground strength and other factors) of 1 zergling each, and assigns the squads to watch the bases closest by ground to the enemy main. It may also assign overlords to watch further bases, but usually by the time there are overlords to spare, it is not safe to assign them. A Watch squad behaves like any other squad, except that if a squad member finds itself at the order position and is able to burrow, it does. (It’s literally a few lines of code.) Once at least one zergling is under the ground, the combat commander attempts to keep the most important Watch squad on station despite any reverses, because to disband it would throw away the investment.

When Steamhammer decides to expand to a base, any Watch squad stationed there is disbanded immediately. The zergling unburrows and joins the ground army long before the drone trundles in to make the hatchery. The disbanding is 1 line of code in a condition in the combat commander, and the unburrowing and leaving is standard behavior that was written into the squad long ago. The whole Watch implementation is as simple as I could make it.

I’m eager to see how the Watch implementation works in practice. When Steamhammer faces a full range of opponents, the results of a new feature are always more complicated than I see in my testing.

configuration

• I added a new configuration section Skills which is intended to separate out some items from the long Strategy section. For now, it has Burrow, MaxQueens and MaxInfestedTerrans items. Later I’ll move some items over from Strategy.

For this SSCAIT, Burrow is true, MaxQueens is 1, and MaxInfestedTerrans is 0. The strategy boss is willing to make up to 2 queens, but I decided that the second one probably costs more than it is worth for now. Steamhammer has a bug in the production system that prevents it from making infested terrans, so it’s better not to try.

infrastructure

UnitInfo keeps track of whether a terran building was lifted when it was last seen. For some reason I resisted doing this earlier, but it’s important information. The first use is in squad targeting, when checking whether an enemy building is a good target for a given squad.

• Another use of the terran lifted building info is a new skill: If all known enemy buildings are lifted and all known enemy units are air units, Steamhammer will only include anti-air units in its unit mix. It sounds obvious, but ultra-ling is a potent way to finish off a zerg or protoss which has only air units left, and is only weak versus terran that has lifted buildings. This skill is intended to solve a rare difficulty in finishing off a terran—I have seen it happen in only 2 games.

• Don’t try to expand to a base which is known to be blocked by an enemy building or burrowed unit. There’s no point in sending a drone to build on top of a spider mine which has been scouted. This also, of course, checks whether the building is lifted.

• Efficiency fix: Use base->getTileDistance() precalculated ground distances in some places instead of recalculating the distances.

Config::Debug::DrawMapDistances now draws tile distances from its current main base rather than from its starting base. You can see what Steamhammer considers to be its current main base, which may change during the game.

• I removed the unfinished and unused Region and Regions classes. I had forgotten they were there.

zerg

Research Burrow, if enabled in the configuration, usually just after the third base is taken. The strategy boss will delay the research for some emergencies or if the economy doesn’t justify it.

The Watch squad scouts and denies bases. It is implemented for zerg only. Other races don’t have enough cheap units to dedicate some to sitting around, and are better off with the Recon squad alone.

A critical bug in upgrade checking could cause production freezes. Ouch. Fixed.

• In ZvZ, get +1 melee attack instead of +1 ground carapace as the first ground upgrade. It’s cheaper, and it’s what humans usually do. I think the theory is that killing drones faster is more important than a small edge in resisting mutalisk bounce attacks.

openings

The 9PoolHatchBurrow opening is added. See above.

• Minor tweak to ZvP_3BaseSpire+Den. It gets 1 more drone.

Steamhammer and next steps

Last night I dreamed that my hatcheries came under air attack by fire-breathing dragons. I had to defeat them with scourge. Did you know that dragons are as tough as battlecruisers or carriers? Six scourge each, it takes a lot of gas to shoot them down!

Meanwhile, Steamhammer is ready for SSCAIT, and has been for a few days. I have been running tests, finding that all is good enough, and refusing to make other fixes or changes. SCHNAIL recently added a file so that bots can recognize when they are running under it, and I even skipped checking for that to reduce the small risk. The Killer Feature works as intended and causes headaches for some opponents, though by no means all. I expect it will be good for several wins, and certain amount of “Ah, now I have to be ready for THAT?” Whatever makes Steamhammer’s play more complex and interesting is worth having.

Immediate plans: Steamhammer 2.4.1 change list shortly after SSCAIT submission closes. Then Steamhammer 2.4.2 a little after with one more change, SCHNAIL recognition so that running under SCHNAIL automatically turns on the HumanOpponent flag. I’ll release source for the 2.4.2 version.

What should I do next? Here are the fixes that would make the biggest difference in the short run:

• Overlords, surprisingly, are not handed out for free. Keep them safe.
• Don’t transfer drones by the dozen through the enemy army.
• Correct gross weaknesses in defense.

The development plan calls for strategy adaptation work. Next steps I could take toward that include:

Improved scouting.
Production goals.
• Opening timing for decision making.

Then there’s the fun stuff. I wrote down about a dozen different tactical tricks suitable for zerg (and a few more that only other races can play), ranging from proxy hatchery to stop lurkers. Three of them are played by current bots, one other in past years by a long-defunct bot, so there is opportunity to surprise opponents. I imagine a bag-of-tricks meta-skill that combines information to decide when to try a trick: Map analysis (“aha, the main has a back door”), cost estimates and success rates, the game situation, and opponent model data. Of course it would record results in the opponent model, so it could learn how to exploit different opponents. That would be cool in itself, and it would also provide a way for forks to customize their behavior.

Looking over the possible next steps, I see some overlap. Overlord safety, drone transfers, and improved scouting all benefit from pathfinding skills. Pathfinding is basic and can improve all movement decisions, so sooner is better. Path analysis skills are useful for many of the tricks. Also overlords are good for scouting, so overlord safety and scouting are closely related. I think I will add pathfinding and overlord skills soon.

prep for the SSCAIT annual tournament

I’ve disabled Randomhammer on SSCAIT in preparation for the tournament. It’s less than a week away.

For Steamhammer, I am trying to overcome my usual deadline intolerance. I fixed one critical bug, and now I am concentrating all my effort on my Killer Feature. Whether it will kill anything is an open question, but it will be fun, and above all it should be finished and tested and tuned by the deadline. I’ll be satisfied if it can catch out a few strong opponents.

As usual, the big improvements promise to arrive after the tournament. I am adding, or on the verge of adding, basic skills that promise stronger play, and it is impossible to exploit new skills fully in a short time. I expect to soon have the infrastructure needed to add nydus canal support, though I don’t know whether I’ll actually add it soon. Nydus canals make island bases much more useful. I am very tempted to delay strategy adaptation work to add a bag-of-tricks meta-skill that knows how to select from a bag of tactical ideas to pose problems to different opponents. I know a lot of tricks that promise to be effective in specific situations.

In the arena of unimportant abilities, it’s tempting to fill out the queen skills. Steamhammer is capable of controlling a fleet of queens simultaneously without blowing out the per-frame time limit, but they tend to all simultaneously broodling the same target. Queens tend to carelessly fly into danger and die, and at the same time do not know how to fly around freely and seek their own targets—they wait for targets to wander into range. A bug in the production system prevents Steamhammer from producing infested terrans, but I’m not fixing the bug yet because it doesn’t have the skill to control them properly. Infested terrans are powerful but must be used carefully, for example dropped from overlords or coordinated with defilers. That’s something I may work on gradually over the next year.

Upcoming: I want to time a few other openings the same way I timed the Styx opening, to compare them. I think it will be enlightening. And I still hope to get back to the AIIDE tournaments and do more analysis; we’ll see if I can pull it off.

a couple games to distract you while I work

I have to write some code to analyze the Styx opening and its variants. Don’t get bored though, here are a couple Steamhammer games to tide you over.

When Locutus plays its dragoon unit mix, it knocks over Steamhammer with no apparent effort. In Steamhammer-Locutus on Heartbreak Ridge it instead chose a zealot-archon unit mix, and brought about a tempestuous brawl. Something similar happened in one AIIDE game.

In Steamhammer-Ecgberht on Fighting Spirit, Steamhammer was clumsy and fell into a losing position. But Ecgberht was not faultless either, and Steamhammer held and started to fight back. Watch the adventures of the zerg queen.

Steamhammer scouting thoughts

Good scouting is a prerequisite for strategy adaptation, and right now Steamhammer’s scouting skills are mediocre.

The ScoutManager controls early game scouting. In the original UAlbertaBot, the scout manager controls the worker scout. Steamhammer extends it to also control one overlord—and that’s all. It coordinates the two units to scout efficiently, but it can’t make use of the zerg’s second overlord, much less any other unit. Furthermore, the scouting paths don’t extract as much information as possible. When the scouting overlord arrives, it sits in one place and has no chance to see buildings started far away. The scouting worker does explore the base, but doesn’t evade defenders and often gets stuck on buildings. The enemy natural is scouted incidentally, if at all.

Steamhammer scouts in the middle game with its Recon squad, a small group of combat units that visit empty bases to see if perhaps they are no longer empty. The squad attacks any undefended buildings or weak enemies that it happens across, and the behavior of zipping across the map in every direction incidentally finds and interferes with a lot of enemy activity that would otherwise go unnoticed: Enemy scouts, abandoned proxy buildings, worker transfers, isolated reinforcements.... The Recon squad is effective, it doesn’t need any changes for now. But it should not be the only form of middle game scouting.

Steamhammer does no deliberate scouting of known enemy bases (after the early game scout), or of possible enemy movements (ever). It sees the enemy move out because its army is normally trying to push forward as far as it can, and it learns what is in the enemy base when an attack reaches that far (or occasionally when it parasites a unit that returns home).

There is a connection with overlord safety. Steamhammer does not know that most maps provide overlord posts where a correctly positioned overlord can safely watch passing enemies. Wraiths or corsairs spoil the party, but until then overlords can ordinarily see when the natural is taken, and see enemy units move out, and spot them as they pass key points, without danger and often without being seen in return. I don’t know of any bot that takes proper advantage of overlord posts.

what do do?

Some bots have a thing like a scout squad: If you want to look around the map, throw whatever units you prefer into the squad, and the squad coordinates them. That’s a step up in generality from Steamhammer’s scout manager.

The scout squad has decisions: Run around the map, or post units at key locations, or some of both? Just look, or harass or fight when it makes sense? If planning to fight like the Recon squad, how big should the groups be? For example, when a pro scouts with scourge, they commonly send 2 scourge, and if a corsair shows up, the scourge have a point to make. The simple scheme of dispatching individual units around the map doesn’t do everything you’d like.

I’m thinking of implementing scouting with 2 squads plus a scout boss that can hand off scouting goals to other squads.

The Recon squad would be little changed from now.

The Watch squad would be responsible for watching over key points with more or less stationary units. It might post single zerglings in likely enemy expansions, or set units to oversee choke points. Like the Recon squad, it would feel free to fight when it saw an advantage—you want to expand here? Fine, see if your probe can beat my zergling. The Recon squad would only visit bases that are not being watched. The size of the Watch squad might be 1 zergling early, and it might replace the Recon squad entirely later in the game. Steamhammer already has some code for the Watch squad, but it’s not in a usable state.

The Scout Boss would maintain goals: A set of things that we’d like to find out if we can, with priorities. At the start of the game, the goals would be to explore starting bases to find the enemy. When the enemy is found, some goals disappear and new goals appear to seek out what the enemy is doing. Later in the game the set of goals could become extensive—we saw a zealot at (x, y), is it still there? Ideally, in Candide’s best of all possible worlds, the Scout Boss should be smart enough to tell when it is worthwhile to sacrifice a unit for more information: How big is the enemy army? Run one zergling in. How many barracks are in that base? Sacrifice an overlord to find out.

A Scout squad can ask the Scout Boss for its goals. So can other squads. When Steamhammer’s mutalisks back away from an over-strong enemy force, they assume that the force will stay there and they remain backed away, wasting time doing nothing. The Scout Boss will want to know where that force goes, and can prompt the mutalisks to return and look. Or the Scourge squad can accept scout goals, and the Scourge squad has the knowledge that scourge should commonly fly around in pairs—or in triples if expecting scouts, something a general scout squad should not have to understand. (2 scourge kill most flyers, but a scout needs 3.)

Anyway, that’s the line I’m thinking along. Maybe I’ll start on it in January.

Soon: Analysis of the Styx opening and variations.

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.