Skip to content

Releases: kant2002/steamhammer

Release 2.1.4

15 Jan 05:08
Compare
Choose a tag to compare

UnitInfo

UnitInfo was inherited from UAlbertaBot. It is responsible for keeping track of enemy units that may be out of sight.

  • Keep track of burrowed units, both zerg burrowed units and spider mines. Formerly, when a unit burrowed, Steamhammer thought “oh, it disappeared from its last seen position” and lost track of where the unit was. Now the units are tracked and get passed to the combat simulator, and could be used for other purposes—”mines are ahead, send an overlord now!” It’s a little tricky, by the way. If you detect a burrowed unit then you detected it, but if detection is not available and a unit disappears, then why? When a zerg unit burrows, it has the order Orders::Burrowing, so you can distinguish a burrowing unit from a unit that merely walks out of sight. But a spider mine has the order Orders::VultureMine no matter what it is doing. So I simply marked spider mines down at the position where they were last seen, and it works accurately so far though it could be wrong in rare cases. BWAPI doesn’t provide “a cloaked unit in this position would be detected if it were there, therefore it’s not there,” so for now I ignore the case of a burrowed unit which moved away or was destroyed while out of sight. At some point I’ll add a feature to cover BWAPI’s lack.
  • I renamed the field lastHealth to lastHP, since that’s what it is. I decided to use “health” to mean HP + shields.
  • Steamhammer 2.0 added UnitInfo::estimateHealth() to estimate the health of an unseen unit, accounting for protoss shield regeneration and zerg HP regeneration. Terran repair and medic healing are not so easy to predict. This version adds separate estimateHP() and estimateShields() for use by the combat simulator.
  • The HP and shields of an undetected enemy are 0 because the enemy unit is not detected (easy to understand, right?). Steamhammer formerly took it literally and did not pass an undetected enemy unit in sight range into the combat simulator, because a unit with 0 HP is paper. I had assumed that Steamhammer was weak against dark templar because FAP doesn’t support cloaking and detection, but it was deeper than that. I fixed UnitInfo and the estimators to assume that a visible but undetected enemy has full HP and shields. Hmm, maybe a better fix is possible?

combat sim

  • Use estimateHP() and estimateShields() for a more accurate representation of the starting situation. Formerly, for unseen enemies, the combat sim used the last known HP and shields (if the HP were not incorrectly 0 for an undetected enemy, as mentioned in the previous bullet). The estimates take into account regeneration since the units were last seen. Cloaked units are understood much better, though FAP still doesn’t understand that it can’t hit them without detection. Otherwise, the estimators rarely make a big difference.
  • Mutalisks versus spore colonies situations play adequately again. A bug was introduced in version 2.1.
  • Combat sim is centered on the nearest enemy rather than the frontmost friendly unit. UAlbertaBot provided a system where it picks one of its own units as the vanguard of its force, draws a circle around the vanguard, and includes everything that can fire into the circle in the combat sim. When our force moves forward, more enemies are included, so we may retreat, causing fewer enemies to be included, so we advance, etc. Steamhammer 2.0 changes this to include one cluster of friendly units (based on the unit clustering algorithm) in the combat sim, plus the enemies in the circle. Steamhammer 2.1.4 now centers the circle on the nearest enemy instead of the vanguard friendly unit. As friendly forces move back and forth, the set of enemies often stays the same. It greatly reduces vacillation and unit suicides. The circle is also smaller, to encourage aggression.
  • Bruce @ Locutus pointed out a FAP bug confusing ground and air units in unitsim(). I fixed it, and it helps... to a limited extent. It’s a severe bug, and I expected a bigger difference.
  • The FAP unit field airMinRange is always 0. I removed it and all its uses. Since it was tested in an inside loop, all sims involving air units run a trifle faster. The groundMinRange affects sieged tanks, so it has a use.
  • Units that are under maelstrom (detail stolen from MCRS) or under disruption web are excluded from the combat sim by UnitUtil::IsCombatSimUnit(). A dwebbed unit could move out of dweb, but will it? The combat sim doesn’t understand it.
  • The whichEnemies is reworked and completed. It specifies which types of enemies should be included in the combat sim, which makes a difference because Steamhammer decides the result by the unusual but successful criterion “who has more stuff left over at the end?” I renamed AntigroundEnemies to ZerglingEnemies because, believe it or not, it’s clearer, even though it doesn’t apply only to zerglings. You’re a zergling enemy if you’re on the ground (a zergling can hit you) or you’re in the air and you can shoot down (you can hit a zergling). A corsair is not a zergling enemy and is excluded. I added GuardianEnemies (which is unused) and DevourerEnemies (used) to complete the set (AllEnemies was already there). The CombatSimulation setup class calculates all the exclusions more accurately than before to pass the right units to the combat sim.
  • Steamhammer scores the combat sim by unit prices. Some units have deceptive prices that don’t represent their value. For example, BWAPI arbitrarily says that a spider mine has mineral cost 1. I made special cases for deceptive prices.

