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