BWAPI::Position CombatCommander::getMainAttackLocation() { BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); // First choice: Attack an enemy region if we can see units inside it if (enemyBaseLocation) { BWAPI::Position enemyBasePosition = enemyBaseLocation->getPosition(); // get all known enemy units in the area BWAPI::Unitset enemyUnitsInArea; MapGrid::Instance().GetUnits(enemyUnitsInArea, enemyBasePosition, 800, false, true); bool onlyOverlords = true; for (auto & unit : enemyUnitsInArea) { if (unit->getType() != BWAPI::UnitTypes::Zerg_Overlord) { onlyOverlords = false; } } if (!BWAPI::Broodwar->isExplored(BWAPI::TilePosition(enemyBasePosition)) || !enemyUnitsInArea.empty()) { if (!onlyOverlords) { return enemyBaseLocation->getPosition(); } } } // Second choice: Attack known enemy buildings for (const auto & kv : InformationManager::Instance().getUnitInfo(BWAPI::Broodwar->enemy())) { const UnitInfo & ui = kv.second; if (ui.type.isBuilding() && ui.lastPosition != BWAPI::Positions::None) { return ui.lastPosition; } } // Third choice: Attack visible enemy units that aren't overlords for (auto & unit : BWAPI::Broodwar->enemy()->getUnits()) { if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) { continue; } if (UnitUtil::IsValidUnit(unit) && unit->isVisible()) { return unit->getPosition(); } } // Fourth choice: We can't see anything so explore the map attacking along the way return MapGrid::Instance().getLeastExplored(); }
BWAPI::TilePosition BuildingManager::getBuildingLocation(const Building & b) { int numPylons = BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Protoss_Pylon); if (b.isGasSteal) { BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); UAB_ASSERT(enemyBaseLocation,"Should have enemy base location before attempting gas steal"); UAB_ASSERT(enemyBaseLocation->getGeysers().size() > 0,"Should have spotted an enemy geyser"); for (auto & unit : enemyBaseLocation->getGeysers()) { BWAPI::TilePosition tp(unit->getInitialTilePosition()); return tp; } } if (b.type.requiresPsi() && numPylons == 0) { return BWAPI::TilePositions::None; } if (b.type.isRefinery()) { return BuildingPlacer::Instance().getRefineryPosition(); } if (b.type.isResourceDepot()) { // get the location BWAPI::TilePosition tile = MapTools::Instance().getNextExpansion(); return tile; } if (b.type == BWAPI::UnitTypes::Terran_Bunker) { BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); UAB_ASSERT(enemyBaseLocation, "Should have enemy base location before attempting gas steal"); BWTA::Chokepoint * chokePoint = BWTA::getNearestChokepoint(enemyBaseLocation->getTilePosition()); std::pair<BWAPI::Position, BWAPI::Position> sides = chokePoint->getSides(); BWAPI::Position poi = enemyBaseLocation->getPosition().getDistance(sides.first) > enemyBaseLocation->getPosition().getDistance(sides.second) ? sides.first : sides.second; //BWAPI::Broodwar->printf("Tisssle Position (%d, %d)", BWAPI::TilePosition(poi).x, BWAPI::TilePosition(poi).y); return BWAPI::TilePosition(sides.second); } // set the building padding specifically int distance = b.type == BWAPI::UnitTypes::Protoss_Photon_Cannon ? 0 : Config::Macro::BuildingSpacing; if (b.type == BWAPI::UnitTypes::Protoss_Pylon && (numPylons < 3)) { distance = Config::Macro::PylonSpacing; } // get a position within our region return BuildingPlacer::Instance().getBuildLocationNear(b,distance,false); }
void CombatCommander::updateAttackSquads() { Squad & mainAttackSquad = _squadData.getSquad("MainAttack"); //check for overlord in squad bool containsoverlord = false; int numOverlords = 0; for (auto& unit : mainAttackSquad.getUnits()) { if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) { containsoverlord = true; numOverlords++; } } // BWAPI::Broodwar->printf("Overlords in Attack squad: %d", numOverlords); for (auto & unit : _combatUnits) { if (unit->getType() == BWAPI::UnitTypes::Zerg_Scourge && UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Zerg_Hydralisk) < 30) { continue; } // get every unit of a lower priority and put it into the attack squad if (!unit->getType().isWorker() && (unit->getType() != BWAPI::UnitTypes::Zerg_Lurker) && _squadData.canAssignUnitToSquad(unit, mainAttackSquad)) { if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) { if (!containsoverlord && numOverlords < 2) { _squadData.assignUnitToSquad(unit, mainAttackSquad); containsoverlord = true; numOverlords++; } } else { _squadData.assignUnitToSquad(unit, mainAttackSquad); } } } // Defend bases until we have 3 lurkers if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg && mainAttackSquad.getUnits().size() < 10) { BWTA::BaseLocation * pos = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->self()); SquadOrder mainAttackOrder(SquadOrderTypes::Defend, pos->getPosition(), 250, "Defend Region!"); mainAttackSquad.setSquadOrder(mainAttackOrder); return; } SquadOrder mainAttackOrder(SquadOrderTypes::Attack, getMainAttackLocation(), 800, "Attack Enemy Base"); mainAttackSquad.setSquadOrder(mainAttackOrder); }
void ScoutManager::onRevoke( BWAPI::Unit unit, double bid ) { if ( m_scouts.find( unit ) != m_scouts.end() ) { BWTA::BaseLocation* lostTarget = m_scouts[unit].m_target; if ( m_baseLocationsExplored.find( lostTarget ) == m_baseLocationsExplored.end() ) { m_baseLocationsToScout.push_back( lostTarget ); if ( m_debugMode ) { BWAPI::Broodwar->printf( "Reassigning ( %d, %d )", lostTarget->getPosition().x, lostTarget->getPosition().y ); } } m_scouts.erase( unit ); } }
void InformationManager::checkEnemyMovedOut(){ BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); BWTA::BaseLocation * ourBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->self()); BWAPI::TilePosition ourBase = BWAPI::TilePosition(ourBaseLocation->getPosition()); if (enemyBaseLocation == nullptr) { double baseToBase = 0; if (_distToFarthestBase < 1.0) { double currentBtoB = 0; for (auto &bases : BWTA::getStartLocations()) { currentBtoB = BWTA::getGroundDistance(ourBase, bases->getTilePosition()); if (currentBtoB > baseToBase) { baseToBase = currentBtoB; } } _distToFarthestBase = baseToBase; } baseToBase = _distToFarthestBase; double baseToUnit; for (auto &unit : InformationManager::Instance().getUnitInfo(BWAPI::Broodwar->enemy())) { if (UnitUtil::IsCombatUnit(unit.second.unit)) { BWAPI::TilePosition enemyPos = BWAPI::TilePosition(unit.second.lastPosition); if (_movedOutMap.count(enemyPos) != 0) { if (_movedOutMap[enemyPos] == true) { //BWAPI::Broodwar->printf("Enemy has moved out!"); _enemyMovedOut = true; return; } } else { baseToUnit = BWTA::getGroundDistance(ourBase, BWAPI::TilePosition(unit.second.lastPosition)); if (baseToUnit < baseToBase) { //BWAPI::Broodwar->printf("Enemy has moved out!"); _enemyMovedOut = true; _movedOutMap[enemyPos] = true; return; } else { _movedOutMap[enemyPos] = false; } } } } _enemyMovedOut = false; //BWAPI::Broodwar->printf("Enemy in their base"); } else { BWAPI::TilePosition enemyChoke = BWAPI::TilePosition(BWTA::getNearestChokepoint(enemyBaseLocation->getPosition())->getCenter()); if (_distToEnemyChoke < 1.0) { _distToEnemyChoke = BWTA::getGroundDistance(ourBase, enemyChoke); } double baseToChoke = _distToEnemyChoke; double baseToUnit; for (auto &unit : InformationManager::Instance().getUnitInfo(BWAPI::Broodwar->enemy())) { if (UnitUtil::IsCombatUnit(unit.second.unit)) { BWAPI::TilePosition enemyPos = BWAPI::TilePosition(unit.second.lastPosition); if (_movedOutMap.count(enemyPos) != 0) { if (_movedOutMap[enemyPos] == true) { //BWAPI::Broodwar->printf("Enemy has moved out!"); _enemyMovedOut = true; return; } } else { baseToUnit = BWTA::getGroundDistance(ourBase, enemyPos); if (baseToUnit < baseToChoke) { //BWAPI::Broodwar->printf("Enemy has moved out!"); _enemyMovedOut = true; _movedOutMap[enemyPos] = true; return; } else { _movedOutMap[enemyPos] = false; } } } } _enemyMovedOut = false; //BWAPI::Broodwar->printf("Enemy in their base"); } }
void ScoutManager::moveScouts() { if (!_workerScout || !_workerScout->exists() || !(_workerScout->getHitPoints() > 0)) { return; } int scoutHP = _workerScout->getHitPoints() + _workerScout->getShields(); gasSteal(); // get the enemy base location, if we have one BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); int scoutDistanceThreshold = 30; if (_workerScout->isCarryingGas()) { BWAPI::Broodwar->drawCircleMap(_workerScout->getPosition(), 10, BWAPI::Colors::Purple, true); } // if we initiated a gas steal and the worker isn't idle, bool finishedConstructingGasSteal = _workerScout->isIdle() || _workerScout->isCarryingGas(); if (!_gasStealFinished && _didGasSteal && !finishedConstructingGasSteal) { return; } // check to see if the gas steal is completed else if (_didGasSteal && finishedConstructingGasSteal) { _gasStealFinished = true; } // if we know where the enemy region is and where our scout is if (_workerScout && enemyBaseLocation) { int scoutDistanceToEnemy = MapTools::Instance().getGroundDistance(_workerScout->getPosition(), enemyBaseLocation->getPosition()); bool scoutInRangeOfenemy = scoutDistanceToEnemy <= scoutDistanceThreshold; // we only care if the scout is under attack within the enemy region // this ignores if their scout worker attacks it on the way to their base if (scoutHP < _previousScoutHP) { _scoutUnderAttack = true; } if (!_workerScout->isUnderAttack() && !enemyWorkerInRadius()) { _scoutUnderAttack = false; } // if the scout is in the enemy region if (scoutInRangeOfenemy) { // get the closest enemy worker BWAPI::Unit closestWorker = closestEnemyWorker(); // if the worker scout is not under attack if (!_scoutUnderAttack) { // if there is a worker nearby, harass it if (Config::Strategy::ScoutHarassEnemy && (!Config::Strategy::GasStealWithScout || _gasStealFinished) && closestWorker && (_workerScout->getDistance(closestWorker) < 800)) { _scoutStatus = "Harass enemy worker"; _currentRegionVertexIndex = -1; Micro::SmartAttackUnit(_workerScout, closestWorker); } // otherwise keep moving to the enemy region else { _scoutStatus = "Following perimeter"; followPerimeter(); } } // if the worker scout is under attack else { _scoutStatus = "Under attack inside, fleeing"; followPerimeter(); } } // if the scout is not in the enemy region else if (_scoutUnderAttack) { _scoutStatus = "Under attack inside, fleeing"; followPerimeter(); } else { _scoutStatus = "Enemy region known, going there"; // move to the enemy region followPerimeter(); } } // for each start location in the level if (!enemyBaseLocation) { _scoutStatus = "Enemy base unknown, exploring"; for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations()) { // if we haven't explored it yet if (!BWAPI::Broodwar->isExplored(startLocation->getTilePosition())) { // assign a zergling to go scout it Micro::SmartMove(_workerScout, BWAPI::Position(startLocation->getTilePosition())); return; } } } _previousScoutHP = scoutHP; }
void CombatCommander::updateDefenseSquads() { if (_combatUnits.empty() || BWAPI::Broodwar->self()->allUnitCount(BWAPI::UnitTypes::Terran_Science_Vessel) == 1) { return; } BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); BWTA::Region * enemyRegion = nullptr; if (enemyBaseLocation) { enemyRegion = BWTA::getRegion(enemyBaseLocation->getPosition()); } // for each of our occupied regions for (BWTA::Region * myRegion : InformationManager::Instance().getOccupiedRegions(BWAPI::Broodwar->self())) { // don't defend inside the enemy region, this will end badly when we are stealing gas if (myRegion == enemyRegion) { continue; } BWAPI::Position regionCenter = myRegion->getCenter(); if (!regionCenter.isValid()) { continue; } // start off assuming all enemy units in region are just workers int numDefendersPerEnemyUnit = 2; // all of the enemy units in this region BWAPI::Unitset enemyUnitsInRegion; for (auto & unit : BWAPI::Broodwar->enemy()->getUnits()) { // if it's an overlord, don't worry about it for defense, we don't care what they see if (unit->getType() == BWAPI::UnitTypes::Zerg_Overlord) { continue; } if (BWTA::getRegion(BWAPI::TilePosition(unit->getPosition())) == myRegion) { enemyUnitsInRegion.insert(unit); } } // we can ignore the first enemy worker in our region since we assume it is a scout for (auto & unit : enemyUnitsInRegion) { if (unit->getType().isWorker()) { enemyUnitsInRegion.erase(unit); break; } } int numEnemyFlyingInRegion = std::count_if(enemyUnitsInRegion.begin(), enemyUnitsInRegion.end(), [](BWAPI::Unit u) { return u->isFlying(); }); int numEnemyGroundInRegion = std::count_if(enemyUnitsInRegion.begin(), enemyUnitsInRegion.end(), [](BWAPI::Unit u) { return !u->isFlying(); }); std::stringstream squadName; squadName << "Base Defense " << regionCenter.x << " " << regionCenter.y; // if there's nothing in this region to worry about if (enemyUnitsInRegion.empty()) { // if a defense squad for this region exists, remove it if (_squadData.squadExists(squadName.str())) { _squadData.getSquad(squadName.str()).clear(); } // and return, nothing to defend here continue; } else { // if we don't have a squad assigned to this region already, create one if (!_squadData.squadExists(squadName.str())) { SquadOrder defendRegion(SquadOrderTypes::Defend, regionCenter, 32 * 25, "Defend Region!"); _squadData.addSquad(squadName.str(), Squad(squadName.str(), defendRegion, BaseDefensePriority)); } } // assign units to the squad if (_squadData.squadExists(squadName.str())) { Squad & defenseSquad = _squadData.getSquad(squadName.str()); // figure out how many units we need on defense int flyingDefendersNeeded = numDefendersPerEnemyUnit * numEnemyFlyingInRegion; int groundDefensersNeeded = numDefendersPerEnemyUnit * numEnemyGroundInRegion; updateDefenseSquadUnits(defenseSquad, flyingDefendersNeeded, groundDefensersNeeded); } else { UAB_ASSERT_WARNING(false, "Squad should have existed: %s", squadName.str().c_str()); } } // for each of our defense squads, if there aren't any enemy units near the position, remove the squad std::set<std::string> uselessDefenseSquads; for (const auto & kv : _squadData.getSquads()) { const Squad & squad = kv.second; const SquadOrder & order = squad.getSquadOrder(); if (order.getType() != SquadOrderTypes::Defend) { continue; } bool enemyUnitInRange = false; for (auto & unit : BWAPI::Broodwar->enemy()->getUnits()) { if (unit->getPosition().getDistance(order.getPosition()) < order.getRadius()) { enemyUnitInRange = true; break; } } if (!enemyUnitInRange) { _squadData.getSquad(squad.getName()).clear(); } } }
void ScoutManager::moveScouts() { if (!workerScout || !workerScout->exists() || !workerScout->getPosition().isValid() || !(workerScout->getHitPoints() > 0)) { return; } // get the enemy base location, if we have one BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); // determine the region that the enemy is in BWTA::Region * enemyRegion = enemyBaseLocation ? enemyBaseLocation->getRegion() : NULL; // determine the region the scout is in BWAPI::TilePosition scoutTile(workerScout->getPosition()); BWTA::Region * scoutRegion = scoutTile.isValid() ? BWTA::getRegion(scoutTile) : NULL; // we only care if the scout is under attack within the enemy region // this ignores if their scout worker attacks it on the way to their base if (workerScout->isUnderAttack() && (scoutRegion == enemyRegion)) { scoutUnderAttack = true; } if (!workerScout->isUnderAttack() && !enemyWorkerInRadius()) { scoutUnderAttack = false; } // if we know where the enemy region is and where our scout is if (enemyRegion && scoutRegion) { // if the scout is in the enemy region if (scoutRegion == enemyRegion) { std::vector<GroundThreat> groundThreats; fillGroundThreats(groundThreats, workerScout->getPosition()); // get the closest enemy worker BWAPI::UnitInterface* closestWorker = closestEnemyWorker(); // if the worker scout is not under attack if (!scoutUnderAttack) { // if there is a worker nearby, harass it if (closestWorker && (workerScout->getDistance(closestWorker) < 800)) { smartAttack(workerScout, closestWorker); } // otherwise keep moving to the enemy region else { // move to the enemy region smartMove(workerScout, enemyBaseLocation->getPosition()); BWAPI::Broodwar->drawLineMap(workerScout->getPosition().x, workerScout->getPosition().y, enemyBaseLocation->getPosition().x, enemyBaseLocation->getPosition().y, BWAPI::Colors::Yellow); } } // if the worker scout is under attack else { BWAPI::Position fleeTo = calcFleePosition(groundThreats, NULL); if (Options::Debug::DRAW_UALBERTABOT_DEBUG) BWAPI::Broodwar->drawCircleMap(fleeTo.x, fleeTo.y, 10, BWAPI::Colors::Red); for (BWAPI::UnitInterface* unit : BWAPI::Broodwar->getUnitsInRadius(fleeTo, 10)) { if (Options::Debug::DRAW_UALBERTABOT_DEBUG) BWAPI::Broodwar->drawCircleMap(unit->getPosition().x, unit->getPosition().y, 5, BWAPI::Colors::Cyan, true); } smartMove(workerScout, fleeTo); } } // if the scout is not in the enemy region else if (scoutUnderAttack) { smartMove(workerScout, BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation())); } else { // move to the enemy region smartMove(workerScout, enemyBaseLocation->getPosition()); } } // for each start location in the level if (!enemyRegion) { for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations()) { // if we haven't explored it yet if (!BWAPI::Broodwar->isExplored(startLocation->getTilePosition())) { // assign a zergling to go scout it smartMove(workerScout, BWAPI::Position(startLocation->getTilePosition())); return; } } } }
void ScoutManager::updateScoutAssignments() { // Remove scout positions if the enemy is not there. for ( std::map< BWAPI::Unit, ScoutData >::iterator s = m_scouts.begin(); s != m_scouts.end(); s++ ) { if ( s->second.m_mode == ScoutData::Searching && s->first->getPosition().getDistance( s->second.m_target->getPosition() ) < s->first->getType().sightRange() ) { bool empty = true; for ( int x = s->second.m_target->getTilePosition().x; x < s->second.m_target->getTilePosition().x + 4; x++ ) { for ( int y = s->second.m_target->getTilePosition().y; y < s->second.m_target->getTilePosition().y + 3; y++ ) { for( BWAPI::Unit u : BWAPI::Broodwar->getUnitsOnTile( x, y ) ) { if ( u->getType().isResourceDepot() ) { empty = false; break; } } if ( !empty ) break; } if ( !empty ) break; } if ( empty ) { m_informationManager->setBaseEmpty( s->second.m_target ); } BWTA::BaseLocation* exploredBaseLocation = s->second.m_target; m_baseLocationsToScout.remove( exploredBaseLocation ); m_baseLocationsExplored.insert( exploredBaseLocation ); s->second.m_mode = ScoutData::Idle; if ( m_debugMode ) { BWAPI::Broodwar->printf( "Sucessfully scouted ( %d, %d )", exploredBaseLocation->getPosition().x, exploredBaseLocation->getPosition().y ); } } } // Set scouts to scout. if ( m_baseLocationsToScout.size() > 0 ) // are there still positions to scout? { for ( std::map< BWAPI::Unit, ScoutData >::iterator s = m_scouts.begin(); s != m_scouts.end(); s++ ) { if ( s->second.m_mode == ScoutData::Idle ) { double minDist = 100000000; BWTA::BaseLocation* target = NULL; for( BWTA::BaseLocation* bl : m_baseLocationsToScout ) { double distance = s->first->getPosition().getDistance( bl->getPosition() ); if ( distance < minDist ) { minDist = distance; target = bl; } } if ( target != NULL ) { s->second.m_mode = ScoutData::Searching; s->first->rightClick( target->getPosition() ); s->second.m_target = target; m_baseLocationsToScout.remove( target ); if ( m_debugMode ) { BWAPI::Broodwar->printf( "Scouting ( %d, %d )", target->getPosition().x, target->getPosition().y ); } } } } } }
void ScoutManager::moveScouts() { if (!_workerScout || !_workerScout->exists() || !(_workerScout->getHitPoints() > 0)) { return; } int scoutHP = _workerScout->getHitPoints() + _workerScout->getShields(); gasSteal(); // get the enemy base location, if we have one BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); int scoutDistanceThreshold = 30; if (_workerScout->isCarryingGas()) { BWAPI::Broodwar->drawCircleMap(_workerScout->getPosition(), 10, BWAPI::Colors::Purple, true); } // if we initiated a gas steal and the worker isn't idle, bool finishedConstructingGasSteal = _workerScout->isIdle() || _workerScout->isCarryingGas(); if (!_gasStealFinished && _didGasSteal && !finishedConstructingGasSteal) { return; } // check to see if the gas steal is completed else if (_didGasSteal && finishedConstructingGasSteal) { _gasStealFinished = true; } for (auto & iter : explore_val) { int x1 = _workerScout->getPosition().x; int y1 = _workerScout->getPosition().y; int x2 = (iter.first)->getPosition().x; int y2 = (iter.first)->getPosition().y; double distance = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + 0.0); if (distance > 800) { continue; } if (enemyBaseLocation != nullptr && iter.first == enemyBaseLocation) { patrol_counter++; if (patrol_counter >= 480) { patrol_counter = 0; iter.second = 0; } } else if (distance <= 100) { iter.second = 0; } } BWAPI::Position scout_pos = _workerScout->getPosition(); double cur_dis = scout_pos.getDistance(next_pos); BWAPI::Broodwar->drawTextScreen(200, 280, "Next position : %d %d", next_pos.x, next_pos.y); BWAPI::Broodwar->drawTextScreen(200, 290, "distance to next position:\t%.2lf", cur_dis); if (cur_dis > 150) { Micro::SmartMove(_workerScout, next_pos); return; } // if we know where the enemy region is and where our scout is if (_workerScout && enemyBaseLocation) { //lpx int max_prior = 0; for (auto iter : explore_val) { if (iter.second > max_prior) { max_prior = iter.second; pass_by = iter.first; } } if (pass_by != enemyBaseLocation) { next_pos = BWAPI::Position(pass_by->getTilePosition()); Micro::SmartMove(_workerScout, next_pos); _scoutStatus = "Found higher priority than enemy base, first going there"; return; } int scoutDistanceToEnemy = MapTools::Instance().getGroundDistance(_workerScout->getPosition(), enemyBaseLocation->getPosition()); bool scoutInRangeOfenemy = scoutDistanceToEnemy <= scoutDistanceThreshold; // we only care if the scout is under attack within the enemy region // this ignores if their scout worker attacks it on the way to their base if (scoutHP < _previousScoutHP) { _scoutUnderAttack = true; } if (!_workerScout->isUnderAttack() && !enemyWorkerInRadius()) { _scoutUnderAttack = false; } // if the scout is in the enemy region if (scoutInRangeOfenemy) { // get the closest enemy worker BWAPI::Unit closestWorker = closestEnemyWorker(); // if the worker scout is not under attack if (!_scoutUnderAttack) { /* // if there is a worker nearby, harass it if (Config::Strategy::ScoutHarassEnemy && (!Config::Strategy::GasStealWithScout || _gasStealFinished) && closestWorker && (_workerScout->getDistance(closestWorker) < 800)) { _scoutStatus = "Harass enemy worker"; _currentRegionVertexIndex = -1; Micro::SmartAttackUnit(_workerScout, closestWorker); } // otherwise keep moving to the enemy region */ _scoutStatus = "Following perimeter"; followPerimeter(); } // if the worker scout is under attack else { _scoutStatus = "Under attack inside, fleeing"; followPerimeter(); } } // if the scout is not in the enemy region else if (_scoutUnderAttack) { _scoutStatus = "Under attack inside, fleeing"; followPerimeter(); } else { _scoutStatus = "Enemy region known, going there"; // move to the enemy region followPerimeter(); } } // for each start location in the level if (!enemyBaseLocation) { _scoutStatus = "Enemy base unknown, exploring"; for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations()) { // if we haven't explored it yet if (!BWAPI::Broodwar->isExplored(startLocation->getTilePosition())) { // assign a zergling to go scout it next_pos = BWAPI::Position(startLocation->getPosition()); Micro::SmartMove(_workerScout, BWAPI::Position(startLocation->getTilePosition())); return; } } } _previousScoutHP = scoutHP; }