micro

  • Nearly all micro actions now have bookkeeping in MicroInfo, and the action of moving (which is when units get stuck) is handled completely by the MicroInfo system. Any move commands are now carried out at the end of the frame, after additional checks are done. I think units get stuck less often, though with more experience it becomes harder to see; maybe I’m fooling myself. At worst, the extra bookkeeping will make it easier to get units to follow their orders. On the downside, some bugs in the previous test versions were caused by failing to record changed orders in the MicroInfo system. I believe that this includes the recent production freeze bug, which I hope is fixed now. I should figure out how to avoid the risk of this kind of bug; I will have to change something.
  • DistanceAndDirection() is corrected and simplified. It’s a utility in Common.cpp which takes a base point, a direction point, and a distance. The direction point specifies a direction from the base point, and the routine returns a point at the given distance from the base point in that direction (it’s scaling a vector). The distance can be negative. There was a basic error: It calculated the (x, y) offset from the base point correctly, but forgot to add the base point to the offset, so the code looked right when I read it but the result was completely wrong! Since I was touching it anyway, I also simplified the code.
  • A ground unit which finds itself directly next to an undetected enemy dark templar will try to flee away from the DT (using DistanceAndDirection()). The DT has to work harder and some units escape danger, but many units still get hit, especially if there is more than one DT. A disadvantage is that the fleeing units get disorganized and work together even less well than usual.
  • Guardians are kited by the same code as mutalisks. It reduces cases where they marry a target and refuse to switch to a better one.

operations and tactics

  • Attempt to retreat behind static defense, instead of stopping in front of it. It’s not entirely successful, but it seems to help some.
  • There are a number of changes to base defense. There is a minor rewrite to simplify one part and improve efficiency. The enemy scout worker is no longer ignored; any enemy in the base is now reason to form a Base squad and clear the base; it helps deny enemy scouting. When deciding on how many defenders to assign, Steamhammer now weights enemy workers more lightly and certain tough enemy units more heavily, so the squad size should be more appropriate to the threat.
  • The base defense squad also assigns a detector under narrower conditions, which ameliorates one major cause of mass overlord suicide. Unfortunately there are other causes.
  • Don’t assign a detector to an otherwise empty squad. There was a loophole.
  • Fixed a minor bug in dropping the empty Base squad of a destroyed base. It had no important effect. I think there is still one more case where dropping an empty squad does not happen as intended.
  • For most of Steamhammer’s life, it has been the case that a melee unit next to a sieged tank does not retreat, but attacks the tank instead. I extended it slightly: If the tank is in the process of sieging or unsieging, the unit also does not retreat. It’s a little more insistent about hitting the tank while it can.
  • For purposes of operations targeting, a refinery building is considered always reachable by ground. It’s one of the 4 cooperating bugs that I hit recently. This is, of course, a workaround and not a fix. If Steamhammer becomes aware of a refinery on an island....

early-game scouting

  • In the scouting code that Steamhammer inherited from UAlbertaBot, a potential enemy starting base is considered scouted and unoccupied if we have explored the TilePosition where the enemy resource depot would be, and nothing is there. But that’s a little inefficient; it’s the position of the upper left corner tile of a building which is 4x3 tiles in size. If we are approaching from the right, say, then it’s one of the last tiles of the building location that we see. So now Steamhammer can recognize a base as unoccupied if we have scouted any of the 4 corners of the building location. The early game worker scout sometimes saves giant fractions of a second in finding the enemy. Someday I’ll add creep recognition too, which will save a useful amount of time when...
Read more

Release 2.1

15 Jan 04:56
Compare
Choose a tag to compare

Here is the change list:

opponent model

  • Fixed a bug in InformationManager that could fail to recognize an in-base proxy.
    macro
  • Configured WorkersPerPatch to 2.0 for terran and protoss, to reflect mineral locking. Mineral locking helps terran and protoss over zerg, because bases tend to have more workers. Reducing the maximum worker count per base while maintaining full mining efficiency means that much more cash and supply to spend on tech and army.

tactics

  • Medics and tanks act in clusters. They are controlled by their own code, which needed updating.
  • Bug fix: A cluster of all medics which happened to reach the front line would then continue to advance heedlessly into the enemy position and die. Now it falls back toward the base—normally it will soon merge with another cluster that is on the way. To implement this, I split the former “no fight” case into 2 cases, “I have no fighting units” and “there are no enemies nearby,” which behave differently. All medics is an example of no fighting units.
  • Steamhammer knows a number of places that a cluster of units can retreat to. I moved “retreat to join up with another cluster” (which can be an advance rather than a retreat) ahead of “retreat to the location of a cluster unit which is not near the enemy” in priority order. It helps clusters merge a little more often.
  • When there are many clusters, Steamhammer saves execution time by not updating all clusters every frame. It divides the clusters into “phases” and updates one phase per frame. In Steamhammer 2.0, the phases were calculated incorrectly, which contributed to bad micro (though it wasn’t the biggest cause). Fixed.

combat sim

  • Combat sim scores are based on the cost of units, not the destroyScore, because destroyScore is sometimes strange. For now I set score = mineral cost + gas cost.
  • Steamhammer uses the combat sim scores in an unusual way to decide who won the simulation: It’s the side that ended up with more stuff surviving. It seems illogical, but it tested better than alternatives I tried, such as the side that lost less. Still, there are pathological cases where it gives a wrong answer. I fixed this pathological case: If you lost nothing, then you won the simulation, even if you finished with less stuff surviving. (If the other side also lost nothing, then you still won, because a draw counts as a win.)
  • I also changed the units included in the combat sim in special cases. 1. If you have nothing but ground units that can’t shoot up, then ignore enemy air units that can’t shoot down. Because the side with more surviving stuff wins, this can affect who wins the simulation. This fixes another pathological case, where for example zerglings might run away from corsairs. 2. If you’re scourge, include only ground enemies that can shoot up. Scourge are never afraid of the air units that they want to destroy, only of useless death by ground enemies.

