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 }
int main(int argc, const char* argv[]) { std::cout << "Connecting..." << std::endl;; reconnect(); while(true) { std::cout << "waiting to enter match" << std::endl; while ( !Broodwar->isInGame() ) { BWAPI::BWAPIClient.update(); if (!BWAPI::BWAPIClient.isConnected()) { std::cout << "Reconnecting..." << std::endl;; reconnect(); } } std::cout << "starting match!" << std::endl; Broodwar->sendText("Hello world!"); Broodwar << "The map is " << Broodwar->mapName() << ", a " << Broodwar->getStartLocations().size() << " player map" << std::endl; // Enable some cheat flags Broodwar->enableFlag(Flag::UserInput); // Uncomment to enable complete map information //Broodwar->enableFlag(Flag::CompleteMapInformation); show_bullets=false; show_visibility_data=false; if (Broodwar->isReplay()) { Broodwar << "The following players are in this replay:" << std::endl;; Playerset players = Broodwar->getPlayers(); for(Playerset::iterator p = players.begin(); p != players.end(); ++p ) { if ( !p->getUnits().empty() && !p->isNeutral() ) Broodwar << p->getName() << ", playing as " << p->getRace() << std::endl; } } else { Broodwar << "The match up is " << Broodwar->self()->getRace() << " vs " << Broodwar->enemy()->getRace() << std::endl; //send each worker to the mineral field that is closest to it Unitset units = Broodwar->self()->getUnits(); Unitset minerals = Broodwar->getMinerals(); for ( Unitset::iterator i = units.begin(); i != units.end(); ++i ) { if ( i->getType().isWorker() ) { Unit closestMineral = NULL; for( Unitset::iterator m = minerals.begin(); m != minerals.end(); ++m ) { if ( !closestMineral || i->getDistance(*m) < i->getDistance(closestMineral)) closestMineral = *m; } if ( closestMineral ) i->rightClick(closestMineral); } else if ( i->getType().isResourceDepot() ) { //if this is a center, tell it to build the appropiate type of worker i->train(Broodwar->self()->getRace().getWorker()); } } } while(Broodwar->isInGame()) { for(std::list<Event>::const_iterator e = Broodwar->getEvents().begin(); e != Broodwar->getEvents().end(); ++e) { switch(e->getType()) { case EventType::MatchEnd: if (e->isWinner()) Broodwar << "I won the game" << std::endl; else Broodwar << "I lost the game" << std::endl; break; case EventType::SendText: if (e->getText()=="/show bullets") { show_bullets=!show_bullets; } else if (e->getText()=="/show players") { showPlayers(); } else if (e->getText()=="/show forces") { showForces(); } else if (e->getText()=="/show visibility") { show_visibility_data=!show_visibility_data; } else { Broodwar << "You typed \"" << e->getText() << "\"!" << std::endl; } break; case EventType::ReceiveText: Broodwar << e->getPlayer()->getName() << " said \"" << e->getText() << "\"" << std::endl; break; case EventType::PlayerLeft: Broodwar << e->getPlayer()->getName() << " left the game." << std::endl; break; case EventType::NukeDetect: if (e->getPosition()!=Positions::Unknown) { Broodwar->drawCircleMap(e->getPosition(), 40, Colors::Red, true); Broodwar << "Nuclear Launch Detected at " << e->getPosition() << std::endl; } else Broodwar << "Nuclear Launch Detected" << std::endl; break; case EventType::UnitCreate: if (!Broodwar->isReplay()) Broodwar << "A " << e->getUnit()->getType() << " [" << e->getUnit() << "] has been created at " << e->getUnit()->getPosition() << std::endl; else { // if we are in a replay, then we will print out the build order // (just of the buildings, not the units). if (e->getUnit()->getType().isBuilding() && e->getUnit()->getPlayer()->isNeutral()==false) { int seconds=Broodwar->getFrameCount()/24; int minutes=seconds/60; seconds%=60; Broodwar->sendText("%.2d:%.2d: %s creates a %s", minutes, seconds, e->getUnit()->getPlayer()->getName().c_str(), e->getUnit()->getType().c_str()); } } break; case EventType::UnitDestroy: if (!Broodwar->isReplay()) Broodwar->sendText("A %s [%x] has been destroyed at (%d,%d)",e->getUnit()->getType().c_str(), e->getUnit(), e->getUnit()->getPosition().x, e->getUnit()->getPosition().y); break; case EventType::UnitMorph: if (!Broodwar->isReplay()) Broodwar->sendText("A %s [%x] has been morphed at (%d,%d)",e->getUnit()->getType().c_str(), e->getUnit(), e->getUnit()->getPosition().x, e->getUnit()->getPosition().y); else { // if we are in a replay, then we will print out the build order // (just of the buildings, not the units). if (e->getUnit()->getType().isBuilding() && e->getUnit()->getPlayer()->isNeutral()==false) { int seconds=Broodwar->getFrameCount()/24; int minutes=seconds/60; seconds%=60; Broodwar->sendText("%.2d:%.2d: %s morphs a %s" ,minutes, seconds, e->getUnit()->getPlayer()->getName().c_str(), e->getUnit()->getType().c_str()); } } break; case EventType::UnitShow: if (!Broodwar->isReplay()) Broodwar->sendText("A %s [%x] has been spotted at (%d,%d)", e->getUnit()->getType().c_str(), e->getUnit(), e->getUnit()->getPosition().x, e->getUnit()->getPosition().y); break; case EventType::UnitHide: if (!Broodwar->isReplay()) Broodwar->sendText("A %s [%x] was last seen at (%d,%d)", e->getUnit()->getType().c_str(), e->getUnit(), e->getUnit()->getPosition().x, e->getUnit()->getPosition().y); break; case EventType::UnitRenegade: if (!Broodwar->isReplay()) Broodwar->sendText("A %s [%x] is now owned by %s", e->getUnit()->getType().c_str(), e->getUnit(), e->getUnit()->getPlayer()->getName().c_str()); break; case EventType::SaveGame: Broodwar->sendText("The game was saved to \"%s\".", e->getText().c_str()); break; } } if (show_bullets) drawBullets(); if (show_visibility_data) drawVisibilityData(); drawStats(); Broodwar->drawTextScreen(300,0,"FPS: %f",Broodwar->getAverageFPS()); BWAPI::BWAPIClient.update(); if (!BWAPI::BWAPIClient.isConnected()) { std::cout << "Reconnecting..." << std::endl; reconnect(); } } std::cout << "Game ended" << std::endl; } std::cout << "Press ENTER to continue..." << std::endl; std::cin.ignore(); return 0; }