what inferences do bots draw from scouting?
Yesterday I wondered what bots concluded from their scouting info. Today I try to find out.
I grabbed the AIIDE 2015 sources of 10 bots from Starcraft AI Competition - Data Archive. What inferences could I catch them drawing from scouting data? There’s a ton of code and I didn’t read most of it, so I may have missed a lot. Here’s what I failed to miss.
Bots that I did not catch making any inferences: AIUR, GarmBot, LetaBot, Overkill, Skynet, tscmoo (though it’s hard to read), Xelnaga. I think all these bots are adaptive (except possibly Xelnaga), but they seem to adapt based on directly observed data tied to decision code, not based on separately drawn inferences. You could take adaptation choices as implicit inferences, if you like.
One inference I intentionally skipped over was inference of where the enemy base is, given that all but one starting spot has been scouted. I think it’s a common ability.
Bottom line: Adaptivity is common, but explicit inferences seem scarce, and those that I found are not deep or clever. Certain bots have special-purpose “You are XIMP, I will beat you like this” code or settings, but I want some bot to say, “You built that much static defense? Are you nuts or what? Please excuse me while I take the map... hmm, siege down the front or drop?” Maybe Killerbot does that?
IceBot
IceBot recognizes enemy strategies in MentalState.cpp
(I love the name). Here it recognizes terran marine rushes based on the game time, the scv count, the marine count, and the buildings it sees. The bb == 0
check (no barracks has been seen) presumably recognizes that no useful scouting happened, or that it’s facing proxy barracks.
bc = enemyInfo->CountEunitNum(UnitTypes::Terran_Command_Center); bb = enemyInfo->CountEunitNum(UnitTypes::Terran_Barracks); ba = enemyInfo->CountEunitNum(UnitTypes::Terran_Academy); vf = enemyInfo->CountEunitNum(UnitTypes::Terran_Factory); vs = enemyInfo->CountEunitNum(UnitTypes::Terran_Starport); scv = enemyInfo->CountEunitNum(UnitTypes::Terran_SCV); marine = enemyInfo->CountEunitNum(UnitTypes::Terran_Marine); tank = enemyInfo->CountEunitNum(UnitTypes::Terran_Siege_Tank_Tank_Mode); vulture = enemyInfo->CountEunitNum(UnitTypes::Terran_Vulture); if (Broodwar->getFrameCount() <= 24*60*2) { if (bb > 0) STflag = TrushMarine; } if (Broodwar->getFrameCount() <= 24*60*2 + 24*30) { if (marine > 0) STflag = TrushMarine; } if (Broodwar->getFrameCount() >= 24*60*3) { if (bb == 0 || (bb >= 2 && (vf == 0 || bc == 1)) || (scv > 0 && scv <= 11)) { STflag = TrushMarine; } }
IceBot has similar code to recognize zergling rushes. The protoss code is the most elaborate, recognizing 6 different protoss strategies. In MentalState.h
is the enumeration of all strategies it knows of, though it doesn’t seem to recognize or use all of them.
enum eStrategyType { NotSure = 1, PrushZealot, PrushDragoon, PtechDK, PtechReaver, BeCareful, P2Base, PtechCarrier, ZrushZergling, Ztech, Zexpansion, TrushMarine, Ttech, Texpansion, };
Tyr
Tyr makes an attempt to infer something about its opponent’s strategy, though it doesn’t try hard. The possible strategy classes, from ScoutGroup.java
:
public static int unknown = 0; public static int zealotPush = 1; public static int cannons = 2; public static int tech = 3; public static int defensive = 4; public static int besiege = 5;
With several rules like this to detect protoss strategies:
if(gatewayCount >= 2) opponentStrategy = zealotPush;
Curiously, an expanding opponent is under the “tech” strategy class.
if(nexusCount >= 2) opponentStrategy = tech;
This version of Tyr can classify a terran strategy as “defensive” or “unknown”. It doesn’t have any rules for zerg strategy. The “besiege” strategy class is referred to once in the rest of the code but is never recognized.
UAlbertaBot
UAlbertaBot seems to draw few inferences, but it knows to suspect cloaked units as soon as it sees a Citadel of Adun—it doesn’t wait for the Templar Archives. I didn’t notice any sign that it suspects mines when it sees vultures or lurkers when it sees hydra den + lair. From InformationManager.cpp
:
bool InformationManager::enemyHasCloakedUnits() { for (const auto & kv : getUnitData(_enemy).getUnits()) { const UnitInfo & ui(kv.second); if (ui.type.isCloakable()) { return true; } // assume they're going dts if (ui.type == BWAPI::UnitTypes::Protoss_Citadel_of_Adun) { return true; } if (ui.type == BWAPI::UnitTypes::Protoss_Observatory) { return true; } } return false; }