At some point I’ll add the other natural special case, for air units that can’t shoot down. All this combat sim stuff could be way more sophisticated....

micro

• I fixed the biggest cause of poor micro in Steamhammer 2.0. As part of choosing an enemy target, the melee and ranged unit controllers called CanCatchUnit() to see whether the enemy unit would be able to escape if chased. It was meant to reduce goose chases. Anyway, the results of CanCatchUnit() are apparently wrong. I haven’t looked into what the trouble was, because I found that removing the calls had no effect on goose chases—long chases have become rare due to other changes. The error caused units to overlook targets that they could, and often should, attack. Zergling micro became weak, and zealot micro was worse. It’s all back to normal now.

  • Vultures and wraiths would become fixated on their targets, unable to switch away even to retreat in an emergency. Fixed.
  • Like clusters, defiler actions are divided into phases. There was a bug in coordinating the cluster phases and defiler phases, so that defiler actions might be skipped for a long time depending on the phase of the cluster the defiler was in. Fixing it makes defilers more active, though they still don’t swarm or plague as often as they should.
  • Scourge is allowed to spread out more in regrouping. Mutalisks should usually group tight, scourge should spread out some. Formerly, all air units behaved the same.
  • I made a couple adjustments to defiler plague. 1. Plague on a building was formerly worth 0.6 of plague on units with the same hit point loss; I changed the discount to 0.3, half as much, so that defilers will try harder to plague units. Buildings have a lot of hit points and threaten to dominate the scoring. (Static defense buildings are treated the same as mobile units, though.) 2. Plague gets a bonus for carrier interceptors, to exploit the plague-on-interceptor behavior, but I didn’t see Steamhammer trying hard to plague XIMP’s interceptors (only the carriers themselves). I increased the bonus by a factor of 4.

zerg

  • Scourge are in their own squad, the Scourge squad. They behave somewhat better in my tests, but it’s primitive and they still have a long way to go. I mentioned a couple other improvements to scourge behavior above. It was surprisingly difficult to get scourge to do anything sensible.
  • Get an evolution chamber and a spore colony for air defense when needed even if still in book. Steamhammer formerly waited until the book line came to an end before it dared defend itself. I think this will be a net gain, though it will make mistakes sometimes.
  • Tweak: Enemy dragoons and dark templar loom a little larger as reasons to make static defense.
  • Fixed a bug in deciding to get defilers. Battlecruisers are an excellent reason to get defilers; valkyries, not so much.
  • Strongly avoid spawning mutalisks versus large valkyrie counts. Valkyries in numbers pass through mutas like they’re hardly there.

openings

  • Fixed a typo in the opening name Over10Hatch2SunkHard in the AntiZealot strategy combo. When this opening was selected, Steamhammer couldn’t find it and played its default 9 pool instead, a poor choice against mass zealots.
  • Added the zerg opening AntiFactoryHydra, which may be better against SAIDA’s unit mix than Steamhammer's original AntiFactory, and the terran opening 10-10-10FD in a form close to that popularized by Flash. 10-10-10 is an opening stem that gets a super-fast factory, and 10-10-10 FD is a followup that continues into an attack with 2 tanks and 8 marines, which is strong against protoss that techs too hard or expands fast.
  • I configured terran and protoss counters to Naked expand by protoss. That means configuring which openings are to be tried as counters to an expected enemy plan. 10-10-10FD should be a good counter to protoss Naked expand.

debug drawing

  • In the game info display (drawn in the upper left of the screen when turned on), Steamhammer 2.0 added an overall score versus this opponent, shown next to the opponent name, “2-3” meaning 2 wins and 3 losses. Steamhammer 2.1 also adds a score for the chosen opening, drawn next to the opening name. The context makes it easier to interpret Steamhammer’s choices. The numbers are specific to the matchup. Randomhammer will show different numbers depending on what race it rolled.
  • Squads have 2 settable flags, “fight visible only” (only include visible enemies in the combat sim, not all known enemies) and “meatgrinder” (be more aggressive, willing to accept high losses). Visible-only is used by the Recon squad, and meatgrinder tested poorly and is not used. If the squad info display is turned on, it draws cyan V and M left of the squad’s information line if the flags are turned on.

Release 2.0

15 Jan 04:45
Compare
Choose a tag to compare

