void ScoutManager::drawScoutInformation(int x, int y) { if (!Config::Debug::DrawScoutInfo) { return; } BWAPI::Broodwar->drawTextScreen(x, y - 10, "Enemy base timer == %d", patrol_counter); BWAPI::Broodwar->drawTextScreen(x, y, "ScoutInfo: %s", _scoutStatus.c_str()); BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); double distance = 0.0; if (_workerScout && _workerScout->exists() && enemyBaseLocation) { BWAPI::Position tmp = BWAPI::Position(enemyBaseLocation->getTilePosition()); int x1 = _workerScout->getPosition().x; int y1 = _workerScout->getPosition().y; int x2 = tmp.x; int y2 = tmp.y; distance = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2) + 0.0); } BWAPI::Broodwar->drawTextScreen(x, y+10, "Distance to enemy base: %.2lf", distance); for (size_t i(0); i < _enemyRegionVertices.size(); ++i) { BWAPI::Broodwar->drawCircleMap(_enemyRegionVertices[i], 4, BWAPI::Colors::Green, false); BWAPI::Broodwar->drawTextMap(_enemyRegionVertices[i], "%d", i); } }
BWAPI::TilePosition getNextExpansionLocation(TilePosition currentExpo) { //remove the current expo from the list //loop through expos and find the nearest one std::set<BWTA::BaseLocation*> bases; for (auto &u : allBases) { //make sure we delete the current expansion if (u->getTilePosition() == currentExpo) { allBases.erase(u); } } BWTA::BaseLocation *ret = *allBases.begin(); int minDistance = currentExpo.getApproxDistance(ret->getTilePosition()); //make sure we dont accidently find current expansion for (auto &u : allBases) { int tempDistance = currentExpo.getApproxDistance(u->getTilePosition()); if (tempDistance < minDistance && tempDistance > 10) { //found a closer base minDistance = tempDistance; ret = u; } } return ret->getTilePosition(); }
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 building a bunker for strategy "Terran_Custom", return one location near an attacked unit if ((b.type == BWAPI::UnitTypes::Terran_Bunker) && (Config::Strategy::StrategyName == "Terran_Custom")) { for (auto & unit : BWAPI::Broodwar->self()->getUnits()) { if (unit->isUnderAttack()) { return BuildingPlacer::Instance().getBuildLocationNear(b, 1, false); break; } } } if (b.type.isRefinery()) { return BuildingPlacer::Instance().getRefineryPosition(); } if (b.type.isResourceDepot()) { // get the location BWAPI::TilePosition tile = MapTools::Instance().getNextExpansion(); return tile; } // 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); }
BWAPI::Unit ScoutManager::getEnemyGeyser() { BWAPI::Unit geyser = nullptr; BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); for (auto & unit : enemyBaseLocation->getGeysers()) { geyser = unit; } return geyser; }
BWAPI::UnitInterface* ScoutManager::getEnemyGeyser() { BWAPI::UnitInterface* geyser = NULL; BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); for (BWAPI::UnitInterface* unit : enemyBaseLocation->getGeysers()) { geyser = unit; } return geyser; }
void ProbeUnit::check() { if (backUpMineral == NULL || !backUpMineral->exists()) { if (Broodwar->getFrameCount() < 10*24*60) { BWTA::BaseLocation* b = BWTA::getStartLocation(Broodwar->self()); if (b != NULL && !b->getMinerals().empty()) backUpMineral = *(b->getMinerals().begin()); if (backUpMineral == NULL || !backUpMineral->exists()) backUpMineral = NULL; } } }
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 ); } }
BWTA::BaseLocation* BaseManager::expand(int priority) { BWTA::BaseLocation* location = NULL; BWTA::BaseLocation* locationWithoutGas = NULL; double minDist=-1; BWTA::BaseLocation* home = BWTA::getStartLocation(BWAPI::Broodwar->self()); std::set<BWTA::BaseLocation*>::const_iterator i; for(i = BWTA::getBaseLocations().begin(); i != BWTA::getBaseLocations().end(); i++) { BWTA::BaseLocation *baseLocation = (*i); if (baseLocation->isIsland()) { continue; } double dist = home->getGroundDistance(baseLocation); if (dist > 0 && getBase(baseLocation) == NULL) { if (minDist == -1 || dist < minDist) { if (baseLocation->isMineralOnly()) { locationWithoutGas = baseLocation; } else { location = baseLocation; minDist = dist; } } } } if (location == NULL && locationWithoutGas != NULL) { BWAPI::Broodwar->printf("Expanding to location without gas."); location = locationWithoutGas; } return expand(location, priority); }
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); }
bool WorkerManager::isGasStealRefinery(BWAPI::Unit unit) { BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); if (!enemyBaseLocation) { return false; } if (enemyBaseLocation->getGeysers().empty()) { return false; } for (auto & u : enemyBaseLocation->getGeysers()) { if (unit->getTilePosition() == u->getTilePosition()) { return true; } } return false; }
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"); } }
BWAPI::TilePosition MapTools::getNextExpansion(BWAPI::Player player) { BWTA::BaseLocation * closestBase = nullptr; double minDistance = 100000; BWAPI::TilePosition homeTile = player->getStartLocation(); // for each base location for (BWTA::BaseLocation * base : BWTA::getBaseLocations()) { // if the base has gas if (!base->isMineralOnly() && !(base == BWTA::getStartLocation(player))) { // get the tile position of the base BWAPI::TilePosition tile = base->getTilePosition(); bool buildingInTheWay = false; for (int x = 0; x < BWAPI::Broodwar->self()->getRace().getCenter().tileWidth(); ++x) { for (int y = 0; y < BWAPI::Broodwar->self()->getRace().getCenter().tileHeight(); ++y) { BWAPI::TilePosition tp(tile.x + x, tile.y + y); for (auto & unit : BWAPI::Broodwar->getUnitsOnTile(tp)) { if (unit->getType().isBuilding() && !unit->isFlying()) { buildingInTheWay = true; break; } } } } if (buildingInTheWay) { continue; } // the base's distance from our main nexus BWAPI::Position myBasePosition(player->getStartLocation()); BWAPI::Position thisTile = BWAPI::Position(tile); double distanceFromHome = MapTools::Instance().getGroundDistance(thisTile,myBasePosition); // if it is not connected, continue if (!BWTA::isConnected(homeTile,tile) || distanceFromHome < 0) { continue; } if (!closestBase || distanceFromHome < minDistance) { closestBase = base; minDistance = distanceFromHome; } } } if (closestBase) { return closestBase->getTilePosition(); } else { return BWAPI::TilePositions::None; } }
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 ScoutManager::calculateEnemyRegionVertices() { BWTA::BaseLocation * enemyBaseLocation = InformationManager::Instance().getMainBaseLocation(BWAPI::Broodwar->enemy()); //UAB_ASSERT_WARNING(enemyBaseLocation, "We should have an enemy base location if we are fleeing"); if (!enemyBaseLocation) { return; } BWTA::Region * enemyRegion = enemyBaseLocation->getRegion(); //UAB_ASSERT_WARNING(enemyRegion, "We should have an enemy region if we are fleeing"); if (!enemyRegion) { return; } const BWAPI::Position basePosition = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()); const std::vector<BWAPI::TilePosition> & closestTobase = MapTools::Instance().getClosestTilesTo(basePosition); std::set<BWAPI::Position> unsortedVertices; // check each tile position for (size_t i(0); i < closestTobase.size(); ++i) { const BWAPI::TilePosition & tp = closestTobase[i]; if (BWTA::getRegion(tp) != enemyRegion) { continue; } // a tile is 'surrounded' if // 1) in all 4 directions there's a tile position in the current region // 2) in all 4 directions there's a buildable tile bool surrounded = true; if (BWTA::getRegion(BWAPI::TilePosition(tp.x+1, tp.y)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x+1, tp.y)) || BWTA::getRegion(BWAPI::TilePosition(tp.x, tp.y+1)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x, tp.y+1)) || BWTA::getRegion(BWAPI::TilePosition(tp.x-1, tp.y)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x-1, tp.y)) || BWTA::getRegion(BWAPI::TilePosition(tp.x, tp.y-1)) != enemyRegion || !BWAPI::Broodwar->isBuildable(BWAPI::TilePosition(tp.x, tp.y -1))) { surrounded = false; } // push the tiles that aren't surrounded if (!surrounded && BWAPI::Broodwar->isBuildable(tp)) { if (Config::Debug::DrawScoutInfo) { int x1 = tp.x * 32 + 2; int y1 = tp.y * 32 + 2; int x2 = (tp.x+1) * 32 - 2; int y2 = (tp.y+1) * 32 - 2; BWAPI::Broodwar->drawTextMap(x1+3, y1+2, "%d", MapTools::Instance().getGroundDistance(BWAPI::Position(tp), basePosition)); BWAPI::Broodwar->drawBoxMap(x1, y1, x2, y2, BWAPI::Colors::Green, false); } unsortedVertices.insert(BWAPI::Position(tp) + BWAPI::Position(16, 16)); } } std::vector<BWAPI::Position> sortedVertices; BWAPI::Position current = *unsortedVertices.begin(); _enemyRegionVertices.push_back(current); unsortedVertices.erase(current); // while we still have unsorted vertices left, find the closest one remaining to current while (!unsortedVertices.empty()) { double bestDist = 1000000; BWAPI::Position bestPos; for (const BWAPI::Position & pos : unsortedVertices) { double dist = pos.getDistance(current); if (dist < bestDist) { bestDist = dist; bestPos = pos; } } current = bestPos; sortedVertices.push_back(bestPos); unsortedVertices.erase(bestPos); } // let's close loops on a threshold, eliminating death grooves int distanceThreshold = 100; while (true) { // find the largest index difference whose distance is less than the threshold int maxFarthest = 0; int maxFarthestStart = 0; int maxFarthestEnd = 0; // for each starting vertex for (int i(0); i < (int)sortedVertices.size(); ++i) { int farthest = 0; int farthestIndex = 0; // only test half way around because we'll find the other one on the way back for (size_t j(1); j < sortedVertices.size()/2; ++j) { int jindex = (i + j) % sortedVertices.size(); if (sortedVertices[i].getDistance(sortedVertices[jindex]) < distanceThreshold) { farthest = j; farthestIndex = jindex; } } if (farthest > maxFarthest) { maxFarthest = farthest; maxFarthestStart = i; maxFarthestEnd = farthestIndex; } } // stop when we have no long chains within the threshold if (maxFarthest < 4) { break; } double dist = sortedVertices[maxFarthestStart].getDistance(sortedVertices[maxFarthestEnd]); std::vector<BWAPI::Position> temp; for (size_t s(maxFarthestEnd); s != maxFarthestStart; s = (s+1) % sortedVertices.size()) { temp.push_back(sortedVertices[s]); } sortedVertices = temp; } _enemyRegionVertices = sortedVertices; }
// STEP 6: CHECK FOR COMPLETED BUILDINGS void BuildingManager::checkForCompletedBuildings() { std::vector<Building> toRemove; // for each of our buildings under construction for (auto & b : _buildings) { if (b.status != BuildingStatus::UnderConstruction) { continue; } // if the unit has completed if (b.buildingUnit->isCompleted()) { if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg) { if (b.buildingUnit->getType() == BWAPI::UnitTypes::Zerg_Creep_Colony) { //b.buildingUnit->upgrade(b.buildingUnit->getUpgrade()); //b.buildingUnit->buildAddon(BWAPI::UnitTypes::Zerg_Sunken_Colony); // MAKE SUNKEN //b.buildingUnit->morph(BWAPI::UnitTypes::Zerg_Sunken_Colony); MetaType type(BWAPI::UnitTypes::Zerg_Sunken_Colony); //ProductionManager::Instance()._queue.queueAsHighestPriority(type, true); } if (b.buildingUnit->getType() == BWAPI::UnitTypes::Zerg_Hatchery) { createdHatchery = true; } /* if (b.buildingUnit->getType() == BWAPI::UnitTypes::Zerg_Hatchery) { for (BWAPI::Unit p : BWAPI::Broodwar->self()->getUnits()) { if (!madeFirstSunken && p->getType().isWorker() && p->getPosition() == firstHatcheryPosition) { //BWAPI::Position tempPosition; //tempPosition.x = b.finalPosition.x + 3; //tempPosition.y = b.finalPosition.y + 3; MetaType type(BWAPI::UnitTypes::Zerg_Creep_Colony); ProductionManager::Instance()._queue.queueAsHighestPriority(type, true); /* BWAPI::TilePosition sunkPos = getSunkenPosition(); createdSunkenSet.insert(sunkPos); createdSunkenVector.push_back(sunkPos); createdBuilding.insert(sunkPos); p->build(BWAPI::UnitTypes::Zerg_Hatchery, sunkPos); madeFirstSunken = true; BWAPI::TilePosition sunkPos2 = getSunkenPosition(); createdSunkenSet.insert(sunkPos2); createdSunkenVector.push_back(sunkPos2); createdBuilding.insert(sunkPos2); p->build(BWAPI::UnitTypes::Zerg_Hatchery, sunkPos2); //b.builderUnit->build(b.type, b.finalPosition); break; //candidateProducers.insert(p); } } } */ } // if we are terran, give the worker back to worker manager if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Terran) { if (b.isGasSteal) { ScoutManager::Instance().setWorkerScout(b.builderUnit); } // otherwise tell the worker manager we're finished with this unit else { WorkerManager::Instance().finishedWithWorker(b.builderUnit); } } // remove this unit from the under construction vector toRemove.push_back(b); } else { if (b.type == 131 && b.buildingUnit->getHitPoints() >= 1050 && !transferredDrones) { //BWAPI::Broodwar->printf("Send Drone"); //BWAPI::Unitset candidateProducers; BWAPI::UnitType sunk = BWAPI::UnitTypes::Zerg_Creep_Colony; Building z(sunk, createdHatcheriesVector[0]); //BWAPI::Unit workerToAssign = WorkerManager::Instance().getMoveWorker(BWAPI::Position(createdHatcheriesVector[0])); //BWAPI::Unit workerToAssign2 = WorkerManager::Instance().getMoveWorker(BWAPI::Position(createdHatcheriesVector[0])); //WorkerManager::Instance().setMoveWorker(0, 0, BWAPI::Position(createdHatcheriesVector[0])); //WorkerManager::Instance().setMoveWorker(0, 0, BWAPI::Position(createdHatcheriesVector[0])); //_reservedMinerals += 75; BWAPI::Unit workerToAssign = WorkerManager::Instance().getBuilder(z); BWAPI::Unit workerToAssign2 = WorkerManager::Instance().getBuilder(z); //WorkerData m; //m.setWorkerJob(workerToAssign, WorkerData::Minerals, b.type); /* for (BWAPI::Unit p : BWAPI::Broodwar->self()->getUnits()) { WorkerData k; WorkerData::WorkerJob j = k.getWorkerJob(p); if (p->getType().isWorker() && j != WorkerData::Scout) { */ const std::set<BWTA::BaseLocation*, std::less<BWTA::BaseLocation*>> locations = BWTA::getBaseLocations(); BWTA::BaseLocation *myLocation; for (BWTA::BaseLocation *p : locations) { BWAPI::TilePosition z = p->getTilePosition(); if (z == createdHatcheriesVector[0]){ // This is the BWTA::Location of the first hatchery. myLocation = p; } } // Get the set of mineral patches closest to BWTA::Location of the hatchery(it will return like 8 mineral patches usually in the set) const BWAPI::Unitset mineralSet = myLocation->getMinerals(); BWAPI::Unit myMineral; for (BWAPI::Unit p : mineralSet) { myMineral = p; // Calculate the difference between LeftMostMineralPatch.x - ExpansionHatchery.x and store it in theX //theX = p->getTilePosition().x - hatchPosition.x; // Calculate the difference between LeftMostMineralPatch.y - ExpansionHatchery.y and store it in theY //theY = p->getTilePosition().y - hatchPosition.y; break; } workerToAssign->gather(myMineral); workerToAssign2->gather(myMineral); sunkenUnit = workerToAssign; sunkenUnit2 = workerToAssign2; //sunkenID = workerToAssign->getID(); transferredDrones = true; } if (b.type == 131 && b.buildingUnit->getHitPoints() >= 1225 && !sentFirstDroneForSunken) { MetaType type(BWAPI::UnitTypes::Zerg_Creep_Colony); ProductionManager::Instance()._queue.queueAsHighestPriority(type, true); //sunkenID2 = workerToAssign2->getID(); //BWAPI::TilePosition tempPosition; //tempPosition.x = b.finalPosition.x+4; //tempPosition.y = b.finalPosition.y+4; //Micro::SmartMove(p, BWAPI::Position(tempPosition)); //Micro::SmartMove(p, BWAPI::Position(tempPosition)); //p->move(BWAPI::Position(tempPosition)); //p->move(BWAPI::Position(tempPosition)); //break; //candidateProducers.insert(p); //MetaType type(BWAPI::UnitTypes::Zerg_Creep_Colony); //ProductionManager::Instance()._queue.queueAsHighestPriority(type, true); sentFirstDroneForSunken = true; } } } removeBuildings(toRemove); }
void BasicAIModule::onStart() { Broodwar->enableFlag( Flag::UserInput ); BWTA::readMap(); BWTA::analyze(); BWSAL::resetLog(); m_informationManager = InformationManager::create(); m_borderManager = BorderManager::create( m_informationManager ); m_baseManager = BaseManager::create( m_borderManager ); m_buildingPlacer = new BFSBuildingPlacer(); m_reservedMap = ReservedMap::create(); m_unitArbitrator = new UnitArbitrator(); m_unitGroupManager = UnitGroupManager::create(); m_buildUnitManager = BuildUnitManager::create(); m_buildEventTimeline = BuildEventTimeline::create( m_buildUnitManager ); m_taskScheduler = TaskScheduler::create( m_buildEventTimeline, m_buildUnitManager ); m_taskExecutor = TaskExecutor::create( m_unitArbitrator, m_buildEventTimeline, m_reservedMap, m_buildingPlacer ); m_workerManager = WorkerManager::create( m_unitArbitrator, m_baseManager ); m_scoutManager = ScoutManager::create( m_unitArbitrator, m_informationManager ); m_defenseManager = DefenseManager::create( m_unitArbitrator, m_borderManager ); m_buildOrderManager = BuildOrderManager::create( m_taskScheduler, m_taskExecutor, m_buildUnitManager ); m_supplyManager = SupplyManager::create( m_buildOrderManager, m_taskScheduler ); m_enhancedUI = new EnhancedUI(); m_buildEventTimeline->initialize(); m_scoutManager->initialize(); m_modules.push_back( m_informationManager ); m_modules.push_back( m_borderManager ); m_modules.push_back( m_baseManager ); m_modules.push_back( m_buildEventTimeline ); m_modules.push_back( m_reservedMap ); m_modules.push_back( m_unitGroupManager ); m_modules.push_back( m_buildUnitManager ); m_modules.push_back( m_taskScheduler ); m_modules.push_back( m_taskExecutor ); m_modules.push_back( m_workerManager ); m_modules.push_back( m_scoutManager ); m_modules.push_back( m_defenseManager ); BWAPI::Race race = Broodwar->self()->getRace(); BWAPI::Race enemyRace = Broodwar->enemy()->getRace(); double minDist; BWTA::BaseLocation* natural = NULL; BWTA::BaseLocation* home = BWTA::getStartLocation( Broodwar->self() ); foreach( BWTA::BaseLocation* bl, BWTA::getBaseLocations() ) { if ( bl != home ) { double dist = home->getGroundDistance( bl ); if ( dist > 0 ) { if ( natural == NULL || dist < minDist) { minDist = dist; natural = bl; } } } } int buildID = 1; if ( race == Races::Zerg ) { // Send an overlord out if Zerg m_scoutManager->setScoutCount( 1 ); if (buildID == 1) { //morph 5 lurkers (tests dependency resolver, task scheduler) m_buildOrderManager->build( 8, UnitTypes::Zerg_Drone, 90 ); m_buildOrderManager->buildAdditional( 1, UnitTypes::Zerg_Overlord, 85 ); m_buildOrderManager->build( 12, UnitTypes::Zerg_Drone, 84 ); m_buildOrderManager->buildAdditional( 1, UnitTypes::Zerg_Lair, 82); m_buildOrderManager->buildAdditional( 5, UnitTypes::Zerg_Lurker, 80); m_buildOrderManager->build( 12, UnitTypes::Zerg_Drone, 30 ); } else if (buildID >= 2) { //12 pool 6 lings (tests larva task scheduler) m_buildOrderManager->build( 8, UnitTypes::Zerg_Drone, 90 ); m_buildOrderManager->buildAdditional( 1, UnitTypes::Zerg_Overlord, 85 ); m_buildOrderManager->build( 12, UnitTypes::Zerg_Drone, 84 ); m_buildOrderManager->buildAdditional( 1, UnitTypes::Zerg_Spawning_Pool, 70 ); m_buildOrderManager->buildAdditional( 3, UnitTypes::Zerg_Zergling, 65 ); m_buildOrderManager->build( 40, UnitTypes::Zerg_Drone, 62 ); } } else if ( race == Races::Terran ) { if (buildID == 1) { //build 3 comsat stations (tests dependency resolver) m_buildOrderManager->build(9,UnitTypes::Terran_SCV,90); m_buildOrderManager->build(1,UnitTypes::Terran_Supply_Depot,85); m_buildOrderManager->build(20,UnitTypes::Terran_SCV,80); m_buildOrderManager->buildAdditional(3,UnitTypes::Terran_Comsat_Station,60); } else if (buildID == 2) { //a complex build order m_buildOrderManager->build(9,UnitTypes::Terran_SCV,90); m_buildOrderManager->build(1,UnitTypes::Terran_Supply_Depot,85); m_buildOrderManager->build(20,UnitTypes::Terran_SCV,80); m_buildOrderManager->buildAdditional(1,UnitTypes::Terran_Barracks,60); m_buildOrderManager->buildAdditional(9,UnitTypes::Terran_Marine,45); m_buildOrderManager->buildAdditional(1,UnitTypes::Terran_Refinery,42); m_buildOrderManager->buildAdditional(1,UnitTypes::Terran_Barracks,40); m_buildOrderManager->buildAdditional(1,UnitTypes::Terran_Academy,39); m_buildOrderManager->buildAdditional(9,UnitTypes::Terran_Medic,38); m_buildOrderManager->research(TechTypes::Stim_Packs,35); m_buildOrderManager->research(TechTypes::Tank_Siege_Mode,35); m_buildOrderManager->buildAdditional(3,UnitTypes::Terran_Siege_Tank_Tank_Mode,34); m_buildOrderManager->buildAdditional(2,UnitTypes::Terran_Science_Vessel,30); m_buildOrderManager->research(TechTypes::Irradiate,30); m_buildOrderManager->upgrade(1,UpgradeTypes::Terran_Infantry_Weapons,20); m_buildOrderManager->build(3,UnitTypes::Terran_Missile_Turret,13); m_buildOrderManager->upgrade(3,UpgradeTypes::Terran_Infantry_Weapons,12); m_buildOrderManager->upgrade(3,UpgradeTypes::Terran_Infantry_Armor,12); m_buildOrderManager->build(1,UnitTypes::Terran_Engineering_Bay,11); m_buildOrderManager->buildAdditional(40,UnitTypes::Terran_Marine,10); m_buildOrderManager->build(6,UnitTypes::Terran_Barracks,8); m_buildOrderManager->build(2,UnitTypes::Terran_Engineering_Bay,7); m_buildOrderManager->buildAdditional(10,UnitTypes::Terran_Siege_Tank_Tank_Mode,5); } else if (buildID >= 3) { //terran mech - tests task ordering with add-on requiring units m_buildOrderManager->build(9,UnitTypes::Terran_SCV,90); m_buildOrderManager->build(1,UnitTypes::Terran_Supply_Depot,85); m_buildOrderManager->build(20,UnitTypes::Terran_SCV,80); m_buildOrderManager->buildAdditional(2,BWAPI::UnitTypes::Terran_Machine_Shop,70); m_buildOrderManager->buildAdditional(3,BWAPI::UnitTypes::Terran_Factory,60); m_buildOrderManager->research(TechTypes::Spider_Mines,55); m_buildOrderManager->research(TechTypes::Tank_Siege_Mode,55); m_buildOrderManager->buildAdditional(20,BWAPI::UnitTypes::Terran_Vulture,40); m_buildOrderManager->buildAdditional(20,BWAPI::UnitTypes::Terran_Siege_Tank_Tank_Mode,40); m_buildOrderManager->upgrade(3,UpgradeTypes::Terran_Vehicle_Weapons,20); } } else if (race == Races::Protoss) { //build 20 carriers - tests dependency resolver m_buildOrderManager->build(8,UnitTypes::Protoss_Probe,90); m_buildOrderManager->build(1,UnitTypes::Protoss_Pylon,85); m_buildOrderManager->build(20,UnitTypes::Protoss_Probe,80); m_buildOrderManager->buildAdditional(10,UnitTypes::Protoss_Dragoon,70); m_buildOrderManager->buildAdditional(10,UnitTypes::Protoss_Zealot,70); m_buildOrderManager->upgrade(1,UpgradeTypes::Singularity_Charge,61); m_buildOrderManager->buildAdditional(20,UnitTypes::Protoss_Carrier,60); } m_drawTasks = true; m_drawAssignments = false; m_drawResources = true; m_drawLarva = Broodwar->self()->getRace() == Races::Zerg; }
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; }
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 // Make every other base for zerg a macro hatch. bool is_macro = false; if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg) { int num_mains = UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Zerg_Hatchery) + UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Zerg_Lair) + UnitUtil::GetAllUnitCount(BWAPI::UnitTypes::Zerg_Hive); if (num_mains % 2 == 1) is_macro = true; } if (!is_macro || Config::Strategy::StrategyName == "GreedyHydras") { BWAPI::TilePosition tile = MapTools::Instance().getNextExpansion(); return tile; } } if (b.type == BWAPI::UnitTypes::Zerg_Creep_Colony) { // Half way between start and choke. BWAPI::TilePosition startLocation = BWAPI::Broodwar->self()->getStartLocation(); BWAPI::TilePosition chokeLocation = BWAPI::TilePosition(BWTA::getNearestChokepoint(startLocation)->getCenter()); // IS THIS HOW I AVERAGE POINTS? HAHA, LET'S SEE. return BWAPI::Broodwar->getBuildLocation(b.type, chokeLocation, 64, true); } // 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 InformationManager::updateBaseLocationInfo() { _occupiedRegions[_self].clear(); _occupiedRegions[_enemy].clear(); // if we haven't found the enemy main base location yet if (!_mainBaseLocations[_enemy]) { // how many start locations have we explored int exploredStartLocations = 0; bool baseFound = false; // an undexplored base location holder BWTA::BaseLocation * unexplored = nullptr; for (BWTA::BaseLocation * startLocation : BWTA::getStartLocations()) { if (isEnemyBuildingInRegion(BWTA::getRegion(startLocation->getTilePosition()))) { if (Config::Debug::DrawScoutInfo) { BWAPI::Broodwar->printf("Enemy base found by seeing it"); } baseFound = true; _mainBaseLocations[_enemy] = startLocation; updateOccupiedRegions(BWTA::getRegion(startLocation->getTilePosition()), BWAPI::Broodwar->enemy()); } // if it's explored, increment if (BWAPI::Broodwar->isExplored(startLocation->getTilePosition())) { exploredStartLocations++; // otherwise set the unexplored base } else { unexplored = startLocation; } } // if we've explored every start location except one, it's the enemy if (!baseFound && exploredStartLocations == ((int)BWTA::getStartLocations().size() - 1)) { if (Config::Debug::DrawScoutInfo) { BWAPI::Broodwar->printf("Enemy base found by process of elimination"); } _mainBaseLocations[_enemy] = unexplored; updateOccupiedRegions(BWTA::getRegion(unexplored->getTilePosition()), BWAPI::Broodwar->enemy()); } // otherwise we do know it, so push it back } else { updateOccupiedRegions(BWTA::getRegion(_mainBaseLocations[_enemy]->getTilePosition()), BWAPI::Broodwar->enemy()); } // for each enemy unit we know about size_t enemyBaseCount = 0; size_t enemySunkenCount = 0; for (const auto & kv : _unitData[_enemy].getUnits()) { const UnitInfo & ui(kv.second); BWAPI::UnitType type = ui.type; // if the unit is a building if (type.isBuilding()) { // update the enemy occupied regions updateOccupiedRegions(BWTA::getRegion(BWAPI::TilePosition(ui.lastPosition)), BWAPI::Broodwar->enemy()); } if (type.isResourceDepot()) { ++enemyBaseCount; } if (type == BWAPI::UnitTypes::Zerg_Sunken_Colony){ ++enemySunkenCount; } } if (_mainBaseLocations[_enemy]){ if (BWAPI::Broodwar->isExplored(_mainBaseLocations[_enemy]->getTilePosition()) && !_scoutTimer) _scoutTimer = BWAPI::Broodwar->getFrameCount() + 100; } if (enemyBaseCount > 1 && BWAPI::Broodwar->getFrameCount() < _scoutTimer){ _enemyExpand = true; } if (enemySunkenCount > 1){ Config::Micro::UseSparcraftSimulation = true; } // for each of our units for (const auto & kv : _unitData[_self].getUnits()) { const UnitInfo & ui(kv.second); BWAPI::UnitType type = ui.type; // if the unit is a building if (type.isBuilding()) { // update the enemy occupied regions updateOccupiedRegions(BWTA::getRegion(BWAPI::TilePosition(ui.lastPosition)), BWAPI::Broodwar->self()); } } }
// Get a sunken position depending on whether or not we have an expansion. BWAPI::TilePosition BuildingManager::getSunkenPosition() { BWAPI::UnitType sunk = BWAPI::UnitTypes::Zerg_Creep_Colony; // Always make sunkens at natural expansion if you can. if (createdHatcheriesSet.size() >= 1) { BWAPI::TilePosition hatchPosition = createdHatcheriesVector[0]; BWAPI::Unit pExpansion = BWAPI::Broodwar->getClosestUnit(BWAPI::Position(hatchPosition), BWAPI::Filter::IsResourceDepot); BWAPI::Unitset myUnits = pExpansion->getUnitsInRadius(200); BWAPI::UnitType larva = BWAPI::UnitTypes::Zerg_Larva; BWAPI::UnitType egg = BWAPI::UnitTypes::Zerg_Egg; std::set<BWAPI::TilePosition> stuffBlocking; for (BWAPI::Unit p : myUnits) { if (p->getType() == larva || p->getType() == egg) { stuffBlocking.insert(p->getTilePosition()); } } while (buildableSunkenTilePositions.size() >= 1) { std::set<BWAPI::TilePosition>::iterator it = buildableSunkenTilePositions.begin(); BWAPI::TilePosition mySunkPosition = *it; Building z(sunk, mySunkPosition); if (!isCreepStarted()) { if (BWAPI::Broodwar->hasCreep(mySunkPosition) && createdBuilding.find(mySunkPosition) == createdBuilding.end() && stuffBlocking.find(mySunkPosition) == stuffBlocking.end()) { return *it; } else { buildableSunkenTilePositions.erase(*it); } } else { if (BWAPI::Broodwar->hasCreep(mySunkPosition) && BuildingPlacer::Instance().canBuildHere(mySunkPosition, z) && createdBuilding.find(mySunkPosition) == createdBuilding.end() && stuffBlocking.find(mySunkPosition) == stuffBlocking.end()) { return *it; } else { buildableSunkenTilePositions.erase(*it); } } } //BWAPI::Position hatchPositionBWP = BWAPI::Position(hatchPosition); BWAPI::TilePosition sunkPosition; const std::set<BWTA::BaseLocation*, std::less<BWTA::BaseLocation*>> locations = BWTA::getBaseLocations(); BWTA::BaseLocation *myLocation; for (BWTA::BaseLocation *p : locations) { BWAPI::TilePosition z = p->getTilePosition(); if (z == hatchPosition){ // This is the BWTA::Location of the first hatchery. myLocation = p; } } // Get the set of mineral patches closest to BWTA::Location of the hatchery(it will return like 8 mineral patches usually in the set) const BWAPI::Unitset mineralSet = myLocation->getMinerals(); //const std::set<BWAPI::Unit*> mineralSet = myLocation->getMinerals(); int counter3 = 0; int theX = 0; int theY = 0; for (BWAPI::Unit p : mineralSet) { // Calculate the difference between LeftMostMineralPatch.x - ExpansionHatchery.x and store it in theX theX = p->getTilePosition().x - hatchPosition.x; // Calculate the difference between LeftMostMineralPatch.y - ExpansionHatchery.y and store it in theY theY = p->getTilePosition().y - hatchPosition.y; break; } int gasX = 0; int gasY = 0; int counter4 = 0; //Get all geysers near the expansion -- it should only return 1 for every map we play.. const BWAPI::Unitset gasSet = myLocation->getGeysers(); for (BWAPI::Unit p : gasSet) { // Calculate the difference between Geyser.x- ExpansionHatchery.x and store it in gasX gasX = p->getTilePosition().x - hatchPosition.x; // Calculate the difference between Geyser.y- ExpansionHatchery.y and store it in gasY gasY = p->getTilePosition().y - hatchPosition.y; break; } int newx, newy; int outercounter = 0; int counter = 0; newx = hatchPosition.x; newy = hatchPosition.y; int beginX = hatchPosition.x; int beginY = hatchPosition.y; //sunkPosition = BWAPI::TilePosition(newx, newy); //test4 = BuildingPlacer::Instance().canBuildHere(sunkPosition, b); // Form a new sunken position that starts at the hatchery positive. std::vector<bool> incrementDecrement(8); bool useGasX = false; bool useGasY = false; bool useMinX = false; bool useMinY = false; if (abs(gasX) > abs(gasY)) { useGasX = true; } else { useGasY = true; } if (abs(theX) > abs(theY)) { useMinX = true; } else { useMinY = true; } // Gas differences is probably more reliable than mineral differences. if (useGasX && useMinX) { useMinX = false; useMinY = true; } // Gas differences is probably more reliable than mineral differences. if (useGasY && useMinY) { useMinY = false; useMinX = true; } // This is where we decide which directions we can make sunkens in // It is based on X and Y differences in LeftMostMineral - Hatchery and Geyser - Hatchery // It is not very good right now because we only use two variables. We should use four variables for better dection : theX, theY, gasX, gasY // If the difference between LeftMostMineral.y - Hatchery.y is negative : It means the mierals are North of the hatchery // If the difference between Geyser.X - Hatchery.X is negative : It means that the geyser is Left of the Hatchery if (useMinY && useGasX) { if (theY < 0 && gasX < 0) { /* Allow the following directions for sunken to be built : Increase X & Keep Y the same (East) Increase X & Increase Y (Go South East) Decrease X & Increase Y (Go South West) Keep X Same, Increase Y (Go South) Go NORTHEAST **Test** */ incrementDecrement = { true, false, true, true, false, false, true, false }; } // If the difference between LeftMostMineral.y - Hatchery.y is positive : It means the mierals are South of the hatchery // If the difference between Geyser.X - Hatchery.X is negative : It means that the geyser is Left of the Hatchery else if (gasX < 0 && theY > 0) { /* Allow the following directions for sunken to be built : Increase X & Keep Y the same (East) Increase X & Decrease Y (Go North East) Decrease X & Decrease Y (Go North West) Keep X Same, Decrease Y (Go North) GO SOUTHEAST --> Test */ incrementDecrement = { false, true, true, false, true, false, false, true }; } // If the difference between LeftMostMineral.y - Hatchery.y is negative : It means the mierals are North of the hatchery // If the difference between Geyser.X - Hatchery.X is positive : It means that the geyser is Right or East of the Hatchery else if (gasX > 0 && theY < 0) { /* Allow the following directions for sunken to be built : Decrease X & Keep Y the same (West) Decrease X & Increase Y (Go South West) Increase X & Increase Y (Go South East) Keep X Same, Increase Y (Go South) Go Northwest */ incrementDecrement = { true, false, false, true, false, true, true, false }; } // If the difference between LeftMostMineral.y - Hatchery.y is positive : It means the mierals are South of the hatchery // If the difference between Geyser.X - Hatchery.X is positive : It means that the geyser is Right or East of the Hatchery else if (theY > 0 && gasX > 0) { /* Decrease X & Keep Y the same (West) Decrease X & Decrease Y (Go North West) Increase X & Decrease Y (Go North East) Don't change X Decrease y (Go North) Go Southwest */ incrementDecrement = { false, true, false, false, true, true, false, true }; } } else if (useMinX && useGasY) { // If the difference between LeftMostMineral.x - Hatchery.x is positive : It means the mierals are East of the hatchery // If the difference between Geyser.Y - Hatchery.Y is negative : It means that the geyser is North of the Hatchery if (gasY < 0 && theX > 0) { /* Decrease X(Go West) Increase Y(Go South) Decrease X, Increase Y(Go South West) Decrease X, Decrease Y(Go North West) I think can try SouthEast ? */ incrementDecrement = { false, false, false, true, true, true, true, false }; } // If the difference between LeftMostMineral.x - Hatchery.x is positive : It means the mierals are East of the hatchery // If the difference between Geyser.Y - Hatchery.Y is positive : It means that the geyser is South of the Hatchery else if (theX > 0 && gasY > 0) { /* Decrease X(Go West) Decrease Y(Go North) Decrease X, INcrease Y(Go SOuth West) Decrease X, Decrease Y(Go North West) I think can try NOrthEast? */ incrementDecrement = { false, false, false, true, true, true, false, true }; } // If the difference between LeftMostMineral.x - Hatchery.x is negative : It means the minerals are West of the hatchery // If the difference between Geyser.Y - Hatchery.Y is negative : It means that the geyser is North of the Hatchery else if (gasY < 0 && theX < 0) { /* Increase X(Go East) Increase Y(Go South) Increase X, Increase Y(Go South East) Increase X, Decrease Y(Go North East) I think maybe Southwest is okay?.. Even NW might be okay */ incrementDecrement = { true, true, true, false, false, false, true, false }; } // If the difference between LeftMostMineral.x - Hatchery.x is negative : It means the minerals are West of the hatchery // If the difference between Geyser.Y - Hatchery.Y is positive : It means that the geyser is South of the Hatchery else if (gasY > 0 && theX < 0) { incrementDecrement = { true, true, true, false, false, false, false, true }; /* Increase X(Go East) Decrease Y(Go North) Increase X, Increase Y(Go South East) Increase X, Decrease Y(Go North East) I think maybe Northwest is okay? */ } } beginX = hatchPosition.x; beginY = hatchPosition.y; std::vector<std::pair<int, int> > myVec; std::pair<int, int> p1; for (int i = 0; i < 8; i++) { if (incrementDecrement[i]) { if (i == 0) { p1.first = 1; p1.second = 1; } else if (i == 1) { p1.first = 1; p1.second = -1; } else if (i == 2) { p1.first = 1; p1.second = 0; } else if (i == 3) { p1.first = -1; p1.second = 1; } else if (i == 4) { p1.first = -1; p1.second = -1; } else if (i == 5) { p1.first = -1; p1.second = 0; } else if (i == 6) { p1.first = 0; p1.second = 1; } else if (i == 7) { p1.first = 0; p1.second = -1; } myVec.push_back(p1); } } for (int i = 0; i < 30; i++) for (int j = 0; j < 30; j++) for (int k = 0; k < 30; k++) for (int l = 0; l < 30; l++) { int xChange = beginX; int yChange = beginY; xChange += i * myVec[0].first; yChange += i * myVec[0].second; xChange += j * myVec[1].first; yChange += j * myVec[1].second; xChange += k * myVec[2].first; yChange += k * myVec[2].second; xChange += l * myVec[3].first; yChange += l * myVec[3].second; /* if (beginX + 1 == xChange) { if (yChange == beginY) { BWAPI::Broodwar->printf("%d", xChange); } } */ sunkPosition = BWAPI::TilePosition(xChange, yChange); Building b(sunk, sunkPosition); if (!isCreepStarted()) { if (BWAPI::Broodwar->hasCreep(sunkPosition) && stuffBlocking.find(sunkPosition) == stuffBlocking.end() && createdBuilding.find(sunkPosition) == createdBuilding.end()) { buildableSunkenTilePositions.insert(sunkPosition); } } else { if (BWAPI::Broodwar->hasCreep(sunkPosition) && BuildingPlacer::Instance().canBuildHere(sunkPosition, b) && stuffBlocking.find(sunkPosition) == stuffBlocking.end() && createdBuilding.find(sunkPosition) == createdBuilding.end()) { buildableSunkenTilePositions.insert(sunkPosition); } } } if (buildableSunkenTilePositions.size() != 0) { std::set<BWAPI::TilePosition>::iterator it = buildableSunkenTilePositions.begin(); return *it; } else { return BWAPI::TilePositions::None; } } }
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; } } } }
BWAPI::TilePosition BuildingPlacer::getBuildLocationNear(const Building & b, int buildDist, bool horizontalOnly) const { SparCraft::Timer t; t.start(); BWTA::BaseLocation *home = findHome(); BWAPI::TilePosition chokeTile = findChoke(home); int homex = home->getTilePosition().x; int homey = home->getTilePosition().y; int midx = (chokeTile.x + homex) / 2; int midy = (chokeTile.y + homey) / 2; static int px = midx; static int py = midy; // 1 if choke farther right, -1 if farther left int ix = chokeTile.x > midx ? 1 : -1; // 1 if choke farther south, -1 if farther north int iy = chokeTile.y < midy ? -1 : 1; // get the precomputed vector of tile positions which are sorted closes to this location const std::vector<BWAPI::TilePosition> & closestToBuilding = MapTools::Instance().getClosestTilesTo(BWAPI::Position(b.desiredPosition)); double ms1 = t.getElapsedTimeInMilliSec(); // special easy case of having no pylons int numPylons = BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Protoss_Pylon); int numGate = BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Protoss_Gateway); int numCan = BWAPI::Broodwar->self()->completedUnitCount(BWAPI::UnitTypes::Protoss_Photon_Cannon); if (b.type.requiresPsi() && numPylons == 0) { return BWAPI::TilePositions::None; } if (BWAPI::Broodwar->mapName().compare(1,9,"Andromeda")) { if (b.type == BWAPI::UnitTypes::Protoss_Pylon && numPylons == 0) { BWAPI::TilePosition pos = drawPylon(midx, midy, ix, iy, b); if (pos != BWAPI::TilePositions::None) { px = pos.x; py = pos.y; return pos; } } else if (b.type == BWAPI::UnitTypes::Protoss_Forge) { BWAPI::TilePosition pos = drawForge(midx, midy, ix, iy, b); if (pos != BWAPI::TilePositions::None) { return pos; } } else if (b.type == BWAPI::UnitTypes::Protoss_Photon_Cannon) { BWAPI::TilePosition pos = drawProtonCannon(homex, homey, ix, iy, b); if (pos != BWAPI::TilePositions::None) { return pos; } } //else if (b.type == BWAPI::UnitTypes::Protoss_Gateway && numGate == 0) { // return drawGateway(homex, homey, ix, iy, b); //} } // iterate through the list until we've found a suitable location for (size_t i(0); i < closestToBuilding.size(); ++i) { if (b.type == BWAPI::UnitTypes::Protoss_Gateway && numGate == 0) { buildDist = 0; } if (canBuildHereWithSpace(closestToBuilding[i], b, buildDist, horizontalOnly)) { double ms = t.getElapsedTimeInMilliSec(); //BWAPI::Broodwar->printf("Building Placer Took %d iterations, lasting %lf ms @ %lf iterations/ms, %lf setup ms", i, ms, (i / ms), ms1); return closestToBuilding[i]; } } double ms = t.getElapsedTimeInMilliSec(); //BWAPI::Broodwar->printf("Building Placer Took %lf ms", ms); return BWAPI::TilePositions::None; }
// STEP 6: CHECK FOR COMPLETED BUILDINGS void BuildingManager::checkForCompletedBuildings() { std::vector<Building> toRemove; // for each of our buildings under construction for (auto & b : _buildings) { if (b.status != BuildingStatus::UnderConstruction) { continue; } // if the unit has completed if (b.buildingUnit->isCompleted()) { if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Zerg) { if (b.buildingUnit->getType() == BWAPI::UnitTypes::Zerg_Creep_Colony) { //b.buildingUnit->upgrade(b.buildingUnit->getUpgrade()); //b.buildingUnit->buildAddon(BWAPI::UnitTypes::Zerg_Sunken_Colony); // MAKE SUNKEN //b.buildingUnit->morph(BWAPI::UnitTypes::Zerg_Sunken_Colony); //MetaType type(BWAPI::UnitTypes::Zerg_Sunken_Colony); //ProductionManager::Instance()._queue.queueAsHighestPriority(type, true); } if (b.buildingUnit->getType() == BWAPI::UnitTypes::Zerg_Hatchery) { MetaType type(BWAPI::UnitTypes::Zerg_Creep_Colony); ProductionManager::Instance()._queue.queueAsHighestPriority(type, true); createdHatchery = true; } /* for (BWAPI::Unit p : BWAPI::Broodwar->self()->getUnits()) { if (!madeFirstSunken && p->getType().isWorker() && p->getPosition() == firstHatcheryPosition) { //BWAPI::Position tempPosition; //tempPosition.x = b.finalPosition.x + 3; //tempPosition.y = b.finalPosition.y + 3; /* BWAPI::TilePosition sunkPos = getSunkenPosition(); createdSunkenSet.insert(sunkPos); createdSunkenVector.push_back(sunkPos); createdBuilding.insert(sunkPos); p->build(BWAPI::UnitTypes::Zerg_Hatchery, sunkPos); madeFirstSunken = true; BWAPI::TilePosition sunkPos2 = getSunkenPosition(); createdSunkenSet.insert(sunkPos2); createdSunkenVector.push_back(sunkPos2); createdBuilding.insert(sunkPos2); p->build(BWAPI::UnitTypes::Zerg_Hatchery, sunkPos2); //b.builderUnit->build(b.type, b.finalPosition); break; //candidateProducers.insert(p); } } } */ } // if we are terran, give the worker back to worker manager if (BWAPI::Broodwar->self()->getRace() == BWAPI::Races::Terran) { if (b.isGasSteal) { ScoutManager::Instance().setWorkerScout(b.builderUnit); } // otherwise tell the worker manager we're finished with this unit else { WorkerManager::Instance().finishedWithWorker(b.builderUnit); } } // remove this unit from the under construction vector toRemove.push_back(b); } else { if (b.type == 131 && b.buildingUnit->getHitPoints() >= 1050 && !sentFirstDroneForSunken) { BWAPI::UnitType sunk = BWAPI::UnitTypes::Zerg_Creep_Colony; Building z(sunk, createdHatcheriesVector[0]); BWAPI::Unit workerToAssign = WorkerManager::Instance().getBuilder(z); BWAPI::Unit workerToAssign2 = WorkerManager::Instance().getBuilder(z); const std::set<BWTA::BaseLocation*, std::less<BWTA::BaseLocation*>> locations = BWTA::getBaseLocations(); BWTA::BaseLocation *myLocation; for (BWTA::BaseLocation *p : locations) { BWAPI::TilePosition z = p->getTilePosition(); if (z == createdHatcheriesVector[0]){ // This is the BWTA::Location of the first hatchery. myLocation = p; } } // Get the set of mineral patches closest to BWTA::Location of the hatchery(it will return like 8 mineral patches usually in the set) const BWAPI::Unitset mineralSet = myLocation->getMinerals(); BWAPI::Unit myMineral; for (BWAPI::Unit p : mineralSet) { myMineral = p; break; } workerToAssign->gather(myMineral); workerToAssign2->gather(myMineral); sunkenUnit = workerToAssign; sunkenUnit2 = workerToAssign2; sentFirstDroneForSunken = true; } int x = 0; } } removeBuildings(toRemove); }