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(); }
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 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); }
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; }
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()); } } }
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; } }