Code changes

  • More stuff in UnitUtil: Cooldown and FramesToReachAttackRange() functions added, and used in micro. GetWeapon() functions reworked for simplicity. Damage-per-frame functions added to compare weapon strengths. IsCompletedResourceDepot() added, factoring out code that was repeated in several places.
  • UnitInfo::estimateHealth() estimates the health of a unit which may not been seen for a while, accounting for protoss shield regeneration and zerg hp regeneration. (Terran medic healing and SCV repair are not easy to predict.)
  • InformationManager::enemyHasSiegeMode() added, and used in tactical calculations.
  • In GameCommander, I sorted the manager calls so that managers which gather information are called first, and managers which use the information are called later. They had gotten jumbled over time. The main effect is that Steamhammer reacts 1 frame faster after discovering the race of a random opponent, a crucial difference that I estimate will, over Steamhammer’s lifetime, save approximately zero games.
  • I renamed SquadData::addSquad() to createSquad(), since that’s what it does, and reworked it for simplicity. I removed the declaration of SquadData::clearSquad(), which was not implemented.
  • Some calls in WorkerManager iterate through bases instead of through units to find base-related information. It’s faster and simpler (but I did have to spend time to fix a bug that I introduced in the process).
  • More unnecessary includes removed, bringing a negligible improvement in compile times.
  • I removed the configuration option Config::Micro::UnitNearEnemyRadius. The value is now chosen dynamically in code.
  • In the game info display (turned on with Config::Debug::DrawGameInfo and drawn in the upper left), most labels were not needed because the meaning is obvious. I removed the labels of items other than “Opp Plan”. Less clutter is better.
  • The TimerManager display, turned on with Config::Debug::DrawModuleTimers, had grown disorganized and probably incorrect. I straightened it out. I also improved comments in the code to prevent future disorganization.

opponent model

The opponent model has always distinguished between opponents that appear to follow the same plan every game, and opponents that vary their play. Until this version, it used the information only in a minor way. Now it selects openings using an entirely different method for multi-strategy enemies. If you play the same every game, Steamhammer will try to find the best single response, exploiting your predictability. If you mix up your play to confuse Steamhammer, then Steamhammer will mix up its play to confuse you; you get minimal predictability to exploit. We’ll see how well it works, but I’m expecting it to make a big difference in a long tournament like AIIDE.

  • Against a single-strategy opponent, Steamhammer sticks with the variant of epsilon-greedy that it has always used: With probability epsilon, explore randomly; otherwise, choose the best known opening according to a weighted win rate that tries to take the maps into account. It’s not strictly classic epsilon-greedy, though, because epsilon varies according to the loss rate: If we are losing a lot, explore more often and play the best known opening less often. (It’s an adaptation to having more openings available than can be tried.) I have modified it so that the exploration rate increases more rapidly with the loss rate, because I found it was too often repeating an opening that won 1 game out of many, instead of looking for a better choice.
  • Against a multi-strategy opponent, Steamhammer starts with the same weighted-win-rate calculation that it uses in the single-strategy case. Each opening it has already played is an option, and has a measured win rate. Exploring a new opening is an option, and its win rate is the mean win rate of openings that have been tried, its best estimate of how likely a newly explored opening is to win—but with a hard floor, so that the exploration rate never goes too close to zero. It randomly chooses among the possibilities, giving each a probability proportional to the square of its win rate. Squaring the rates gives openings with win rates near zero little chance of being chosen—unless most openings have win rates near zero. If all win rates are zero, because there are no wins yet, the hard floor on exploration means that Steamhammer explores every time. If the win rates are high for some openings and low for many others, exploration will be rare and Steamhammer will most often randomly choose one of the better openings. It’s ad hoc but makes a certain amount of sense.

macro

  • Mineral locking. Steamhammer’s implementation follows Locutus in outline, but is different in detail. Mineral locking helps mainly in macro games, which Steamhammer is now able to play better because of the squad changes, so this was an opportune time to add it.

construction

  • Prefer to expand to bases near the edge of the map. Bases near the edge are usually (not always) more protected than bases near the center of the map. In practice, Steamhammer now mostly avoids taking the risky center bases on Heartbreak Ridge and other maps, and the exposed mineral only bases on Python, at least until later in the game. I had to tune it carefully so that the natural of the 1 o’clock base on Tau Cross, far from the edge, is still preferred over the exposed 3rd base at the edge. Someday I’ll implement map analysis and figure out a real measure of exposure to attack.
  • Bug fix: Don’t try to build at a location which a worker cannot reach. It never happened, as far as I know, but there was a mistake in the code.

tactics

  • In the overview I said that workers are not transferred to base that is in danger, but there is more to it than that. Each base keeps track of whether it is being attacked severely enough that workers appear to be in danger; the estimate is made by CombatCommander::updateBaseDefenseSquads(), which I wrote about under base defense, and can be accessed via the Base objects for each base with base->inWorkerDanger(). If a worker is idle, meaning it is due to be assigned a new task if one is available, then it is not assigned a task at a base where workers are in danger. A worker is normally made idle after completing any task: worker was just created, gas collection is being turned off so worker no longer needs to mine gas, worker is finished defending itself and should be put back to work, and other cases. Workers are not only not transferred to an endangered base, they are often (not always) transferred away from the endangered base because they had to defend themselves, or were pulled for defense, or otherwise changed tasks. It’s hardly perfect, but it saves workers and greatly improves Steamhammer’s resilience to attack. It was a critical improvement. Related weaknesses remain: Steamhammer may still try to build at the endangered base, or transfer drones to a distant base through the enemy army.
  • Fixed CombatCommander bugs in deciding which enemy base to attack.
  • Rules for recognizing enemy cloaking and assigning detectors to our squads are slightly improved. Steamhammer pays attention to whether it has cloaked units itself and needs to catch enemy observers. This allows overlords to stay safer in some game situations: We don’t have lurkers, therefore we don’t have a strong need to hunt observers, therefore overlords can stay home.
  • In feeding units to the combat sim, an enemy building which was last seen uncompleted is entered as completed if is currently out of sight. It is sometimes an improvement, sometimes a mistake. It would be better to track the estimated completion time and use that (a number of bots do).

