#include "KoraBot.h" #include "BWEM/src/bwem.h" #include using namespace BWAPI; using namespace Filter; using namespace BWEM; using namespace BWEM::BWAPI_ext; using namespace BWEM::utils; namespace { auto& theMap = BWEM::Map::Instance(); } KoraBot::KoraBot() { } void KoraBot::onStart() { Broodwar->setLatCom(false); // Hello World! //Broodwar->sendText("Hello world!"); //self = custom::Player(Broodwar->self()->getID()); // Print the map name. // BWAPI returns std::string when retrieving a string, don't forget to add .c_str() when printing! // Broodwar << "The map is " << Broodwar->mapName() << "!" << std::endl; // Enable the UserInput flag, which allows us to control the bot and type messages. Broodwar->enableFlag(Flag::UserInput); // Uncomment the following line and the bot will know about everything through the fog of war (cheat). //Broodwar->enableFlag(Flag::CompleteMapInformation); // Set the command optimization level so that common commands can be grouped // and reduce the bot's APM (Actions Per Minute). Broodwar->setCommandOptimizationLevel(2); // Check if this is a replay if (Broodwar->isReplay()) { // Announce the players in the replay Broodwar << "The following players are in this replay:" << std::endl; // Iterate all the players in the game using a std:: iterator Playerset players = Broodwar->getPlayers(); for (auto p : players) { // Only print the player if they are not an observer if (!p->isObserver()) Broodwar << p->getName() << ", playing as " << p->getRace() << std::endl; } } else // if this is not a replay { // Retrieve you and your enemy's races. enemy() will just return the first enemy. // If you wish to deal with multiple enemies then you must use enemies(). /*if (Broodwar->enemy()) // First make sure there is an enemy Broodwar << "The matchup is " << Broodwar->self()->getRace() << " vs " << Broodwar->enemy()->getRace() << std::endl;*/ // Retrieve you and your enemy's races. enemy() will just return the first enemy. // If you wish to deal with multiple enemies then you must use enemies(). //if (Broodwar->enemy()) // First make sure there is an enemy // Broodwar << "The matchup is " << Broodwar->self()->getRace() << " vs " << Broodwar->enemy()->getRace() << std::endl; for (auto p : Broodwar->getPlayers()) { if (!p->isNeutral()) { Macro::addPlayer(p); if (p->getID() == Broodwar->self()->getID()) { Macro::setSelfID(p->getID()); } else if (p->isEnemy(Broodwar->self())) Macro::setEnemyID(p->getID()); } } try { theMap.Initialize(); theMap.EnableAutomaticPathAnalysis(); bool startingLocationsOK = theMap.FindBasesForStartingLocations(); assert(startingLocationsOK); BWEM::utils::MapPrinter::Initialize(&theMap); BWEM::utils::printMap(theMap); // will print the map into the file /bwapi-data/map.bmp BWEM::utils::pathExample(theMap); // add to the printed map a path between two starting locations int count = 0; for (const Area& area : theMap.Areas()) { for (const Base& base : area.Bases()) { Macro::addBase(base.Location()); Macro::addLocation(base.Location(), base.Starting()); } } Macro::addSquad(); } catch (const std::exception& e) { Broodwar << "EXCEPTION: " << e.what() << std::endl; } Broodwar << "KoraBot 1.0" << std::endl; } } void KoraBot::onEnd(bool isWinner) { // Called when the game ends if (isWinner) { // Log your win here! } } void KoraBot::onFrame() { Broodwar->drawTextScreen(60, 0, "FPS: %d", Broodwar->getFPS()); Broodwar->drawTextScreen(60, 20, "Average FPS: %f", Broodwar->getAverageFPS()); // Called once every game frame try { // these work but i don't need them right now //BWEM::utils::gridMapExample(theMap); //BWEM::utils::drawMap(theMap); if (Broodwar->getFrameCount() > 5) { int count = 0; //for (auto s : Macro::scouts) //{ // Broodwar->drawTextScreen(200, 10 + (count * 20), "%d", s.unit->getID()); // count++; //} Broodwar->drawTextScreen(200, 10, "likelihood: %f", Military::likelihoodToAttack()); Broodwar->drawTextScreen(200, 30, "stop production: %d", Macro::stopProduction); // Util::drawQueue(); //for (auto unit : BWAPI::Broodwar->getNeutralUnits()) //{ //Broodwar->drawTextMap(unit->getPosition(), unit->getType().c_str()); //} //for (auto u : Macro::players.at(Macro::selfID).units) //{ // Broodwar->drawTextMap(u.unit->getPosition(), "%d", u.unit->getID()); //} //for (auto u : Broodwar->self()->getUnits()) //{ // Position p = Position(u->getPosition().x - 10, u->getPosition().y - 10); // Broodwar->drawTextMap(p, "%d", u->getID()); //} //for (auto b : Macro::players.at(Macro::selfID).bases) //{ // Broodwar->drawTextMap(b.position, "%d", b.mineralPatches); //} } } catch (const std::exception& e) { Broodwar << "EXCEPTION: " << e.what() << std::endl; } /// 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; // in the top right spawn of jade, exposed to center is false for the natural unless it's run later if (Broodwar->getFrameCount() == 240 * 24) { for (size_t i = 0; i < Macro::players.at(Macro::selfID).bases.size(); i++) { Macro::players.at(Macro::selfID).bases.at(i).exposedToCenter = Macro::players.at(Macro::selfID).bases.at(i).isExposedToCenter(); } } // functions to be run about every eight seconds (191 frames, 192 frames is 8 seconds) if (Broodwar->getFrameCount() % 191 == 0) { CheckItem::checkBases(); CheckItem::checkEvoChamber(); CheckItem::checkGas(); CheckItem::checkGroundArmor(); CheckItem::checkHive(); CheckItem::checkHydraDen(); CheckItem::checkHydraRange(); CheckItem::checkHydraSpeed(); CheckItem::checkLair(); CheckItem::checkLingSpeed(); CheckItem::checkMissile(); CheckItem::checkOverlordSpeed(); CheckItem::checkMacroHatch(); CheckItem::checkQueensNest(); CheckItem::checkSpawningPool(); CheckItem::checkSpire(); CheckItem::checkSpore(); CheckItem::checkSunken(); CheckItem::checkUltraCavern(); Macro::morphCreepColonies(); Military::checkAttack(); Military::checkSquads(); Scouting::setScouts(); } // functions to be run about every two seconds if (Broodwar->getFrameCount() % 47 == 0) { Scouting::scout(); } // functions to be run about once a second if (Broodwar->getFrameCount() % 23 == 0) { Military::checkDefense(); CheckItem::checkNewBase(); } // functions to be run every thirteenth frame (about twice a second) if (Broodwar->getFrameCount() % 13 == 0) { if (Broodwar->getFrameCount() > 10) { CheckItem::checkMutalisk(); CheckItem::checkHydralisk(); CheckItem::checkSupply(); //auto start = std::chrono::high_resolution_clock::now(); CheckItem::checkWorkers(); //std::chrono::duration elapsed = std::chrono::high_resolution_clock::now() - start; CheckItem::checkUltralisk(); CheckItem::checkZergling(); // start here - use this to check other function times /*Broodwar->registerEvent( [elapsed](Game*) { Broodwar->drawTextScreen(Position(400, 10), "%f", elapsed.count()); }, nullptr, 12);*/ } } // functions to be run every fifth frame (4.8 times a second) - unit production / macro analysis if (Broodwar->getFrameCount() % 5 == 0) { if (Broodwar->getFrameCount() > 6) { Macro::analyzeQueue(); //Macro::drawActions(); } } if (Broodwar->getFrameCount() > 5) { //Macro::drawPlayers(); } // functions to be run every tick (24 times a second) - unit micro } void KoraBot::onSendText(std::string text) { BWEM::utils::MapDrawer::ProcessCommand(text); // Send the text to the game if it is not being processed. Broodwar->sendText("%s", text.c_str()); // Make sure to use %s and pass the text as a parameter, // otherwise you may run into problems when you use the %(percent) character! } void KoraBot::onReceiveText(BWAPI::Player player, std::string text) { // Parse the received text //Broodwar << player->getName() << " said \"" << text << "\"" << std::endl; } void KoraBot::onPlayerLeft(BWAPI::Player player) { // Interact verbally with the other players in the game by // announcing that the other player has left. Broodwar->sendText("GG %s!", player->getName().c_str()); } void KoraBot::onNukeDetect(BWAPI::Position target) { // Check if the target is a valid position if (target) { // if so, print the location of the nuclear strike target Broodwar << "Nuclear Launch Detected at " << target << std::endl; } else { // Otherwise, ask other players where the nuke is! Broodwar->sendText("Where's the nuke?"); } // You can also retrieve all the nuclear missile targets using Broodwar->getNukeDots()! } void KoraBot::onUnitDiscover(BWAPI::Unit unit) { Macro::onUnitDiscover(unit); } void KoraBot::onUnitEvade(BWAPI::Unit unit) { } void KoraBot::onUnitShow(BWAPI::Unit unit) { Macro::onUnitShow(unit); } void KoraBot::onUnitHide(BWAPI::Unit unit) { } void KoraBot::onUnitCreate(BWAPI::Unit unit) { if (Broodwar->isReplay()) { // if we are in a replay, then we will print out the build order of the structures if (unit->getType().isBuilding() && !unit->getPlayer()->isNeutral()) { int seconds = Broodwar->getFrameCount() / 24; int minutes = seconds / 60; seconds %= 60; Broodwar->sendText("%.2d:%.2d: %s creates a %s", minutes, seconds, unit->getPlayer()->getName().c_str(), unit->getType().c_str()); } } else { Macro::onUnitCreate(unit); } } void KoraBot::onUnitDestroy(BWAPI::Unit unit) { try { if (!Broodwar->isReplay()) { Macro::onUnitDestroy(unit); } else { if (unit->getType().isMineralField()) theMap.OnMineralDestroyed(unit); else if (unit->getType().isSpecialBuilding()) theMap.OnStaticBuildingDestroyed(unit); } } catch (const std::exception& e) { Broodwar << "EXCEPTION: " << e.what() << std::endl; } } void KoraBot::onUnitMorph(BWAPI::Unit unit) { if (Broodwar->isReplay()) { // if we are in a replay, then we will print out the build order of the structures if (unit->getType().isBuilding() && !unit->getPlayer()->isNeutral()) { int seconds = Broodwar->getFrameCount() / 24; int minutes = seconds / 60; seconds %= 60; Broodwar->sendText("%.2d:%.2d: %s morphs a %s", minutes, seconds, unit->getPlayer()->getName().c_str(), unit->getType().c_str()); } } else { Macro::onUnitMorph(unit); } } void KoraBot::onUnitRenegade(BWAPI::Unit unit) { } void KoraBot::onSaveGame(std::string gameName) { Broodwar << "The game was saved to \"" << gameName << "\"" << std::endl; } void KoraBot::onUnitComplete(BWAPI::Unit unit) { if (Broodwar->getFrameCount() > 0 && !Broodwar->isReplay()) { if (unit->getPlayer() == Broodwar->self()) { Macro::onUnitComplete(unit); } } }