Skip to content

Release 2.3.5

Compare
Choose a tag to compare
@kant2002 kant2002 released this 04 Sep 05:38
· 8 commits to master since this release

Opponent model

  • Support pre-learned data files. If Steamhammer does not find a learning file for a given opponent in the read directory, it looks next in a “static” directory to see if there is a data file for the opponent there. The config variable Config::IO::StaticDirectory points to the static directory, and is set to bwapi-data/AI/om/ in the release version (“om” stands for “opponent model”). After the game, it proceeds as usual: It writes the pre-learned game records, followed by the game record for the current game, into the write directory; after write is copied to read, there is no reason to refer back to the static directory. Locutus does it essentially the same way.

The AIIDE version of Steamhammer includes pre-learned opponent model files for 12 of the registered bots. Most of these files don’t have much in them beyond a few sample strategies that have won in the past, so that Steamhammer doesn’t have to cast about blindly to find a likely build. Best play against Iron is more complicated—Steamhammer knows 3 very different successful openings with varying win rates depending on the map—so the pre-learned file for Iron includes 50 games to give Steamhammer an excellent winning rate right from the start. All the game records were originally extracted from Steamhammer’s learning files on BASIL.

Operations

  • Squad targeting: In deciding what enemy base to attack, count defenders in a smaller radius, unless the enemy is terran and has siege mode (then we need the wide radius to include any tanks that may be sieged). This helps Steamhammer more accurately choose the least-defended enemy base to attack next.

  • There was a copy-paste error in the code to detect whether the enemy has siege mode. The siege mode information was returned correctly, but it mistakenly set the flag that means “the enemy has static air defense,” so Steamhammer would believe there were turrets whether there were or not.

  • Squad targeting: Don’t order a squad to attack an addon. I changed ranged units to never attack addons, to avoid wasting time when they should be attacking something else. (Melee units will, though, because it may be the closest thing.) That unexpectedly caused difficulties in finishing off games versus terran, when units might collect around an enemy addon and never attack it, rather than attacking a known building that was perhaps farther away.

  • Squad targeting: If no enemy buildings are known, seek enemy units which may still be findable. This can help Steamhammer finish off winning games faster.

  • A terrific bug caused enemy unit counts to be horribly wrong in many cases. Steamhammer sometimes believed that the enemy had a negative number of units of some type. The broken unit counts were not used by many decisions—the most important decisions use the player snapshot unit counts, which are accurate—but decisions that did use them could be completely wrong.

  • UnitInfo projects when enemy buildings will complete, based on their HP when last seen. It’s not entirely accurate; the calculation leaves out some factor that I haven’t figured out yet. To see the calculated times on the screen, turn on the config option Debug::DrawEnemyUnitInfo. In code, the call getEnemyBuildingTiming() is one way to get the information. This data could make plan recognition more accurate, but is not used for that yet; it is used only to check the enemy spire timing in ZvZ.

Tactics

  • Calculate map tiles in range of enemy static defense and keep the data available. There are separate grids of ground danger zones and air danger zones. A few uses of the data are implemented; many more are possible. Steamhammer will not place buildings in a ground danger zone; this is a vital skill to survive cannon rushes, and has saved games for Steamhammer against AIUR by Florian Richoux. The information also feeds into unit targeting decisions. Steamhammer’s units prefer to fight outside enemy static defense range when possible; Steamhammer has a stronger preference to pick off undefended targets.

  • Squad detectors avoid danger and seek cloaked enemies. Formerly, detectors stayed with their squads and otherwise ignored the world around them. Steamhammer lost overlords freely, a major weakness. Now they retreat out of range of enemies that could shoot them down, and move toward cloaked enemies that need to be detected. Science vessels and observers benefit too. It’s usually a big improvement, but there are cases where enemy ranged units zone out the overlords, or enemy cloaked units distract them from where they need to be. Overlords that are not acting as squad detectors (some act as base detectors and some are left idle) are as carefree as ever and can still be lost at a high rate.

  • A squad detector is supposed to move back home when it finds itself abandoned—when the squad it was detecting for is gone. I don’t think this feature works, or at least, detectors still make all sorts of illogical movements.

  • Better combat sim results against cloaked enemies. If all enemies in the area are undetected and they can hit us, retreat without further calculation. If some enemies are detected, do the sim to see whether to fight or run. The change makes play vastly stronger in certain situations.

  • FAP accounts for cost of scarabs and interceptors, and the full cost of zerg morphed stuff. It doesn’t make a big difference, but combat sim scores are a little more accurate.

  • Ranged units are better at ignoring enemy zerg larvas when moving somewhere else. They’ll get distracted less often.

