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); }
//ctx add BWAPI::TilePosition BuildingPlacer::getBuildLocationFarFromChokePoint(const Building & b, int buildDist, bool horizontalOnly, bool flag) const { SparCraft::Timer t; t.start(); BWAPI::TilePosition startTitlePos = BWAPI::Broodwar->self()->getStartLocation(); BWTA::Chokepoint *chokePoint = BWTA::getNearestChokepoint(startTitlePos); BWAPI::Position chokeCenterPosition = chokePoint->getCenter(); BWTA::Region *baseRegion = BWTA::getRegion(BWAPI::Broodwar->self()->getStartLocation()); BWTA::Polygon basePolygon = baseRegion->getPolygon(); BWAPI::Position farPosition = BWAPI::Position(0, 0); BWAPI::TilePosition resultPosition = BWAPI::TilePosition(0, 0); double dis = 0.0; for (int i = 0; i < (int)basePolygon.size(); i++) { BWAPI::Position point = basePolygon[i]; double ms1 = t.getElapsedTimeInMilliSec(); if (point.getDistance(chokeCenterPosition) > dis) { dis = point.getDistance(chokeCenterPosition); farPosition = point; } } const std::vector<BWAPI::TilePosition> & closestToBuilding = MapTools::Instance().getClosestTilesTo(BWAPI::Position(b.desiredPosition)); //get best solution dis = farPosition.getDistance(BWAPI::Position(startTitlePos)); if (flag == true) { for (size_t i = 0; i < closestToBuilding.size(); ++i) { double ms1 = t.getElapsedTimeInMilliSec(); if (canBuildHereWithSpace(closestToBuilding[i], b, buildDist, horizontalOnly) && dis > farPosition.getDistance(BWAPI::Position(closestToBuilding[i]))) { resultPosition = closestToBuilding[i]; break; //return closestToBuilding[i]; } } } else { for (size_t i = 0; i < closestToBuilding.size(); ++i) { double ms1 = t.getElapsedTimeInMilliSec(); if (canBuildHereWithSpace(closestToBuilding[i], b, buildDist, horizontalOnly) && dis < farPosition.getDistance(BWAPI::Position(closestToBuilding[i]))) { resultPosition = closestToBuilding[i]; break; //return closestToBuilding[i]; } } } if (!basePolygon.isInside(BWAPI::Position(resultPosition))) { resultPosition = getBuildLocationNear(b, buildDist, horizontalOnly); } return resultPosition; }
void ProductionManager::buildBunker() { BWAPI::Position base = BWAPI::Position(BWAPI::Broodwar->self()->getStartLocation()); BWTA::Chokepoint *entrance = BWTA::getNearestChokepoint(base); MetaType bunker = MetaType(BWAPI::UnitTypes::Terran_Bunker); BWAPI::Unit producer = ProductionManager::Instance().getProducer(bunker, entrance->getCenter()); int numBarracks = BWAPI::Broodwar->self()->allUnitCount(BWAPI::UnitTypes::Terran_Barracks); bool canMake = canMakeNow(producer, bunker); Building b(bunker.getUnitType(), BWAPI::TilePosition(entrance->getCenter())); b.isGasSteal = false; // set the producer as the closest worker, but do not set its job yet producer = WorkerManager::Instance().getBuilder(b, false); // get a possible building location for the building if (!_haveLocationForThisBuilding) { _predictedTilePosition = BuildingManager::Instance().getBuildingLocation(b); } if (_predictedTilePosition != BWAPI::TilePositions::None) { _haveLocationForThisBuilding = true; } if (producer && canMake && (numBarracks > 0)) { // create it create(producer, BuildOrderItem(bunker, 1, true)); _assignedWorkerForThisBuilding = false; _haveLocationForThisBuilding = false; // draw a box where the building will be placed int x1 = _predictedTilePosition.x * 32; int x2 = x1 + (b.type.tileWidth()) * 32; int y1 = _predictedTilePosition.y * 32; int y2 = y1 + (b.type.tileHeight()) * 32; if (Config::Debug::DrawWorkerInfo) { BWAPI::Broodwar->drawBoxMap(x1, y1, x2, y2, BWAPI::Colors::Blue, false); } // where we want the worker to walk to BWAPI::Position walkToPosition = BWAPI::Position(x1 + (b.type.tileWidth() / 2) * 32, y1 + (b.type.tileHeight() / 2) * 32); // compute how many resources we need to construct this building int mineralsRequired = std::max(0, b.type.mineralPrice() - getFreeMinerals()); int gasRequired = std::max(0, b.type.gasPrice() - getFreeGas()); // get a candidate worker to move to this location BWAPI::Unit moveWorker = WorkerManager::Instance().getMoveWorker(walkToPosition); // Conditions under which to move the worker: // - there's a valid worker to move // - we haven't yet assigned a worker to move to this location // - the build position is valid // - we will have the required resources by the time the worker gets there if (moveWorker && _haveLocationForThisBuilding && !_assignedWorkerForThisBuilding && (_predictedTilePosition != BWAPI::TilePositions::None) && WorkerManager::Instance().willHaveResources(mineralsRequired, gasRequired, moveWorker->getDistance(walkToPosition))) { // we have assigned a worker _assignedWorkerForThisBuilding = true; // tell the worker manager to move this worker WorkerManager::Instance().setMoveWorker(mineralsRequired, gasRequired, walkToPosition); } } }