/** * Counts the barracks constructed or under construction around a command center */ int ExampleAIModule::calculateBarracksFromCommandCenter(Unit cmdCenter) { //first: count built barracks around the command center Position commandCenterPos = cmdCenter->getPosition(); Unitset units = Broodwar->getUnitsInRadius(commandCenterPos, BASE_RADIUS); int builtBarracks = 0; for ( Unitset::iterator u = units.begin(); u != units.end(); ++u ) { if ( u->getType() == UnitTypes::Terran_Barracks && u->isCompleted()) { builtBarracks++; } } //second: count the SCVs constructing around the command center int scheduledForConstruction = 0; for(auto scv = scvMap.begin(); scv != scvMap.end(); scv++){ //if SCV is not constructing the barracks but is moving towards it... if(scv->second->state == BUILDING_BARRACKS && Position(scv->second->newBuildingLocation).getApproxDistance(commandCenterPos) < BASE_RADIUS ){ Broodwar->drawCircleMap(scv->second->gameUnit->getPosition(),20,Color(Colors::Cyan)); scheduledForConstruction++; } } //Broodwar->sendText("%d - %d",builtBarracks,scheduledForConstruction); return builtBarracks + scheduledForConstruction; }
void ExampleAIModule::onFrame() { // Called once every game frame // Display the game frame rate as text in the upper left area of the screen Broodwar->drawTextScreen(200, 0, "FPS: %d", Broodwar->getFPS() ); Broodwar->drawTextScreen(200, 20, "Average FPS: %f", Broodwar->getAverageFPS() ); // Return if the game is a replay or is paused if ( Broodwar->isReplay() || Broodwar->isPaused() || !Broodwar->self() ) return; // Prevent spamming by only running our onFrame once every number of latency frames. // Latency frames are the number of frames before commands are processed. if ( Broodwar->getFrameCount() % Broodwar->getLatencyFrames() != 0 ) return; // Iterate through all the units that we own Unitset myUnits = Broodwar->self()->getUnits(); for ( Unitset::iterator u = myUnits.begin(); u != myUnits.end(); ++u ) { // Ignore the unit if it no longer exists // Make sure to include this block when handling any Unit pointer! if ( !u->exists() ) continue; // Ignore the unit if it has one of the following status ailments if ( u->isLockedDown() || u->isMaelstrommed() || u->isStasised() ) continue; // Ignore the unit if it is in one of the following states if ( u->isLoaded() || !u->isPowered() || u->isStuck() ) continue; // Ignore the unit if it is incomplete or busy constructing if ( !u->isCompleted() || u->isConstructing() ) continue; // Finally make the unit do some stuff! // If the unit is a worker unit if ( u->getType().isWorker() ) { // if our worker is idle if ( u->isIdle() ) { // Order workers carrying a resource to return them to the center, // otherwise find a mineral patch to harvest. if ( u->isCarryingGas() || u->isCarryingMinerals() ) { u->returnCargo(); } else if ( !u->getPowerUp() ) // The worker cannot harvest anything if it { // is carrying a powerup such as a flag // Harvest from the nearest mineral patch or gas refinery if ( !u->gather( u->getClosestUnit( IsMineralField || IsRefinery )) ) { // If the call fails, then print the last error message Broodwar << Broodwar->getLastError() << std::endl; } } // closure: has no powerup } // closure: if idle } else if ( u->getType().isResourceDepot() ) // A resource depot is a Command Center, Nexus, or Hatchery { // Order the depot to construct more workers! But only when it is idle. if ( u->isIdle() && !u->train(u->getType().getRace().getWorker()) ) { // If that fails, draw the error at the location so that you can visibly see what went wrong! // However, drawing the error once will only appear for a single frame // so create an event that keeps it on the screen for some frames Position pos = u->getPosition(); Error lastErr = Broodwar->getLastError(); Broodwar->registerEvent([pos,lastErr](Game*){ Broodwar->drawTextMap(pos, "%c%s", Text::White, lastErr.c_str()); }, // action nullptr, // condition Broodwar->getLatencyFrames()); // frames to run // Retrieve the supply provider type in the case that we have run out of supplies UnitType supplyProviderType = u->getType().getRace().getSupplyProvider(); static int lastChecked = 0; // If we are supply blocked and haven't tried constructing more recently if ( lastErr == Errors::Insufficient_Supply && lastChecked + 400 < Broodwar->getFrameCount() && Broodwar->self()->incompleteUnitCount(supplyProviderType) == 0 ) { lastChecked = Broodwar->getFrameCount(); // Retrieve a unit that is capable of constructing the supply needed Unit supplyBuilder = u->getClosestUnit( GetType == supplyProviderType.whatBuilds().first && (IsIdle || IsGatheringMinerals) && IsOwned); // If a unit was found if ( supplyBuilder ) { if ( supplyProviderType.isBuilding() ) { TilePosition targetBuildLocation = Broodwar->getBuildLocation(supplyProviderType, supplyBuilder->getTilePosition()); if ( targetBuildLocation ) { // Register an event that draws the target build location Broodwar->registerEvent([targetBuildLocation,supplyProviderType](Game*) { Broodwar->drawBoxMap( Position(targetBuildLocation), Position(targetBuildLocation + supplyProviderType.tileSize()), Colors::Blue); }, nullptr, // condition supplyProviderType.buildTime() + 100 ); // frames to run // Order the builder to construct the supply structure supplyBuilder->build( supplyProviderType, targetBuildLocation ); } } else { // Train the supply provider (Overlord) if the provider is not a structure supplyBuilder->train( supplyProviderType ); } } // closure: supplyBuilder is valid } // closure: insufficient supply } // closure: failed to train idle unit } } // closure: unit iterator }