Micro

  • Issue at most 1 move command per 3 frames in the micro system. Zerglings get stuck less often. I still see it happen from time to time, but I think most watchers will see zergling movement as smooth. The underlying code can send move commands to the micro system every frame if it likes, but the micro system will skip or delay some of the commands if they are too closely spaced.

  • MoveNear() had a potential crashing bug. It never happened as far as I saw, but a unit being given its first command ever could execute invalid code and crash.

  • Use MoveNear() rather than Move() in more cases, to reduce unnecessary commanding. MoveNear() ignores commands that “don’t make a difference”—it says, “eh, we’ll end up close enough, don’t bother.” It’s for use when precision doesn’t matter, which is a lot of the time.

  • Builder workers were being issued an unnecessary move command on the same frame that they were told to start construction. In the worst case, which was not frequent, building construction might be delayed by 1 frame. Still, it’s fixed.

  • Steamhammer’s melee units can be configured to retreat when low on health, to regenerate health (by zerg regeneration or terran medic healing or protoss shield regeneration). The change is, this no longer happens if the unit is irradiated. Net regeneration will not happen, and since it’s a melee unit it’s likely to be right next to the enemy, exposing enemies to the radiation. This mainly helps ultralisks.

  • Clip the result of DistanceAndDirection() to the map boundaries, instead of returning a bad result for the caller to deal with. In practice, the effect is that in some situations a unit will move to the edge of the map rather than not moving at all. I’m not sure it’s an improvement in play terms, but the code is safer.

Zerg defilers

  • An outrageous bug could put a defiler into both the defiler controller and the melee unit controller, meaning that defilers were issued zergling commands intermixed with their defiler commands. “Now AttackUnit() that building!” I was floored. The error was in code that was “so simple it could not have a bug,” and the bug was caught by an error check in the micro system, far away from the underlying problem. At least it was easy to fix.

  • Cast dark swarm over enemy ranged units, not only over enemy buildings. Formerly, Steamhammer could not use swarm against, say, marines on the open field; it had to reach the enemy base before the conditions for the spell were triggered. It was a severe limitation (justified by Steamhammer’s poor swarm skills at the time).

  • Choose the nearest zerglings as defiler food, not the first zerglings that happen to come up in looping through units. Defilers consume sooner and cast swarm and plague at a higher rate. A defiler generally arrives at the front line already charged up with energy, so even if it is irradiated instantly it is still likely to get a swarm or plague off.

  • A typo prevented research of Metasynaptic Node, the defiler energy upgrade. I fixed it and adjusted the conditions to be safer.

  • Slightly loosen the conditions for making a defiler in the first place. They work better now, make ‘em sooner.

• Swarm and plague scoring adjusted for better effect. The thresholds are reduced, so that the spells can be cast in more situations. Swarm over lurkers counts double. Plague counts more on carrier interceptors, less on buildings. Various other tweaks.

  • Fixed a bug in avoiding the overlap of dark swarms. Swarms less often overlap wastefully (though it still happens, for at least 3 reasons).

  • FAP bugs in understanding dark swarm are fixed (I added dark swarm to FAP, so all the bugs are my doing). There was an error in recognizing melee units that can hit under dark swarm because of a confusion between range and squared range (I renamed stuff and added comments to make it clearer). FAP also now realizes that a worker cannot do damage under dark swarm, while a reaver can. The effect of the fixes is that units under dark swarm make more accurate decisions about whether to keep attacking.

  • A rare bug could allow multiple defiler mounds.

