// get the attack priority of a type in relation to a zergling int MeleeManager::getAttackPriority(BWAPI::Unit attacker, BWAPI::Unit unit) { BWAPI::UnitType type = unit->getType(); if (attacker->getType() == BWAPI::UnitTypes::Protoss_Dark_Templar && unit->getType() == BWAPI::UnitTypes::Terran_Missile_Turret && (BWAPI::Broodwar->self()->deadUnitCount(BWAPI::UnitTypes::Protoss_Dark_Templar) == 0)) { return 13; } if (attacker->getType() == BWAPI::UnitTypes::Protoss_Dark_Templar && unit->getType().isWorker()) { return 12; } // highest priority is something that can attack us or aid in combat if (type == BWAPI::UnitTypes::Terran_Bunker) { return 11; } else if (type == BWAPI::UnitTypes::Terran_Medic || (type.groundWeapon() != BWAPI::WeaponTypes::None && !type.isWorker()) || type == BWAPI::UnitTypes::Terran_Bunker || type == BWAPI::UnitTypes::Protoss_High_Templar || type == BWAPI::UnitTypes::Protoss_Reaver || (type.isWorker() && unitNearChokepoint(unit))) { return 10; } // next priority is worker else if (type.isWorker()) { return 9; } // next is special buildings else if (type == BWAPI::UnitTypes::Zerg_Spawning_Pool) { return 5; } // next is special buildings else if (type == BWAPI::UnitTypes::Protoss_Pylon) { return 5; } // next is buildings that cost gas else if (type.gasPrice() > 0) { return 4; } else if (type.mineralPrice() > 0) { return 3; } // then everything else else { return 1; } }
void SwarmCAT::onUnitComplete(BWAPI::Unit unit) { if (!Broodwar->isReplay()) { if (unit->getPlayer() == util::game::getSelf()) { if (unit->getType().isResourceDepot()) { DesireHelper::updateSupplyDesire(unit->getType()); int unitCount = util::game::getSelf()->allUnitCount(unit->getType()); if( unitCount > 1) util::eval::logExpansion(unitCount -1); } AgentHelper::createAgent(unit); auto unitZone = MapHelper::getZone(unit->getRegion()); if (unit->getType() == BWAPI::UnitTypes::Terran_Bunker) { for (auto &zone : unitZone->getNeighbourhood()) zone->setBunkerDefense(true); } if (unit->getType() == BWAPI::UnitTypes::Terran_Missile_Turret) { for (auto &zone : unitZone->getNeighbourhood()) zone->setTurretDefense(true); } DesireHelper::setDefendDesire(unitZone, unitZone->getEnemyScore()); } } }
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); }
void MicroManager::trainSubUnits(BWAPI::Unit unit) const { if (unit->getType() == BWAPI::UnitTypes::Protoss_Reaver) { unit->train(BWAPI::UnitTypes::Protoss_Scarab); } else if (unit->getType() == BWAPI::UnitTypes::Protoss_Carrier) { unit->train(BWAPI::UnitTypes::Protoss_Interceptor); } }
void StrategOS::onUnitDestroy(BWAPI::Unit unit) { try { lastKill = std::chrono::steady_clock::now(); if (unit->getType().isMineralField()) Map::Instance().OnMineralDestroyed(unit); else if (unit->getType().isSpecialBuilding()) Map::Instance().OnStaticBuildingDestroyed(unit); } catch (const std::exception &e) { Broodwar << "EXCEPTION: " << e.what() << std::endl; } }
void GameTraceCollector::CollectGameTraceForTrainedUnit(const BWAPI::Unit trainee, const BWAPI::Unit trainer) { if (!trainer) { LogInfo("Unable to find trainee %s trainer, will use normal trace collector", trainee->getPlayer()->getName().c_str()); CollectGameTraceForUnitOrder(trainee); return; } ActionType action; UNREFERENCED_PARAMETER(trainee); LogInfo("(P%d,%s) %s[%d]: %s", trainer->getPlayer()->getID(), trainer->getPlayer()->getName().c_str(), trainer->getType().c_str(), trainer->getID(), "Train"); _ASSERTE(g_Database.ActionMapping.ContainsFirst(Orders::Train.getID())); action = g_Database.ActionMapping.GetByFirst(Orders::Train.getID()); GameTrace *pTrace = nullptr; PlanStepParameters actionParams = m_abstractor.GetAbstractedParameter(trainee, trainer); pTrace = new GameTrace(Broodwar->getFrameCount(), action, actionParams, g_Game->Snapshot(), m_playerToObserve); SendGameTrace(pTrace); }
int InterceptorManager::getPrioritySaveCarrier(BWAPI::Unit attacker, BWAPI::Unit unit) { BWAPI::UnitType type = unit->getType(); int tmpPriority = getPriorityDefault(attacker, unit); if (unit->getType().airWeapon().getID() != BWAPI::WeaponTypes::Enum::None || unit->getType().isFlyer()) { tmpPriority = static_cast<int>(getPriorityDefault(attacker, unit)*_microDecision->getFlightOrientatedFactor()); } if (unit->getType() == BWAPI::UnitTypes::Protoss_Photon_Cannon || unit->getType() == BWAPI::UnitTypes::Zerg_Spore_Colony || unit->getType() == BWAPI::UnitTypes::Terran_Missile_Turret) { tmpPriority = std::max(tmpPriority, static_cast<int>(6 * _microDecision->getFlightOrientatedFactor())); } return tmpPriority; }
//BWAPI calls this when an accessible unit is created. Note that this is NOT called when a unit changes type void ExampleAIModule::onUnitCreate(BWAPI::Unit unit) { if ( Broodwar->isReplay() ) { // if we are in a replay, then we will print out the build order of the structures if ( unit->getType().isBuilding() && !unit->getPlayer()->isNeutral() ) { int seconds = Broodwar->getFrameCount()/24; int minutes = seconds/60; seconds %= 60; Broodwar->sendText("%.2d:%.2d: %s creates a %s", minutes, seconds, unit->getPlayer()->getName().c_str(), unit->getType().c_str()); } } /*else{ if(unit->getType() == UnitTypes::Terran_Command_Center){ Unitset visibleMinerals = Broodwar->getMinerals(); //when base is created, check if it covers all accessible minerals bool allVisible = true; for(Unitset::iterator min = visibleMinerals.begin(); min != visibleMinerals.end(); ++min){ if(unit->getDistance(*min) < BASE_RADIUS){ //allVisible = false; //break; mineralsOutOfBaseRange--; } } } }*/ }
bool MeleeManager::meleeUnitShouldRetreat(BWAPI::Unit meleeUnit, const BWAPI::Unitset & targets) { // terran don't regen so it doesn't make any sense to retreat if (meleeUnit->getType().getRace() == BWAPI::Races::Terran) { return false; } // we don't want to retreat the melee unit if its shields or hit points are above the threshold set in the config file // set those values to zero if you never want the unit to retreat from combat individually if (meleeUnit->getShields() > Config::Micro::RetreatMeleeUnitShields || meleeUnit->getHitPoints() > Config::Micro::RetreatMeleeUnitHP) { return false; } // if there is a ranged enemy unit within attack range of this melee unit then we shouldn't bother retreating since it could fire and kill it anyway for (auto & unit : targets) { int groundWeaponRange = unit->getType().groundWeapon().maxRange(); if (groundWeaponRange >= 64 ) { //the possibility of retreat from rangeunits is determined by their distance and weaponrange return rand() % 100<std::max(0,60-((int) unit->getDistance(meleeUnit) - groundWeaponRange)); } } return true; }
//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); }
OutputHandler::OutputHandler(double outputArray[], int outputSize, std::vector<Unit*> allyUnits, std::vector<Unit*> enemyUnits, BWAPI::Game* game, double initCentralDist){ int allyNum = allyUnits.size(); int enemyNum = enemyUnits.size(); // full size including attack scores for each ally unit enemy unit pair and move score/destination for each ally units int outputFullSize = allyNum * enemyNum + allyNum * 3; // mini size including attack scores for each enemy unit int outputMiniSize = enemyNum; double maxScore = -10000.0; BWAPI::Unit* target = enemyUnits[0]; int outputIndex; int dest_x; int dest_y; double d; double angle; double PI = 3.14159; for(int i = 0; i < outputSize; i++){ game->sendText("output %d: %f", i, outputArray[i]); } if(outputSize == outputMiniSize){ for(int i = 0; i < enemyNum; i++){ if(enemyUnits[i]->exists() && maxScore < outputArray[i]){ maxScore = outputArray[i]; target = enemyUnits[i]; } } for(int i = 0; i < allyNum; i++){ if(allyUnits[i]->exists()){ allyUnits[i]->attack(target); } } } else if(outputSize == outputFullSize){ for(int i = 0; i < allyNum; i++){ if(allyUnits[i]->exists()){ for(int j = 0; j < enemyNum; j++){ outputIndex = i * 6 + j; if(enemyUnits[j]->exists() && maxScore < outputArray[outputIndex]){ maxScore = outputArray[outputIndex]; target = enemyUnits[i]; } } outputIndex = i * 6 + 4; if(maxScore < outputArray[outputIndex]){ // denormalize the relative distance d = outputArray[outputIndex + 1] * initCentralDist; // denormalize the angle angle = outputArray[outputIndex + 2] * 2 * PI - PI; dest_x = allyUnits[i]->getPosition().x() + int(d * cos(angle) + 0.5); dest_y = allyUnits[i]->getPosition().y() + int(d * sin(angle) + 0.5); allyUnits[i]->move(BWAPI::Position(dest_x, dest_y)); game->sendText("Ally unit #%d will move to (%d, %d)", i, dest_x, dest_y); } else { allyUnits[i]->attack(target); game->sendText("Ally unit #%d will attack %d", i, target->getType().getID()); } } } } }
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 RangedManager::getPrioritySaveCarrier(BWAPI::Unit attacker, BWAPI::Unit unit) { BWAPI::UnitType type = unit->getType(); int tmpPriority = getPriorityDefault(attacker, unit); if (unit->getType().airWeapon().getID() != BWAPI::WeaponTypes::Enum::None || unit->getType().isFlyer()) { tmpPriority = static_cast<int>(getPriorityDefault(attacker, unit)*2); } if (unit->getType() == BWAPI::UnitTypes::Protoss_Photon_Cannon || unit->getType() == BWAPI::UnitTypes::Zerg_Spore_Colony || unit->getType() == BWAPI::UnitTypes::Terran_Missile_Turret) { tmpPriority = std::max(tmpPriority, 10); } return tmpPriority; }
void SwarmCAT::onUnitDestroy(BWAPI::Unit unit) { if (!Broodwar->isReplay()) { if (unit->getPlayer() == util::game::getSelf() && !unit->isBeingConstructed()) { if (unit->getType() == BWAPI::UnitTypes::Terran_Bunker) { int bunkerCount = 0; const MapHelper::Field& neighbourhood = MapHelper::getZone(unit->getRegion())->getNeighbourhood(); for (const auto &zone : neighbourhood) bunkerCount += zone->getRegion()->getUnits(BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Bunker).size(); if (bunkerCount == 0) { for (const auto &zone : neighbourhood) zone->setBunkerDefense(false); } } if (unit->getType() == BWAPI::UnitTypes::Terran_Missile_Turret) { int turretCount = 0; for (auto &zone : MapHelper::getZone(unit->getRegion())->getNeighbourhood()) turretCount += zone->getRegion()->getUnits(BWAPI::Filter::IsOwned && BWAPI::Filter::GetType == BWAPI::UnitTypes::Terran_Missile_Turret).size(); if (turretCount == 0) { for (auto &zone : MapHelper::getZone(unit->getRegion())->getNeighbourhood()) zone->setTurretDefense(false); } } DesireHelper::updateSupplyDesire(unit->getType(), true); AgentHelper::removeAgent(unit->getID()); } if (unit->getPlayer() == util::game::getEnemy()) { if (unit->getType().isBuilding()) ArmyHelper::removeTargetPriority(unit); else ArmyHelper::removeScoutedUnit(unit->getID()); } } }
void SwarmCAT::onUnitShow(BWAPI::Unit unit) { if (!Broodwar->isReplay()) { if (unit->getPlayer() == util::game::getEnemy()) ArmyHelper::addScoutedUnit(unit->getID(), unit->getType()); } }
void SwarmCAT::onUnitDiscover(BWAPI::Unit unit) { if (!Broodwar->isReplay()) { if (unit->getType().isBuilding() && unit->getPlayer() == util::game::getEnemy()) ArmyHelper::addTargetPriority(unit); } }
void StrategOS::onUnitCreate(BWAPI::Unit unit) { if (Broodwar->getFrameCount() == 0) { return; } if (unit->getPlayer()->getID() != Broodwar->self()->getID()) { return; } if (unit->getType().getID() == UnitTypes::Zerg_Larva.getID()) { return; } Blackboard::Instance().unlock(unit->getType()); agents.push_back(AgentFactory::makeAgent(unit)); }
void WorkerManager::onUnitShow(BWAPI::Unit unit) { UAB_ASSERT(unit != nullptr, "Unit was null"); // add the depot if it exists if (unit->getType().isResourceDepot() && unit->getPlayer() == BWAPI::Broodwar->self()) { workerData.addDepot(unit); } // if something morphs into a worker, add it if (unit->getType().isWorker() && unit->getPlayer() == BWAPI::Broodwar->self() && unit->getHitPoints() >= 0) { //BWAPI::Broodwar->printf("A worker was shown %d", unit->getID()); workerData.addWorker(unit); } }
void WorkerManager::onUnitMorph(BWAPI::Unit unit) { UAB_ASSERT(unit != nullptr, "Unit was null"); // if something morphs into a worker, add it if (unit->getType().isWorker() && unit->getPlayer() == BWAPI::Broodwar->self() && unit->getHitPoints() >= 0) { workerData.addWorker(unit); } // if something morphs into a building, it was a worker? if (unit->getType().isBuilding() && unit->getPlayer() == BWAPI::Broodwar->self() && unit->getPlayer()->getRace() == BWAPI::Races::Zerg) { //BWAPI::Broodwar->printf("A Drone started building"); workerData.workerDestroyed(unit); } }
void WorkerData::setWorkerJob(BWAPI::Unit unit, enum WorkerJob job, BWAPI::Unit jobUnit) { if (!unit) { return; } clearPreviousJob(unit); workerJobMap[unit] = job; if (job == Minerals) { // increase the number of workers assigned to this nexus depotWorkerCount[jobUnit] += 1; // set the mineral the worker is working on workerDepotMap[unit] = jobUnit; BWAPI::Unit mineralToMine = getMineralToMine(unit); workerMineralAssignment[unit] = mineralToMine; addToMineralPatch(mineralToMine, 1); // right click the mineral to start mining Micro::SmartRightClick(unit, mineralToMine); } else if (job == Gas) { // increase the count of workers assigned to this refinery refineryWorkerCount[jobUnit] += 1; // set the refinery the worker is working on workerRefineryMap[unit] = jobUnit; // right click the refinery to start harvesting Micro::SmartRightClick(unit, jobUnit); } else if (job == Repair) { // only SCVs can repair assert(unit->getType() == BWAPI::UnitTypes::Terran_SCV); // set the building the worker is to repair workerRepairMap[unit] = jobUnit; // start repairing if (!unit->isRepairing()) { Micro::SmartRepair(unit, jobUnit); } } else if (job == Scout) { } else if (job == Build) { BWAPI::Broodwar->printf("Setting worker job to build"); } }
void InformationManager::onUnitDestroy(BWAPI::Unit unit) { if (unit->getType().isNeutral()) { return; } _unitData[unit->getPlayer()].removeUnit(unit); }
// 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; } }
void WorkerManager::onUnitDestroy(BWAPI::Unit unit) { UAB_ASSERT(unit != nullptr, "Unit was null"); if (unit->getType().isResourceDepot() && unit->getPlayer() == BWAPI::Broodwar->self()) { workerData.removeDepot(unit); } if (unit->getType().isWorker() && unit->getPlayer() == BWAPI::Broodwar->self()) { workerData.workerDestroyed(unit); } if (unit->getType() == BWAPI::UnitTypes::Resource_Mineral_Field) { rebalanceWorkers(); } }
void StrategOS::onUnitMorph(BWAPI::Unit unit) { if (unit->getPlayer()->getID() != Broodwar->self()->getID()) { return; } if (unit->getType().getID() == UnitTypes::Zerg_Larva.getID()) { return; } agents.push_back(AgentFactory::makeAgent(unit)); }
// on unit destroy void ProductionManager::onUnitDestroy(BWAPI::Unit unit) { // we don't care if it's not our unit if (!unit || unit->getPlayer() != BWAPI::Broodwar->self()) { return; } if (Config::Modules::UsingBuildOrderSearch) { // if it's a worker or a building, we need to re-search for the current goal if ((unit->getType().isWorker() && !WorkerManager::Instance().isWorkerScout(unit)) || unit->getType().isBuilding()) { if (unit->getType() != BWAPI::UnitTypes::Zerg_Drone) { performBuildOrderSearch(); } } } }
// Gets a SparCraft unit from a BWAPI::Unit, used for our own units since we have all their info const SparCraft::Unit CombatSimulation::getSparCraftUnit(BWAPI::Unit unit) const { return SparCraft::Unit( unit->getType(), SparCraft::Position(unit->getPosition()), unit->getID(), getSparCraftPlayerID(unit->getPlayer()), unit->getHitPoints() + unit->getShields(), 0, BWAPI::Broodwar->getFrameCount(), BWAPI::Broodwar->getFrameCount()); }
//BWAPI calls this when a unit dies or otherwise removed from the game (i.e. a mined out mineral patch) void ExampleAIModule::onUnitDestroy(BWAPI::Unit unit){ if (unit->getPlayer() == Broodwar->self()){ Broodwar->sendText("%s lost.", unit->getType().getName().c_str()); if(unit->getType() == UnitTypes::Terran_SCV){ // Delete this SCV from the map scvMap.erase(unit->getID()); } else if(unit->getType() == UnitTypes::Terran_Marine){ marines.erase(unit->getID()); } else if (unit->getType() == UnitTypes::Terran_Command_Center){ //Broodwar->sendText("cmdSize before: %d",commandCenters.size()); commandCenters.erase(unit); //Broodwar->sendText("cmdSize AFTER: %d",commandCenters.size()); } } else { Broodwar->sendText("%s shot down.", unit->getType().getName().c_str()); } }
void ExampleAIModule::onUnitMorph(BWAPI::Unit unit) { if ( Broodwar->isReplay() ) { // if we are in a replay, then we will print out the build order of the structures if ( unit->getType().isBuilding() && !unit->getPlayer()->isNeutral() ) { int seconds = Broodwar->getFrameCount()/24; int minutes = seconds/60; seconds %= 60; Broodwar->sendText("%.2d:%.2d: %s morphs a %s", minutes, seconds, unit->getPlayer()->getName().c_str(), unit->getType().c_str()); } } }
void SwarmCAT::onUnitCreate(BWAPI::Unit unit) { if (!Broodwar->isReplay()) { if (unit->getPlayer() == util::game::getSelf() && !(unit->getType().supplyProvided() == 16 || unit->getType().isBuilding())) DesireHelper::updateSupplyDesire(unit->getType()); if (Broodwar->isReplay()) { // if we are in a replay, then we will print out the build order of the structures if (unit->getType().isBuilding() && !unit->getPlayer()->isNeutral()) { int seconds = Broodwar->getFrameCount() / 24; int minutes = seconds / 60; seconds %= 60; Broodwar->sendText("%.2d:%.2d: %s creates a %s", minutes, seconds, unit->getPlayer()->getName().c_str(), unit->getType().c_str()); } } } }
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); } } }