archive by month
Skip to content

many ways to beat Steamhammer

Steamhammer’s elo stabilized over 2300 before the last mini-tournament. It is clearly the strongest version yet. Randomhammer’s elo rose to around 2100, as I forecast. All races are stronger than before.

Then Steamhammer’s elo crashed during the tournament. 5 Pool had just learned how to beat it, and Tscmoo protoss finally settled on its winning opening too. Also of course it was playing a larger proportion of games against Iron and Krasi0, and against Killerbot by Marian Devecka, which this Steamhammer scores about 50% against.

After the tournament, with 5 Pool disabled, Steamhammer’s elo still hasn’t recovered. It hovers around 2200. Tscmoo protoss hasn’t forgotten its winning opening. Also the zergs Ailien and Microwave have improved to beat it more often, getting better air defense and reducing their strategy mistakes. Even lower-ranked protoss Lukas Moravec has been winning games with its zealot rush, stealing gas in some games. Steamhammer doesn’t work around the BWAPI geyser bug and its game plan is derailed by a gas steal. I think Steamhammer’s #3 rank (since lost) and its status as the handle of a fork with many tines made it a target, and since it has plain weaknesses, people have figured out how to exploit them. Or maybe they’re trying to reprioritize my to-do list, “This is the important weakness, please help.” :-)

Meanwhile, I’ve been spending most of my effort on skills for protoss and terran. The next Steamhammer will come with protoss DT drop and terran vulture drop, but no zerg drops. Overlords are more complicated, and I decided to save it for later. (Getting drop to work at all needed a mess of code changes across classes: CombatCommander, Squad, SquadOrder, MicroManager, other micro classes, StrategyManager—and that is accepting the limitation of dropping a fixed set of units, once, from one dropship or shuttle, and then transitioning out.) Terran will track its use of scan and have more infantry skills and smarter tanks, protoss will support more unit types and use them, both will have more transitions and other improvements. Also I’m making micro changes for all races which add flexibility but require tuning, so there may be new micro weaknesses until I figure out what works.

I hope to get in zerg specific improvements to overcome the biggest weaknesses. I know what to do, but the list is long and I’m not sure how far I’ll get. Anyway, the bottom line: I can’t promise that the next version will be stronger. What I know for sure is that it will be more interesting.

And I can’t wait to get back to zerg.

many ways to beat XIMP

I enjoyed this game of m-khan’s KaonBot versus XIMP by Tomas Vajda, showing another way to beat the carriers.

As I write, KaonBot is rated about 1900, so it is a slightly worse than average bot. I would say that it is at the high end of the low-ranking terran bots. KaonBot goes mass marines every game (with medics and upgrades), which is a severe limitation, but it has above-average smarts in adapting its economy to the situation. Against XIMP, KaonBot quickly took the entire map, except the island bases. XIMP could not get a third base because they were all taken!

Marines are deadly efficient at shooting down interceptors, because they do normal damage rather than explosive damage like goliaths, dragoons, or hydralisks. The picture shows marines fighting interceptors and cannons. The carriers could not keep interceptors in the air. This first infantry force was not enough to clear the cannons, but a later one was.

marines versus carriers and cannons

KaonBot seems to score around 50% against XIMP, which is pretty good.

Ways to beat XIMP, with example bots:

  • cloaked wraiths - WOPR by Soeren Klett (with goliath-tank followup)
  • goliaths - Krasi0
  • marines - KaonBot
  • tanks - Tyr by Simon Prins (wipe out the cannons before the carriers are out)
  • ghosts - nobody yet?
  • hydralisks - Killerbot by Marian Devecka
  • hydra-scourge - UAlbertaBot by Dave Churchill (special build order for XIMP)
  • ultralisks - Ailien (ignore the carriers, kill the bases)
  • dragoons - Steamhammer playing protoss (with a 13 nexus build)

Protoss has the most trouble against the carriers, but when Randomhammer rolls protoss, it goes with a straightforward nexus-first build that produces enough units to break the cannons. AIUR does the same thing sometimes, though not as consistently. If you get far enough ahead in macro, it should be easy to win with almost any strategy.