micro

  • Previous versions changed former stateless module Micro into an object with state, but did nothing new. This version updates the state with each of our unit’s orders and a little more information, but still doesn’t use the state for anything. It’s all prepared for serious work, though.
  • Enemy unit movement prediction is smarter. It takes distance into account. Also, prediction is used differently in different cases to get better results in practical situations. Mutalisks, wraiths, and vultures now use prediction; as instant-acceleration units they are kited by a different routine than other units, which didn’t use prediction until now.
  • Kite only units which the enemy has targeted. If nobody wants to shoot you, you don’t have to step back from the shooting. This especially helps hydralisks, which fire more slowly when kited and tend to get in each other’s way.
  • Some bits of micro explicitly take latency into account in their calculations, especially kiting. It’s more accurate.
  • Don’t chase an enemy if we’re predicted to be unable to catch it. CanCatchUnit() (defined in Common.cpp) figures it out. It makes less difference than I expected.
  • Targeting priority: A ghost which is nuking is the highest priority target. An enemy defiler is also a high priority. These two were oversights. There are other targeting tweaks, for example to reduce cases of attacking the pylon when the cannon behind it is firing; it’s not fully successful.

zerg

  • If we are short of mutas or lurkers (by a simple hardcoded count), then do not substitute a drone for a muta or lurker, no matter how much we may want drones. This was the biggest cause of delayed tech switches, and fixing it makes strategic play crisper at key times. This was one of the most important fixes in version 2.0.
  • Late in the game, add extractors willy-nilly everywhere that they are possible. Steamhammer was too often gas-starved in the late game, too slow to get more gas when it was needed. This is also an important fix.
  • Limit scourge more stringently. Sometimes Steamhammer makes so much scourge that it has no gas for anything else, causing macro problems as it delays production to get more gas.
  • The building mana...
Read more

Release 1.4.7

07 Sep 12:31
Compare
Choose a tag to compare
Update to Release 1.4.7

Release 1.4.4

07 Sep 12:19
Compare
Choose a tag to compare

the Bruce bugs

The bugs found by Bruce Nielsen (Locutus) and related fixes.

  • BuildingManager::validateWorkersAndBuildings() copied building objects unnecessarily.
  • BuildingManager::cancelQueuedBuildings() and BuildingManager::cancelBuildingType() unsafely deleted buildings from the _buildings vector while looping through it.
  • Squad::releaseWorkers() had a similar deletion bug.
  • MapTools::nextExpansion() had a typo that caused it to do a check with the wrong coordinates.

other code changes

  • UnitUtil::GetAttackRange() and UnitUtil::GetAttackRangeAssumingUpgrades() mistakenly returned the weapons range of a reaver or a carrier as 8 pixels, rather than 8 tiles (8 * 32 pixels). “We’re perfectly safe at this distance, folks!”
  • I am reworking DistanceMap as the foundation of a range of classes that keep a number for each tile of the map. A new base class Grid provides the basic data structure, initialization to a constant value, and lookup. DistanceMap is renamed to GridDistances. I wrote a new class GridAttacks as a start on a kind of influence map; some code is there, but it is not yet tested or used, so exercise care.
  • Removed the unused BuildingData class, and the unused method MicroManager::calcCenter().
  • Removed more unnecessary includes.

zerg

  • If an expansion hatchery fails to build, the building manager turns it into a macro hatchery instead. It prevents Steamhammer from sending drone after drone to expand and losing them all. It’s a low-level trick instead of the high-level tactical safety analysis that should be done, but it’s simple and it works moderately well.
  • Versus protoss, count only corsairs, scouts, and carriers as reason to make devourers. Steamhammer played a game in which it made devourers to combat the enemy’s large number of observers. “I know how to beat that plan!”
  • On 2 player maps, increase the chance of playing rush-safe ZvZ openings. Also rejiggered fast pool chances (suggestion by Antiga). A number of other probabilities are adjusted, mostly to make more diverse choices so that learning has data to work with.

Official press-release: http://satirist.org/ai/starcraft/blog/archives/594-Steamhammer-1.4.4-change-list.html

Release 1.4.2

17 May 05:53
Compare
Choose a tag to compare

Here list of changes which go into that release from Jay Scott