Zerg scourge

  • Do not target an enemy that is covered by enemy static air defense. Steamhammer used to throw scourge away by the ton to cannons or turrets; this solves the issue. Scourge will chase the enemy, but turn around for home if the enemy reaches a defended area. (Mobile enemies might still shoot down the scourge; retreating in that case is decided by combat sim and the regular advance/retreat logic.)

  • Do not target overlords or interceptors. Shooting down those targets is usually a waste of gas. Neither the scourge squad nor the scourge units will seek overlords or interceptors. This solves another serious issue.

  • Predict the target’s movement. This helps scourge hit the target directly, instead of doing that weird little loop before suiciding. It also means that scourge cut corners in a turn, but only a hair.

  • There was a bug in choosing scourge squad targets that were goneFromLastPosition, that is, known to no longer be where they were last seen. It caused wasteful scourge movement.

  • In choosing a scourge unit target, pay less attention to target priority (“the science vessel is more important to destroy than the wraith”) and more attention to target distance (“it’s right here, just hit it!”). That wraith is now less likely to shoot the scourge down while the scourge chases a more distant science vessel.

  • If we have lurkers, then enemy observers are higher priority to destroy.

  • Further limit scourge production. I tuned it down repeatedly, but Steamhammer was still sometimes spending too much gas on scourge, leaving too little for everything else.

Other zerg skills

  • Sometimes make 1 queen, use parasite, infest command centers. The queen likes to parasite expensive units like carriers and arbiters, and it also likes shuttles and dropships. It will parasite something else if it has excess energy or gets irradiated. As I expected, few enemies understand what to do when they get parasited. A common outcome is that the parasited unit gets scourged at the first opportunity. If the parasited unit stays in a safe place instead, it’s often a valuable spy. The infested command centers don’t do anything but sit there and get in the way; I haven’t yet seen this cause Steamhammer any problems in game, but it could happen. If the queen dies, which happens a lot because it plays recklessly, the strategy boss waits 3 game minutes and makes another queen.

  • There was a critical crashing bug affecting spellcasters in the late game. Fixed, whew.

  • In an emergency, set the drone production rate to 0.15 rather than the previous 0.10—that is, make a drone instead of a combat unit 15% of the time. This helps Steamhammer build up its economy even while under heavy pressure, without falling to the pressure. It increases the win rate against zealot rushers and other opponents that press attacks over a long period, like Gaoyuan Chen.

  • Prefer to make units at hatcheries with more larvas. Steamhammer used to often lose production capacity by using up all the larvas at one hatchery before moving to the next hatchery. A hatchery with 3 larvas will not produce more larvas, so that meant the total rate of larva production was lower, and more total hatcheries were needed to cover the next surge of zergling or drone production (cheap units that call for a lot of larvas).

  • Prefer to make drones at undersaturated bases. It is a smaller improvement than it may sound. Formerly, Steamhammer used a cheap but effective trick: It preferred to make drones at the base farthest from the main base. It was the right choice most of the time, but could go wrong if the main was attacked and lost drones. The new method balances workers well in all cases, not only the common case.

  • Steamhammer tries to make fewer macro hatcheries before expanding beyond its first and second bases. I saw games where it made as many as 4 hatcheries in its main before taking the natural—it might be OK if the bot is contained, but not the other 6 days of the week.

  • Delay the second gas a little. Steamhammer consistently took the second geyser too soon. I think it’s still usually too soon, but the loss is reduced.

  • Dark templar more strongly indicate the need for static defense. They hit hard.

  • Make a defensive spire in reaction to enemy drop or certain air units. Formerly, only overlord hunters like corsairs would trigger a defensive spire.

  • In ZvZ, prefer to counter hydras and especially lurkers with mutas, not lings only. Steamhammer usually did the right thing, but in a few games made a severe strategy mistake.

  • In ZvZ, Steamhammer formerly made an evolution chamber if it saw an enemy spire, no matter the state of its own spire. That’s a mistake; the evo is often unneeded, and in ZvZ the drone to make the building is valuable. Now Steamhammer attempts to time the enemy spire and make the evo only if needed. I don’t find it particularly accurate, but it is an improvement.

  • In ZvZ, enemy scourge more strongly discourages Steamhammer from making guardians and devourers. See the game I posted last time, where Steamhammer scourged Microwave’s devourers. Devourers and guardians have little ability to defend themselves against scourge; they can only survive with the help of escorts.

  • Limit devourers further. Devourers are support units, so try to keep more mutalisks than devourers.

  • A lost defiler mound could cause a production freeze. It was rare, but a production freeze can be a game-losing bug. It’s frustrating, but there remain rare production freezes that I have not traced.

  • Emergency reactions: When there are 0 drones, Steamhammer can cancel upgrades and more building types. Formerly it could cancel only units and a few building types.

  • Emergency reactions: Correctly account for the gain of canceling a building (you get 3/4 of the cost back). It helps in making the right cancelation decisions.

  • Emergency reactions: A bug could allow a planned hatchery to be dropped even though it was the only hatchery.

  • ZvZ mutalisk target selection adjusted in a few cases.

  • Lurkers prefer the most distant target. It helps visibly.

  • Fixed lurker vibration: Sometimes lurkers would move back and forth, achieving nothing, instead of advancing on the enemy.

  • Attackers can no longer permanently drive overlords away from the spore colonies where they are sheltering. This was a bug introduced in a recent version.