It should be, but it isn’t always. Steamhammer zerg still struggles against XIMP, losing games due to several bugs and limitations. On 2-player maps Steamhammer doesn’t finish its opening build order, and depending on how it scouts, it may not make a spire (which makes the win easier). In the most recent game, Steamhammer took many bases and crushed XIMP’s natural and main with ultralisks, leaving only the protoss third, then lost by streaming ultra-ling into the empty protoss main to be slaughtered by carriers until zerg finally mined out. It’s a combination of a scouting limitation, a tactical limitation, and an expansion bug. Too much to fix!

Krasi0 and other updates

I count 10 bots updated since the mini-tournament. That’s a lot. 5 Pool started losing some games and was disabled, with a message “Want to create a bot which doesn’t only 5 pool.” I think the strategy is showing its limits. Once you’ve seen the range of followups, it seems to me not all so hard to counter all of them.

I miss Pinfel, disabled before the mini-tournament with a losing score of 3-10. It played a zealot-probe all-in bringing every single unit, unlike any other bot. I recommend occasional all-ins for strong bots, even if they’re risky. If you have opponent modeling, recognize greedy opponents and bust them; if you have good judgment, recognize opportunities and seize them; if you’re not that bright, like Steamhammer, then randomly all-in (say) 5% of the time to keep ’em on their toes, to challenge their opponent models and judgment.

A few observations on Krasi0’s new play:

• I thought Krasi0 was more cautious about detaching groups and sending them forward without enough support. That’s an improvement. It also seemed even more hesitant than before to expand, at least while under pressure. I suspect that a bot which could keep up constant pressure while simultaneously defending its expansions from vulture raids and harassment drops might starve out Krasi0 and win.

• Against Iron, Krasi0 backed up its bunker with a vulture, which appeared to forestall Iron’s runby—and then went 2 port wraith! Is that a new build, or is only the vulture new? An early vulture seems normal in a 2 port wraith build. Anyway, it worked well enough; Krasi0 beat Iron, which it has rarely done lately.

2 port wraith could be deadly against macro zergs, or against any bot which doesn’t grasp air defense. For terran against Iron, for the middle game I suggest a tank-heavy army with some goliaths mixed in. I think that meets all of Iron’s preferred unit mixes.

2 starport build

• In the most recent games, I noticed that against Steamhammer’s mutalisk play, Krasi0 made turrets only near the bunker where Steamhammer persistently maneuvers. Against 5 Pool’s mutalisks, Krasi0 made turrets all over its base before any attack, which was helpful given how that zerg plays. What’s the difference? Is it a hard-coded behavior, or is it the result of opponent modeling? Or did I watch the wrong games?

a new UAlbertaBot bug fix

The bot bftjoe by Joseph Huang fixes a bug in UAlbertaBot that I did not catch.

bool UnitUtil::CanAttack(BWAPI::Unit attacker, BWAPI::Unit target)
{
    return GetWeapon(attacker, target) != BWAPI::UnitTypes::None;
}

Easy to type, easy to read past... and totally wrong. Unit type None is 228, which does not match the value of any weapon type, so it will always return true. “All ints are the same type, right?” Bjarne Stroustrup: “Uh, sure.”

bool UnitUtil::CanAttack(BWAPI::Unit attacker, BWAPI::Unit target)
{
    return GetWeapon(attacker, target) != BWAPI::WeaponTypes::None;
}

In UAlbertaBot, CanAttack() is used only in the tank manager, so the damage, er, fallout, er... severity is limited. Steamhammer additionally uses the function in controlling lurkers, which it does not build by default because its control is so poor. So the next Steamhammer version should be a little less clumsy with tanks and lurkers. Still pretty clumsy, though; the clumsiness runs deep.

Tomorrow: The newly uploaded Krasi0 seems to be playing new builds.

Steamhammer will drop

It’s decided. The next Steamhammer version will support drop. Dave Churchill had already implemented most of the skill: Choosing a transport for the job, sending it on a sneaky path around the edge of the map, and unloading it near the enemy’s mineral line. The remaining bits are proving surprisingly tricky: Choosing units to load, keeping them together until everything is ready, loading them up (seems like a key step), and not doing anything too ridiculous after they land (“oh no it’s scary here, let’s skip this job and go home”). Even so, I expect to get it working reasonably well by tomorrow, the day after at worst.

