BWAPI::TilePosition BuildingPlacer::getBuildLocationNear(const Building & b, int buildDist, bool horizontalOnly) const { SparCraft::Timer t; t.start(); // 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); if (b.type.requiresPsi() && numPylons == 0) { return BWAPI::TilePositions::None; } // iterate through the list until we've found a suitable location for (size_t i(0); i < closestToBuilding.size(); ++i) { 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; }
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; }
BWAPI::TilePosition BuildingPlacer::getBuildLocationNear(const Building & b, int buildDist, bool inRegionPriority, bool horizontalOnly) const { //returns a valid build location near the specified tile position. //searches outward in a spiral. int x = b.desiredPosition.x; int y = b.desiredPosition.y; int length = 1; int j = 0; bool first = true; int dx = 0; int dy = 1; SparCraft::Timer t; t.start(); int iter = 0; int buildingPlacerTimeLimit = 2000; while (length < BWAPI::Broodwar->mapWidth()) //We'll ride the spiral to the end { if (t.getElapsedTimeInMilliSec() > buildingPlacerTimeLimit) { if (Options::Debug::DRAW_UALBERTABOT_DEBUG) { BWAPI::Broodwar->printf("Building Placer Timed Out %d ms", buildingPlacerTimeLimit); } return BWAPI::TilePositions::None; } //if we can build here, return this tile position if (x >= 0 && x < BWAPI::Broodwar->mapWidth() && y >= 0 && y < BWAPI::Broodwar->mapHeight()) { iter++; // can we build this building at this location bool canBuild = this->canBuildHereWithSpace(BWAPI::TilePosition(x, y), b, buildDist, horizontalOnly); // my starting region BWTA::Region * myRegion = BWTA::getRegion(BWTA::getStartLocation(BWAPI::Broodwar->self())->getTilePosition()); // the region the build tile is in BWTA::Region * tileRegion = BWTA::getRegion(BWAPI::TilePosition(x,y)); // is the proposed tile in our region? bool tileInRegion = (tileRegion == myRegion); // if this location has priority to be built within our own region if (inRegionPriority) { // if the tile is in region and we can build it there if (tileInRegion && canBuild) { if (Options::Debug::DRAW_UALBERTABOT_DEBUG) { //BWAPI::Broodwar->printf("Building Placer Took %lf ms", t.getElapsedTimeInMilliSec()); } // return that position return BWAPI::TilePosition(x, y); } } // otherwise priority is not set for this building else { if (canBuild) { if (Options::Debug::DRAW_UALBERTABOT_DEBUG) { //BWAPI::Broodwar->printf("Building Placer Took %lf ms", t.getElapsedTimeInMilliSec()); } return BWAPI::TilePosition(x, y); } } } //otherwise, move to another position x = x + dx; y = y + dy; //count how many steps we take in this direction j++; if (j == length) //if we've reached the end, its time to turn { //reset step counter j = 0; //Spiral out. Keep going. if (!first) length++; //increment step counter if needed //first=true for every other turn so we spiral out at the right rate first =! first; //turn counter clockwise 90 degrees: if (dx == 0) { dx = dy; dy = 0; } else { dy = -dx; dx = 0; } } //Spiral out. Keep going. } return BWAPI::TilePositions::None; }
//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; }
BWAPI::TilePosition BuildingPlacer::getBuildLocationNear(const Building & b, int buildDist, int timeLimitMS, bool inRegionPriority, bool horizontalOnly) const { struct SearchState{ int _length; int _j; bool _first; int _dx; int _dy; int _x; int _y; bool _timeOut; BWAPI::TilePosition _candidatePos; SearchState(int length, int j, bool first, int dx, int dy, int x, int y, bool timeOut = false, BWAPI::TilePosition candidatePos = BWAPI::TilePositions::None) : _length(length), _j(j), _first(first), _dx(dx), _dy(dy), _x(x), _y(y), _timeOut(timeOut), _candidatePos(candidatePos) {} SearchState() :_timeOut(false), _candidatePos(BWAPI::TilePositions::None) {} }; struct SearchParams{ Building _b; int _buildDist; bool _inRegionPriority; bool _horizontalOnly; SearchParams(const Building & b, int buildDist, bool inRegionPriority, bool horizontalOnly): _b(b), _buildDist(buildDist), _inRegionPriority(inRegionPriority), _horizontalOnly(horizontalOnly) {} SearchParams() {} bool operator==(const SearchParams& other) { return _b.type == other._b.type && _b.desiredPosition == other._b.desiredPosition&& _b.builderUnit == other._b.builderUnit&& _buildDist == other._buildDist&& _inRegionPriority == other._inRegionPriority&& _horizontalOnly == other._horizontalOnly; } }; if (timeLimitMS <= 0) { throw std::runtime_error("Building Placer not given any time: "+timeLimitMS); } static SearchState lastState; static SearchParams lastParams; SearchState state(1, 0, true, 0, 1, b.desiredPosition.x, b.desiredPosition.y); SearchParams params(b, buildDist, inRegionPriority, horizontalOnly); if (lastState._timeOut && lastParams == params) { state = lastState; //BWAPI::Broodwar->printf("Building Placer for building %s resuming... %d",b.type.getName().c_str(),state._length); //Logger::LogAppendToFile(UAB_LOGFILE, "Building Placer for building %s resuming... %d\n", b.type.getName().c_str(), state._length); } SparCraft::Timer t; t.start(); // my starting region //BWTA::Region * myRegion = BWTA::getRegion(BWTA::getStartLocation(BWAPI::Broodwar->self())->getTilePosition()); BWTA::Region * myRegion = BWTA::getRegion(b.desiredPosition); //get max spiral size int maxDist = 0; for (auto point : myRegion->getPolygon()) { int radius = std::ceil((BWAPI::TilePosition(point) - b.desiredPosition).getLength()); if (radius > maxDist) { maxDist = radius; } } while (state._length < maxDist || (state._length <BWAPI::Broodwar->mapWidth() && state._candidatePos == BWAPI::TilePositions::None)) //We'll ride the spiral to the end { if (t.getElapsedTimeInMilliSec() > timeLimitMS) { if (Options::Debug::DRAW_UALBERTABOT_DEBUG && !state._timeOut) { //BWAPI::Broodwar->printf("Building Placer Timed Out at %d ms on building %s", timeLimitMS, b.type.getName().c_str()); //Logger::LogAppendToFile(UAB_LOGFILE, "Building Placer Timed Out at %d ms on building %s\n", timeLimitMS, b.type.getName().c_str()); } lastState = state; lastState._timeOut = true; lastParams = params; throw std::runtime_error("Building Placer Timed Out. State saved for resuming later."); } //if we can build here, return this tile position if (state._x >= 0 && state._x < BWAPI::Broodwar->mapWidth() && state._y >= 0 && state._y < BWAPI::Broodwar->mapHeight()) { // can we build this building at this location bool canBuild = this->canBuildHereWithSpace(BWAPI::TilePosition(state._x, state._y), b, buildDist, horizontalOnly); if (canBuild) { // if this location has priority to be built within our own region if (inRegionPriority) { // the region the build tile is in BWTA::Region * tileRegion = BWTA::getRegion(BWAPI::TilePosition(state._x, state._y)); // is the proposed tile in our region? bool tileInRegion = (tileRegion == myRegion); // if the tile is in region and we can build it there if (tileInRegion) { if (Options::Debug::DRAW_UALBERTABOT_DEBUG) { //BWAPI::Broodwar->printf("Building Placer Took %lf ms", t.getElapsedTimeInMilliSec()); //BWAPI::Broodwar->printf("Building position found in region"); //Logger::LogAppendToFile(UAB_LOGFILE, "Building position found in region\n"); } // return that position lastState._timeOut = false; return BWAPI::TilePosition(state._x, state._y); } else if (state._candidatePos==BWAPI::TilePositions::None)//save an out of region position as candidate { if (Options::Debug::DRAW_UALBERTABOT_DEBUG) { //BWAPI::Broodwar->printf("Saving position found not in region"); //Logger::LogAppendToFile(UAB_LOGFILE, "Saving position found not in region\n"); } state._candidatePos = BWAPI::TilePosition(state._x, state._y); } } // otherwise priority is not set for this building else { if (Options::Debug::DRAW_UALBERTABOT_DEBUG) { //BWAPI::Broodwar->printf("Building Placer Took %lf ms", t.getElapsedTimeInMilliSec()); //BWAPI::Broodwar->printf("Building position found not in region"); //Logger::LogAppendToFile(UAB_LOGFILE, "Building position found not in region\n"); } lastState._timeOut = false; return BWAPI::TilePosition(state._x, state._y); } } } //otherwise, move to another position state._x = state._x + state._dx; state._y = state._y + state._dy; //count how many steps we take in this direction state._j++; if (state._j == state._length) //if we've reached the end, its time to turn { //reset step counter state._j = 0; //Spiral out. Keep going. if (!state._first) { state._length++; //increment step counter if needed } //first=true for every other turn so we spiral out at the right rate state._first = !state._first; //turn counter clockwise 90 degrees: if (state._dx == 0) { state._dx = state._dy; state._dy = 0; } else { state._dy = -state._dx; state._dx = 0; } } //Spiral out. Keep going. } lastState._timeOut = false; if (Options::Debug::DRAW_UALBERTABOT_DEBUG) { //BWAPI::Broodwar->printf("Rode spiral out. Building %s position: %d %d", b.type.getName().c_str(), state._candidatePos.x, state._candidatePos.y); //Logger::LogAppendToFile(UAB_LOGFILE, "Rode spiral out. Building %s position: %d %d\n", b.type.getName().c_str(), state._candidatePos.x, state._candidatePos.y); } return state._candidatePos; }
void ProductionManager::manageBuildOrderQueue(int timeLimitMS) { // if there is nothing in the queue, oh well if (queue.isEmpty()) { return; } SparCraft::Timer t; t.start(); // the current item to be used BuildOrderItem & currentItem = queue.getHighestPriorityItem(); // while there is still something left in the queue while (!queue.isEmpty()) { // this is the unit which can produce the currentItem BWAPI::UnitInterface* producer = getProducer(currentItem.metaType); // check to see if we can make it right now bool canMake = canMakeNow(producer, currentItem.metaType); // if we try to build too many refineries manually remove it if (currentItem.metaType.isRefinery() && (BWAPI::Broodwar->self()->allUnitCount(BWAPI::Broodwar->self()->getRace().getRefinery() >= 3))) { queue.removeCurrentHighestPriorityItem(); break; } // if the next item in the list is a building and we can't yet make it if (currentItem.metaType.isBuilding() && !(producer && canMake) && !currentItem.metaType.unitType.isAddon()) { // construct a temporary building object Building b(currentItem.metaType.unitType, BWAPI::Broodwar->self()->getStartLocation()); // set the producer as the closest worker, but do not set its job yet producer = WorkerManager::Instance().getBuilder(b, false); // predict the worker movement to that building location predictWorkerMovement(b, timeLimitMS - t.getElapsedTimeInMilliSec()); } // if we can make the current item if (producer && canMake) { // create it createMetaType(producer, currentItem.metaType); assignedWorkerForThisBuilding = false; haveLocationForThisBuilding = false; // and remove it from the queue queue.removeCurrentHighestPriorityItem(); // don't actually loop around in here break; } // otherwise, if we can skip the current item else if (queue.canSkipItem()) { // skip it queue.skipItem(); // and get the next one currentItem = queue.getNextHighestPriorityItem(); } else { // so break out break; } } }