Zerg openings

  • 3HatchLingBust2 makes the minimum number of drones and goes all-in on the bust. This version is now configured in place of the original 3HatchLingBust as one counter to protoss forge-expand builds.

  • 12Hatch_4HatchLing makes the right number of drones for continuous zergling production from 4 hatcheries. It’s similar to 3HatchLingBust2.

  • 2HatchMutaPure and 3HatchMutaPure each make only 1 pair of zerglings, and instead get as many drones as possible without delaying the mutalisks. The 2 hatchery one is especially elegant. These are for use against opponents that sit back and defend for a time before moving out.

  • Overpool2HatchLurker and 3GasMuta similarly are more effective against opponents that are late to attack.

  • DefilerRush rushes for defilers to support highly-upgraded zerglings. I used it mostly in testing defilers, but there are opponents it could be strong against. The defiler rush is similar to the existing HiveRush build, but better optimized (and of course it also makes a defiler).

  • 12PoolHydra is configured as one counter to terran factory-first openings. 12PoolLurker fills a gap in the lineup of lurker openings. ZvZ_12PoolLingB is a minor variant of ZvZ_12PoolLing. ZvZ_12Gas11Pool is a gas-first stem that fills a gap.

  • Overpool_3HatchSpeed, Overpool_3HatchLing, and Overpool_4HatchLing try to combine the early zerglings of overpool, which can keep the opponent in the dark and defensive, with a mass zergling followup. Overpool_4HatchLing is configured to be played 1% of the time in ZvZ versus an unknown opponent—it’s risky but can also be hard for the opponent to understand and counter (it makes a third base that the opponent is not likely to scout in time).

  • 10Pool9Gas and 10Pool9Hatch fill small gaps in the ZvZ opening repertoire.

  • 7Pool6GasMuta is derived from one of my 7 pool 6 gas dawn lurker rush builds. It’s quite easy to defeat, even without air defense, with an early attack. I suspect it is useful mainly against opponents which want to defend and fail to figure out how to defend so early.

  • Minor tweak to 2HatchHydra. Bigger adjustments to OverpoolTurtle so that it can more consistently beat those (weak) opponents it is intended to beat.

Other changes

  • Fixed the protoss ForgeExpand opening. At some point it was edited incorrectly and started to place the cannons in the main, where they were nicely protected since the enemy tore down the natural first.

  • Added a protoss 10-12ForwardGateExpo opening. It puts gateways in the natural and tries to scare the enemy with some zealots before expanding. Whether the gateways successfully fit in the natural may vary by map....

  • Added a zerg UltraRush opening. It’s not useful as written, unless maybe some opponent is extremely passive and at the same time highly skilled in stopping defilers. But I left it in.