Opponent model

  • Select openings which have been successful against this opponent before. Take the map into account; with experience, Steamhammer will play different openings on different maps (though with 14 maps to learn about, map adaptation is slow as a snail). If past opening choices are not fully successful, try out different openings. With an increasing number of games, this increasingly includes openings that aren’t tagged as suitable for the opponent’s recognized plan, or for the opponent’s race, or even openings that Steamhammer otherwise won’t play at all. We will occasionally see openings that Steamhammer has never played in public before, because they were written in but not configured to be played. This is more or less as described in my earlier plans. I’ll post a more detailed description separately.

  • When recording the opponent’s game record to a file at the end of each game, rewrite the entire file instead of appending to it. Appending works on SSCAIT, but most other competitions require the file to be rewritten.

  • The plan recognizer recognizes a new Factory plan that can be followed only by terran. It means terran is starting with a mech opening. Zerg is configured to counter the Factory plan with an AntiFactory opening. In tests against different opponents, the plan is accurately recognized, and the change produces much stronger zerg play against terran mech openings. Terran and protoss are not configured with anti-mech openings, but could be.

  • The plan recognizer is smarter in one way: If the opponent plays a fast opening plan, the recognizer doesn't change its mind later when it sees signs of a slow opening plan; it wants to recognize the first thing the opponent does. The plan recognizer was doing things like correctly recognizing a 5 pool as Fast rush, then later seeing the 5 pooler add a second hatchery, and deciding that it was a macro opening after all. In the next game, Steamhammer could react incorrectly.

  • There was a typo in the UCB code! Fixed. This affected the auto gas steal, if it was turned on.

  • Separately, the auto gas steal is a little more conservative. It wants to see more evidence that it is useful before it is repeated.

  • Try to detect whether the opponent always plays the same strategy. If so, the game info display notes it as (say) “surely Fast rush” instead of “expect Fast rush”. The opponent model uses the information behind the scenes (a little bit).

Map analysis

  • New code calculates base locations and stores related information. It works, and is used for some purposes, but most of Steamhammer still relies on BWTA. The information manager indexes bases by their BWTA::BaseLocation, and it turns out to be something that should be redone in one sweep. Later I’ll move the information manager functions into the new Bases class.

Openings

  • The opponent model is now in charge of choosing openings, so the CounterStrategies section of the configuration file is now used only when the opponent model wants to try out openings that respond to the enemy's expected plan, rather than whenever the enemy has an expected plan. I made the probabilities more even, so that stronger counters are still preferred but weaker counters will come up more often than they used to. That will help the opponent model collect the data it needs.

  • I haven’t documented it before, but Steamhammer for a time has had some openings which are included in the configuration file but not configured to be played. Bot authors might choose them for their own bots, or take them as starting points for developing new openings. The opponent model is now able to select these openings. It will occasionally choose one at random and try it out against an opponent which it has played many games against, and if the opening is successful it will keep playing it against that opponent. For this release, I added more unconfigured openings.

  • Included in the openings provided but not configured to be played are a bunch of new protoss openings from Antiga. They deserve attention, but I ran out of time.

  • OverpoolSpeed was accidentally replaced with a bad opening in the previous version. I restored the good version.

  • The classic Over10Hatch opening was restored under that name. It makes 2 sunkens at earlier timing than the newer Over10Hatch2Sunk, and builds fewer drones. The idea is that restoring it should allow old learned data at SSCAIT to remain useful—it’s useless when it refers to an opening name that no longer exists. Plus there are times when the low-economy version works better.

  • New zergling rushes 5PoolHard2Player which hits harder on 2 player maps, and 6PoolSpeed which hits differently.

  • Zerg has a new AntiFactory opening to combat early vultures and their followup. It works great. Terran has a corresponding VultureWraith opening for TvZ. I wrote it as one of the tests of AntiFactory, and found that it is effective against zerg opponents which aren’t ready. And the opponent model should now be able to tell which opponents are not ready.

  • New zerg openings Over10HatchBust, Over10HatchSlowLings, and Over10Hatch2SunkHard are variations of the anti-zealot rush build and may be suitable for different opponents. They are intended as food for the opponent model. Overpool+1 is a weaker version of the ZvZ opening played by Marian Devecka’s Killerbot. Because of a limitation of the strategy boss, it gets carapace +1 instead of melee attack +1, which reduces its effectiveness. None of these openings is particularly good, but I expect they will have value against some opponents.

Production

  • No more queue deadlocks. Steamhammer avoids most production jams by recognizing and dropping jammed items. This affects terran and protoss; zerg already had virtually no production jams.

  • Effective queue reordering. The previous version occasionally reordered queue items for more efficient production. This version generalizes the technique and benefits from it much, much more often. If the next queue item can’t be started immediately, and a later item up to 4 places ahead can be, and other conditions are satisfied, the later item is moved to the front of the queue and produced immediately. This affects all races, terran the most, protoss somewhat less, zerg the least.

