// get a target for the zealot to attack BWAPI::Unit RangedManager::getTarget(BWAPI::Unit rangedUnit, const BWAPI::Unitset & targets) { int bestPriorityDistance = 1000000; int bestPriority = 0; double bestLTD = 0; int highPriority = 0; double closestDist = std::numeric_limits<double>::infinity(); BWAPI::Unit closestTarget = nullptr; for (const auto & target : targets) { double distance = rangedUnit->getDistance(target); double LTD = UnitUtil::CalculateLTD(target, rangedUnit); int priority = getAttackPriority(rangedUnit, target); bool targetIsThreat = LTD > 0; if (!closestTarget || (priority > highPriority) || (priority == highPriority && distance < closestDist)) { closestDist = distance; highPriority = priority; closestTarget = target; } } return closestTarget; }
//get real priority double MeleeManager::getRealPriority(BWAPI::Unit attacker, BWAPI::Unit target) { int groundWeaponRange = attacker->getType().groundWeapon().maxRange(); int distA2T = std::max(0, attacker->getDistance(target) - groundWeaponRange); double Health = (((double)target->getHitPoints() + target->getShields())); return getAttackPriority(attacker, target)*exp(-distA2T / 5) / (Health + 160); }
// When the next item in the _queue is a building, this checks to see if we should move to it // This function is here as it needs to access prodction manager's reserved resources info void ProductionManager::predictWorkerMovement(const Building & b) { if (b.isGasSteal) { return; } // get a possible building location for the building if (!_haveLocationForThisBuilding) { _predictedTilePosition = BuildingManager::Instance().getBuildingLocation(b); } if (_predictedTilePosition != BWAPI::TilePositions::None) { _haveLocationForThisBuilding = true; } else { return; } // draw a box where the building will be placed int x1 = _predictedTilePosition.x * 32; int x2 = x1 + (b.type.tileWidth()) * 32; int y1 = _predictedTilePosition.y * 32; int y2 = y1 + (b.type.tileHeight()) * 32; if (Config::Debug::DrawWorkerInfo) { BWAPI::Broodwar->drawBoxMap(x1, y1, x2, y2, BWAPI::Colors::Blue, false); } // where we want the worker to walk to BWAPI::Position walkToPosition = BWAPI::Position(x1 + (b.type.tileWidth()/2)*32, y1 + (b.type.tileHeight()/2)*32); // compute how many resources we need to construct this building int mineralsRequired = std::max(0, b.type.mineralPrice() - getFreeMinerals()); int gasRequired = std::max(0, b.type.gasPrice() - getFreeGas()); // get a candidate worker to move to this location BWAPI::Unit moveWorker = WorkerManager::Instance().getMoveWorker(walkToPosition); // Conditions under which to move the worker: // - there's a valid worker to move // - we haven't yet assigned a worker to move to this location // - the build position is valid // - we will have the required resources by the time the worker gets there if (moveWorker && _haveLocationForThisBuilding && !_assignedWorkerForThisBuilding && (_predictedTilePosition != BWAPI::TilePositions::None) && WorkerManager::Instance().willHaveResources(mineralsRequired, gasRequired, moveWorker->getDistance(walkToPosition)) ) { // we have assigned a worker _assignedWorkerForThisBuilding = true; // tell the worker manager to move this worker WorkerManager::Instance().setMoveWorker(mineralsRequired, gasRequired, walkToPosition); } }
// get a target for the zealot to attack BWAPI::Unit TankManager::getTarget(BWAPI::Unit tank, const BWAPI::Unitset & targets) { int bestPriorityDistance = 1000000; int bestPriority = 0; double bestLTD = 0; BWAPI::Unit bestTargetThreatInRange = nullptr; double bestTargetThreatInRangeLTD = 0; int highPriority = 0; double closestDist = std::numeric_limits<double>::infinity(); BWAPI::Unit closestTarget = nullptr; int siegeTankRange = BWAPI::UnitTypes::Terran_Siege_Tank_Siege_Mode.groundWeapon().maxRange() - 32; BWAPI::Unitset targetsInSiegeRange; for (auto & target : targets) { if (target->getDistance(tank) < siegeTankRange && UnitUtil::CanAttack(tank, target)) { targetsInSiegeRange.insert(target); } } const BWAPI::Unitset & newTargets = targetsInSiegeRange.empty() ? targets : targetsInSiegeRange; // check first for units that are in range of our attack that can cause damage // choose the highest priority one from them at the lowest health for (const auto & target : newTargets) { if (!UnitUtil::CanAttack(tank, target)) { continue; } double distance = tank->getDistance(target); double LTD = UnitUtil::CalculateLTD(target, tank); int priority = getAttackPriority(tank, target); bool targetIsThreat = LTD > 0; BWAPI::Broodwar->drawTextMap(target->getPosition(), "%d", priority); if (!closestTarget || (priority > highPriority) || (priority == highPriority && distance < closestDist)) { closestDist = distance; highPriority = priority; closestTarget = target; } } if (bestTargetThreatInRange) { return bestTargetThreatInRange; } return closestTarget; }
double InterceptorManager::getRealPriority(BWAPI::Unit attacker, BWAPI::Unit target) { int groundWeaponRange = attacker->getType().groundWeapon().maxRange(); int distA2T = std::max(0, attacker->getDistance(target) - groundWeaponRange); //Protoss_Interceptor ignore distance if (attacker->getType() == BWAPI::UnitTypes::Protoss_Interceptor) distA2T = 0; double Health = (((double)target->getHitPoints() + target->getShields())); return getAttackPriority(attacker, target)*exp(-distA2T / 5) / (Health + 160); }
bool MicroManager::unitNearChokepoint(BWAPI::Unit unit) const { for (BWTA::Chokepoint * choke : BWTA::getChokepoints()) { if (unit->getDistance(choke->getCenter()) < 80) { return true; } } return false; }
double RangedManager::getRealPriority(BWAPI::Unit attacker, BWAPI::Unit target) { if (!attacker||!target) return 0; int groundWeaponRange = attacker->getType().groundWeapon().maxRange(); double distA2T = std::max(0, attacker->getDistance(target) - groundWeaponRange); //Protoss_Interceptor ignore distance if (attacker->getType() == BWAPI::UnitTypes::Protoss_Interceptor) distA2T = 0; double Health = (((double)target->getHitPoints() + target->getShields())); if (target->getType().size() == BWAPI::UnitSizeTypes::Small) Health *= 2; if (target->getType().size() == BWAPI::UnitSizeTypes::Medium) Health *= 1.5; return getAttackPriority(attacker, target)*exp(-distA2T / 5) / (Health + 160); }
int ScoutManager::getClosestVertexIndex(BWAPI::Unit unit) { int closestIndex = -1; double closestDistance = 10000000; for (size_t i(0); i < _enemyRegionVertices.size(); ++i) { double dist = unit->getDistance(_enemyRegionVertices[i]); if (dist < closestDistance) { closestDistance = dist; closestIndex = i; } } return closestIndex; }
void Micro::MutaDanceTarget(BWAPI::Unit muta, BWAPI::Unit target) { UAB_ASSERT(muta, "MutaDanceTarget: Muta not valid"); UAB_ASSERT(target, "MutaDanceTarget: Target not valid"); if (!muta || !target) { return; } const int cooldown = muta->getType().groundWeapon().damageCooldown(); const int latency = BWAPI::Broodwar->getLatency(); const double speed = muta->getType().topSpeed(); const double range = muta->getType().groundWeapon().maxRange(); const double distanceToTarget = muta->getDistance(target); const double distanceToFiringRange = std::max(distanceToTarget - range,0.0); const double timeToEnterFiringRange = distanceToFiringRange / speed; const int framesToAttack = static_cast<int>(timeToEnterFiringRange) + 2*latency; // How many frames are left before we can attack? const int currentCooldown = muta->isStartingAttack() ? cooldown : muta->getGroundWeaponCooldown(); BWAPI::Position fleeVector = GetKiteVector(target, muta); BWAPI::Position moveToPosition(muta->getPosition() + fleeVector); // If we can attack by the time we reach our firing range if(currentCooldown <= framesToAttack) { // Move towards and attack the target muta->attack(target); } else // Otherwise we cannot attack and should temporarily back off { // Determine direction to flee // Determine point to flee to if (moveToPosition.isValid()) { muta->rightClick(moveToPosition); } } }
// get the attack priority of a type in relation to a zergling int LurkerManager::getAttackPriority(BWAPI::Unit LurkerUnit, BWAPI::Unit target) { BWAPI::UnitType LurkerType = LurkerUnit->getType(); BWAPI::UnitType targetType = target->getType(); bool isThreat = LurkerType.isFlyer() ? targetType.airWeapon() != BWAPI::WeaponTypes::None : targetType.groundWeapon() != BWAPI::WeaponTypes::None; if (target->getType().isWorker()) { isThreat = false; } if (target->getType() == BWAPI::UnitTypes::Zerg_Larva || target->getType() == BWAPI::UnitTypes::Zerg_Egg) { return 0; } // if the target is building something near our base something is fishy BWAPI::Position ourBasePosition = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()); if (target->getType().isWorker() && (target->isConstructing() || target->isRepairing()) && target->getDistance(ourBasePosition) < 1200) { return 100; } if (target->getType().isBuilding() && (target->isCompleted() || target->isBeingConstructed()) && target->getDistance(ourBasePosition) < 1200) { return 90; } // highest priority is something that can attack us or aid in combat if (targetType == BWAPI::UnitTypes::Terran_Bunker || isThreat) { return 11; } // next priority is worker else if (targetType.isWorker()) { return 11; } // next is special buildings else if (targetType == BWAPI::UnitTypes::Protoss_Pylon) { return 5; } // next is buildings that cost gas else if (targetType.gasPrice() > 0) { return 4; } else if (targetType.mineralPrice() > 0) { return 3; } // then everything else else { return 50; } }
int InterceptorManager::getPriorityDefault(BWAPI::Unit rangedUnit, BWAPI::Unit target) { BWAPI::UnitType rangedType = rangedUnit->getType(); BWAPI::UnitType targetType = target->getType(); if (target->getType() == BWAPI::UnitTypes::Protoss_Photon_Cannon || target->getType() == BWAPI::UnitTypes::Zerg_Sunken_Colony) { return 8; } if (rangedUnit->getType() == BWAPI::UnitTypes::Zerg_Scourge) { if (target->getType() == BWAPI::UnitTypes::Protoss_Carrier) { return 100; } if (target->getType() == BWAPI::UnitTypes::Protoss_Corsair) { return 90; } } bool isThreat = rangedType.isFlyer() ? targetType.airWeapon() != BWAPI::WeaponTypes::None : targetType.groundWeapon() != BWAPI::WeaponTypes::None; if (target->getType().isWorker()) { isThreat = false; } if (target->getType() == BWAPI::UnitTypes::Zerg_Larva || target->getType() == BWAPI::UnitTypes::Zerg_Egg) { return 0; } if (rangedUnit->isFlying() && target->getType() == BWAPI::UnitTypes::Protoss_Carrier) { return 101; } // if the target is building something near our base something is fishy BWAPI::Position ourBasePosition = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()); if (target->getType().isWorker() && (target->isConstructing() || target->isRepairing()) && target->getDistance(ourBasePosition) < 1200) { return 100; } if (target->getType().isBuilding() && (target->isCompleted() || target->isBeingConstructed()) && target->getDistance(ourBasePosition) < 1200) { return 90; } // highest priority is something that can attack us or aid in combat if (targetType == BWAPI::UnitTypes::Terran_Bunker || isThreat) { return 11; } // next priority is worker else if (targetType.isWorker()) { if (rangedUnit->getType() == BWAPI::UnitTypes::Terran_Vulture) { return 11; } return 11; } // next is special buildings else if (targetType == BWAPI::UnitTypes::Zerg_Spawning_Pool) { return 5; } // next is special buildings else if (targetType == BWAPI::UnitTypes::Protoss_Pylon) { return 5; } // next is buildings that cost gas else if (targetType.gasPrice() > 0) { return 4; } else if (targetType.mineralPrice() > 0) { return 3; } // then everything else else { return 1; } }
void Micro::SmartKiteTarget(BWAPI::Unit rangedUnit, BWAPI::Unit target) { UAB_ASSERT(rangedUnit, "SmartKiteTarget: Unit not valid"); UAB_ASSERT(target, "SmartKiteTarget: Target not valid"); if (!rangedUnit || !target) { return; } double range(rangedUnit->getType().groundWeapon().maxRange()); if (rangedUnit->getType() == BWAPI::UnitTypes::Protoss_Dragoon && BWAPI::Broodwar->self()->getUpgradeLevel(BWAPI::UpgradeTypes::Singularity_Charge)) { range = 6*32; } // determine whether the target can be kited bool kiteLonger = Config::Micro::KiteLongerRangedUnits.find(rangedUnit->getType()) != Config::Micro::KiteLongerRangedUnits.end(); if (!kiteLonger && (range <= target->getType().groundWeapon().maxRange())) { //if we can't kite it, there's no point Micro::SmartAttackUnit(rangedUnit, target); return; } bool kite(true); double dist(rangedUnit->getDistance(target)); double speed(rangedUnit->getType().topSpeed()); // if the unit can't attack back don't kite if ((rangedUnit->isFlying() && !UnitUtil::CanAttackAir(target)) || (!rangedUnit->isFlying() && !UnitUtil::CanAttackGround(target))) { kite = false; } double timeToEnter = std::max(0.0,(dist - range) / speed); if ((timeToEnter >= rangedUnit->getGroundWeaponCooldown())) { kite = false; } if (target->getType().isBuilding()) { kite = false; } // if we can't shoot, run away if (kite) { //BWAPI::Broodwar->printf("Kite"); BWAPI::Position fleePosition(rangedUnit->getPosition() - target->getPosition() + rangedUnit->getPosition()); BWAPI::Broodwar->drawLineMap(rangedUnit->getPosition(), fleePosition, BWAPI::Colors::Cyan); Micro::SmartMove(rangedUnit, fleePosition); } // otherwise shoot else { //BWAPI::Broodwar->printf("Not kite"); Micro::SmartAttackUnit(rangedUnit, target); } }
void ProductionManager::buildBunker() { BWAPI::Position base = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()); BWTA::Chokepoint *entrance = BWTA::getNearestChokepoint(base); MetaType bunker = MetaType(BWAPI::UnitTypes::Terran_Bunker); BWAPI::Unit producer = ProductionManager::Instance().getProducer(bunker, entrance->getCenter()); int numBarracks = BWAPI::Broodwar->self()->allUnitCount(BWAPI::UnitTypes::Terran_Barracks); bool canMake = canMakeNow(producer, bunker); Building b(bunker.getUnitType(), BWAPI::TilePosition(entrance->getCenter())); b.isGasSteal = false; // set the producer as the closest worker, but do not set its job yet producer = WorkerManager::Instance().getBuilder(b, false); // get a possible building location for the building if (!_haveLocationForThisBuilding) { _predictedTilePosition = BuildingManager::Instance().getBuildingLocation(b); } if (_predictedTilePosition != BWAPI::TilePositions::None) { _haveLocationForThisBuilding = true; } if (producer && canMake && (numBarracks > 0)) { // create it create(producer, BuildOrderItem(bunker, 1, true)); _assignedWorkerForThisBuilding = false; _haveLocationForThisBuilding = false; // draw a box where the building will be placed int x1 = _predictedTilePosition.x * 32; int x2 = x1 + (b.type.tileWidth()) * 32; int y1 = _predictedTilePosition.y * 32; int y2 = y1 + (b.type.tileHeight()) * 32; if (Config::Debug::DrawWorkerInfo) { BWAPI::Broodwar->drawBoxMap(x1, y1, x2, y2, BWAPI::Colors::Blue, false); } // where we want the worker to walk to BWAPI::Position walkToPosition = BWAPI::Position(x1 + (b.type.tileWidth() / 2) * 32, y1 + (b.type.tileHeight() / 2) * 32); // compute how many resources we need to construct this building int mineralsRequired = std::max(0, b.type.mineralPrice() - getFreeMinerals()); int gasRequired = std::max(0, b.type.gasPrice() - getFreeGas()); // get a candidate worker to move to this location BWAPI::Unit moveWorker = WorkerManager::Instance().getMoveWorker(walkToPosition); // Conditions under which to move the worker: // - there's a valid worker to move // - we haven't yet assigned a worker to move to this location // - the build position is valid // - we will have the required resources by the time the worker gets there if (moveWorker && _haveLocationForThisBuilding && !_assignedWorkerForThisBuilding && (_predictedTilePosition != BWAPI::TilePositions::None) && WorkerManager::Instance().willHaveResources(mineralsRequired, gasRequired, moveWorker->getDistance(walkToPosition))) { // we have assigned a worker _assignedWorkerForThisBuilding = true; // tell the worker manager to move this worker WorkerManager::Instance().setMoveWorker(mineralsRequired, gasRequired, walkToPosition); } } }