It’s limited. It only supports 1 transport, and after dropping it does not know how to reset itself for a second drop. Better make the one try count! I wrote a dark templar drop build for protoss. I’ll try to add a terran drop build, though it won’t be as dangerous. If I feel ambitious I’ll do the bit of extra work for a lurker drop too.

It’s a good start. Fancier versions can come along later.

Update: The first time I got a dark templar drop to land in a terran base, the dark templar said “Uh oh, our own base is under attack. We must ignore the enemy in front of us and walk across the whole map to defend!” Not doing anything too ridiculous after they land is a vital skill....

Steamhammer-Microwave razor close game

SSCAIT’s mini-tournament is not quite finished as I write.

The irritating news of the tournament: Steamhammer played 2 tournament games versus XIMP by Tomas Vajda, plus one game shortly before the tourney, on the same map (Benzene) with the same starting positions (protoss on the left, zerg on the right). Just how random is it? The 3 games were nearly identical, down to individual army movements, and Steamhammer lost, as it should have, because it doesn’t understand map blocks and couldn’t finish its opening build. Sometimes luck hits like a truck.

The interesting news of the tournament: Tscmoo protoss is doing surprisingly well, including against opponents that it has a mixed record against. Did its opening learning, which was reset in December, finally gather enough data to make good decisions? We’ve seen before that Tscmoo brings its best against strong opponents. What’s behind that?

A razor close game between Steamhammer and Microwave on Python: Steamhammer opened with overpool into fast spire, while Microwave went overpool with zergling speed and mass lings, leading to a later spire. Steamhammer made 2 sunkens with its spire. When Microwave’s zergling numbers grew large enough, it defeated Steamhammer’s lings and pushed in; the sunkens and 2 fresh zerglings were barely enough to hold them off. When its faster second hatchery came online, Microwave attacked again; the second wave killed the sunkens and a couple of drones, but the first mutas cleaned up. The third wave left 2 Steamhammer drones alive, and by then Microwave’s spire was up too, and soon Microwave destroyed Steamhammer’s spire. Steamhammer scourged an overlord, which delayed Microwave just enough. Here Microwave is adding drones when it should be replenishing its army.

Steamhammer’s spire is destroyed

If you make too many drones in ZvZ, you die. Microwave was behind in air power and did not keep the pressure on. Steamhammer killed another overlord, outmicroed the scourge...

Steamhammer outmicroes scourge

... and brought down the excessive number of drones while defeating mutalisks that spawned one at a time. Microwave helped by transferring drones from its natural to the main where the mutas were. Microwave might have held if it had gotten up a spore colony in time, but it was too late.

Steamhammer clears drones and mutas

Steamhammer is #1

Oops, Steamhammer became the #1 bot on the SSCAIT ranking.

detail of SSCAIT rating list

It pulled ahead of Krasi0 by a hair. I don’t expect it to stay #1 for long. It still can’t beat Iron or Krasi0 more than occasionally. Iron has lost rating points lately because Igor Dimitrijevic is putting it through a strategy change, and it will take time to tune up Iron’s new play. As that proceeds, Iron will work to claw back its first place. In the meantime, apparently Steamhammer has been defeating lower-ranked bots about as reliably as Krasi0 does.

I have to give in and admit that Steamhammer is no longer merely a threat to the top bots, it is a top bot itself, even if it struggles head-to-head against the very best. Well, I predicted all along that bug fix release 1.2.2 would restore the strength of 1.2 and then some, after the dip caused by bugs in version 1.2.1.

Meanwhile, Randomhammer has been getting fewer games and its rating has not stabilized yet. I’m expecting it to reach about 2100, maybe a little more. The bug fixes should make all races stronger.

Moral: Experience shows that feature releases are sometimes stronger and sometimes weaker, but bug fix releases are always stronger. Fix more bugs!

a new secret weapon in ZvZ

Yesterday I watched a pro ZvZ game from 2010 where the winner played an opening I had not seen before. “Hmm, does that have good timings against overpool?” I thought. It seems to be a rare opening and is not documented on Liquipedia, but I coded up a version and tested it out. The scores are Steamhammer 1.2.2 set to play one fixed opening, versus each opponent.