With production unjamming and queue reordering working together, terran and protoss macro is way smoother. Production unjamming is aggressive; it drops any item which will cause a long delay. BOSS will often order (say) a cyber core and then dragoon range immediately afterward. It caused a long delay, though not a deadlock. Now when that happens, Steamhammer usually finds when it gets to dragoon range that the cyber core is still in the building manager’s queue and hasn’t been started yet, so it drops the research. BOSS will order the research again on its next cycle; not ideal but a big improvement overall. Meanwhile, the next cycle comes sooner because queue reordering makes production of this cycle faster. If the cyber core was started and hasn’t finished, other queue items will be pulled in front of dragoon range and produced first. Unfortunately, BOSS is as happy as ever to order all buildings and no units. Queue reordering can only mitigate the flaw to an extent.

  • It’s possible in principle for queue reordering to be too thorough and break an opening’s intended build order. To cope with that, I added a new command that can be included in a build order, "go queue barrier". Nothing after "go queue barrier" will be reordered to happen before it. It was just a tiny little bit trivial to implement, because it’s a command that does nothing; queue items are never reordered across any command. No openings use "go queue barrier" currently; I tested the likely candidates and found that they worked fine with queue reordering.

  • Protoss should not overstep the time limit when its base fills up with buildings. This is a major improvement for protoss. There are 2 contributors to the slowness: Failing building placement in the building manager, and failing building placement in the production manager when it tries to predict when a building can be started (it needs to know where, so it can figure out how far ahead of time to send a worker). The change is applied in both places; both are fixed. The production manager’s problem was already mitigated by a workaround which retries building placement less often, and I kept the mitigation since placement can fail for other reasons. The problem won’t be 100% solved and shelved until building placement is fast and reliable.

If the debug option Config::Debug::DrawBuildingInfo is turned on, then buildings which are currently stalled and cannot be built are in red. After a pylon finishes and the buildings unstall, they turn back to the normal yellow color.

  • Earlier versions tried to work around the protoss building placement problem in part by allowing certain types of protoss buildings to touch each other vertically. This made building layout more compact, but had the side effect of sometimes trapping units in enclosures. This version drops the workaround. Protoss base layout is loose to the point that it is awkward and causes problems, but that is not as bad as trapping units.

  • Terran addons are produced via production goals, which construct them more reliably and earlier. It is a significant improvement for terran. Some terran openings are improved to take advantage; there is more room to improve them. I removed a workaround for a BOSS comsat bug, since production goals work around the bug automatically.

Tactics and micro

  • Deciding which base to attack now takes into account some of the enemy units seen near that base. Earlier versions took into account static defense only: Attack the base with the least static defense. This version also takes into account certain slow-mov...
Read more

Release 1.4.1

05 Apr 16:27
Compare
Choose a tag to compare

Fixes and improvements

Maps

  • Fixed a crash on a certain seemingly messed-up version of Bloody Ridge.
  • Nicer code for distance maps, borrowed from a later UAlbertaBot. The new code is much cleaner and less bug-prone.

Configuration file

  • The debug option DrawBWTAInfo is replaced with DrawMapInfo, since I’m preparing to drop BWTA. For now, DrawMapInfo doesn’t do anything, since the new map code is turned off. The old BWTA info drawing code is removed.
  • Bug fix: "n x item @ macrolocation" finally works, e.g. "2 x photon cannon @ natural". It was a bug in parsing.
  • Added a new macrolocation @ center. Don’t use it though, except maybe on specific maps where you’ve tested it out; it doesn’t work consistently due to building placement bugs. If you ask for 2 buildings in the center, you may get 1 or none.

Opponent model

  • A new strategy reaction for all races: If the opponent is following a heavy macro strategy and we are still in the opening, drop any planned static defense. We won’t need it right off. Static defense added later (as a reaction to seeing scary enemy stuff) is built as normal.

Tactics

  • A squad that can’t find any buildings or units to attack has always been sent to explore the map. The change is, if the squad includes air units, it can be sent to explore tiles which are only reachable by air. It will help... if any opponent ever expands to an island or builds on a cliff, which hasn’t been seen so far.
  • Steamhammer decides which enemy base to attack based on how much static defense it has. The change is, the enemy static defense is counted only up to a smaller distance. The longer distance was causing some mistakes in choosing targets.
  • Bug fix: Units like scourge, which could belong to either the ground squad or the flying squad, could sometimes be mistakenly stuck permanently in the ground squad. The change is to CombatCommander::updateAttackSquads(). I saw a game today where this change would have helped, so I’m hopeful that it is a useful fix (but it’s certainly a fix).

Micro

  • Melee units (other than workers) prefer targets under dark swarm, in hope of also staying under swarm. This mainly helps protoss for now, but it is also preparation for when Steamhammer gets defiler support.
  • Dark templar target zerg spore colonies with higher priority. I saw a bad game.

Other stuff

  • A few more opponent-specific strategies were dropped from the configuration, after experience showed that they were not needed any longer. My plan is to drop the remaining ones in the next version, 1.4.2, and rely solely on learning.
  • Seeing a unit in the act of burrowing now tells Steamhammer that the enemy has burrow tech. It used to have to detect the burrowed unit to know. So many details to catch....
  • The old ProductionManager::goOutOfBook() is renamed to goOutOfBookAndClearQueue(), which is what it does. A new goOutOfBook() goes out of the opening book if we are in it, and nothing else. This simplifies a few bits of code and makes them easier to understand.
  • The unused BuildOrderQueue.queueItem() is removed.

Terran and Protoss

  • Emergency response: If we have fewer than 3 workers, urgently make more if possible. This provides a small chance of surviving an extreme emergency—maybe the opponent is broken too.
  • New 21Nexus opening, borrowed from Antiga.
  • In tank openings, get vulture speed earlier. It was too late.
  • Limit gateways to 10 total, an idea borrowed from the excellent Steamhammer fork Locutus. There are 2 benefits:
    1. BOSS likes to order far too many gateways, so limiting the total prevents unnecessary expenditure.
    2. What’s even more important is, it works around the building placement bug that causes the bot to exceed the per-frame time limit and lose games. The bug comes up when Steamhammer runs out of space to add buildings, so adding fewer buildings prevents it from happening. It is a super successful mitigation; it works better than all my other tries put together. In fact, I’ve been thinking of removing the vertical building placement workaround, which now probably causes more problems than it solves—maybe next version.

