Skynet - mine dragging
Spider mines do a ton of splash damage when they explode, and they don’t discriminate. Everything in splash range suffers, enemy or friendly. So it’s popular to intentionally trigger enemy mines while running up to enemy units, dragging the mine into the enemy to cause damage. Mines can sometimes follow a unit for quite a distance before going off. Protoss usually drags mines with zealots, though dark templar are also good. Zerg usually uses speedy zerglings in small groups, because they’re cheap and fast. Terran can sometimes trigger enemy mines with drops, but doesn’t have an appropriate unit to drag mines otherwise.
Skynet knows how to drag mines with a zealot. It uses the same system of micro actions that I touched on yesterday. In Behaviour::createDefaultActions() it records a possible mine drag micro action for every zealot:
if(unitType == BWAPI::UnitTypes::Protoss_Zealot) mMicroActions.push_back(MicroAction(new MineDragAction(mUnit)));
By the way, the micro actions are evaluated in Behaviour::update(), which checks them in order. Each unit can only execute one micro action at a time, and the first action to return true is what happens. Skynet’s only prioritization is to record the most important micro actions first in createDefaultActions(). Mine dragging is recorded near the end, as a low-priority action. Yesterday’s archon-zealot undetected unit attack is higher priority.
Here is the entirety of MineDragAction::update():
bool MineDragAction::update(const Goal &squadGoal, const UnitGroup &squadUnitGroup)
{
for each(Unit unit in UnitInformation::Instance().getUnitsTargetting(mUnit))
{
if(unit->getType() == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine)
{
int distance = std::numeric_limits<int>::max();
Unit closestUnit;
for each(Unit enemyUnit in UnitTracker::Instance().selectAllEnemy())
{
if(enemyUnit->getType().isFlyer() || enemyUnit->isLifted() || enemyUnit->getType().isBuilding() || enemyUnit->getType() == BWAPI::UnitTypes::Terran_Vulture_Spider_Mine)
continue;
int thisDistance = mUnit->getDistance(enemyUnit);
if(thisDistance < distance)
{
distance = distance;
closestUnit = enemyUnit;
}
}
if(closestUnit && distance < 32*5)
{
mUnit->attack(closestUnit);
return true;
}
}
}
return false;
}
This seems to only notice spider mines which have already popped up and are targeting the current zealot. If one is found, then the code checks for suitable enemy units (not stuff in the air, for example) that are close enough. If any is found, then the zealot targets the nearest for attack, end of story.
That’s basic mine dragging. A stronger version would also consider detected or remembered mines: If a mine in the ground is detected or remembered to be near valuable enemies, then check whether it can be activated and dragged into the enemies. You can remember a mine location if you detected it in the past, or if you saw it being laid or moving and reburrowing. That’s more complicated, but human players do it as a matter of course. Humans will even try to drag mines that they expect or hope are there, without being sure.
Tomorrow: Arbiter control.
Comments
krasi0 on :
distance = distance;
should be distance = thisDistance;
Because of that issue, the following if (closestUnit && distance < 32*5)
would never execute the "then" block so I am not sure if this works at all
Jay Scott on :
Jay Scott on :
Jay Scott on :