victimscoreversion
Ailien13-2uploaded 4 April
Killerbot14-1SSCAIT 2016
Microwave14-10.15, uploaded 5 April
Steamhammer11-41.2.2, latest release with 11 ZvZ openings
Zia15-0uploaded 7 September

Holy Saint Isidore, Batman! Bots are not prepared for this!

Killerbot scored 1 win when Steamhammer made a tactical mistake of a kind that I intend to fix in the upcoming version. Microwave was able to exploit a risk inherent to the opening—once. Zia tried its builds one after another and lost with all of them. Ailien’s machine learning came the closest to finding an answer; it tried different tacks, and a few of the games were fierce. By the end of the match it seemed to be grasping at straws: Do hydras work? No! Do lurkers work? No! Every fixed opening has counterbuilds, and a human player who knew what was coming would find it easy to beat. It is possible that the counterbuilds are outside Ailien’s gamut, or take over 15 games to find. The release version of Steamhammer itself put up the strongest fight but was forced down.

Of course Steamhammer does not play fixed openings outside of tests like this. I think that adding the new opening to its repertoire is likely to make Steamhammer impervious for a long time to machine learning attacks on its openings.

I’ll be holding my secret weapon in reserve until version 1.2.3 comes out. Everything will be published then, but I also enjoy springing surprises. This will change the meta, and I would like to be 2 steps ahead.

Steamhammer 1.2.2 change list

Steamhammer 1.2.2 is uploaded. It is a bug fix release, mostly to fix strength-reducing bugs introduced in 1.2.1.

Next will be 1.2.3, primarily a feature release to help all races play stronger and more interesting games, then 1.2.4 to fix lingering bugs.

bug fixes

6 bugs are fixed, 3 serious bugs that caused losses for all races in version 1.2.1, and 3 zerg bugs that are smaller and didn’t cause any losses that I could identify. There are still no known crashing bugs.

• The bug in retreating to the natural is fixed. When retreating with no fresh units on the way, Steamhammer now retreats to the natural if it has been taken, or to the main otherwise. Retreating blindly to the natural caused many losses when the bot did things like retreat from the main to the natural when the enemy was at the ramp. (Squad::calcRegroupPosition())

The retreat system is confused in the first place. The first choice of retreat point is the closest friendly unit that is not “near” the enemy. It is supposed to close up gaps in the formation—that is why it is called “regrouping”. But in practice the closest friendly unit might be anywhere, and Steamhammer may retreat to the natural, to the main, or in a direction that makes no sense at all. Only when there is no friendly unit to retreat toward does it retreat to the natural or main as appropriate.

• Errors related to pulling workers for emergency defense are fixed. There were subtle issues causing workers to be left in the base defense squad after they were supposed to be released. It sometimes caused weird worker dances and other bad behavior. I also tightened it up; workers are now pulled to fight a proxy only if no combat units are out yet, and to fight zerglings only when they come very close to the mineral line, and otherwise not at all. Steamhammer will self-destruct less often, and (I hope) continue to successfully defend itself when it can. (CombatCommander::updateBaseDefenseSquads()—I renamed it for consistency.)

• A change in 1.2.1 to put more idle workers back to work introduced a bug where it also put building workers back to work before they started building, sometimes delaying the start of construction by as much as a few seconds. When timing is critical, it causes losses. In particular, it caused the 9 hatch opening to lose to 9 pool, when it should defend in time. Excess worker pulling contributed. (WorkerManager::updateWorkerStatus())

Lukas Moravec has found another bug that makes buildings start later, but the effect is smaller. I decided to delay fixing it until I understand it thoroughly.

• Zerg mistakenly made sunkens to defend against air attack. Oops. (StrategyBossZerg::checkGroundDefenses())

• Zerg was ignoring its absoluteMaxDrones value and making too many drones in long games, cutting into the supply available for its army. (StrategyBossZerg::updateGameState())

• Zerg catches more cases of deadlocks that cause production freezes. It should only have happened when Steamhammer was already in trouble, though. (StrategyBossZerg::nextInQueueIsUseless())

other improvements