Zerg

  • When dropping excess upcoming hatcheries, count unstarted hatcheries in the limit. Steamhammer still often makes excess hatcheries, but it’s a little less severe. Steamhammer can’t time its hatcheries accurately, because it depends on future production timings and future unit mix, which Steamhammer doesn’t try to predict. The heuristics it uses instead are usually not far off, and this change is a small improvement to one of them.
  • Supply counting for overlord production simulates how supply changes as queue production proceeds. The simulation is not exact, because it doesn’t account for timings such as how long hatcheries take to finish, but it is as exact as possible otherwise. This makes it possible for opening lines to order overlords at exact points and expect that runtime execution will follow the instructions. In practice there’s no gain for most openings, because overlord production was already fairly accurate. For occasional openings that depend on producing later overlords at precise timings, the difference is dramatic. Overlord production outside the opening is not improved, because overlords aren’t queued ahead of time then. (They aren’t always queued in the opening either. It’s optional, and overlords are only included when they are to be made at specific timings.)
  • Important macro improvement: In midgame and later, make overlords faster. This fixes Steamhammer’s tendency to repeatedly supply block itself once the drone count grows over 40 or 50. Steamhammer still has some zerg macro weaknesses, but they are getting to be so slight that they aren’t worth attention for now. Well, except for one problem where it accumulates minerals versus terran....
  • If the lair, spire, or hydralisk den is lost or cannot be made, break out of the opening. The plan has gone awry, so give it up and hand over control to the strategy boss.
  • If the enemy has air tech or cloak tech, order a lair even if we don’t otherwise need a lair yet. The lair is a precondition for existing rules to fire, adding a spire or researching overlord speed to react to the enemy tech. I added this after watching Steamhammer lose a game where it thought that fast hydras with slow overlords were a good counter to dark templar (they could be good enough if it knew the right way to use them...).
  • If hydras are needed in a hurry, get hydras in a hurry. If Steamhammer finds that zerglings are bad and hydralisks are good, and lair tech is still far away, then get hydras immediately without considering the longer term plan. This is a simplified way of accounting for the time it takes to get tech, as well as the value of the tech. In some future version, Steamhammer will calculate the time to get each tech and the urgency with which it is needed, and take all into account uniformly.
  • Critical bug fix: Tech target calculation was wrong because a condition was coded as “if we have hive” instead of “unless we have hive”. This stopped many tech switches that should have happened in the middle game. This should improve play in many games, especially versus terran—though I have seen one or two games where Steamhammer probably played better because of the bug. Steamhammer’s understanding of tech switches remains shallow.
  • Slight tweaks to ZvT tech choices.
  • All zerg openings are updated to allow sunken colonies to auto-morph.
  • The overhatch openings played versus random are switched from the in-base hatchery to the expo hatchery versions. The expo hatchery is better versus terran and protoss and still playable versus zerg, so it should be an improvement.
  • New openings: Over10Hatch1Sunk ZvZ_12PoolMain ZvZ_12PoolLing 2.5HatchMuta. The openings offer new choices against all races and should make Steamhammer even harder to prepare against. Also renamed a few existing openings with more specific names, to fit with the new ones.

Announcement: http://satirist.org/ai/starcraft/blog/archives/520-Steamhammer-1.4.1-change-list.html

Release 1.4

05 Apr 16:13
18f78d6
Compare
Choose a tag to compare

The major new feature of 1.4 is an opponent model which learns how different opponents play so that it can adapt to defeat them. See the opponent model in Steamhammer 1.4 for a description of how it works, which is quite different from how most bots learn about their opponents (those that do it at all).

There are many, many bug fixes and improvements to strategy, tactics, and unit control since the previous release version. See the change list.

Steamhammer 1.4a3, the last test version before the 1.4 release, played in the SSCAIT 2017 tournament and finished #6 out of 78 entrants in the round robin phase. The release version 1.4 scored about 2:1 against 1.4a3 in a test match where both played with random race.

Release 1.3.1

05 Sep 16:11
Compare
Choose a tag to compare

You can download the archive I submitted to AIIDE 2017, which is Steamhammer 1.3.1. It follows the AIIDE rules: It includes a compiled binary, the configuration file, and source. Unlike an SSCAIT submission, it does not include the BWAPI 4.1.2 library.

The configuration file is specialized for the tournament. The terran and protoss opening lines are removed, and it is intended to play zerg only. I did all my testing with zerg, and mostly on the AIIDE maps. Everything is optimized for the best AIIDE performance, at the expense of anything else.

Next is Steamhammer 1.3.2 for SSCAIT. It will restore the terran and protoss configuration. I also made a minor change that should improve devourer play (at least a little), and may make a few other small fixes. I need to test that protoss and terran are working well. It shouldn’t take more than a day or two, and then I’ll be right back on opponent modeling.

Original post:
http://satirist.org/ai/starcraft/blog/archives/361-Steamhammer-AIIDE-2017-version.html