//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; }