The change list is big this time. I took over a month to do it, but I did a lot. This is primarily a feature release to add skills for terran and protoss, and to improve tactics and micro for all races.
History says that my feature releases are sometimes weaker than the previous version due to bugs. I already see new bugs that never came up in testing, bugs I did not see even in the Randomhammer test version. Sigh. Yesterday’s bug list was longer than I could hope to finish before July, and today’s....
drop
Terran and protoss have limited support for drop strategies. Dave Churchill implemented part of it in UAlbertaBot, and I filled in the many gaps and made it work.
Terran and protoss can drop once, with a predetermined unit mix, from 1 dropship or shuttle, near the mineral line in the enemy main base. The transport cannot pick its units up again. The transport cannot return to pick up a new load (it idles in the enemy base after unloading). If you make a second transport, there’s no support for loading it up and making a second drop. The transport follows a fixed sneaky path around the edge of the map. (It would be easy to change the drop target, though.) Even with these severe limitations, drop strategies can be worth playing.
Zerg drop is not supported because it’s a little more complicated. Zerg has to research drop and then choose an overlord, and usually research overlord speed too. Also dropping once with 1 overlord is not as useful for zerg. I’ll probably implement multiple-ship drops and repeated drops around the same time as zerg drop. I have made a start, and it will get better.
As written, the setup for the drop—arranging the production of the tech and units—is fully in the hands of the opening book. The opening book sets the OpeningGroup
to "drop"
to declare a drop build. The StrategyManager
can then do as it will with the drop opening group; I had it transfer to another opening group. It should be no problem to move drop setup into StrategyManager
so that drop can happen or not depending on game events.
The drop is coordinated by CombatCommander
using newly added squad order types. See CombatCommander::updateDropSquads()
. To change the units to drop, modify CombatCommander::unitIsGoodToDrop()
. The transport movement is carried out by MicroTransports
, most of which was written by Dave Churchill with additions, tweaks, and bug fixes by me.
Terran plays a vulture drop strategy around 10% of the time (depending on the matchup and map). Protoss plays a dark templar drop strategy around 15% of the time (ditto). The dark templar drop especially can be deadly.
tactical changes
• Every race (not only zerg) gets separate ground and flying squads. See CombatCommander::updateAttackSquads()
.
• Every race is supposed to get a mobile detector for each squad, as zerg does, provided the detector has been made. I noticed that it doesn’t work for terran science vessels, which sit by the starport. Another bug for the list. I’ve seen it work for observers, so I hope there is not a regression.
• Don’t assign an air target to a squad that can’t shoot at air units, or a ground target to a squad that can’t shoot those. See CombatCommander::getMainAttackLocation()
. One hydralisk among the ultra-ling will get the squad assigned to shoot down carriers, so bad behavior is possible, but it is... self-limiting.
• Overlords are an acceptable tactical target in CombatCommander::getMainAttackLocation()
. It’s made possible by the above fix. In UAlbertaBot, overlords are explicitly skipped over so that zealots and zerglings aren’t sent to chase them.
micro changes
• Targeting is more flexible, relying on a combined score rather than separate priority and range (which was brittle). The change needs more tuning to approach its potential. The change allows others:
• To reduce goose chases, fast enemies score lower when they are moving.
• Workers are always acceptable micro targets in MicroManager::execute()
. UAlbertaBot and former Steamhammer versions often ignore workers in the middle of the map to reduce goose chases. The code was complicated and introduced a harmful limitation.
• Targeting priorities are adjusted, especially priorities related to workers.
• When regrouping, do not retreat from an enemy unit that cannot attack you. Retreating units used to stand back 128 pixels even from enemies that could not harm them, so you would sometimes see mutalisks fleeing from firebats.
• When retreating from an enemy that can harm you, retreat beyond enemy sight range as well as beyond enemy firing range. This often results in retreating farther. I added bonus distance for retreating from tanks, though I see in games that it is still not far enough. Units try to retreat out of range but don’t understand how to navigate around each other.
• Detectors, such as overlords, are a little more cautious and should wander into enemy fire slightly less willingly. They still die a lot.
• UnitUtil::CanAttack()
had a bug inherited from UAlbertaBot. Instead of only fixing the bug, I rewrote the function to understand more unit types, which made it possible to simplify other code. It now understands that bunkers, reavers, and carriers should be treated as able to attack.
• UnitUtil::GetAttackRange()
tried to understand bunker range, but had a bug, and it didn’t know about reavers or carriers. I think it now understands bunker, reaver, and carrier range correctly.
• The bot surrenders when all hope is lost. It says “gg” and goes idle for 1.5 seconds before leaving the game. See GameCommander::update()
and GameCommander::surrenderMonkey()
. The behavior can be turned on or off by a new config option Config::Strategy::SurrenderWhenHopeIsLost
.
terran
• Terran tracks the locations and times of comsat scans to avoid scanning redundantly. I implemented a very simple system using MapGrid
. It’s not fully accurate but it’s a huge improvement over the previous version, which would blow 100% of scanner energy of all scanners the moment it spotted a dark templar. Now it scans only moderately more often than it should (it scans cloaked units it notices whether it can fight them or not).
• Marines and firebats use stim, an important skill.
• Medics mostly stay near marines and don’t run ahead. This is a bigger improvement than stim. Medics still have a problem with regrouping. Even so, infantry play is much improved.
• Tanks stay sieged while an enemy is in range. They still siege and unsiege way too often, but now they behave better when fighting in sight of enemy buildings.
• StrategyManager::getTerranBuildOrderGoal()
is updated to research stim, to make more transitions, and stuff like that.
• The 2 factory openings are more efficient: The vulture opening and the tank opening. My inexperience with terran openings was showing.
protoss
• Protoss supports more units: Reavers, carriers, and archons (which all require special handling). Reavers crawl around and try to join the army; they work reasonably well. Carriers stay home until they have 4 interceptors (well, occasionally they wander off). Carriers (like scourge) should be put into the flying squad only if there are other flying units; otherwise they stay with the ground squad. Since there is no support for psionic storm, high templar as they are produced automatically merge into archons. I didn’t implement a way to ask for an archon, you get one when you make 2 high templar.
• StrategyManager::getProtossBuildOrderGoal()
is updated to use the new units. Zealot openings add archons and carriers later in the game. Dragoon openings add reavers after the second nexus. Plus various other less important changes.
• The 10-12 gate opening is improved.
zerg
Zerg has the most changes by count, but they are simpler. Except for the openings, all the changes are in StrategyBossZerg
.
• No longer get scourge before they are known to be needed. It turned out to hurt more often than it helped.
• Make a second evo chamber only if the first is busy. The bot too often started a second evo before it had scared up funds to upgrade carapace in the first, or made 2 evos when rebuilding even when no more upgrades were needed.
• Fixed an oversight allowing a rare production freeze related to overlord speed.
• Make a spire for air defense, even if it is not otherwise needed.
• Make emergency zerglings when under dangerous ground threat.
• Ground emergencies end after 20 seconds, not 30. I’m considering whether 15 or 10 seconds might be better.
• Choice of air or ground units is improved versus all races. For example, if the enemy has too many spores, the bot will stop mutalisk production. A bug causes a useless hydra den to be made against terran; I fixed that once, it is a regression.
• Go ultra-hydra much less often. The bot was way overusing that unit mix.
• When the enemy makes static defenses, respond with drones. The change is simple but effective, as seen in the recent game against XIMP by Tomas Vajda where Steamhammer took the map much faster than before. You can see Steamhammer make a burst of drones when it finds more cannons, until it reaches the maximum 75 drones.
• New overhatch openings, other opening tweaks. Some openings are shortened because the strategy boss can now do the right thing.
configuration file
• Strategy mixes can get different weights depending on the map size, and repeated strategy mixes can be factored out into strategy combos. It's explained in this post and implemented in ParseUtils
. (Tech note: I used BWTA to count the start locations, so I had to move map analysis ahead of config file parsing in UAlbertaBotModule
. I didn’t realize in time that BWAPI can count the start locations. All you should have to do is change BWTA::
to BWAPI::Broodwar->
in the call to getStartLocations().size()
to remove that point of dependency.) All races use the map size feature to prefer some strategies on appropriate maps.
• I added a boolean strategy option SurrenderWhenHopeIsLost
to control surrendering.
• I added a macro option AbsoluteMaxWorkers
and set it to 75 for all races. Zerg already adhered to the 75 maximum, so this affects terran and protoss. Making too many workers is bad because it reduces the army size in the late game. 75 workers leaves 125 supply for army.
• I added another macro option ProductionJamFrameLimit
and set it to 1440, which is 1 minute. If no macro action (like producing a unit or starting research) is carried out in that time, the production manager assumes that production is frozen by a deadlock and clears the production queue. This at least prevents production freeze bugs from bringing Fimbulwinter, and it doesn’t cause harm if production is slow because of lack of workers. Terran and protoss have many production freeze bugs, and zerg has a few despite an eradication campaign.
• I added a debug option DrawMapDistances
.
• I removed the debug option DrawStrategySketch
since it was limited and only for zerg. Use DrawStrategyBossInfo
to get the same zerg info and more.
code
• The regex bugfix in MacroAct::MacroAct(const std::string & name)
. I learned it from gnuborg, who credits jaj22.
• I fixed bugs related to finding the unit type of a MacroAct
that is not a unit. The bugs probably caused occasional bad behavior, though I don’t know what.
• Renamed the micro managers with a Micro- prefix. RangedManager
became MicroRanged
, TransportManager
became MicroTransports
, etc. More specific names make the code easier to understand.
• Removed unused files HardCodedInfo.*
and snips of unused code throughout. Some unused code I left in place, when it seemed potentially useful.
• No longer time MapTools
every frame, since the class doesn’t have a job that it does per frame. It’s a utility to be called by others.
• SquadData::addSquad()
no longer redundantly requires the squad’s name (already known by the squad itself).
• SquadOrder::isCombatOrder()
and SquadOrder::isRegroupableOrder()
factor out decisions that used to be scattered through the micro managers.
• I changed many cases of for (auto & unit : units)
to (const auto unit : units)
. A unit is already a pointer, no need to take a reference to it. I hope the optimizer comes up with the same code in both cases, but redundant references are bad style.
• CombatCommander::update()
updates all squad memberships in one go. In a previous version I tried to optimize it to spread the work across frames, which turned out to risk problems.