• I tuned up the ZvZ 12 pool opening, and adjusted some opening settings.

• The true/false configuration options KiteWithRangedUnits, WorkersDefendRush, and ScoutHarassEnemy can now be set differently per race, to better support playing random. The feature is not used in the default configuration; all races are set to the same value. I also removed UseSparcraftSimulation, since it was already unused in the code.

Stone

This version does do worse versus Stone. In a test match, it scored 12-3 with 2 close calls where it went down to 2 drones. When worker defense was first implemented, Steamhammer scored 15-0 with 1 close call where it was taken down to 3 drones. The cause seems to be the return cargo bug fix. The effect is hard to see, but it makes workers more likely to stop and defend themselves in spots where other workers will not help them out. I decided that the correct fix is to improve worker micro, and I didn’t want to try something so delicate in a bug fix release.

Steamhammer 1.2.2 getting extra tests

Steamhammer 1.2.2 needs no more work, but the SSCAIT stream seems to be down so I guess there’s no point in uploading it right away. I’ll use the time to run extra tests and make extra sure that it’s extra solid. The last release was not tested carefully enough, but this one should be good.

I put in 3 serious bug fixes that affect all races, 3 lesser bug fixes for zerg, and 2 minor improvements. Version 1.2.1 was weaker than 1.2; if I did my job, version 1.2.2 should make up the difference and then some.

Steamhammer is failing on bgh

It’s April 1, time for Big Game Hunters, and—ack! Steamhammer is refusing to start up on the map! Another bug to fix, and one that may not matter again until next year. I regularly try it on maps outside the SSCAIT pack, but not on maps this strange.... Should I add another test to my release checklist?

Update: It’s working for me locally, with the WebMaps version of Big Game Hunters. What version of bgh is SSCAIT using?

Steamhammer 1.2.1 docs, 1.2.2 plans

Documentation is written, a bit slowly, as usual. Updating for future versions will be quicker, also as usual. I am now allowed to touch the code again.

It’s short. Is it good? Will it help people get started (or decide whether to get started)? It’s only possible to write documentation if you know details, and it’s only possible to judge documentation if you don’t, so... I’m listening.

version 1.2.2

Version 1.2.1 seems to be 100 points weaker than 1.2, rather than 20 points stronger as I expected. Almost all the strength loss seems to be due to the single retreat-to-the-natural bug. Nevertheless, doing my best to follow the zero-one-infinity rule, I’ve identified a half-dozen quick fixes for version 1.2.2. Expect it in 2 days, plus or minus 1 day.

Steamhammer 1.2.1 early results

1. The feature of retreating to the natural base if it exists is buggy. Steamhammer always retreats to the natural, whether it has been taken or not, causing trouble especially in ZvZ games. This is hilarious, if “hilarious” means “it’s bad, but at least it’s easy to fix.” I added the feature at the last minute with only a brief test: Tally another loss for poor testing and inadequate commenting!

2. Meanwhile, units that retreat to recover from their damage still return to the main, not the natural. In general, the code has confusions between retreating the squad and retreating individual units to regenerate (which only applies to melee units, and only if configured). It doesn’t seem urgent to fix, though.

3. A unit which is inside the minimum range of a sieged tank refuses to retreat with its squad. It doesn't necessarily attack the tank, but it attacks something. This behavior has only triggered a couple times, but so far it looks like a successful improvement.

4. The system of pulling workers for defense is questionable. If it made correct decisions, it would be great. As it stands, it is sometimes good and sometimes bad, and I can’t judge whether it is worth it overall. It averages out pretty close to zero, maybe?

5. I thought the loss against Stone was due to a new weakness, but on a closer look I don’t see one. It’s the first loss against Stone since worker harass defense was implemented, so I’ll test more closely to make sure.

6. Speaking of worker harass, gas workers now defend themselves the same way as mineral workers. I don’t know whether this will turn out to be a win, because harassed gas workers get switched out; harassment can potentially disrupt gas mining. So far, this behavior has triggered against LetaBot, when it looked highly effective. But LetaBot is a lazy harasser, so the jury is still out.

