kora-bot/Source/Util.cpp

388 lines
10 KiB
C++

#include "Util.h"
namespace { auto & map = BWEM::Map::Instance(); }
// gets the index of a drone that's currently mining minerals
int Util::buildWorkerIndex()
{
for (size_t i = 0; i < Macro::players.at(Macro::selfID).units.size(); i++)
{
if (Macro::players.at(Macro::selfID).units.at(i).unit->getType() == UnitTypes::Zerg_Drone
&& Macro::players.at(Macro::selfID).units.at(i).action == "minerals"
&& Macro::players.at(Macro::selfID).units.at(i).miningBase > -1)
{
return i;
}
}
return -1;
}
// checks if there's at least one complete building of the type specified
bool Util::completedBuilding(BWAPI::UnitType unitType)
{
for (auto u : Macro::players.at(Macro::selfID).units)
{
if (u.unit->getType() == unitType && u.unit->isCompleted()) return true;
if (unitType == UnitTypes::Zerg_Spire
&& u.unit->getType() == UnitTypes::Zerg_Greater_Spire && u.unit->isCompleted()) return true;
if (unitType == UnitTypes::Zerg_Hatchery
&& u.unit->getType() == UnitTypes::Zerg_Lair && u.unit->isCompleted()) return true;
if (unitType == UnitTypes::Zerg_Hatchery
&& u.unit->getType() == UnitTypes::Zerg_Hive && u.unit->isCompleted()) return true;
if (unitType == UnitTypes::Zerg_Lair
&& u.unit->getType() == UnitTypes::Zerg_Hive && u.unit->isCompleted()) return true;
}
return false;
}
int Util::countUnits(int playerID, BWAPI::UnitType unitType)
{
int count = 0;
for (auto u : Macro::players.at(playerID).units)
{
if (u.unitType == unitType) count++;
// if the unit is changing into the target UnitType,
// count it
else if (u.targetUnit == unitType) count++;
// lairs and hives count as hatcheries,
// hives count as lairs
if (unitType == UnitTypes::Zerg_Hatchery)
{
if (u.unitType == UnitTypes::Zerg_Lair) count++;
if (u.unitType == UnitTypes::Zerg_Hive) count++;
}
else if (unitType == UnitTypes::Zerg_Lair)
if (u.unitType == UnitTypes::Zerg_Hive) count++;
}
return count;
}
// draws the queue at the top center of the screen
void Util::displayQueue()
{
int count = 0;
for (auto e : Macro::queue)
{
if (e.unit != UnitTypes::Unknown)
Broodwar->drawTextScreen(200, 50 + (count * 20), "%s: %d", e.unit.c_str(), e.inProgress);
else
Broodwar->drawTextScreen(200, 50 + (count * 20), "%s: %d", e.upgrade.c_str(), e.inProgress);
count++;
}
}
// number of units of a particular type being produced
int Util::eggCount(BWAPI::UnitType unitType)
{
int count = 0;
for (auto u : Macro::players.at(Macro::selfID).units)
{
if (u.unit->getBuildType() == unitType &&
u.unit->isMorphing()) count++;
}
return count;
}
// return the index of a building that can research a particular upgrade
int Util::findUpgradeBuilding(UpgradeType upgradeType)
{
for (size_t i = 0; i < Macro::players.at(Macro::selfID).units.size(); i++)
{
for (auto u : Macro::players.at(Macro::selfID).units.at(i).unit->getType().upgradesWhat())
{
if (upgradeType == u) return i;
}
if (Macro::players.at(Macro::selfID).units.at(i).unit->getType() == UnitTypes::Zerg_Hive)
{
for (auto u : UnitTypes::Zerg_Lair.upgradesWhat())
{
if (upgradeType == u) return i;
}
for (auto u : UnitTypes::Zerg_Hatchery.upgradesWhat())
{
if (upgradeType == u) return i;
}
}
if (Macro::players.at(Macro::selfID).units.at(i).unit->getType() == UnitTypes::Zerg_Lair)
{
for (auto u : UnitTypes::Zerg_Hatchery.upgradesWhat())
{
if (upgradeType == u) return i;
}
}
}
return -1;
}
int Util::getBaseIndex(Unit u)
{
for (size_t i = 0; i < Macro::players.at(u->getPlayer()->getID()).bases.size(); i++)
{
if (u->getID() == Macro::players.at(u->getPlayer()->getID()).bases.at(i).base->getID())
{
return i;
}
}
return -1;
}
//@TODO move this to CUnit
int Util::getClosestOwnedBase(Unit unit)
{
unit->getUnitsInRadius(256*32, BWAPI::Filter::IsResourceDepot);
double distance = 1000;
int index = -1;
for (size_t i = 0; i < Macro::players.at(Macro::selfID).bases.size(); i++)
{
double d = getDistance(unit->getTilePosition(), Macro::players.at(Macro::selfID).bases.at(i).tilePosition);
if (d < distance)
{
distance = d;
index = i;
}
}
return index;
}
// get air distance between two TilePositions
double Util::getDistance(TilePosition tp1, TilePosition tp2)
{
double deltaX = tp1.x - tp2.x;
double deltaY = tp1.y - tp2.y;
return sqrt(pow(deltaX, 2.0) + pow(deltaY, 2.0));
}
// get the index of a Location
int Util::getLocation(TilePosition tp)
{
for (size_t i = 0; i < Macro::locations.size(); i++)
{
if (Macro::locations.at(i).tilePosition == tp)
return i;
}
return -1;
}
// on a path from a1 to a2, get the Area adjacent to a1
std::pair<const BWEM::Area*, bool> Util::getNeighborArea(const BWEM::Area* a1, const BWEM::Area* a2)
{
const BWEM::Area* area;
int count = 0;
std::vector< const BWEM::Area*> path = CMap::getPath(a1, a2);
if(path.size() > 1)
return std::pair<const BWEM::Area*, bool>(path.at(1), true);
return std::pair<const BWEM::Area*, bool>(area, false);
}
// things to consider:
// how close the base is by ground
// how close the base is to the enemy
CBase Util::getNextExpand(int playerID)
{
double distance = 1000;
int index = -1;
int count = 0;
for (auto b : Macro::bases)
{
if (!b.isOwned())
{
CBase home = Macro::players.at(playerID).bases.front();
double dist = getWalkDistance(home.tilePosition, b.tilePosition);
if (dist < distance
&& !(home.tilePosition.x == b.tilePosition.x && home.tilePosition.y == b.tilePosition.y)
&& map.GetArea(home.tilePosition)->AccessibleFrom(map.GetArea(b.tilePosition)))
{
distance = dist;
index = count;
}
}
count++;
}
return Macro::bases.at(index);
}
int Util::getQueueIndex(UnitType ut)
{
for (size_t i = 0; i < Macro::queue.size(); i++)
{
if (Macro::queue.at(i).unit == ut)
{
return i;
}
}
return -1;
}
int Util::getStaticDCount(int playerID, std::string type = "all")
{
if (type == "air")
{
return (countUnits(playerID, UnitTypes::Terran_Missile_Turret)
+ countUnits(playerID, UnitTypes::Terran_Bunker)
+ countUnits(playerID, UnitTypes::Protoss_Photon_Cannon)
+ countUnits(playerID, UnitTypes::Zerg_Spore_Colony));
}
else if (type == "ground")
{
return (countUnits(playerID, UnitTypes::Terran_Bunker)
+ countUnits(playerID, UnitTypes::Protoss_Photon_Cannon)
+ countUnits(playerID, UnitTypes::Zerg_Sunken_Colony));
}
return (countUnits(playerID, UnitTypes::Terran_Bunker)
+ countUnits(playerID, UnitTypes::Terran_Missile_Turret)
+ countUnits(playerID, UnitTypes::Protoss_Photon_Cannon)
+ countUnits(playerID, UnitTypes::Zerg_Sunken_Colony)
+ countUnits(playerID, UnitTypes::Zerg_Spore_Colony));
}
// return another starting location besides the one provided
// for the purpose of pathing / defense placement
//
//@TODO once the enemy's base is known, just return that
std::pair<const BWEM::Area*, bool> Util::getTargetArea(const BWEM::Area* startingArea, bool startLocation)
{
const BWEM::Area* area;
for (const TilePosition tp : map.StartingLocations())
{
const BWEM::Area* nearestArea = map.GetNearestArea(tp);
if (!isSameArea(nearestArea, startingArea));
{
bool chk = true;
if (!startLocation
&& Macro::players.at(Macro::selfID).bases.size() > 0
&& Macro::players.at(Macro::selfID).bases.front().tilePosition == tp)
{
chk = false;
}
if (chk)
{
return std::pair<const BWEM::Area*, bool>(nearestArea, true);
}
}
}
return std::pair<const BWEM::Area*, bool>(area, false);
}
int Util::getUnitIndex(Unit unit)
{
for (size_t i = 0; i < Macro::players.at(unit->getPlayer()->getID()).units.size(); i++)
{
if (unit->getID() == Macro::players.at(unit->getPlayer()->getID()).units.at(i).unit->getID())
{
return i;
}
}
return -1;
}
double Util::getWalkDistance(TilePosition tp1, TilePosition tp2)
{
double distance = 0;
const BWEM::Area* area = map.GetArea(tp1);
const BWEM::Area* targetArea = map.GetArea(tp2);
TilePosition currentPosition = tp1;
int count = 0;
for (auto a : CMap::getPath(area, targetArea))
{
if (count > 0)
{
TilePosition nextPosition = CMap::getAreaAverage(a);
distance += getDistance(currentPosition, nextPosition);
currentPosition = nextPosition;
}
count++;
}
return distance;
}
bool Util::isAttackingUnit(CUnit u)
{
return (!u.unit->getType().isBuilding()
&& u.unit->getType() != UnitTypes::Zerg_Larva
&& u.unit->getType() != UnitTypes::Zerg_Egg
&& u.unit->getType() != UnitTypes::Zerg_Drone
&& u.unit->getType() != UnitTypes::Zerg_Overlord);
}
// run on hatcheries to see if they're a macro hatch or a mining base
bool Util::isBase(Unit unit)
{
for (auto b : Macro::bases)
{
if (isSameTilePosition(unit->getTilePosition(), b.tilePosition))
{
return true;
}
}
return false;
}
// determines if a tileposition is a base position
bool Util::isBasePosition(TilePosition tp)
{
for (auto b : Macro::bases)
{
if (tp == b.tilePosition)
return true;
}
return false;
}
bool Util::isSameArea(const BWEM::Area* area1, const BWEM::Area* area2)
{
return (area1->TopLeft().x == area2->TopLeft().x
&& area1->TopLeft().y == area2->TopLeft().y);
}
bool Util::isSameTilePosition(TilePosition tp1, TilePosition tp2)
{
return (tp1.x == tp2.x && tp1.y == tp2.y);
}
// returns id of player who owns a base at tileposition tp
int Util::ownedBy(TilePosition tp)
{
for (size_t i = 0; i < Macro::players.size(); i++)
{
for (size_t j = 0; j < Macro::players.at(i).bases.size(); j++)
{
if (Macro::players.at(i).bases.at(j).tilePosition == tp) return i;
}
}
return -1;
}
bool Util::unitCounted(Unit unit)
{
for (auto u : Macro::players.at(unit->getPlayer()->getID()).units)
{
if (unit->getID() == u.unit->getID())
{
return true;
}
}
return false;
}
// checks number of workers who have been told to build a certain building
int Util::workerBuildingTargetCount(UnitType unit)
{
int i = 0;
for (auto u : Macro::players.at(Macro::selfID).units)
{
if (u.unit->getType() == UnitTypes::Zerg_Drone
&& u.targetUnit == unit)
i++;
}
return i;
}