TilePosition StructureAgent::getNextScanLocation() { TilePosition ePos = ExplorationManager::getInstance()->getClosestSpottedBuilding(Broodwar->self()->getStartLocation()); if (ePos.x() > -1) { //Already found enemy base return TilePosition(-1, -1); } for(set<BaseLocation*>::const_iterator i=getStartLocations().begin();i!=getStartLocations().end();i++) { TilePosition basePos = (*i)->getTilePosition(); bool needScan = true; //1. Check previous scans for (int i = 0; i < (int)hasScanned.size(); i++) { if (hasScanned.at(i).x() == basePos.x() && hasScanned.at(i).y() == basePos.y()) { needScan = false; } } //2. Check if we have this base vector<BaseAgent*> agents = AgentManager::getInstance()->getAgents(); for (int i = 0; i < (int)agents.size(); i++) { if (agents.at(i)->isAlive()) { double dist = basePos.getDistance(agents.at(i)->getUnit()->getTilePosition()); if (dist <= 10) { needScan = false; break; } } } //3. Check if enemy units are near for(set<Unit*>::const_iterator j=Broodwar->enemy()->getUnits().begin();j!=Broodwar->enemy()->getUnits().end();j++) { if ((*j)->exists()) { double dist = basePos.getDistance((*j)->getTilePosition()); if (dist <= 10) { needScan = false; break; } } } if (needScan) { return basePos; } } return TilePosition(-1, -1); }
void ExplorationManager::unitDestroyed(Unit* unit) { TilePosition uPos = unit->getTilePosition(); if (unit->getType().isBuilding()) { bool removed = false; for (int i = 0; i < (int)spottedBuildings.size(); i++) { TilePosition sPos = spottedBuildings.at(i)->getTilePosition(); if (uPos.x() == sPos.x() && uPos.y() == sPos.y()) { spottedBuildings.at(i)->setInactive(); removed = true; } } if (!removed) { //Broodwar->printf("[EM]: Building %s at (%d,%d) was not removed from EM!!!", unit->getType().getName().c_str(), uPos.x(), uPos.y()); } } else { for (int i = 0; i < (int)spottedUnits.size(); i++) { if (spottedUnits.at(i)->getUnitID() == unit->getID()) { spottedUnits.at(i)->setInactive(); //Broodwar->printf("[EM]: Remove %s at (%d,%d)", unit->getType().getName().c_str(), uPos.x(), uPos.y()); } } } }
bool PFManager::moveToGoal(BaseAgent* agent, TilePosition checkpoint, TilePosition goal) { if (checkpoint.x() == -1 || goal.x() == -1) return false; Unit* unit = agent->getUnit(); if (unit->isStartingAttack() || unit->isAttacking()) { return false; } Position toReach = Position(checkpoint); double distToReach = toReach.getDistance(unit->getPosition()); int engageDist = unit->getType().groundWeapon().maxRange(); if (agent->isOfType(UnitTypes::Terran_Medic)) { engageDist = 6 * 32; } if (engageDist <= 64) { engageDist = 64; } if (distToReach <= engageDist) { if (unit->isMoving()) unit->stop(); return true; } //Move if (!unit->isMoving()) return unit->attack(toReach); else return true; }
bool Squad::isVisible(TilePosition pos) { if (!ExplorationManager::canReach(Broodwar->self()->getStartLocation(), pos)) { return true; } if (Broodwar->isVisible(pos)) { return true; } if (getCenter().getDistance(pos) <= 3) { return true; } for (int i = 0; i < (int)hasVisited.size(); i++) { TilePosition vPos = hasVisited.at(i); if (vPos.x() == pos.x() && vPos.y() == pos.y()) { return true; } } return false; }
void UnitClass::drawUnitTilePosition() { TilePosition tile = getTilePosition(); BWAPI::UnitType type = getType(); Player player = getPlayer(); BWAPI::Broodwar->drawBox(BWAPI::CoordinateType::Map, tile.x()*32, tile.y()*32, (tile.x()+type.tileWidth())*32, (tile.y()+type.tileHeight())*32, player->getColor()); }
void CoverMap::blockPosition(TilePosition buildSpot) { if (buildSpot.x() == -1) { //Error check return; } cover_map[buildSpot.x()][buildSpot.y()] = BLOCKED; }
bool CoverMap::canBuildAt(UnitType toBuild, TilePosition pos) { int maxW = w - toBuild.tileWidth() - 1; int maxH = h - toBuild.tileHeight() - 1; //Out of bounds check if (pos.x() >= 0 && pos.x() < maxW && pos.y() >= 0 && pos.y() < maxH) { if (canBuild(toBuild, pos)) { return true; } } return false; }
bool Commander::isOccupied(BWTA::Region* region) { BWTA::Polygon p = region->getPolygon(); vector<BaseAgent*> agents = AgentManager::getInstance()->getAgents(); for (int i = 0; i < (int)agents.size(); i++) { BaseAgent* agent = agents.at(i); if (agent->isAlive() && agent->getUnitType().isResourceDepot()) { BWTA::Region* aRegion = getRegion(agents.at(i)->getUnit()->getTilePosition()); Position c1 = region->getCenter(); Position c2 = aRegion->getCenter(); if (c2.x() == c1.x() && c2.y() == c1.y()) { return true; } } } //Check expansion site TilePosition expansionSite = ExplorationManager::getInstance()->getExpansionSite(); TilePosition center = TilePosition(region->getCenter()); if (expansionSite.x() >= 0) { double dist = expansionSite.getDistance(center); if (dist <= 15) { return true; } } return false; }
void UnitClass::build(TilePosition target, BWAPI::UnitType type) { if(exists()) { const Position targetPosition(target.x()*32+type.tileWidth()*16, target.y()*32+type.tileHeight()*16); if(getDistance(type, targetPosition) > 48 || !MapHelper::isAllVisible(target, type)) { move(targetPosition, 0); return; } if(mUnit->getOrder() == BWAPI::Orders::PlaceBuilding) { if(mUnit->getBuildType() == type && mUnit->getOrderTargetPosition() == targetPosition) return; } if(mUnit->getLastCommand().getType() == BWAPI::UnitCommandTypes::Build && mUnit->getLastCommand().getUnitType() == type && mUnit->getLastCommand().getTargetTilePosition() == target) { if(mLastOrderExecuteTime >= BWAPI::Broodwar->getFrameCount()) return; } if(mUnit->build(target, type)) mLastOrderExecuteTime = BWAPI::Broodwar->getFrameCount() + BWAPI::Broodwar->getRemainingLatencyFrames(); else move(targetPosition, 0); } }
void Squad::removeMember(BaseAgent* agent) { //Step 1. Remove the agent instance for (int i = 0; i < (int)agents.size(); i++) { if (agents.at(i)->getUnitID() == agent->getUnitID()) { agents.at(i)->setSquadID(-1); agents.at(i)->assignToDefend(); agents.erase(agents.begin() + i); break; } } //Step 2. Update the setup list for (int i = 0; i < (int)setup.size(); i++) { if (setup.at(i).equals(agent->getUnitType())) { setup.at(i).current--; } } //Step 3. If Explorer, set destination as explored (to avoid being killed at the same //place over and over again). if (isExplorer()) { TilePosition goal = agent->getGoal(); if (goal.x() >= 0) { ExplorationManager::Instance().setExplored(goal); } } }
TilePosition ExplorationManager::scanForVulnerableBase() { TilePosition spot = TilePosition(-1, -1); for (int i = 0; i < (int)spottedBuildings.size(); i++) { if (spottedBuildings.at(i)->isActive()) { SpottedObject* obj = spottedBuildings.at(i); if (obj->getType().isResourceDepot()) { if (!isDetectorCovering(obj->getTilePosition())) { //Broodwar->printf("Found probable vulnerable base at (%d,%d)", obj->getTilePosition().x(), obj->getTilePosition().y()); spot = obj->getTilePosition(); } } } } if (spot.x() < 0) { //Broodwar->printf("Scan: No vulnerable base found"); } return spot; }
TilePosition CoverMap::findBuildSpot(UnitType toBuild, TilePosition start) { //Check start pos if (canBuildAt(toBuild, start)) return start; //Search outwards bool found = false; int cDiff = 1; TilePosition spot = TilePosition(-1, -1); while (!found) { //Top TilePosition s = TilePosition(start.x() - cDiff, start.y() - cDiff); TilePosition e = TilePosition(start.x() + cDiff, start.y() - cDiff); spot = findSpotAtSide(toBuild, s, e); if (spot.x() != -1 && spot.y() != -1) { found = true; break; } //Bottom s = TilePosition(start.x() - cDiff, start.y() + cDiff); e = TilePosition(start.x() + cDiff, start.y() + cDiff); spot = findSpotAtSide(toBuild, s, e); if (spot.x() != -1 && spot.y() != -1) { found = true; break; } //Left s = TilePosition(start.x() - cDiff, start.y() - cDiff); e = TilePosition(start.x() - cDiff, start.y() + cDiff); spot = findSpotAtSide(toBuild, s, e); if (spot.x() != -1 && spot.y() != -1) { found = true; break; } //Right s = TilePosition(start.x() + cDiff, start.y() - cDiff); e = TilePosition(start.x() + cDiff, start.y() + cDiff); spot = findSpotAtSide(toBuild, s, e); if (spot.x() != -1 && spot.y() != -1) { found = true; break; } cDiff++; if (cDiff > range) found = true; } return spot; }
TilePosition Commander::findChokePoint() { //First, check the DefenseLocator //for a stored defense position. DefenseLocator* df = DefenseLocator::getInstance(); TilePosition storedPos = df->getBaseDefensePos(Broodwar->mapHash()); if (storedPos.x() != -1) return storedPos; double bestPrio = -1; Chokepoint* bestChoke = NULL; for(set<BWTA::Region*>::const_iterator i=getRegions().begin();i!=getRegions().end();i++) { if (isOccupied((*i))) { for(set<Chokepoint*>::const_iterator c=(*i)->getChokepoints().begin();c!=(*i)->getChokepoints().end();c++) { if (isEdgeChokepoint((*c))) { double cPrio = getChokepointPrio(TilePosition((*c)->getCenter())); if (cPrio > bestPrio) { bestPrio = cPrio; bestChoke = (*c); } } } } } TilePosition guardPos = Broodwar->self()->getStartLocation(); if (bestChoke != NULL) { guardPos = findDefensePos(bestChoke); //guardPos = TilePosition(bestChoke->getCenter()); //Pre-calculate path TilePosition b = ExplorationManager::getInstance()->getClosestSpottedBuilding(guardPos); if (b.x() >= 0) { Pathfinder::getInstance()->requestPath(guardPos, b); } } return guardPos; }
void ExplorationManager::setExpansionSite(TilePosition pos) { if (pos.x() >= 0) { siteSetFrame = Broodwar->getFrameCount(); expansionSite = pos; } }
bool CoverMap::positionFree(TilePosition pos) { if (cover_map[pos.x()][pos.y()] == BUILDABLE) { return true; } return false; }
bool AgentManager::unitsInArea(TilePosition pos, int tileWidth, int tileHeight, int unitID) { for (int i = 0; i < (int)agents.size(); i++) { if (agents.at(i)->isAlive()) { if (agents.at(i)->getUnit()->getID() != unitID) { TilePosition aPos = agents.at(i)->getUnit()->getTilePosition(); if (aPos.x() >= pos.x() && aPos.x() <= pos.x() + tileWidth && aPos.y() >= pos.y() && aPos.y() <= pos.y() + tileWidth) { return true; } } } } return false; }
bool ExplorationManager::canReach(TilePosition a, TilePosition b) { int w = Broodwar->mapWidth(); int h = Broodwar->mapHeight(); if (a.x() < 0 || a.x() >= w || a.y() < 0 || a.y() >= h) { return false; } if (b.x() < 0 || b.x() >= w || b.y() < 0 || b.y() >= h) { return false; } bool ok = true; ok = a.hasPath(b); return ok; }
TilePosition CoverMap::findSpotAtSide(UnitType toBuild, TilePosition start, TilePosition end) { int dX = end.x() - start.x(); if (dX != 0) dX = 1; int dY = end.y() - start.y(); if (dY != 0) dY = 1; TilePosition cPos = start; bool done = false; while (!done) { if (canBuildAt(toBuild, cPos)) return cPos; int cX = cPos.x() + dX; int cY = cPos.y() + dY; cPos = TilePosition(cX, cY); if (cPos.x() == end.x() && cPos.y() == end.y()) done = true; } return TilePosition(-1, -1); }
void Squad::defend(TilePosition mGoal) { if (mGoal.x() == -1 || mGoal.y() == -1) return; if (currentState != STATE_DEFEND) { if (currentState == STATE_ASSIST && !isUnderAttack()) { currentState = STATE_DEFEND; } } setGoal(mGoal); }
void Commander::updateGoals() { TilePosition defSpot = findChokePoint(); if (defSpot.x() != -1) { for (int i = 0; i < (int)squads.size(); i++) { Squad* sq = squads.at(i); squads.at(i)->defend(defSpot); } } }
void Commander::forceAttack() { TilePosition cGoal = getClosestEnemyBuilding(Broodwar->self()->getStartLocation()); Broodwar->printf("[%d] Launch attack (%d,%d)", Broodwar->getFrameCount(), cGoal.x(), cGoal.y()); if (cGoal.x() == -1) { return; } for (int i = 0; i < (int)squads.size(); i++) { if (squads.at(i)->isOffensive() || squads.at(i)->isSupport()) { if (cGoal.x() >= 0) { squads.at(i)->forceActive(); squads.at(i)->attack(cGoal); } } } currentState = ATTACK; }
bool Squad::isThisGoal(TilePosition mGoal) { int xDiff = goal.x() - mGoal.x(); if (xDiff < 0) xDiff *= -1; int yDiff = goal.y() - mGoal.y(); if (yDiff < 0) yDiff *= -1; //Broodwar->printf("SQ %d: (%d,%d) = (%d,%d)", id, goal.x(), goal.y(), mGoal.x(), mGoal.y()); if (xDiff <= 2 && yDiff <= 2) { return true; } return false; }
double Commander::getChokepointPrio(TilePosition center) { TilePosition ePos = ExplorationManager::getInstance()->getClosestSpottedBuilding(center); if (ePos.x() >= 0) { double dist = ePos.getDistance(center); return 1000 - dist; } else { double dist = Broodwar->self()->getStartLocation().getDistance(center); return dist; } }
void BTHAIModule::onNukeDetect(BWAPI::Position target) { // TODO: React on this! Make all units move outside of the blast radius? // Notify the commander and let it make a decision? if (target != Positions::Unknown) { TilePosition t = TilePosition(target); Broodwar->printf("Nuclear Launch Detected at (%d,%d)",t.x(),t.y()); Commander::Instance().onNukeDetect(target); } else { Broodwar->printf("Nuclear Launch Detected"); } }
void BuildPlanner::expand(UnitType commandCenterUnit) { if (containsType(commandCenterUnit)) { return; } TilePosition pos = CoverMap::getInstance()->findExpansionSite(); if (pos.x() == -1) { //No expansion site found. return; } addBuildingFirst(commandCenterUnit); }
bool Commander::shallEngage() { TilePosition closeEnemy = getClosestEnemyBuilding(Broodwar->self()->getStartLocation()); if (closeEnemy.x() == -1) { //No enemy sighted. Dont launch attack. return false; } for (int i = 0; i < (int)squads.size(); i++) { if (squads.at(i)->isRequired() && !squads.at(i)->isActive()) { return false; } } return true; }
void ExplorationSquad::computeActions() { if (!active) { if (isFull()) { active = true; } return; } //First, remove dead agents for(int i = 0; i < (int)agents.size(); i++) { if(!agents.at(i)->isAlive()) { agents.erase(agents.begin() + i); i--; } } //All units dead, go back to inactive if ((int)agents.size() == 0) { active = false; return; } if (active) { if (activePriority != priority) { priority = activePriority; } TilePosition nGoal = ExplorationManager::Instance().getNextToExplore(this); if (nGoal.x() >= 0) { this->goal = nGoal; setMemberGoals(goal); } } }
Corners CoverMap::getCorners(UnitType type, TilePosition center) { int x1 = center.x(); int y1 = center.y(); int x2 = x1 + type.tileWidth() - 1; int y2 = y1 + type.tileHeight() - 1; int margin = 1; if (type.canProduce()) { margin = 1; } if (BaseAgent::isOfType(type, UnitTypes::Terran_Supply_Depot)) { margin = 0; } if (BaseAgent::isOfType(type, UnitTypes::Protoss_Pylon)) { margin = 0; } x1 -= margin; x2 += margin; y1 -= margin; y2 += margin; //Special case: Terran Addon buildings //Add 2 extra spaces to the right to make space for the addons. if (BaseAgent::isOfType(type, UnitTypes::Terran_Factory) || BaseAgent::isOfType(type, UnitTypes::Terran_Starport) || BaseAgent::isOfType(type, UnitTypes::Terran_Command_Center) || BaseAgent::isOfType(type, UnitTypes::Terran_Science_Facility)) { x2 += 2; } Corners c; c.x1 = x1; c.y1 = y1; c.x2 = x2; c.y2 = y2; return c; }
void Squad::attack(TilePosition mGoal) { if (mGoal.x() == -1 || mGoal.y() == -1) return; if (currentState != STATE_ATTACK) { if (!isUnderAttack()) { if (isActive()) { currentState = STATE_ATTACK; } } } if (isActive()) { setGoal(mGoal); } }
void Squad::assist(TilePosition mGoal) { if (mGoal.x() == -1 || mGoal.y() == -1) return; if (currentState != STATE_ASSIST) { if (!isUnderAttack() && currentState == STATE_DEFEND) { currentState = STATE_ASSIST; setGoal(mGoal); } } else { if (goal.x() == -1) { setGoal(mGoal); } } }