7. Other surprise losses by Steamhammer were due to randomly choosing openings that the opponent countered. For example, in the first ever loss against protoss Lukas Moravec, Steamhammer went 5 pool, which was objectively poor against the 2 gate opening. Steamhammer nevertheless pulled ahead and was winning until it bungled its tech switch.

I’ll be inserting another bug-fix release to solve the retreat-to-natural bug before I get down to features.

Steamhammer 1.2.1 is out

Steamhammer 1.2.1 is out. All races should play more strongly. Steamhammer 1.2 kept up an average elo in the high 2200s, peaking over 2300. I think 1.2.1 is likely to average over 2300.

I was originally planning more improvements for protoss than for other races, but it turned out differently. Terran got the most improvements, and protoss the least. Terran needed them more. Version 1.2.2 is planned to focus more on features than on bugs, and will have some protoss features.

Web site update tomorrow, with source code.

I tried to make this change list more thorough and detailed than earlier ones, since more people are using Steamhammer code. It’s a nice long change list; I got a lot done this time.

config file

• Some options can be set differently for each race, to support playing random.

• New build order commands “go defensive” and “go aggressive”. Defensive means that your units stay at home for the time being; aggressive means that they seek out the enemy. The default is to be aggressive all the time, which is good for zerg. For terran, “go defensive” is good at the start of most openings. For protoss, I had the dark templar rush stay defensive (with its one zealot and one dragoon) until the dark templar start. If you don’t go aggressive in the build order, aggression automatically turns on when the opening build order is over. For now, the only way to stay defensive longer is to write a longer build order (or write code).

• New debug option drawUnitOrders. Besides unit orders, it draws on the screen what a research building is researching and what is going to come out of an egg, cocoon, or production building. I’ve been using the option often.

macro changes

• Updated terran and protoss openings and production code.

• Terran and protoss build more workers.

• All races pay closer attention to the configured maximum number of workers per mineral patch. WorkerManager::getMaxWorkers() gives the largest number of workers that can efficiently mine your existing bases, based on the configured values and the resources at the bases.

• The scout defense worker (used only by terran, in the default configuration) is less likely to move out while carrying minerals. Losing minerals is bad luck.

• More idle workers are recognized and put to work.

• Choosing a new main base caused mostly minor but widespread confusion, now fixed. Various bits of code were unclear about the difference between the start location and the current main base. The most obvious effect was that the first expansion sought after a new main base was chosen was always the start location, which had usually just been destroyed and might still be occupied by the enemy.

• Protoss is less likely to overstep the time limit when its main fills up with buildings. The problem turned out to be fundamental to the building placer, and I resorted to cheap hacks. Someday I’ll spend a few weeks to write a proper building planner with more capability. For now I tightened up protoss building placement so that more buildings fit, spread pylons farther apart so they power a larger area, and taught the production manager not to retry the building placer on every frame after it fails once (which caused a huge slowdown). All 3 measures together are still not sufficient, so I may do more in the next version. One cause is that BOSS orders up more gateways than it needs; its production plans are not as efficient as promised.

• The zerg strategy boss discounts extractors at destroyed bases. It was a minor bug that I could fix in passing.

• Zerg doesn’t make double queen’s nests, a rare bug.

• Zerg will no longer order up a hive while overlord speed was still researching in the lair, causing production to pause until overlord speed finished.

• When zerg has extra larvas and minerals and is short of gas, it goes ahead and makes zerglings. Version 1.2 will often wait for gas, letting minerals build up and reducing total production. Steamhammer’s late game armies will tend to be larger.

micro and tactics changes

• Turned special vulture kiting back on. Vulture micro should be improved.

• Terran by default uses the scout defense feature, unlike protoss and zerg. Terran needs to take extra measures to protect SCVs that are constructing buildings.

• Terran loads and unloads bunkers as needed. It’s not very skilled at it, but it does the basic job. I added a new 8RaxDefense opening to illustrate it (and also to hold rushes for which the bot’s micro is too weak).

• Bunkers can be placed tight up against obstacles.

• Terran builds comsat stations and scans cloaked units (even if it doesn’t have anything around to fight them).

• When terran needs emergency detection, it builds 3 turrets, not 2 like before. It seemed necessary.

