kora-bot/Source/Korabot.cpp

412 lines
11 KiB
C++

#include "KoraBot.h"
#include "BWEM/src/bwem.h"
#include <iostream>
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 <StarCraftFolder>/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<double, std::milli> 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);
}
}
}