I’ve uploaded a test version, which I call 1.2.4 just to keep my folders nicely sorted, of both Steamhammer and Randomhammer. It’s a big version with a ton of bug fixes and several new features. I hope I can get by with only a few more tweaks and minor fixes and put out release version 1.3 shortly. It will depend on how the test version does.
This version configures more enemy-specific openings than ever before. It’s a last hurrah. Most of my time from now until the AIIDE submission date on 1 September will go into opening learning. That version should have no enemy specific openings.
configuration
• Always use race (e.g. "Zerg"
) not "StrategyMix"
in strategy mixes. This fixes a bug in nested strategy mixes.
• A bug caused SurrenderWhenHopeIsLost
to be set to true and ScoutHarassEnemy
to be set to the value of SurrenderWhenHopeIsLost
. It caused Steamhammer to harass with its scout even though ScoutHarassEnemy
was configured to false.
• The extractor trick works. BWAPI bug workaround found by Arrak, thanks! I removed the command "go extractor trick"
, splitting it into "go extractor trick drone"
and "go extractor trick zergling"
. And I updated some zerg openings to use the extractor trick; fast rushes and some 9 pool openings should be a touch stronger.
• On command, pull workers for combat, and release them when done. Workers pulled from mining go into the MainAttack
squad (the ground squad, needless to say). The commands are "go pull workers n"
(pull a given number), "go pull workers leaving n"
(pull all except a given number), "go release workers"
(send the workers back home to mine). I added a terran BBS opening which pulls workers for added punch. Also the zerg strategy boss has code to pull workers to hold early terran marine attacks, though the code is poorly tested and likely buggy.
map analysis
• The distance map data structure drops unused data and uses shorts to save memory. It should use less than half as much memory and be faster to calculate. I also dropped dead code, like MapTools::parseMap()
and MapTools::reset()
.
• Since distance maps take less memory, I increased the distance map cache size constant allMapsSize
in MapTools.h
to 40 (from 20). Distance maps should need recalculating less often.
• I fixed a bug in MapTools
in analyzing blocked tiles. Steamhammer now consistently considers a build tile (32 x 32 pixels) unwalkable if any of its constituent walk tiles (8 x 8 pixels) is unwalkable. This should correct a few... edge cases.
• Ground distances take map blocks into account. Both mineral patches and buildings that block map paths at the start of the game are considered to block the paths permanently. This only affects distance calculations, not the paths that units follow, but it is the first step.
• MapGrid
remembers our units only if they are completed. The change is to MapGrid::update()
. This reduces wasted memory and computation and implements MicroDK’s suggestion to ignore uncompleted units in the combat simulation.
production
• WorkerManager::willHaveResources()
sends the worker to construct a building 24 frames early, not 50 frames. When constructing a nearby building, workers now get into position at close to the correct time, so less mining time is lost. They are still late when running off to construct a distant building.
• Better reactions to workers lost in the opening, for terran and protoss. Instead of resetting the build entirely, Steamhammer now replaces the lost worker and tries to get back into the flow of the opening. In some situations where it’s urgent it may make a combat unit. I tried the same change for zerg, but it turned out to interact badly with the extractor trick and I haven’t had time to debug the interaction yet, so the reaction is disabled for zerg.
• Fixed a major bug that caused drones to go permanently idle in the base. That bug cost a lot of games. It primarily affected zerg, but theoretically could affect the other races on occasion.
• From time to time, randomly change the choice of “main base” where all buildings are constructed. Actually it changes pretty often. The main goal is to fix the protoss “my main is full, I can’t build anywhere” issue, the root of many protoss losses. The change affects all races, although it sometimes has bad effects, prompting terran and zerg to build unsoundly toward the center of the map. See InformationManager::maybeChooseNewMainBase()
.
SparCraft
• The new SparCraft version. A goal of this test release is to find out whether the new version is fast enough to be usable. The question may be moot—even if it turns out plenty fast in practice, there’s a strong chance that I’ll switch to FAP.
• I modified SparCraft to reject suicide units (scourge, infested terrans) which it claims to support but doesn’t.
• Exclude unpowered photon cannons from the combat simulation. Steamhammer used to fear cannons that had no pylon.
• Spore colonies are simulated poorly, so drop enemy spore colonies and drop 6 of our mutalisks for each spore dropped. It’s a rude hack.
other tactical changes
All the tactical changes should be real improvements, and some of them are big. Steamhammer should make fewer gross tactical blunders for all races.
• Combat workers are placed in a combat squad, and are no longer controlled by WorkerManager
. They’re treated the same as other melee units. They should fight a little smarter when pulled.
• Some units that get stuck are immediately unstuck. Random stray zerglings are no longer left behind like a trail of breadcrumbs. Unfortunately dragoons still get stuck sometimes, and I have seen a hydralisk get stuck too. I cured one sticking disease, but there is at least one more.
• Units hurrying to defend a base no longer ignore enemies that are in their path, but stop and fight them if they are too close. This should reduce cases of tactical disintegration where Steamhammer sends would-be defenders crashing blindly into enemy armies, losing without a fight.
• I changed the retreat timer. When UAlbertaBot decides to retreat, it starts a timer and does not attack again until the timer runs out, to reduce indecisive play. Even though it can’t attack, it repeats the combat sim while the timer is running, and if the sim still says to retreat then it resets the timer to zero. Steamhammer now 1. has a shorter timer, and 2. doesn’t repeat the combat sim until the timer runs out. The effect is that fewer combat sims are run, and the bot reacts faster when the situation changes (and the code is simpler, an improvement from every angle). For example, suppose the bot is holding back in front of a strong protoss army. If a probe pops out, UAlbertaBot and past Steamhammer versions will retreat from the probe and look like an idiot until the timer runs out—and the timer was just reset, so it will run its full duration before the bot reacts. Current Steamhammer will still retreat until the timer runs out, but that will take only part of the full timer duration, and the chance of killing the probe is higher.
• The unit closest to the enemy is found by air distance for air squads, rather than by ground distance. Squad::unitClosestToEnemy()
is updated. For air squads, this affects detectors, the combat simulation, and regrouping. It also fixes a severe mutalisk retreat bug: Mutalisks retreated by ground distance, so as soon as they went over a wall or reached impassible terrain, they believed they were safe. That bug brought a lot of losses. Using ground distance causes problems even for ground units, but I’m leaving it for now to see how it does.
• Regrouping is slightly simplified, and no longer has a case which checks the base location. MicroManager::regroup()
is updated. This fixes a common mutalisk positioning issue where mutalisks string out over a long distance instead of grouping up, and should help ground squads too. I couldn’t find any disadvantage in my testing, though theoretically it could be harmful for slow units fighting against faster enemies.
• Don’t try to retreat ground units to a spot they can’t reach. Ouch. Squad::calcRegroupPosition()
.
• Smarter targeting for proxy buildings. On some maps (like Python), bases are close by air and some enemy buildings in the enemy main could be close enough to count as “proxy” buildings. Mutalisks would target the “proxy”, attack the buildings and ignore units, and die. Even in a true proxy, attacking the buildings and ignoring enemy units caused awful blunders. I think all the disasters are now avoided.
• Reavers are higher priority for targeting; they weren’t being sniped when they should be. Steamhammer is skilled at sniping high templar with its mutalisks, but tended to overlook reavers. Plus a few other targeting tweaks.
other code changes
• A bug fixed in ScoutManager::enemyWorkerToHarass()
, which chooses which enemy worker our scout should poke at. It was intended to choose the enemy worker closest to the enemy geyser, and now it does. I made other minor tweaks to ScoutManager
along the way.
• Minor cleanup of worker defense code. This should have no visible effect on play.
• I renamed WorkerManager::getClosestEnemyUnit()
to findEnemyTargetForWorker()
, since that’s what it does.
• Arranged for a bit more constness in BuildOrderItem
references.
• Simplified some base defense code.
• Fewer beeps from BOSS. Someday I’ll get rid of BOSS, and until then I don’t want to see so many exceptions on the screen.
• Added a trivial Random
class to centralize random number generation, which is now used in a few places.
• getAir2GroundSupply()
now includes carriers. The bug was caught by bftjoe.
• UnitUtil::CanAttack()
understands floating buildings. It used to treat them as if they were on the ground.
• UnitUtil::GetWeapon()
understands carriers and reavers. It used to say they had no weapon.
• I renamed MapTools::getGroundDistance()
to getGroundTileDistance()
, the ground distance between two positions in units of build tiles. To get the approximate ground distance in pixels, I added getGroundDistance()
, though it is only 32 * getGroundTileDistance()
. That way ground distances are on the same scale as air distances from unit->getDistance()
, which is also in pixels. But the 32 pixel granularity leaves them a little tricky to compare.
• I removed UAlbertaBot’s opening learning code, since I won’t be using it.
• I fixed a parenthesis mistake in GameCommander::setCombatUnits()
that could cause a worker to simultaneously be a scout unit and a combat unit. I couldn’t find any bad effects from the mistake, but it was definitely a bug.
protoss
Protoss only has a couple changes, and they are minor.
• I made the PvZ forge expand opening more likely. It’s working better than I expected, given the poor building placement.
• UAlbertaBot has a “dark templar never retreat” rule so that undetected dark templar aren’t unnecessarily frightened off by large armies. In UAlbertaBot a squad with dark templar usually consists entirely of dark templar, so the rule was simple: If we are following a dark templar opening, and no dark templar has died yet, then the squad does not retreat but keeps attacking.
In Steamhammer the squad often contains visible units as well. The visible units do not retreat either and die pointlessly—even if no dark templar has come out of the gateway yet. The correct fix is to understand dark templar better, but as a quick improvement I put in a different rule: If the squad contains a dark templar, and no dark templar has died yet, the squad does not retreat. It depends on the contents of the squad rather than on the opening, so it behaves a little less foolishly.
terran
Terran has a bunch of changes, and they should substantially improve terran play.
• New BBS opening pulls 4 workers to buffer the marines. The in-base BBS with pulled workers crushes Steamhammer’s mutalisk openings as flat as Tyr’s (by Simon Prins) center BBS does.
• Medics retreat properly.
• Tanks don’t siege if they know they will immediately unsiege again. In the previous version, if a zealot ran up to a tank, then the tank got into a siege-unsiege loop: It unsieged to fight the zealot, then sieged again because it had a target, and would have repeated the process if it lived.
• Tanks are able to unsiege to retreat.
• Make a science vessel if the enemy has cloaking tech.
• Science vessels join their squad as intended. They weren’t counted as combat units, so they used to sit idle by the starport.
• Bio openings add tanks when tanks counter the enemy unit composition. The combination of a vessel and tanks gives Steamhammer terran the ability to fight lurkers with a bio opening.
zerg
Zerg has the most changes of all, but the zerg changes are complex and not as well tested as the others. Probably some will make play worse, and some may not function at all. There are substantial additions and changes to the zerg strategy boss, and it has been hard to get it tuned. Also, since lurkers are new and I want to see how they do, Steamhammer deliberately prefers lurkers in many situations.
• Support for lurkers, guardians, and devourers. The guardians and devourers are particularly likely to be mistuned and/or broken.
• Lurker micro is completely rewritten and much improved. It needs more improvement, but it should be in the same ballpark as other zerg bots’ lurkers. Good enough for now.
• There’s a concept of “auxiliary units” which are made in a fixed quantity. If Steamhammer has lurker tech and its current unit mix does not include lurkers, it may throw in a small number of lurkers anyway depending on the situation. Similarly for guardians and devourers. The variety puts pressure on the opponent to respond. Aux units are also used to produce hydras before lurker tech is done, so some are available to morph right away, and the same for mutalisks and guardians/devourers. I think of aux units as a hack to get by until I write a proper system with flexible production goals.
• Steamhammer tries harder to make enough macro hatcheries. It is improved, at least.
• Ground emergencies are less authoritarian about taking over production. It was causing losses.
• Ground emergencies last 5 seconds (down from 20).
• Don’t compensate for enemy static defense buildings which are proxied. That’s not defense, it’s an attack! So far I’ve seen only 1 game where this would have made a difference, and Steamhammer won anyway, but it is still a bug fix.
• Count a shield battery as enemy static defense. And other changes in strategic reactions to the enemy’s defenses.
• React better to early marine attacks. My attempts down this line so far are too complicated and not very successful. This is another point that is likely to show bugs.
• I added 2 aggressive ZvT openings with low probability, and downgraded other aggressive openings.
• I also added 2 different 1-hatch lurker builds versus terran. One is a 9 pool build optimized for fast lurkers above all, and the other is an overpool build with slightly slower lurkers but a stronger attack. I predict that these fast lurker builds will crush many terrans, though some terrans will survive. Overall, play versus terran should be more varied, more aggressive on average, and less vulnerable to early terran attacks, a weakness of the past Steamhammer version.
• Work around an incorrect calculation in InformationManager
of the number of free geysers. The underlying bug was too sneaky for me to solve quickly. This bug caused overhatch openings to sometimes skip getting gas; that part is solved. The underlying bug still causes other problems.
• In ZvZ, make mutas before scourge. This should give better survival chances, on average, when the enemy gets a faster spire.
• I made adjustments to speed up tech switches. They are still far from as smooth and efficient as I would like, and because there are more tech choices they happen more often.