• Tanks unsiege to fight buildings, or to target enemy units that are too close for siege fire. Tank sieging behavior is still impressively stupid, but it’s a little less bad.

• Protoss is configured to retreat zealots and dark templar which are seriously hurt, hoping they can regenerate shields. (Zerg has retreated weakened zerglings for a long time.) See the RetreatMeleeUnitShields and RetreatMeleeUnitHP config options.

• When zerg sees vultures, it builds a sunken in its natural (unless it already has one). It’s a simple measure to reduce the harm of vulture raids. When Steamhammer accidentally places the sunken in a good spot, it holds out much better against Iron in particular. Future versions will put up stronger defenses.

• A zerg broodling attacks and does not retreat. It doesn’t live long, it can’t afford to waste time.

• For all races, a unit directly next to a sieged tank attacks and does not retreat. If it retreats, it will likely die to siege fire; better to do damage instead.

• Units retreat to the natural, not the main, if the natural has been taken. As suggested by MicroDK. It turned out to be only a couple lines of code, so I threw it in.

• Reavers are targeted with higher priority. It was an oversight.

• Gas workers now defend themselves against harassment, the same as mineral workers. It should reduce worker losses a little more.

• Bugs related to pulling workers for base defense are fixed. The main symptom was that workers at all bases froze in fear, even when another base entirely was under attack. The problem was that putting workers in a base defense squad did not change their job. I had assumed without checking that they would be given the job CombatWorker, but instead they kept the MineralWorker job, so the mineral worker self-defense code interfered. Now workers pulled for defense become combat workers, and WorkerManager is responsible for their combat orders; the squad knows not to issue orders of its own, and resets the workers to idle when they are released. I tried to make WorkerManager a trifle smarter about combat; we will see how that turned out. Finally, I adjusted the conditions under which workers are pulled and tried to make sure that they are never pulled across the map. Zergling rushes are defended again, if configured, and it is turned on by default although I’m not sure it’s a good idea—it sometimes helps and sometimes hurts. In any case, the worst misbehavior should be gone.

• Base defense against air attack now accounts for turrets, cannons, and spore colonies. Fewer defenders are called home if there is static defense to help. (Base defense against ground attack already accounted for static defense.)

• Steamhammer used to go on the attack when its supply went over 170, and revert to normal behavior when its supply fell below 170. When production was high enough it worked well, but other times it caused loops: “Attack! Oh, retreat. Attack! Oh, retreat....” I added hysteresis. Now it starts the attack when supply reaches 195, and does not stop until it falls below 160.

code fixes

• Some cleanups in CombatCommander.

• UAlbertaBot often uses double instead of int where it calls unit->getDistance(), which returns int. It’s not a bug, but it causes unnecessary computation. I fixed some of them, but not all.

ProductionManager works around a BOSS bug in ordering up comsat stations. If you add a second CC and want a total of 2 comsats when you already have 1, BOSS sometimes orders up 2 new comsats instead of 2 comsats total.

• Removed unused code from CombatCommander, RangedManager and MeleeManager.

• Fixed a sneaky crashing bug in StrategyBossZerg::checkGroundDefenses(), the last known crashing bug.

bugs that do not go quietly

I recently fixed 2 bugs that then turned around and bit me.

I fixed a bug that caused Steamhammer to make double queen’s nests in around 1 game out of 150. It was a simple missing condition. But I made a typo in the fix: Parentheses in a function call swallowed up the next condition in the if. In any safe language it would have failed to typecheck, but in any case, the result was that Steamhammer made 3 or more queen’s nests in every game. I think C++ was laughing at me—”Nyah nyah! I’m too sharp a knife for you!”

I also tracked down and fixed the last known crashing bug, a subtle oversight in the strategy boss that causes crashes in around 1% of games. I brought up a game for a first test of the fix and... crash! Somehow I replaced a rare crash with a frequent crash, and even though I only touched a little code, I haven’t found it yet.

Well, it probably won’t take long—though who knows? After that I have 2 other critical bugs, and then 1.2.1 will be ready.

By the way, Steamhammer does suffer from one other crash besides the “last known” crashing bug. In rare cases, it crashes on startup. But the crash happens before any Steamhammer code executes, so there’s not much I can do about it without taking a long detour.