1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Code style: formatting and refactoring of VCAI code

This commit is contained in:
Arseniy Shestakov
2018-04-07 15:44:14 +07:00
committed by ArseniyShestakov
parent 2ede3783dd
commit 25dea1a599
9 changed files with 1864 additions and 1487 deletions

View File

@@ -23,7 +23,7 @@
extern boost::thread_specific_ptr<CCallback> cb; extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<VCAI> ai; extern boost::thread_specific_ptr<VCAI> ai;
extern FuzzyHelper *fh; extern FuzzyHelper * fh;
//extern static const int3 dirs[8]; //extern static const int3 dirs[8];
@@ -32,27 +32,29 @@ const CGObjectInstance * ObjectIdRef::operator->() const
return cb->getObj(id, false); return cb->getObj(id, false);
} }
ObjectIdRef::operator const CGObjectInstance*() const ObjectIdRef::operator const CGObjectInstance *() const
{ {
return cb->getObj(id, false); return cb->getObj(id, false);
} }
ObjectIdRef::ObjectIdRef(ObjectInstanceID _id) : id(_id) ObjectIdRef::ObjectIdRef(ObjectInstanceID _id)
: id(_id)
{ {
} }
ObjectIdRef::ObjectIdRef(const CGObjectInstance *obj) : id(obj->id) ObjectIdRef::ObjectIdRef(const CGObjectInstance * obj)
: id(obj->id)
{ {
} }
bool ObjectIdRef::operator<(const ObjectIdRef &rhs) const bool ObjectIdRef::operator<(const ObjectIdRef & rhs) const
{ {
return id < rhs.id; return id < rhs.id;
} }
HeroPtr::HeroPtr(const CGHeroInstance *H) HeroPtr::HeroPtr(const CGHeroInstance * H)
{ {
if(!H) if(!H)
{ {
@@ -63,7 +65,6 @@ HeroPtr::HeroPtr(const CGHeroInstance *H)
h = H; h = H;
name = h->name; name = h->name;
hid = H->id; hid = H->id;
// infosCount[ai->playerID][hid]++; // infosCount[ai->playerID][hid]++;
} }
@@ -76,11 +77,11 @@ HeroPtr::HeroPtr()
HeroPtr::~HeroPtr() HeroPtr::~HeroPtr()
{ {
// if(hid >= 0) // if(hid >= 0)
// infosCount[ai->playerID][hid]--; // infosCount[ai->playerID][hid]--;
} }
bool HeroPtr::operator<(const HeroPtr &rhs) const bool HeroPtr::operator<(const HeroPtr & rhs) const
{ {
return hid < rhs.hid; return hid < rhs.hid;
} }
@@ -126,55 +127,59 @@ const CGHeroInstance * HeroPtr::operator*() const
return get(); return get();
} }
void foreach_tile_pos(std::function<void(const int3& pos)> foo) void foreach_tile_pos(std::function<void(const int3 & pos)> foo)
{ {
// some micro-optimizations since this function gets called a LOT // some micro-optimizations since this function gets called a LOT
// callback pointer is thread-specific and slow to retrieve -> read map size only once // callback pointer is thread-specific and slow to retrieve -> read map size only once
int3 mapSize = cb->getMapSize(); int3 mapSize = cb->getMapSize();
for(int i = 0; i < mapSize.x; i++) for(int i = 0; i < mapSize.x; i++)
{
for(int j = 0; j < mapSize.y; j++) for(int j = 0; j < mapSize.y; j++)
{
for(int k = 0; k < mapSize.z; k++) for(int k = 0; k < mapSize.z; k++)
foo(int3(i,j,k)); foo(int3(i, j, k));
}
}
} }
void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3& pos)> foo) void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3 & pos)> foo)
{ {
int3 mapSize = cbp->getMapSize(); int3 mapSize = cbp->getMapSize();
for(int i = 0; i < mapSize.x; i++) for(int i = 0; i < mapSize.x; i++)
{
for(int j = 0; j < mapSize.y; j++) for(int j = 0; j < mapSize.y; j++)
{
for(int k = 0; k < mapSize.z; k++) for(int k = 0; k < mapSize.z; k++)
foo(cbp, int3(i,j,k)); foo(cbp, int3(i, j, k));
}
}
} }
void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo) void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> foo)
{ {
CCallback * cbp = cb.get(); // avoid costly retrieval of thread-specific pointer CCallback * cbp = cb.get(); // avoid costly retrieval of thread-specific pointer
for(const int3 & dir : int3::getDirs())
for(const int3 &dir : int3::getDirs())
{ {
const int3 n = pos + dir; const int3 n = pos + dir;
if(cbp->isInTheMap(n)) if(cbp->isInTheMap(n))
foo(pos+dir); foo(pos + dir);
} }
} }
void foreach_neighbour(CCallback * cbp, const int3 &pos, std::function<void(CCallback * cbp, const int3& pos)> foo) void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo)
{ {
for(const int3 &dir : int3::getDirs()) for(const int3 & dir : int3::getDirs())
{ {
const int3 n = pos + dir; const int3 n = pos + dir;
if(cbp->isInTheMap(n)) if(cbp->isInTheMap(n))
foo(cbp, pos+dir); foo(cbp, pos + dir);
} }
} }
bool CDistanceSorter::operator ()(const CGObjectInstance *lhs, const CGObjectInstance *rhs) bool CDistanceSorter::operator()(const CGObjectInstance * lhs, const CGObjectInstance * rhs)
{ {
const CGPathNode *ln = ai->myCb->getPathsInfo(hero)->getPathInfo(lhs->visitablePos()), const CGPathNode * ln = ai->myCb->getPathsInfo(hero)->getPathInfo(lhs->visitablePos());
*rn = ai->myCb->getPathsInfo(hero)->getPathInfo(rhs->visitablePos()); const CGPathNode * rn = ai->myCb->getPathsInfo(hero)->getPathInfo(rhs->visitablePos());
if(ln->turns != rn->turns) if(ln->turns != rn->turns)
return ln->turns < rn->turns; return ln->turns < rn->turns;
@@ -189,11 +194,12 @@ bool compareMovement(HeroPtr lhs, HeroPtr rhs)
ui64 evaluateDanger(crint3 tile) ui64 evaluateDanger(crint3 tile)
{ {
const TerrainTile *t = cb->getTile(tile, false); const TerrainTile * t = cb->getTile(tile, false);
if(!t) //we can know about guard but can't check its tile (the edge of fow) if(!t) //we can know about guard but can't check its tile (the edge of fow)
return 190000000; //MUCH return 190000000; //MUCH
ui64 objectDanger = 0, guardDanger = 0; ui64 objectDanger = 0;
ui64 guardDanger = 0;
auto visObjs = cb->getVisitableObjs(tile); auto visObjs = cb->getVisitableObjs(tile);
if(visObjs.size()) if(visObjs.size())
@@ -207,62 +213,64 @@ ui64 evaluateDanger(crint3 tile)
return std::max(objectDanger, guardDanger); return std::max(objectDanger, guardDanger);
} }
ui64 evaluateDanger(crint3 tile, const CGHeroInstance *visitor) ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor)
{ {
const TerrainTile *t = cb->getTile(tile, false); const TerrainTile * t = cb->getTile(tile, false);
if(!t) //we can know about guard but can't check its tile (the edge of fow) if(!t) //we can know about guard but can't check its tile (the edge of fow)
return 190000000; //MUCH return 190000000; //MUCH
ui64 objectDanger = 0, guardDanger = 0; ui64 objectDanger = 0;
ui64 guardDanger = 0;
auto visitableObjects = cb->getVisitableObjs(tile); auto visitableObjects = cb->getVisitableObjs(tile);
// in some scenarios hero happens to be "under" the object (eg town). Then we consider ONLY the hero. // in some scenarios hero happens to be "under" the object (eg town). Then we consider ONLY the hero.
if(vstd::contains_if(visitableObjects, objWithID<Obj::HERO>)) if(vstd::contains_if(visitableObjects, objWithID<Obj::HERO>))
{
vstd::erase_if(visitableObjects, [](const CGObjectInstance * obj) vstd::erase_if(visitableObjects, [](const CGObjectInstance * obj)
{ {
return !objWithID<Obj::HERO>(obj); return !objWithID<Obj::HERO>(obj);
}); });
}
if(const CGObjectInstance * dangerousObject = vstd::backOrNull(visitableObjects)) if(const CGObjectInstance * dangerousObject = vstd::backOrNull(visitableObjects))
{ {
objectDanger = evaluateDanger(dangerousObject); //unguarded objects can also be dangerous or unhandled objectDanger = evaluateDanger(dangerousObject); //unguarded objects can also be dangerous or unhandled
if (objectDanger) if(objectDanger)
{ {
//TODO: don't downcast objects AI shouldn't know about! //TODO: don't downcast objects AI shouldn't know about!
auto armedObj = dynamic_cast<const CArmedInstance*>(dangerousObject); auto armedObj = dynamic_cast<const CArmedInstance *>(dangerousObject);
if (armedObj) if(armedObj)
{ {
float tacticalAdvantage = fh->getTacticalAdvantage(visitor, armedObj); float tacticalAdvantage = fh->getTacticalAdvantage(visitor, armedObj);
objectDanger *= tacticalAdvantage; //this line tends to go infinite for allied towns (?) objectDanger *= tacticalAdvantage; //this line tends to go infinite for allied towns (?)
} }
} }
if (dangerousObject->ID == Obj::SUBTERRANEAN_GATE) if(dangerousObject->ID == Obj::SUBTERRANEAN_GATE)
{ //check guard on the other side of the gate {
//check guard on the other side of the gate
auto it = ai->knownSubterraneanGates.find(dangerousObject); auto it = ai->knownSubterraneanGates.find(dangerousObject);
if (it != ai->knownSubterraneanGates.end()) if(it != ai->knownSubterraneanGates.end())
{ {
auto guards = cb->getGuardingCreatures(it->second->visitablePos()); auto guards = cb->getGuardingCreatures(it->second->visitablePos());
for (auto cre : guards) for(auto cre : guards)
{ {
vstd::amax (guardDanger, evaluateDanger(cre) * vstd::amax(guardDanger, evaluateDanger(cre) * fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance *>(cre)));
fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance*>(cre)));
} }
} }
} }
} }
auto guards = cb->getGuardingCreatures(tile); auto guards = cb->getGuardingCreatures(tile);
for (auto cre : guards) for(auto cre : guards)
{ {
vstd::amax (guardDanger, evaluateDanger(cre) * fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance*>(cre))); //we are interested in strongest monster around vstd::amax(guardDanger, evaluateDanger(cre) * fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance *>(cre))); //we are interested in strongest monster around
} }
//TODO mozna odwiedzic blockvis nie ruszajac straznika //TODO mozna odwiedzic blockvis nie ruszajac straznika
return std::max(objectDanger, guardDanger); return std::max(objectDanger, guardDanger);
} }
ui64 evaluateDanger(const CGObjectInstance *obj) ui64 evaluateDanger(const CGObjectInstance * obj)
{ {
if(obj->tempOwner < PlayerColor::PLAYER_LIMIT && cb->getPlayerRelations(obj->tempOwner, ai->playerID) != PlayerRelations::ENEMIES) //owned or allied objects don't pose any threat if(obj->tempOwner < PlayerColor::PLAYER_LIMIT && cb->getPlayerRelations(obj->tempOwner, ai->playerID) != PlayerRelations::ENEMIES) //owned or allied objects don't pose any threat
return 0; return 0;
@@ -270,64 +278,65 @@ ui64 evaluateDanger(const CGObjectInstance *obj)
switch(obj->ID) switch(obj->ID)
{ {
case Obj::HERO: case Obj::HERO:
{ {
InfoAboutHero iah; InfoAboutHero iah;
cb->getHeroInfo(obj, iah); cb->getHeroInfo(obj, iah);
return iah.army.getStrength(); return iah.army.getStrength();
} }
case Obj::TOWN: case Obj::TOWN:
case Obj::GARRISON: case Obj::GARRISON2: //garrison case Obj::GARRISON:
{ case Obj::GARRISON2:
InfoAboutTown iat; {
cb->getTownInfo(obj, iat); InfoAboutTown iat;
return iat.army.getStrength(); cb->getTownInfo(obj, iat);
} return iat.army.getStrength();
}
case Obj::MONSTER: case Obj::MONSTER:
{ {
//TODO!!!!!!!! //TODO!!!!!!!!
const CGCreature *cre = dynamic_cast<const CGCreature*>(obj); const CGCreature * cre = dynamic_cast<const CGCreature *>(obj);
return cre->getArmyStrength(); return cre->getArmyStrength();
} }
case Obj::CREATURE_GENERATOR1: case Obj::CREATURE_GENERATOR1:
case Obj::CREATURE_GENERATOR4: case Obj::CREATURE_GENERATOR4:
{ {
const CGDwelling *d = dynamic_cast<const CGDwelling*>(obj); const CGDwelling * d = dynamic_cast<const CGDwelling *>(obj);
return d->getArmyStrength(); return d->getArmyStrength();
} }
case Obj::MINE: case Obj::MINE:
case Obj::ABANDONED_MINE: case Obj::ABANDONED_MINE:
{ {
const CArmedInstance * a = dynamic_cast<const CArmedInstance*>(obj); const CArmedInstance * a = dynamic_cast<const CArmedInstance *>(obj);
return a->getArmyStrength(); return a->getArmyStrength();
} }
case Obj::CRYPT: //crypt case Obj::CRYPT: //crypt
case Obj::CREATURE_BANK: //crebank case Obj::CREATURE_BANK: //crebank
case Obj::DRAGON_UTOPIA: case Obj::DRAGON_UTOPIA:
case Obj::SHIPWRECK: //shipwreck case Obj::SHIPWRECK: //shipwreck
case Obj::DERELICT_SHIP: //derelict ship case Obj::DERELICT_SHIP: //derelict ship
// case Obj::PYRAMID: // case Obj::PYRAMID:
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj)); return fh->estimateBankDanger(dynamic_cast<const CBank *>(obj));
case Obj::PYRAMID: case Obj::PYRAMID:
{ {
if(obj->subID == 0) if(obj->subID == 0)
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj)); return fh->estimateBankDanger(dynamic_cast<const CBank *>(obj));
else else
return 0; return 0;
} }
default: default:
return 0; return 0;
} }
} }
bool compareDanger(const CGObjectInstance *lhs, const CGObjectInstance *rhs) bool compareDanger(const CGObjectInstance * lhs, const CGObjectInstance * rhs)
{ {
return evaluateDanger(lhs) < evaluateDanger(rhs); return evaluateDanger(lhs) < evaluateDanger(rhs);
} }
bool isSafeToVisit(HeroPtr h, crint3 tile) bool isSafeToVisit(HeroPtr h, crint3 tile)
{ {
const ui64 heroStrength = h->getTotalStrength(), const ui64 heroStrength = h->getTotalStrength();
dangerStrength = evaluateDanger(tile, *h); const ui64 dangerStrength = evaluateDanger(tile, *h);
if(dangerStrength) if(dangerStrength)
{ {
if(heroStrength / SAFE_ATTACK_CONSTANT > dangerStrength) if(heroStrength / SAFE_ATTACK_CONSTANT > dangerStrength)
@@ -336,23 +345,33 @@ bool isSafeToVisit(HeroPtr h, crint3 tile)
return true; return true;
} }
else else
{
return false; return false;
}
} }
return true; //there's no danger return true; //there's no danger
} }
bool canBeEmbarkmentPoint(const TerrainTile *t, bool fromWater) bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
{ {
//tile must be free of with unoccupied boat // TODO: Such information should be provided by pathfinder
return !t->blocked // Tile must be free or with unoccupied boat
|| (!fromWater && t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::BOAT); if(!t->blocked)
//do not try to board when in water sector {
return true;
}
else if(!fromWater) // do not try to board when in water sector
{
if(t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::BOAT)
return true;
}
return false;
} }
int3 whereToExplore(HeroPtr h) int3 whereToExplore(HeroPtr h)
{ {
TimeCheck tc ("where to explore"); TimeCheck tc("where to explore");
int radius = h->getSightRadius(); int radius = h->getSightRadius();
int3 hpos = h->visitablePos(); int3 hpos = h->visitablePos();
@@ -361,22 +380,24 @@ int3 whereToExplore(HeroPtr h)
//look for nearby objs -> visit them if they're close enouh //look for nearby objs -> visit them if they're close enouh
const int DIST_LIMIT = 3; const int DIST_LIMIT = 3;
std::vector<const CGObjectInstance *> nearbyVisitableObjs; std::vector<const CGObjectInstance *> nearbyVisitableObjs;
for (int x = hpos.x - DIST_LIMIT; x <= hpos.x + DIST_LIMIT; ++x) //get only local objects instead of all possible objects on the map for(int x = hpos.x - DIST_LIMIT; x <= hpos.x + DIST_LIMIT; ++x) //get only local objects instead of all possible objects on the map
{ {
for (int y = hpos.y - DIST_LIMIT; y <= hpos.y + DIST_LIMIT; ++y) for(int y = hpos.y - DIST_LIMIT; y <= hpos.y + DIST_LIMIT; ++y)
{ {
for (auto obj : cb->getVisitableObjs (int3(x,y,hpos.z), false)) for(auto obj : cb->getVisitableObjs(int3(x, y, hpos.z), false))
{ {
int3 op = obj->visitablePos(); int3 op = obj->visitablePos();
CGPath p; CGPath p;
ai->myCb->getPathsInfo(h.get())->getPath(p, op); ai->myCb->getPathsInfo(h.get())->getPath(p, op);
if (p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT) if(p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT)
if (ai->isGoodForVisit(obj, h, *sm)) {
if(ai->isGoodForVisit(obj, h, *sm))
nearbyVisitableObjs.push_back(obj); nearbyVisitableObjs.push_back(obj);
}
} }
} }
} }
vstd::removeDuplicates (nearbyVisitableObjs); //one object may occupy multiple tiles vstd::removeDuplicates(nearbyVisitableObjs); //one object may occupy multiple tiles
boost::sort(nearbyVisitableObjs, CDistanceSorter(h.get())); boost::sort(nearbyVisitableObjs, CDistanceSorter(h.get()));
if(nearbyVisitableObjs.size()) if(nearbyVisitableObjs.size())
return nearbyVisitableObjs.back()->visitablePos(); return nearbyVisitableObjs.back()->visitablePos();
@@ -385,7 +406,7 @@ int3 whereToExplore(HeroPtr h)
{ {
return ai->explorationBestNeighbour(hpos, radius, h); return ai->explorationBestNeighbour(hpos, radius, h);
} }
catch(cannotFulfillGoalException &e) catch(cannotFulfillGoalException & e)
{ {
//perform exhaustive search //perform exhaustive search
return ai->explorationNewPoint(h); return ai->explorationNewPoint(h);
@@ -394,29 +415,34 @@ int3 whereToExplore(HeroPtr h)
bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder
{ {
return cb->getTile(tileToHit)->topVisitableId() == Obj::BORDER_GATE && if(cb->getTile(tileToHit)->topVisitableId() != Obj::BORDER_GATE)
(dynamic_cast <const CGKeys *>(cb->getTile(tileToHit)->visitableObjects.back()))->wasMyColorVisited (ai->playerID); return false;
auto gate = dynamic_cast<const CGKeys *>(cb->getTile(tileToHit)->topVisitableObj());
return !gate->wasMyColorVisited(ai->playerID);
} }
bool isBlockVisitObj(const int3 &pos) bool isBlockVisitObj(const int3 & pos)
{ {
if (auto obj = cb->getTopObj(pos)) if(auto obj = cb->getTopObj(pos))
if (obj->blockVisit) //we can't stand on that object {
if(obj->blockVisit) //we can't stand on that object
return true; return true;
}
return false; return false;
} }
int howManyTilesWillBeDiscovered(const int3 &pos, int radious, CCallback * cbp) int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp)
{ //TODO: do not explore dead-end boundaries {
//TODO: do not explore dead-end boundaries
int ret = 0; int ret = 0;
for(int x = pos.x - radious; x <= pos.x + radious; x++) for(int x = pos.x - radious; x <= pos.x + radious; x++)
{ {
for(int y = pos.y - radious; y <= pos.y + radious; y++) for(int y = pos.y - radious; y <= pos.y + radious; y++)
{ {
int3 npos = int3(x,y,pos.z); int3 npos = int3(x, y, pos.z);
if(cbp->isInTheMap(npos) && pos.dist2d(npos) - 0.5 < radious && !cbp->isVisible(npos)) if(cbp->isInTheMap(npos) && pos.dist2d(npos) - 0.5 < radious && !cbp->isVisible(npos))
{ {
if (!boundaryBetweenTwoPoints (pos, npos, cbp)) if(!boundaryBetweenTwoPoints(pos, npos, cbp))
ret++; ret++;
} }
} }
@@ -425,21 +451,21 @@ int howManyTilesWillBeDiscovered(const int3 &pos, int radious, CCallback * cbp)
return ret; return ret;
} }
bool boundaryBetweenTwoPoints (int3 pos1, int3 pos2, CCallback * cbp) //determines if two points are separated by known barrier bool boundaryBetweenTwoPoints(int3 pos1, int3 pos2, CCallback * cbp) //determines if two points are separated by known barrier
{ {
int xMin = std::min (pos1.x, pos2.x); int xMin = std::min(pos1.x, pos2.x);
int xMax = std::max (pos1.x, pos2.x); int xMax = std::max(pos1.x, pos2.x);
int yMin = std::min (pos1.y, pos2.y); int yMin = std::min(pos1.y, pos2.y);
int yMax = std::max (pos1.y, pos2.y); int yMax = std::max(pos1.y, pos2.y);
for (int x = xMin; x <= xMax; ++x) for(int x = xMin; x <= xMax; ++x)
{ {
for (int y = yMin; y <= yMax; ++y) for(int y = yMin; y <= yMax; ++y)
{ {
int3 tile = int3(x, y, pos1.z); //use only on same level, ofc int3 tile = int3(x, y, pos1.z); //use only on same level, ofc
if (std::abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5) if(std::abs(pos1.dist2d(tile) - pos2.dist2d(tile)) < 1.5)
{ {
if (!(cbp->isVisible(tile) && cbp->getTile(tile)->blocked)) //if there's invisible or unblocked tile between, it's good if(!(cbp->isVisible(tile) && cbp->getTile(tile)->blocked)) //if there's invisible or unblocked tile between, it's good
return false; return false;
} }
} }
@@ -452,9 +478,9 @@ int howManyTilesWillBeDiscovered(int radious, int3 pos, crint3 dir)
return howManyTilesWillBeDiscovered(pos + dir, radious, cb.get()); return howManyTilesWillBeDiscovered(pos + dir, radious, cb.get());
} }
void getVisibleNeighbours(const std::vector<int3> &tiles, std::vector<int3> &out) void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out)
{ {
for(const int3 &tile : tiles) for(const int3 & tile : tiles)
{ {
foreach_neighbour(tile, [&](int3 neighbour) foreach_neighbour(tile, [&](int3 neighbour)
{ {
@@ -464,7 +490,7 @@ void getVisibleNeighbours(const std::vector<int3> &tiles, std::vector<int3> &out
} }
} }
ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance *t) ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance * t)
{ {
ui64 ret = 0; ui64 ret = 0;
int freeHeroSlots = GameConstants::ARMY_SIZE - h->stacksCount(); int freeHeroSlots = GameConstants::ARMY_SIZE - h->stacksCount();
@@ -478,11 +504,11 @@ ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance *t)
else else
toMove.push_back(slot.second); toMove.push_back(slot.second);
} }
boost::sort(toMove, [](const CStackInstance *lhs, const CStackInstance *rhs) boost::sort(toMove, [](const CStackInstance * lhs, const CStackInstance * rhs)
{ {
return lhs->getPower() < rhs->getPower(); return lhs->getPower() < rhs->getPower();
}); });
for (auto & stack : boost::adaptors::reverse(toMove)) for(auto & stack : boost::adaptors::reverse(toMove))
{ {
if(freeHeroSlots) if(freeHeroSlots)
{ {
@@ -500,12 +526,12 @@ bool compareHeroStrength(HeroPtr h1, HeroPtr h2)
return h1->getTotalStrength() < h2->getTotalStrength(); return h1->getTotalStrength() < h2->getTotalStrength();
} }
bool compareArmyStrength(const CArmedInstance *a1, const CArmedInstance *a2) bool compareArmyStrength(const CArmedInstance * a1, const CArmedInstance * a2)
{ {
return a1->getArmyStrength() < a2->getArmyStrength(); return a1->getArmyStrength() < a2->getArmyStrength();
} }
bool compareArtifacts(const CArtifactInstance *a1, const CArtifactInstance *a2) bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2)
{ {
auto art1 = a1->artType; auto art1 = a1->artType;
auto art2 = a2->artType; auto art2 = a2->artType;

View File

@@ -20,8 +20,8 @@
class CCallback; class CCallback;
typedef const int3& crint3; typedef const int3 & crint3;
typedef const std::string& crstring; typedef const std::string & crstring;
const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1; const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1;
const int ACTUAL_RESOURCE_COUNT = 7; const int ACTUAL_RESOURCE_COUNT = 7;
@@ -36,7 +36,7 @@ extern const int GOLD_RESERVE;
struct HeroPtr struct HeroPtr
{ {
const CGHeroInstance *h; const CGHeroInstance * h;
ObjectInstanceID hid; ObjectInstanceID hid;
public: public:
@@ -44,7 +44,7 @@ public:
HeroPtr(); HeroPtr();
HeroPtr(const CGHeroInstance *H); HeroPtr(const CGHeroInstance * H);
~HeroPtr(); ~HeroPtr();
operator bool() const operator bool() const
@@ -52,15 +52,15 @@ public:
return validAndSet(); return validAndSet();
} }
bool operator<(const HeroPtr &rhs) const; bool operator<(const HeroPtr & rhs) const;
const CGHeroInstance *operator->() const; const CGHeroInstance * operator->() const;
const CGHeroInstance *operator*() const; //not that consistent with -> but all interfaces use CGHeroInstance*, so it's convenient const CGHeroInstance * operator*() const; //not that consistent with -> but all interfaces use CGHeroInstance*, so it's convenient
const CGHeroInstance *get(bool doWeExpectNull = false) const; const CGHeroInstance * get(bool doWeExpectNull = false) const;
bool validAndSet() const; bool validAndSet() const;
template <typename Handler> void serialize(Handler &h, const int version) template<typename Handler> void serialize(Handler & h, const int version)
{ {
h & this->h; h & this->h;
h & hid; h & hid;
@@ -82,16 +82,16 @@ struct ObjectIdRef
{ {
ObjectInstanceID id; ObjectInstanceID id;
const CGObjectInstance *operator->() const; const CGObjectInstance * operator->() const;
operator const CGObjectInstance *() const; operator const CGObjectInstance *() const;
ObjectIdRef(ObjectInstanceID _id); ObjectIdRef(ObjectInstanceID _id);
ObjectIdRef(const CGObjectInstance *obj); ObjectIdRef(const CGObjectInstance * obj);
bool operator<(const ObjectIdRef &rhs) const; bool operator<(const ObjectIdRef & rhs) const;
template <typename Handler> void serialize(Handler &h, const int version) template<typename Handler> void serialize(Handler & h, const int version)
{ {
h & id; h & id;
} }
@@ -101,13 +101,14 @@ struct TimeCheck
{ {
CStopWatch time; CStopWatch time;
std::string txt; std::string txt;
TimeCheck(crstring TXT) : txt(TXT) TimeCheck(crstring TXT)
: txt(TXT)
{ {
} }
~TimeCheck() ~TimeCheck()
{ {
logAi->trace("Time of %s was %d ms.",txt,time.getDiff()); logAi->trace("Time of %s was %d ms.", txt, time.getDiff());
} }
}; };
@@ -115,7 +116,8 @@ struct TimeCheck
struct AtScopeExit struct AtScopeExit
{ {
std::function<void()> foo; std::function<void()> foo;
AtScopeExit(const std::function<void()> &FOO) : foo(FOO) AtScopeExit(const std::function<void()> & FOO)
: foo(FOO)
{} {}
~AtScopeExit() ~AtScopeExit()
{ {
@@ -126,48 +128,50 @@ struct AtScopeExit
class ObjsVector : public std::vector<ObjectIdRef> class ObjsVector : public std::vector<ObjectIdRef>
{ {
private:
}; };
template<int id> template<int id>
bool objWithID(const CGObjectInstance *obj) bool objWithID(const CGObjectInstance * obj)
{ {
return obj->ID == id; return obj->ID == id;
} }
void foreach_tile_pos(std::function<void(const int3& pos)> foo); void foreach_tile_pos(std::function<void(const int3 & pos)> foo);
void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3& pos)> foo); // avoid costly retrieval of thread-specific pointer void foreach_tile_pos(CCallback * cbp, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
void foreach_neighbour(const int3 &pos, std::function<void(const int3& pos)> foo); void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> foo);
void foreach_neighbour(CCallback * cbp, const int3 &pos, std::function<void(CCallback * cbp, const int3& pos)> foo); // avoid costly retrieval of thread-specific pointer void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
int howManyTilesWillBeDiscovered(const int3 &pos, int radious, CCallback * cbp); int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp);
int howManyTilesWillBeDiscovered(int radious, int3 pos, crint3 dir); int howManyTilesWillBeDiscovered(int radious, int3 pos, crint3 dir);
void getVisibleNeighbours(const std::vector<int3> &tiles, std::vector<int3> &out); void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out);
bool canBeEmbarkmentPoint(const TerrainTile *t, bool fromWater); bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater);
bool isBlockedBorderGate(int3 tileToHit); bool isBlockedBorderGate(int3 tileToHit);
bool isBlockVisitObj(const int3 &pos); bool isBlockVisitObj(const int3 & pos);
bool isWeeklyRevisitable (const CGObjectInstance * obj); bool isWeeklyRevisitable(const CGObjectInstance * obj);
bool shouldVisit (HeroPtr h, const CGObjectInstance * obj); bool shouldVisit(HeroPtr h, const CGObjectInstance * obj);
ui64 evaluateDanger(const CGObjectInstance *obj); ui64 evaluateDanger(const CGObjectInstance * obj);
ui64 evaluateDanger(crint3 tile, const CGHeroInstance *visitor); ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor);
bool isSafeToVisit(HeroPtr h, crint3 tile); bool isSafeToVisit(HeroPtr h, crint3 tile);
bool boundaryBetweenTwoPoints (int3 pos1, int3 pos2, CCallback * cbp); bool boundaryBetweenTwoPoints(int3 pos1, int3 pos2, CCallback * cbp);
bool compareMovement(HeroPtr lhs, HeroPtr rhs); bool compareMovement(HeroPtr lhs, HeroPtr rhs);
bool compareHeroStrength(HeroPtr h1, HeroPtr h2); bool compareHeroStrength(HeroPtr h1, HeroPtr h2);
bool compareArmyStrength(const CArmedInstance *a1, const CArmedInstance *a2); bool compareArmyStrength(const CArmedInstance * a1, const CArmedInstance * a2);
bool compareArtifacts(const CArtifactInstance *a1, const CArtifactInstance *a2); bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2);
ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance *t); ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance * t);
int3 whereToExplore(HeroPtr h); int3 whereToExplore(HeroPtr h);
class CDistanceSorter class CDistanceSorter
{ {
const CGHeroInstance * hero; const CGHeroInstance * hero;
public:
CDistanceSorter(const CGHeroInstance * hero): hero(hero) {}
bool operator ()(const CGObjectInstance *lhs, const CGObjectInstance *rhs); public:
CDistanceSorter(const CGHeroInstance * hero)
: hero(hero)
{
}
bool operator()(const CGObjectInstance * lhs, const CGObjectInstance * rhs);
}; };

View File

@@ -29,9 +29,7 @@ class Engine;
class InputVariable; class InputVariable;
class CGTownInstance; class CGTownInstance;
//using namespace Goals; FuzzyHelper * fh;
FuzzyHelper *fh;
extern boost::thread_specific_ptr<CCallback> cb; extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<VCAI> ai; extern boost::thread_specific_ptr<VCAI> ai;
@@ -47,7 +45,7 @@ void engineBase::configure()
logAi->info(engine.toString()); logAi->info(engine.toString());
} }
void engineBase::addRule(const std::string &txt) void engineBase::addRule(const std::string & txt)
{ {
rules.addRule(fl::Rule::parse(txt, &engine)); rules.addRule(fl::Rule::parse(txt, &engine));
} }
@@ -58,7 +56,7 @@ struct armyStructure
ui32 maxSpeed; ui32 maxSpeed;
}; };
armyStructure evaluateArmyStructure (const CArmedInstance * army) armyStructure evaluateArmyStructure(const CArmedInstance * army)
{ {
ui64 totalStrenght = army->getArmyStrength(); ui64 totalStrenght = army->getArmyStrength();
double walkersStrenght = 0; double walkersStrenght = 0;
@@ -69,17 +67,17 @@ armyStructure evaluateArmyStructure (const CArmedInstance * army)
for(auto s : army->Slots()) for(auto s : army->Slots())
{ {
bool walker = true; bool walker = true;
if (s.second->type->hasBonusOfType(Bonus::SHOOTER)) if(s.second->type->hasBonusOfType(Bonus::SHOOTER))
{ {
shootersStrenght += s.second->getPower(); shootersStrenght += s.second->getPower();
walker = false; walker = false;
} }
if (s.second->type->hasBonusOfType(Bonus::FLYING)) if(s.second->type->hasBonusOfType(Bonus::FLYING))
{ {
flyersStrenght += s.second->getPower(); flyersStrenght += s.second->getPower();
walker = false; walker = false;
} }
if (walker) if(walker)
walkersStrenght += s.second->getPower(); walkersStrenght += s.second->getPower();
vstd::amax(maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED)); vstd::amax(maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
@@ -106,7 +104,6 @@ void FuzzyHelper::initTacticalAdvantage()
{ {
try try
{ {
ta.ourShooters = new fl::InputVariable("OurShooters"); ta.ourShooters = new fl::InputVariable("OurShooters");
ta.ourWalkers = new fl::InputVariable("OurWalkers"); ta.ourWalkers = new fl::InputVariable("OurWalkers");
ta.ourFlyers = new fl::InputVariable("OurFlyers"); ta.ourFlyers = new fl::InputVariable("OurFlyers");
@@ -115,12 +112,12 @@ void FuzzyHelper::initTacticalAdvantage()
ta.enemyFlyers = new fl::InputVariable("EnemyFlyers"); ta.enemyFlyers = new fl::InputVariable("EnemyFlyers");
//Tactical advantage calculation //Tactical advantage calculation
std::vector<fl::InputVariable*> helper = std::vector<fl::InputVariable *> helper =
{ {
ta.ourShooters, ta.ourWalkers, ta.ourFlyers, ta.enemyShooters, ta.enemyWalkers, ta.enemyFlyers ta.ourShooters, ta.ourWalkers, ta.ourFlyers, ta.enemyShooters, ta.enemyWalkers, ta.enemyFlyers
}; };
for (auto val : helper) for(auto val : helper)
{ {
ta.engine.addInputVariable(val); ta.engine.addInputVariable(val);
val->addTerm(new fl::Ramp("FEW", 0.6, 0.0)); val->addTerm(new fl::Ramp("FEW", 0.6, 0.0));
@@ -133,7 +130,7 @@ void FuzzyHelper::initTacticalAdvantage()
helper = {ta.ourSpeed, ta.enemySpeed}; helper = {ta.ourSpeed, ta.enemySpeed};
for (auto val : helper) for(auto val : helper)
{ {
ta.engine.addInputVariable(val); ta.engine.addInputVariable(val);
val->addTerm(new fl::Ramp("LOW", 6.5, 3)); val->addTerm(new fl::Ramp("LOW", 6.5, 3));
@@ -145,27 +142,26 @@ void FuzzyHelper::initTacticalAdvantage()
ta.castleWalls = new fl::InputVariable("CastleWalls"); ta.castleWalls = new fl::InputVariable("CastleWalls");
ta.engine.addInputVariable(ta.castleWalls); ta.engine.addInputVariable(ta.castleWalls);
{ {
fl::Rectangle* none = new fl::Rectangle("NONE", CGTownInstance::NONE, CGTownInstance::NONE + (CGTownInstance::FORT - CGTownInstance::NONE) * 0.5f); fl::Rectangle * none = new fl::Rectangle("NONE", CGTownInstance::NONE, CGTownInstance::NONE + (CGTownInstance::FORT - CGTownInstance::NONE) * 0.5f);
ta.castleWalls->addTerm(none); ta.castleWalls->addTerm(none);
fl::Trapezoid* medium = new fl::Trapezoid("MEDIUM", (CGTownInstance::FORT - CGTownInstance::NONE) * 0.5f, CGTownInstance::FORT, fl::Trapezoid * medium = new fl::Trapezoid("MEDIUM", (CGTownInstance::FORT - CGTownInstance::NONE) * 0.5f, CGTownInstance::FORT,
CGTownInstance::CITADEL, CGTownInstance::CITADEL + (CGTownInstance::CASTLE - CGTownInstance::CITADEL) * 0.5f); CGTownInstance::CITADEL, CGTownInstance::CITADEL + (CGTownInstance::CASTLE - CGTownInstance::CITADEL) * 0.5f);
ta.castleWalls->addTerm(medium); ta.castleWalls->addTerm(medium);
fl::Ramp* high = new fl::Ramp("HIGH", CGTownInstance::CITADEL - 0.1, CGTownInstance::CASTLE); fl::Ramp * high = new fl::Ramp("HIGH", CGTownInstance::CITADEL - 0.1, CGTownInstance::CASTLE);
ta.castleWalls->addTerm(high); ta.castleWalls->addTerm(high);
ta.castleWalls->setRange(CGTownInstance::NONE, CGTownInstance::CASTLE); ta.castleWalls->setRange(CGTownInstance::NONE, CGTownInstance::CASTLE);
} }
ta.bankPresent = new fl::InputVariable("Bank"); ta.bankPresent = new fl::InputVariable("Bank");
ta.engine.addInputVariable(ta.bankPresent); ta.engine.addInputVariable(ta.bankPresent);
{ {
fl::Rectangle* termFalse = new fl::Rectangle("FALSE", 0.0, 0.5f); fl::Rectangle * termFalse = new fl::Rectangle("FALSE", 0.0, 0.5f);
ta.bankPresent->addTerm(termFalse); ta.bankPresent->addTerm(termFalse);
fl::Rectangle* termTrue = new fl::Rectangle("TRUE", 0.5f, 1); fl::Rectangle * termTrue = new fl::Rectangle("TRUE", 0.5f, 1);
ta.bankPresent->addTerm(termTrue); ta.bankPresent->addTerm(termTrue);
ta.bankPresent->setRange(0, 1); ta.bankPresent->setRange(0, 1);
} }
@@ -197,23 +193,23 @@ void FuzzyHelper::initTacticalAdvantage()
ta.addRule("if CastleWalls is MEDIUM and OurShooters is MANY and EnemyWalkers is MANY then Threat is LOW"); ta.addRule("if CastleWalls is MEDIUM and OurShooters is MANY and EnemyWalkers is MANY then Threat is LOW");
} }
catch (fl::Exception & pe) catch(fl::Exception & pe)
{ {
logAi->error("initTacticalAdvantage: %s", pe.getWhat()); logAi->error("initTacticalAdvantage: %s", pe.getWhat());
} }
} }
ui64 FuzzyHelper::estimateBankDanger (const CBank * bank) ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
{ {
//this one is not fuzzy anymore, just calculate weighted average //this one is not fuzzy anymore, just calculate weighted average
auto objectInfo = VLC->objtypeh->getHandlerFor(bank->ID, bank->subID)->getObjectInfo(bank->appearance); auto objectInfo = VLC->objtypeh->getHandlerFor(bank->ID, bank->subID)->getObjectInfo(bank->appearance);
CBankInfo * bankInfo = dynamic_cast<CBankInfo *> (objectInfo.get()); CBankInfo * bankInfo = dynamic_cast<CBankInfo *>(objectInfo.get());
ui64 totalStrength = 0; ui64 totalStrength = 0;
ui8 totalChance = 0; ui8 totalChance = 0;
for (auto config : bankInfo->getPossibleGuards()) for(auto config : bankInfo->getPossibleGuards())
{ {
totalStrength += config.second.totalStrength * config.first; totalStrength += config.second.totalStrength * config.first;
totalChance += config.first; totalChance += config.first;
@@ -222,7 +218,7 @@ ui64 FuzzyHelper::estimateBankDanger (const CBank * bank)
} }
float FuzzyHelper::getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy) float FuzzyHelper::getTacticalAdvantage(const CArmedInstance * we, const CArmedInstance * enemy)
{ {
float output = 1; float output = 1;
try try
@@ -240,17 +236,15 @@ float FuzzyHelper::getTacticalAdvantage (const CArmedInstance *we, const CArmedI
ta.enemyFlyers->setValue(enemyStructure.flyers); ta.enemyFlyers->setValue(enemyStructure.flyers);
ta.enemySpeed->setValue(enemyStructure.maxSpeed); ta.enemySpeed->setValue(enemyStructure.maxSpeed);
bool bank = dynamic_cast<const CBank*> (enemy); bool bank = dynamic_cast<const CBank *>(enemy);
if (bank) if(bank)
ta.bankPresent->setValue(1); ta.bankPresent->setValue(1);
else else
ta.bankPresent->setValue(0); ta.bankPresent->setValue(0);
const CGTownInstance * fort = dynamic_cast<const CGTownInstance*> (enemy); const CGTownInstance * fort = dynamic_cast<const CGTownInstance *>(enemy);
if (fort) if(fort)
{
ta.castleWalls->setValue(fort->fortLevel()); ta.castleWalls->setValue(fort->fortLevel());
}
else else
ta.castleWalls->setValue(0); ta.castleWalls->setValue(0);
@@ -258,18 +252,18 @@ float FuzzyHelper::getTacticalAdvantage (const CArmedInstance *we, const CArmedI
ta.engine.process(); ta.engine.process();
output = ta.threat->getValue(); output = ta.threat->getValue();
} }
catch (fl::Exception & fe) catch(fl::Exception & fe)
{ {
logAi->error("getTacticalAdvantage: %s ",fe.getWhat()); logAi->error("getTacticalAdvantage: %s ", fe.getWhat());
} }
if (output < 0 || (output != output)) if(output < 0 || (output != output))
{ {
fl::InputVariable* tab[] = {ta.bankPresent, ta.castleWalls, ta.ourWalkers, ta.ourShooters, ta.ourFlyers, ta.ourSpeed, ta.enemyWalkers, ta.enemyShooters, ta.enemyFlyers, ta.enemySpeed}; fl::InputVariable * tab[] = {ta.bankPresent, ta.castleWalls, ta.ourWalkers, ta.ourShooters, ta.ourFlyers, ta.ourSpeed, ta.enemyWalkers, ta.enemyShooters, ta.enemyFlyers, ta.enemySpeed};
std::string names[] = {"bankPresent", "castleWalls", "ourWalkers", "ourShooters", "ourFlyers", "ourSpeed", "enemyWalkers", "enemyShooters", "enemyFlyers", "enemySpeed" }; std::string names[] = {"bankPresent", "castleWalls", "ourWalkers", "ourShooters", "ourFlyers", "ourSpeed", "enemyWalkers", "enemyShooters", "enemyFlyers", "enemySpeed" };
std::stringstream log("Warning! Fuzzy engine doesn't cover this set of parameters: "); std::stringstream log("Warning! Fuzzy engine doesn't cover this set of parameters: ");
for (int i = 0; i < boost::size(tab); i++) for(int i = 0; i < boost::size(tab); i++)
log << names[i] << ": " << tab[i]->getValue() << " "; log << names[i] << ": " << tab[i]->getValue() << " ";
logAi->error(log.str()); logAi->error(log.str());
assert(false); assert(false);
@@ -296,9 +290,9 @@ FuzzyHelper::TacticalAdvantage::~TacticalAdvantage()
//std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec) //std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec)
Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec) Goals::TSubgoal FuzzyHelper::chooseSolution(Goals::TGoalVec vec)
{ {
if (vec.empty()) //no possibilities found if(vec.empty()) //no possibilities found
return sptr(Goals::Invalid()); return sptr(Goals::Invalid());
ai->cachedSectorMaps.clear(); ai->cachedSectorMaps.clear();
@@ -308,9 +302,9 @@ Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
{ {
return lhs->hero.h < rhs->hero.h; return lhs->hero.h < rhs->hero.h;
}; };
boost::sort (vec, sortByHeroes); boost::sort(vec, sortByHeroes);
for (auto g : vec) for(auto g : vec)
{ {
setPriority(g); setPriority(g);
} }
@@ -319,16 +313,16 @@ Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
{ {
return lhs->priority < rhs->priority; return lhs->priority < rhs->priority;
}; };
boost::sort (vec, compareGoals); boost::sort(vec, compareGoals);
return vec.back(); return vec.back();
} }
float FuzzyHelper::evaluate (Goals::Explore & g) float FuzzyHelper::evaluate(Goals::Explore & g)
{ {
return 1; return 1;
} }
float FuzzyHelper::evaluate (Goals::RecruitHero & g) float FuzzyHelper::evaluate(Goals::RecruitHero & g)
{ {
return 1; //just try to recruit hero as one of options return 1; //just try to recruit hero as one of options
} }
@@ -354,8 +348,8 @@ void FuzzyHelper::initVisitTile()
vt.value->setMinimum(0); vt.value->setMinimum(0);
vt.value->setMaximum(5); vt.value->setMaximum(5);
std::vector<fl::InputVariable*> helper = {vt.strengthRatio, vt.heroStrength, vt.turnDistance, vt.missionImportance, vt.estimatedReward}; std::vector<fl::InputVariable *> helper = {vt.strengthRatio, vt.heroStrength, vt.turnDistance, vt.missionImportance, vt.estimatedReward};
for (auto val : helper) for(auto val : helper)
{ {
vt.engine.addInputVariable(val); vt.engine.addInputVariable(val);
} }
@@ -363,7 +357,7 @@ void FuzzyHelper::initVisitTile()
vt.strengthRatio->addTerm(new fl::Ramp("LOW", SAFE_ATTACK_CONSTANT, 0)); vt.strengthRatio->addTerm(new fl::Ramp("LOW", SAFE_ATTACK_CONSTANT, 0));
vt.strengthRatio->addTerm(new fl::Ramp("HIGH", SAFE_ATTACK_CONSTANT, SAFE_ATTACK_CONSTANT * 3)); vt.strengthRatio->addTerm(new fl::Ramp("HIGH", SAFE_ATTACK_CONSTANT, SAFE_ATTACK_CONSTANT * 3));
vt.strengthRatio->setRange(0, SAFE_ATTACK_CONSTANT * 3 ); vt.strengthRatio->setRange(0, SAFE_ATTACK_CONSTANT * 3);
//strength compared to our main hero //strength compared to our main hero
vt.heroStrength->addTerm(new fl::Ramp("LOW", 0.2, 0)); vt.heroStrength->addTerm(new fl::Ramp("LOW", 0.2, 0));
@@ -386,11 +380,11 @@ void FuzzyHelper::initVisitTile()
vt.estimatedReward->setRange(0.0, 5.0); vt.estimatedReward->setRange(0.0, 5.0);
//an issue: in 99% cases this outputs center of mass (2.5) regardless of actual input :/ //an issue: in 99% cases this outputs center of mass (2.5) regardless of actual input :/
//should be same as "mission Importance" to keep consistency //should be same as "mission Importance" to keep consistency
vt.value->addTerm(new fl::Ramp("LOW", 2.5, 0)); vt.value->addTerm(new fl::Ramp("LOW", 2.5, 0));
vt.value->addTerm(new fl::Triangle("MEDIUM", 2, 3)); //can't be center of mass :/ vt.value->addTerm(new fl::Triangle("MEDIUM", 2, 3)); //can't be center of mass :/
vt.value->addTerm(new fl::Ramp("HIGH", 2.5, 5)); vt.value->addTerm(new fl::Ramp("HIGH", 2.5, 5));
vt.value->setRange(0.0,5.0); vt.value->setRange(0.0, 5.0);
//use unarmed scouts if possible //use unarmed scouts if possible
vt.addRule("if strengthRatio is HIGH and heroStrength is LOW then Value is very HIGH"); vt.addRule("if strengthRatio is HIGH and heroStrength is LOW then Value is very HIGH");
@@ -415,43 +409,47 @@ void FuzzyHelper::initVisitTile()
vt.addRule("if estimatedReward is HIGH then Value is very HIGH"); vt.addRule("if estimatedReward is HIGH then Value is very HIGH");
vt.addRule("if estimatedReward is LOW then Value is somewhat LOW"); vt.addRule("if estimatedReward is LOW then Value is somewhat LOW");
} }
catch (fl::Exception & fe) catch(fl::Exception & fe)
{ {
logAi->error("visitTile: %s",fe.getWhat()); logAi->error("visitTile: %s", fe.getWhat());
} }
} }
float FuzzyHelper::evaluate (Goals::VisitTile & g) float FuzzyHelper::evaluate(Goals::VisitTile & g)
{ {
//we assume that hero is already set and we want to choose most suitable one for the mission //we assume that hero is already set and we want to choose most suitable one for the mission
if (!g.hero) if(!g.hero)
return 0; return 0;
//assert(cb->isInTheMap(g.tile)); //assert(cb->isInTheMap(g.tile));
float turns = 0; float turns = 0;
float distance = CPathfinderHelper::getMovementCost(g.hero.h, g.tile); float distance = CPathfinderHelper::getMovementCost(g.hero.h, g.tile);
if (!distance) //we stand on that tile if(!distance) //we stand on that tile
{
turns = 0; turns = 0;
}
else else
{ {
if (distance < g.hero->movement) //we can move there within one turn if(distance < g.hero->movement) //we can move there within one turn
turns = (fl::scalar)distance / g.hero->movement; turns = (fl::scalar)distance / g.hero->movement;
else else
turns = 1 + (fl::scalar)(distance - g.hero->movement) / g.hero->maxMovePoints(true); //bool on land? turns = 1 + (fl::scalar)(distance - g.hero->movement) / g.hero->maxMovePoints(true); //bool on land?
} }
float missionImportance = 0; float missionImportance = 0;
if (vstd::contains(ai->lockedHeroes, g.hero)) if(vstd::contains(ai->lockedHeroes, g.hero))
missionImportance = ai->lockedHeroes[g.hero]->priority; missionImportance = ai->lockedHeroes[g.hero]->priority;
float strengthRatio = 10.0f; //we are much stronger than enemy float strengthRatio = 10.0f; //we are much stronger than enemy
ui64 danger = evaluateDanger (g.tile, g.hero.h); ui64 danger = evaluateDanger(g.tile, g.hero.h);
if (danger) if(danger)
strengthRatio = (fl::scalar)g.hero.h->getTotalStrength() / danger; strengthRatio = (fl::scalar)g.hero.h->getTotalStrength() / danger;
float tilePriority = 0; float tilePriority = 0;
if(g.objid == -1) if(g.objid == -1)
{
vt.estimatedReward->setEnabled(false); vt.estimatedReward->setEnabled(false);
}
else if(g.objid == Obj::TOWN) //TODO: move to getObj eventually and add appropiate logic there else if(g.objid == Obj::TOWN) //TODO: move to getObj eventually and add appropiate logic there
{ {
vt.estimatedReward->setEnabled(true); vt.estimatedReward->setEnabled(true);
@@ -470,41 +468,41 @@ float FuzzyHelper::evaluate (Goals::VisitTile & g)
//engine.process(VISIT_TILE); //TODO: Process only Visit_Tile //engine.process(VISIT_TILE); //TODO: Process only Visit_Tile
g.priority = vt.value->getValue(); g.priority = vt.value->getValue();
} }
catch (fl::Exception & fe) catch(fl::Exception & fe)
{ {
logAi->error("evaluate VisitTile: %s",fe.getWhat()); logAi->error("evaluate VisitTile: %s", fe.getWhat());
} }
assert (g.priority >= 0); assert(g.priority >= 0);
return g.priority; return g.priority;
} }
float FuzzyHelper::evaluate (Goals::VisitHero & g) float FuzzyHelper::evaluate(Goals::VisitHero & g)
{ {
auto obj = cb->getObj(ObjectInstanceID(g.objid)); //we assume for now that these goals are similar auto obj = cb->getObj(ObjectInstanceID(g.objid)); //we assume for now that these goals are similar
if (!obj) if(!obj)
return -100; //hero died in the meantime return -100; //hero died in the meantime
//TODO: consider direct copy (constructor?) //TODO: consider direct copy (constructor?)
g.setpriority(Goals::VisitTile(obj->visitablePos()).sethero(g.hero).setisAbstract(g.isAbstract).accept(this)); g.setpriority(Goals::VisitTile(obj->visitablePos()).sethero(g.hero).setisAbstract(g.isAbstract).accept(this));
return g.priority; return g.priority;
} }
float FuzzyHelper::evaluate (Goals::GatherArmy & g) float FuzzyHelper::evaluate(Goals::GatherArmy & g)
{ {
//the more army we need, the more important goal //the more army we need, the more important goal
//the more army we lack, the less important goal //the more army we lack, the less important goal
float army = g.hero->getArmyStrength(); float army = g.hero->getArmyStrength();
float ratio = g.value / std::max(g.value - army, 2000.0f); //2000 is about the value of hero recruited from tavern float ratio = g.value / std::max(g.value - army, 2000.0f); //2000 is about the value of hero recruited from tavern
return 5 * (ratio / (ratio + 2)); //so 50% army gives 2.5, asymptotic 5 return 5 * (ratio / (ratio + 2)); //so 50% army gives 2.5, asymptotic 5
} }
float FuzzyHelper::evaluate (Goals::ClearWayTo & g) float FuzzyHelper::evaluate(Goals::ClearWayTo & g)
{ {
if (!g.hero.h) if(!g.hero.h)
throw cannotFulfillGoalException("ClearWayTo called without hero!"); throw cannotFulfillGoalException("ClearWayTo called without hero!");
int3 t = ai->getCachedSectorMap(g.hero)->firstTileToGet(g.hero, g.tile); int3 t = ai->getCachedSectorMap(g.hero)->firstTileToGet(g.hero, g.tile);
if (t.valid()) if(t.valid())
{ {
if (isSafeToVisit(g.hero, t)) if(isSafeToVisit(g.hero, t))
{ {
g.setpriority(Goals::VisitTile(g.tile).sethero(g.hero).setisAbstract(g.isAbstract).accept(this)); g.setpriority(Goals::VisitTile(g.tile).sethero(g.hero).setisAbstract(g.isAbstract).accept(this));
} }
@@ -520,32 +518,32 @@ float FuzzyHelper::evaluate (Goals::ClearWayTo & g)
} }
float FuzzyHelper::evaluate (Goals::BuildThis & g) float FuzzyHelper::evaluate(Goals::BuildThis & g)
{ {
return 1; return 1;
} }
float FuzzyHelper::evaluate (Goals::DigAtTile & g) float FuzzyHelper::evaluate(Goals::DigAtTile & g)
{ {
return 0; return 0;
} }
float FuzzyHelper::evaluate (Goals::CollectRes & g) float FuzzyHelper::evaluate(Goals::CollectRes & g)
{ {
return 0; return 0;
} }
float FuzzyHelper::evaluate (Goals::Build & g) float FuzzyHelper::evaluate(Goals::Build & g)
{ {
return 0; return 0;
} }
float FuzzyHelper::evaluate (Goals::Invalid & g) float FuzzyHelper::evaluate(Goals::Invalid & g)
{ {
return -1e10; return -1e10;
} }
float FuzzyHelper::evaluate (Goals::AbstractGoal & g) float FuzzyHelper::evaluate(Goals::AbstractGoal & g)
{ {
logAi->warn("Cannot evaluate goal %s", g.name()); logAi->warn("Cannot evaluate goal %s", g.name());
return g.priority; return g.priority;
} }
void FuzzyHelper::setPriority (Goals::TSubgoal & g) void FuzzyHelper::setPriority(Goals::TSubgoal & g)
{ {
g->setpriority(g->accept(this)); //this enforces returned value is set g->setpriority(g->accept(this)); //this enforces returned value is set
} }

View File

@@ -24,7 +24,7 @@ public:
engineBase(); engineBase();
void configure(); void configure();
void addRule(const std::string &txt); void addRule(const std::string & txt);
}; };
class FuzzyHelper class FuzzyHelper
@@ -65,23 +65,23 @@ public:
void initTacticalAdvantage(); void initTacticalAdvantage();
void initVisitTile(); void initVisitTile();
float evaluate (Goals::Explore & g); float evaluate(Goals::Explore & g);
float evaluate (Goals::RecruitHero & g); float evaluate(Goals::RecruitHero & g);
float evaluate (Goals::VisitTile & g); float evaluate(Goals::VisitTile & g);
float evaluate (Goals::VisitHero & g); float evaluate(Goals::VisitHero & g);
float evaluate (Goals::BuildThis & g); float evaluate(Goals::BuildThis & g);
float evaluate (Goals::DigAtTile & g); float evaluate(Goals::DigAtTile & g);
float evaluate (Goals::CollectRes & g); float evaluate(Goals::CollectRes & g);
float evaluate (Goals::Build & g); float evaluate(Goals::Build & g);
float evaluate (Goals::GatherArmy & g); float evaluate(Goals::GatherArmy & g);
float evaluate (Goals::ClearWayTo & g); float evaluate(Goals::ClearWayTo & g);
float evaluate (Goals::Invalid & g); float evaluate(Goals::Invalid & g);
float evaluate (Goals::AbstractGoal & g); float evaluate(Goals::AbstractGoal & g);
void setPriority (Goals::TSubgoal & g); void setPriority(Goals::TSubgoal & g);
ui64 estimateBankDanger (const CBank * bank); ui64 estimateBankDanger(const CBank * bank);
float getTacticalAdvantage (const CArmedInstance *we, const CArmedInstance *enemy); //returns factor how many times enemy is stronger than us float getTacticalAdvantage(const CArmedInstance * we, const CArmedInstance * enemy); //returns factor how many times enemy is stronger than us
Goals::TSubgoal chooseSolution (Goals::TGoalVec vec); Goals::TSubgoal chooseSolution(Goals::TGoalVec vec);
//std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec); //std::shared_ptr<AbstractGoal> chooseSolution (std::vector<std::shared_ptr<AbstractGoal>> & vec);
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -21,12 +21,12 @@ class FuzzyHelper;
namespace Goals namespace Goals
{ {
class AbstractGoal; class AbstractGoal;
class VisitTile; class VisitTile;
typedef std::shared_ptr<Goals::AbstractGoal> TSubgoal; typedef std::shared_ptr<Goals::AbstractGoal> TSubgoal;
typedef std::vector<TSubgoal> TGoalVec; typedef std::vector<TSubgoal> TGoalVec;
enum EGoals enum EGoals
{ {
INVALID = -1, INVALID = -1,
WIN, DO_NOT_LOSE, CONQUER, BUILD, //build needs to get a real reasoning WIN, DO_NOT_LOSE, CONQUER, BUILD, //build needs to get a real reasoning
@@ -78,7 +78,8 @@ public:
const CGTownInstance *town; VSETTER(CGTownInstance *, town) const CGTownInstance *town; VSETTER(CGTownInstance *, town)
int bid; VSETTER(int, bid) int bid; VSETTER(int, bid)
AbstractGoal (EGoals goal = INVALID) : goalType (goal) AbstractGoal(EGoals goal = INVALID)
: goalType (goal)
{ {
priority = 0; priority = 0;
isElementar = false; isElementar = false;
@@ -91,35 +92,47 @@ public:
town = nullptr; town = nullptr;
bid = -1; bid = -1;
} }
virtual ~AbstractGoal(){}; virtual ~AbstractGoal(){}
//FIXME: abstract goal should be abstract, but serializer fails to instantiate subgoals in such case //FIXME: abstract goal should be abstract, but serializer fails to instantiate subgoals in such case
virtual AbstractGoal * clone() const {return const_cast<AbstractGoal*>(this);}; virtual AbstractGoal * clone() const
virtual TGoalVec getAllPossibleSubgoals() {TGoalVec vec; return vec;}; {
virtual TSubgoal whatToDoToAchieve() {return sptr(AbstractGoal());}; return const_cast<AbstractGoal *>(this);
}
virtual TGoalVec getAllPossibleSubgoals()
{
return TGoalVec();
}
virtual TSubgoal whatToDoToAchieve()
{
return sptr(AbstractGoal());
}
EGoals goalType; EGoals goalType;
std::string name() const; std::string name() const;
virtual std::string completeMessage() const {return "This goal is unspecified!";}; virtual std::string completeMessage() const
{
return "This goal is unspecified!";
}
bool invalid() const; bool invalid() const;
static TSubgoal goVisitOrLookFor(const CGObjectInstance *obj); //if obj is nullptr, then we'll explore static TSubgoal goVisitOrLookFor(const CGObjectInstance * obj); //if obj is nullptr, then we'll explore
static TSubgoal lookForArtSmart(int aid); //checks non-standard ways of obtaining art (merchants, quests, etc.) static TSubgoal lookForArtSmart(int aid); //checks non-standard ways of obtaining art (merchants, quests, etc.)
static TSubgoal tryRecruitHero(); static TSubgoal tryRecruitHero();
///Visitor pattern ///Visitor pattern
//TODO: make accept work for std::shared_ptr... somehow //TODO: make accept work for std::shared_ptr... somehow
virtual void accept (VCAI * ai); //unhandled goal will report standard error virtual void accept(VCAI * ai); //unhandled goal will report standard error
virtual float accept (FuzzyHelper * f); virtual float accept(FuzzyHelper * f);
virtual bool operator== (AbstractGoal &g); virtual bool operator==(AbstractGoal & g);
virtual bool fulfillsMe (Goals::TSubgoal goal) //TODO: multimethod instead of type check virtual bool fulfillsMe(Goals::TSubgoal goal) //TODO: multimethod instead of type check
{ {
return false; return false;
} }
template <typename Handler> void serialize(Handler &h, const int version) template<typename Handler> void serialize(Handler & h, const int version)
{ {
h & goalType; h & goalType;
h & isElementar; h & isElementar;
@@ -136,10 +149,10 @@ public:
} }
}; };
template <typename T> class CGoal : public AbstractGoal template<typename T> class CGoal : public AbstractGoal
{ {
public: public:
CGoal<T> (EGoals goal = INVALID) : AbstractGoal (goal) CGoal<T>(EGoals goal = INVALID) : AbstractGoal(goal)
{ {
priority = 0; priority = 0;
isElementar = false; isElementar = false;
@@ -164,12 +177,12 @@ public:
OSETTER(CGTownInstance *, town) OSETTER(CGTownInstance *, town)
OSETTER(int, bid) OSETTER(int, bid)
void accept (VCAI * ai) override; void accept(VCAI * ai) override;
float accept (FuzzyHelper * f) override; float accept(FuzzyHelper * f) override;
CGoal<T> * clone() const override CGoal<T> * clone() const override
{ {
return new T(static_cast<T const&>(*this)); //casting enforces template instantiation return new T(static_cast<T const &>(*this)); //casting enforces template instantiation
} }
TSubgoal iAmElementar() TSubgoal iAmElementar()
{ {
@@ -178,9 +191,9 @@ public:
ptr.reset(clone()); ptr.reset(clone());
return ptr; return ptr;
} }
template <typename Handler> void serialize(Handler &h, const int version) template<typename Handler> void serialize(Handler & h, const int version)
{ {
h & static_cast<AbstractGoal&> (*this); h & static_cast<AbstractGoal &>(*this);
//h & goalType & isElementar & isAbstract & priority; //h & goalType & isElementar & isAbstract & priority;
//h & value & resID & objid & aid & tile & hero & town & bid; //h & value & resID & objid & aid & tile & hero & town & bid;
} }
@@ -188,189 +201,403 @@ public:
class Invalid : public CGoal<Invalid> class Invalid : public CGoal<Invalid>
{ {
public: public:
Invalid() : CGoal (Goals::INVALID) {priority = -1e10;}; Invalid()
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; : CGoal(Goals::INVALID)
{
priority = -1e10;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class Win : public CGoal<Win> class Win : public CGoal<Win>
{ {
public: public:
Win() : CGoal (Goals::WIN) {priority = 100;}; Win()
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; : CGoal(Goals::WIN)
{
priority = 100;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class NotLose : public CGoal<NotLose> class NotLose : public CGoal<NotLose>
{ {
public: public:
NotLose() : CGoal (Goals::DO_NOT_LOSE) {priority = 100;}; NotLose()
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; : CGoal(Goals::DO_NOT_LOSE)
{
priority = 100;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
//TSubgoal whatToDoToAchieve() override; //TSubgoal whatToDoToAchieve() override;
}; };
class Conquer : public CGoal<Conquer> class Conquer : public CGoal<Conquer>
{ {
public: public:
Conquer() : CGoal (Goals::CONQUER) {priority = 10;}; Conquer()
: CGoal(Goals::CONQUER)
{
priority = 10;
}
TGoalVec getAllPossibleSubgoals() override; TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class Build : public CGoal<Build> class Build : public CGoal<Build>
{ {
public: public:
Build() : CGoal (Goals::BUILD) {priority = 1;}; Build()
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; : CGoal(Goals::BUILD)
{
priority = 1;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class Explore : public CGoal<Explore> class Explore : public CGoal<Explore>
{ {
public: public:
Explore() : CGoal (Goals::EXPLORE){priority = 1;}; Explore()
Explore(HeroPtr h) : CGoal (Goals::EXPLORE){hero = h; priority = 1;}; : CGoal(Goals::EXPLORE)
{
priority = 1;
}
Explore(HeroPtr h)
: CGoal(Goals::EXPLORE)
{
hero = h;
priority = 1;
}
TGoalVec getAllPossibleSubgoals() override; TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
std::string completeMessage() const override; std::string completeMessage() const override;
bool fulfillsMe (TSubgoal goal) override; bool fulfillsMe(TSubgoal goal) override;
}; };
class GatherArmy : public CGoal<GatherArmy> class GatherArmy : public CGoal<GatherArmy>
{ {
public: public:
GatherArmy() : CGoal (Goals::GATHER_ARMY){}; GatherArmy()
: CGoal(Goals::GATHER_ARMY)
GatherArmy(int val) : CGoal (Goals::GATHER_ARMY){value = val; priority = 2.5;}; {
}
GatherArmy(int val)
: CGoal(Goals::GATHER_ARMY)
{
value = val;
priority = 2.5;
}
TGoalVec getAllPossibleSubgoals() override; TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
std::string completeMessage() const override; std::string completeMessage() const override;
}; };
class BoostHero : public CGoal<BoostHero> class BoostHero : public CGoal<BoostHero>
{ {
public: public:
BoostHero() : CGoal (Goals::INVALID){priority = -1e10;}; //TODO BoostHero()
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; : CGoal(Goals::INVALID)
{
priority = -1e10; //TODO
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
//TSubgoal whatToDoToAchieve() override {return sptr(Invalid());}; //TSubgoal whatToDoToAchieve() override {return sptr(Invalid());};
}; };
class RecruitHero : public CGoal<RecruitHero> class RecruitHero : public CGoal<RecruitHero>
{ {
public: public:
RecruitHero() : CGoal (Goals::RECRUIT_HERO){priority = 1;}; RecruitHero()
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; : CGoal(Goals::RECRUIT_HERO)
{
priority = 1;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class BuildThis : public CGoal<BuildThis> class BuildThis : public CGoal<BuildThis>
{ {
public: public:
BuildThis() : CGoal (Goals::BUILD_STRUCTURE){}; //FIXME: should be not allowed (private) BuildThis()
: CGoal(Goals::BUILD_STRUCTURE)
BuildThis(BuildingID Bid, const CGTownInstance *tid) : CGoal (Goals::BUILD_STRUCTURE) {bid = Bid; town = tid; priority = 5;}; {
BuildThis(BuildingID Bid) : CGoal (Goals::BUILD_STRUCTURE) {bid = Bid; priority = 5;}; //FIXME: should be not allowed (private)
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; }
BuildThis(BuildingID Bid, const CGTownInstance * tid)
: CGoal(Goals::BUILD_STRUCTURE)
{
bid = Bid;
town = tid;
priority = 5;
}
BuildThis(BuildingID Bid)
: CGoal(Goals::BUILD_STRUCTURE)
{
bid = Bid;
priority = 5;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class CollectRes : public CGoal<CollectRes> class CollectRes : public CGoal<CollectRes>
{ {
public: public:
CollectRes() : CGoal (Goals::COLLECT_RES){}; CollectRes()
: CGoal(Goals::COLLECT_RES)
CollectRes(int rid, int val) : CGoal (Goals::COLLECT_RES) {resID = rid; value = val; priority = 2;}; {
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; }
CollectRes(int rid, int val)
: CGoal(Goals::COLLECT_RES)
{
resID = rid;
value = val;
priority = 2;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
};
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class GatherTroops : public CGoal<GatherTroops> class GatherTroops : public CGoal<GatherTroops>
{ {
public: public:
GatherTroops() : CGoal (Goals::GATHER_TROOPS){priority = 2;}; GatherTroops()
: CGoal(Goals::GATHER_TROOPS)
GatherTroops(int type, int val) : CGoal (Goals::GATHER_TROOPS){objid = type; value = val; priority = 2;}; {
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; priority = 2;
}
GatherTroops(int type, int val)
: CGoal(Goals::GATHER_TROOPS)
{
objid = type;
value = val;
priority = 2;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class GetObj : public CGoal<GetObj> class GetObj : public CGoal<GetObj>
{ {
public: public:
GetObj() {}; // empty constructor not allowed GetObj() {} // empty constructor not allowed
GetObj(int Objid) : CGoal(Goals::GET_OBJ) {objid = Objid; priority = 3;}; GetObj(int Objid)
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; : CGoal(Goals::GET_OBJ)
{
objid = Objid;
priority = 3;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
bool operator== (GetObj &g) {return g.objid == objid;} bool operator==(GetObj & g)
bool fulfillsMe (TSubgoal goal) override; {
return g.objid == objid;
}
bool fulfillsMe(TSubgoal goal) override;
std::string completeMessage() const override; std::string completeMessage() const override;
}; };
class FindObj : public CGoal<FindObj> class FindObj : public CGoal<FindObj>
{ {
public: public:
FindObj() {}; // empty constructor not allowed FindObj() {} // empty constructor not allowed
FindObj(int ID) : CGoal(Goals::FIND_OBJ) {objid = ID; priority = 1;}; FindObj(int ID)
FindObj(int ID, int subID) : CGoal(Goals::FIND_OBJ) {objid = ID; resID = subID; priority = 1;}; : CGoal(Goals::FIND_OBJ)
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; {
objid = ID;
priority = 1;
}
FindObj(int ID, int subID)
: CGoal(Goals::FIND_OBJ)
{
objid = ID;
resID = subID;
priority = 1;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class VisitHero : public CGoal<VisitHero> class VisitHero : public CGoal<VisitHero>
{ {
public: public:
VisitHero() : CGoal (Goals::VISIT_HERO){}; VisitHero()
: CGoal(Goals::VISIT_HERO)
VisitHero(int hid) : CGoal (Goals::VISIT_HERO){objid = hid; priority = 4;}; {
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; }
VisitHero(int hid)
: CGoal(Goals::VISIT_HERO)
{
objid = hid;
priority = 4;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
bool operator== (VisitHero &g) { return g.goalType == goalType && g.objid == objid; } bool operator==(VisitHero & g)
bool fulfillsMe (TSubgoal goal) override; {
return g.goalType == goalType && g.objid == objid;
}
bool fulfillsMe(TSubgoal goal) override;
std::string completeMessage() const override; std::string completeMessage() const override;
}; };
class GetArtOfType : public CGoal<GetArtOfType> class GetArtOfType : public CGoal<GetArtOfType>
{ {
public: public:
GetArtOfType() : CGoal (Goals::GET_ART_TYPE){}; GetArtOfType()
: CGoal(Goals::GET_ART_TYPE)
GetArtOfType(int type) : CGoal (Goals::GET_ART_TYPE){aid = type; priority = 2;}; {
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; }
GetArtOfType(int type)
: CGoal(Goals::GET_ART_TYPE)
{
aid = type;
priority = 2;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
}; };
class VisitTile : public CGoal<VisitTile> class VisitTile : public CGoal<VisitTile>
//tile, in conjunction with hero elementar; assumes tile is reachable //tile, in conjunction with hero elementar; assumes tile is reachable
{ {
public: public:
VisitTile() {}; // empty constructor not allowed VisitTile() {} // empty constructor not allowed
VisitTile(int3 Tile) : CGoal (Goals::VISIT_TILE) {tile = Tile; priority = 5;}; VisitTile(int3 Tile)
: CGoal(Goals::VISIT_TILE)
{
tile = Tile;
priority = 5;
}
TGoalVec getAllPossibleSubgoals() override; TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
bool operator== (VisitTile &g) { return g.goalType == goalType && g.tile == tile; } bool operator==(VisitTile & g)
{
return g.goalType == goalType && g.tile == tile;
}
std::string completeMessage() const override; std::string completeMessage() const override;
}; };
class ClearWayTo : public CGoal<ClearWayTo> class ClearWayTo : public CGoal<ClearWayTo>
{ {
public: public:
ClearWayTo() : CGoal (Goals::CLEAR_WAY_TO){}; ClearWayTo()
: CGoal(Goals::CLEAR_WAY_TO)
ClearWayTo(int3 Tile) : CGoal (Goals::CLEAR_WAY_TO) {tile = Tile; priority = 5;}; {
ClearWayTo(int3 Tile, HeroPtr h) : CGoal (Goals::CLEAR_WAY_TO) {tile = Tile; hero = h; priority = 5;}; }
ClearWayTo(int3 Tile)
: CGoal(Goals::CLEAR_WAY_TO)
{
tile = Tile;
priority = 5;
}
ClearWayTo(int3 Tile, HeroPtr h)
: CGoal(Goals::CLEAR_WAY_TO)
{
tile = Tile;
hero = h;
priority = 5;
}
TGoalVec getAllPossibleSubgoals() override; TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
bool operator== (ClearWayTo &g) { return g.goalType == goalType && g.tile == tile; } bool operator==(ClearWayTo & g)
{
return g.goalType == goalType && g.tile == tile;
}
}; };
class DigAtTile : public CGoal<DigAtTile> class DigAtTile : public CGoal<DigAtTile>
//elementar with hero on tile //elementar with hero on tile
{ {
public: public:
DigAtTile() : CGoal (Goals::DIG_AT_TILE){}; DigAtTile()
: CGoal(Goals::DIG_AT_TILE)
DigAtTile(int3 Tile) : CGoal (Goals::DIG_AT_TILE) {tile = Tile; priority = 20;}; {
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; }
DigAtTile(int3 Tile)
: CGoal(Goals::DIG_AT_TILE)
{
tile = Tile;
priority = 20;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override; TSubgoal whatToDoToAchieve() override;
bool operator== (DigAtTile &g) { return g.goalType == goalType && g.tile == tile; } bool operator==(DigAtTile & g)
{
return g.goalType == goalType && g.tile == tile;
}
}; };
class CIssueCommand : public CGoal<CIssueCommand> class CIssueCommand : public CGoal<CIssueCommand>
{ {
std::function<bool()> command; std::function<bool()> command;
public: public:
CIssueCommand(): CGoal(ISSUE_COMMAND){}; CIssueCommand()
: CGoal(ISSUE_COMMAND)
CIssueCommand(std::function<bool()> _command): CGoal(ISSUE_COMMAND), command(_command) {priority = 1e10;}; {
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();}; }
//TSubgoal whatToDoToAchieve() override {return sptr(Invalid());}; CIssueCommand(std::function<bool()> _command)
: CGoal(ISSUE_COMMAND), command(_command)
{
priority = 1e10;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
//TSubgoal whatToDoToAchieve() override {return sptr(Invalid());}
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,7 @@ class AIStatus
BattleState battle; BattleState battle;
std::map<QueryID, std::string> remainingQueries; std::map<QueryID, std::string> remainingQueries;
std::map<int, QueryID> requestToQueryID; //IDs of answer-requests sent to server => query ids (so we can match answer confirmation from server to the query) std::map<int, QueryID> requestToQueryID; //IDs of answer-requests sent to server => query ids (so we can match answer confirmation from server to the query)
std::vector<const CGObjectInstance*> objectsBeingVisited; std::vector<const CGObjectInstance *> objectsBeingVisited;
bool ongoingHeroMovement; bool ongoingHeroMovement;
bool ongoingChannelProbing; // true if AI currently explore bidirectional teleport channel exits bool ongoingChannelProbing; // true if AI currently explore bidirectional teleport channel exits
@@ -58,10 +58,10 @@ public:
bool haveTurn(); bool haveTurn();
void attemptedAnsweringQuery(QueryID queryID, int answerRequestID); void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
void receivedAnswerConfirmation(int answerRequestID, int result); void receivedAnswerConfirmation(int answerRequestID, int result);
void heroVisit(const CGObjectInstance *obj, bool started); void heroVisit(const CGObjectInstance * obj, bool started);
template <typename Handler> void serialize(Handler &h, const int version) template<typename Handler> void serialize(Handler & h, const int version)
{ {
h & battle; h & battle;
h & remainingQueries; h & remainingQueries;
@@ -70,7 +70,12 @@ public:
} }
}; };
enum {NOT_VISIBLE = 0, NOT_CHECKED = 1, NOT_AVAILABLE}; enum
{
NOT_VISIBLE = 0,
NOT_CHECKED = 1,
NOT_AVAILABLE
};
struct SectorMap struct SectorMap
{ {
@@ -98,7 +103,7 @@ struct SectorMap
//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector; //std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
std::map<int, Sector> infoOnSectors; std::map<int, Sector> infoOnSectors;
std::shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles; std::shared_ptr<boost::multi_array<TerrainTile *, 3>> visibleTiles;
SectorMap(); SectorMap();
SectorMap(HeroPtr h); SectorMap(HeroPtr h);
@@ -107,12 +112,12 @@ struct SectorMap
void exploreNewSector(crint3 pos, int num, CCallback * cbp); void exploreNewSector(crint3 pos, int num, CCallback * cbp);
void write(crstring fname); void write(crstring fname);
bool markIfBlocked(TSectorID &sec, crint3 pos, const TerrainTile *t); bool markIfBlocked(TSectorID & sec, crint3 pos, const TerrainTile * t);
bool markIfBlocked(TSectorID &sec, crint3 pos); bool markIfBlocked(TSectorID & sec, crint3 pos);
TSectorID & retrieveTile(crint3 pos); TSectorID & retrieveTile(crint3 pos);
TSectorID & retrieveTileN(TSectorArray & vectors, const int3 & pos); TSectorID & retrieveTileN(TSectorArray & vectors, const int3 & pos);
const TSectorID & retrieveTileN(const TSectorArray &vectors, const int3 &pos); const TSectorID & retrieveTileN(const TSectorArray & vectors, const int3 & pos);
TerrainTile* getTile(crint3 pos) const; TerrainTile * getTile(crint3 pos) const;
std::vector<const CGObjectInstance *> getNearbyObjs(HeroPtr h, bool sectorsAround); std::vector<const CGObjectInstance *> getNearbyObjs(HeroPtr h, bool sectorsAround);
void makeParentBFS(crint3 source); void makeParentBFS(crint3 source);
@@ -128,25 +133,25 @@ public:
//try build an unbuilt structure in maxDays at most (0 = indefinite) //try build an unbuilt structure in maxDays at most (0 = indefinite)
/*bool canBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays=7);*/ /*bool canBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays=7);*/
bool tryBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays=7); bool tryBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays = 7);
//try build ANY unbuilt structure //try build ANY unbuilt structure
BuildingID canBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=7); BuildingID canBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays = 7);
bool tryBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=7); bool tryBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays = 7);
//try build first unbuilt structure //try build first unbuilt structure
bool tryBuildNextStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=7); bool tryBuildNextStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays = 7);
friend class FuzzyHelper; friend class FuzzyHelper;
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > knownTeleportChannels; std::map<TeleportChannelID, std::shared_ptr<TeleportChannel>> knownTeleportChannels;
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates; std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
ObjectInstanceID destinationTeleport; ObjectInstanceID destinationTeleport;
int3 destinationTeleportPos; int3 destinationTeleportPos;
std::vector<ObjectInstanceID> teleportChannelProbingList; //list of teleport channel exits that not visible and need to be (re-)explored std::vector<ObjectInstanceID> teleportChannelProbingList; //list of teleport channel exits that not visible and need to be (re-)explored
//std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs //std::vector<const CGObjectInstance *> visitedThisWeek; //only OPWs
std::map<HeroPtr, std::set<const CGTownInstance *> > townVisitsThisWeek; std::map<HeroPtr, std::set<const CGTownInstance *>> townVisitsThisWeek;
std::map<HeroPtr, Goals::TSubgoal> lockedHeroes; //TODO: allow non-elementar objectives std::map<HeroPtr, Goals::TSubgoal> lockedHeroes; //TODO: allow non-elementar objectives
std::map<HeroPtr, std::set<const CGObjectInstance *> > reservedHeroesMap; //objects reserved by specific heroes std::map<HeroPtr, std::set<const CGObjectInstance *>> reservedHeroesMap; //objects reserved by specific heroes
std::set<HeroPtr> heroesUnableToExplore; //these heroes will not be polled for exploration in current state of game std::set<HeroPtr> heroesUnableToExplore; //these heroes will not be polled for exploration in current state of game
//sets are faster to search, also do not contain duplicates //sets are faster to search, also do not contain duplicates
@@ -154,7 +159,7 @@ public:
std::set<const CGObjectInstance *> alreadyVisited; std::set<const CGObjectInstance *> alreadyVisited;
std::set<const CGObjectInstance *> reservedObjs; //to be visited by specific hero std::set<const CGObjectInstance *> reservedObjs; //to be visited by specific hero
std::map <HeroPtr, std::shared_ptr<SectorMap>> cachedSectorMaps; //TODO: serialize? not necessary std::map<HeroPtr, std::shared_ptr<SectorMap>> cachedSectorMaps; //TODO: serialize? not necessary
TResources saving; TResources saving;
@@ -191,62 +196,62 @@ public:
virtual void init(std::shared_ptr<CCallback> CB) override; virtual void init(std::shared_ptr<CCallback> CB) override;
virtual void yourTurn() override; virtual void yourTurn() override;
virtual void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id virtual void heroGotLevel(const CGHeroInstance * hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id
virtual void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO virtual void commanderGotLevel(const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; //TODO
virtual void showBlockingDialog(const std::string &text, const std::vector<Component> &components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID. virtual void showBlockingDialog(const std::string & text, const std::vector<Component> & components, QueryID askID, const int soundID, bool selection, bool cancel) override; //Show a dialog, player must take decision. If selection then he has to choose between one of given components, if cancel he is allowed to not choose. After making choice, CCallback::selectionMade should be called with number of selected component (1 - n) or 0 for cancel (if allowed) and askID.
virtual void showGarrisonDialog(const CArmedInstance *up, const CGHeroInstance *down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done virtual void showGarrisonDialog(const CArmedInstance * up, const CGHeroInstance * down, bool removableUnits, QueryID queryID) override; //all stacks operations between these objects become allowed, interface has to call onEnd when done
virtual void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override; virtual void showTeleportDialog(TeleportChannelID channel, TTeleportExitsList exits, bool impassable, QueryID askID) override;
void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override; void showMapObjectSelectDialog(QueryID askID, const Component & icon, const MetaString & title, const MetaString & description, const std::vector<ObjectInstanceID> & objects) override;
virtual void saveGame(BinarySerializer & h, const int version) override; //saving virtual void saveGame(BinarySerializer & h, const int version) override; //saving
virtual void loadGame(BinaryDeserializer & h, const int version) override; //loading virtual void loadGame(BinaryDeserializer & h, const int version) override; //loading
virtual void finish() override; virtual void finish() override;
virtual void availableCreaturesChanged(const CGDwelling *town) override; virtual void availableCreaturesChanged(const CGDwelling * town) override;
virtual void heroMoved(const TryMoveHero & details) override; virtual void heroMoved(const TryMoveHero & details) override;
virtual void heroInGarrisonChange(const CGTownInstance *town) override; virtual void heroInGarrisonChange(const CGTownInstance * town) override;
virtual void centerView(int3 pos, int focusTime) override; virtual void centerView(int3 pos, int focusTime) override;
virtual void tileHidden(const std::unordered_set<int3, ShashInt3> &pos) override; virtual void tileHidden(const std::unordered_set<int3, ShashInt3> & pos) override;
virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override; virtual void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override;
virtual void artifactAssembled(const ArtifactLocation &al) override; virtual void artifactAssembled(const ArtifactLocation & al) override;
virtual void showTavernWindow(const CGObjectInstance *townOrTavern) override; virtual void showTavernWindow(const CGObjectInstance * townOrTavern) override;
virtual void showThievesGuildWindow (const CGObjectInstance * obj) override; virtual void showThievesGuildWindow(const CGObjectInstance * obj) override;
virtual void playerBlocked(int reason, bool start) override; virtual void playerBlocked(int reason, bool start) override;
virtual void showPuzzleMap() override; virtual void showPuzzleMap() override;
virtual void showShipyardDialog(const IShipyard *obj) override; virtual void showShipyardDialog(const IShipyard * obj) override;
virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override; virtual void gameOver(PlayerColor player, const EVictoryLossCheckResult & victoryLossCheckResult) override;
virtual void artifactPut(const ArtifactLocation &al) override; virtual void artifactPut(const ArtifactLocation & al) override;
virtual void artifactRemoved(const ArtifactLocation &al) override; virtual void artifactRemoved(const ArtifactLocation & al) override;
virtual void artifactDisassembled(const ArtifactLocation &al) override; virtual void artifactDisassembled(const ArtifactLocation & al) override;
virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start) override; virtual void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override;
virtual void availableArtifactsChanged(const CGBlackMarket *bm = nullptr) override; virtual void availableArtifactsChanged(const CGBlackMarket * bm = nullptr) override;
virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override; virtual void heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance * town) override;
virtual void tileRevealed(const std::unordered_set<int3, ShashInt3> &pos) override; virtual void tileRevealed(const std::unordered_set<int3, ShashInt3> & pos) override;
virtual void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override; virtual void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) override;
virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) override; virtual void heroPrimarySkillChanged(const CGHeroInstance * hero, int which, si64 val) override;
virtual void showRecruitmentDialog(const CGDwelling *dwelling, const CArmedInstance *dst, int level) override; virtual void showRecruitmentDialog(const CGDwelling * dwelling, const CArmedInstance * dst, int level) override;
virtual void heroMovePointsChanged(const CGHeroInstance * hero) override; virtual void heroMovePointsChanged(const CGHeroInstance * hero) override;
virtual void garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) override; virtual void garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) override;
virtual void newObject(const CGObjectInstance * obj) override; virtual void newObject(const CGObjectInstance * obj) override;
virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override; virtual void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override;
virtual void playerBonusChanged(const Bonus &bonus, bool gain) override; virtual void playerBonusChanged(const Bonus & bonus, bool gain) override;
virtual void heroCreated(const CGHeroInstance*) override; virtual void heroCreated(const CGHeroInstance *) override;
virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID) override; virtual void advmapSpellCast(const CGHeroInstance * caster, int spellID) override;
virtual void showInfoDialog(const std::string &text, const std::vector<Component> &components, int soundID) override; virtual void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID) override;
virtual void requestRealized(PackageApplied *pa) override; virtual void requestRealized(PackageApplied * pa) override;
virtual void receivedResource() override; virtual void receivedResource() override;
virtual void objectRemoved(const CGObjectInstance *obj) override; virtual void objectRemoved(const CGObjectInstance * obj) override;
virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override; virtual void showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) override;
virtual void heroManaPointsChanged(const CGHeroInstance * hero) override; virtual void heroManaPointsChanged(const CGHeroInstance * hero) override;
virtual void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override; virtual void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
virtual void battleResultsApplied() override; virtual void battleResultsApplied() override;
virtual void objectPropertyChanged(const SetObjectProperty * sop) override; virtual void objectPropertyChanged(const SetObjectProperty * sop) override;
virtual void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) override; virtual void buildChanged(const CGTownInstance * town, BuildingID buildingID, int what) override;
virtual void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) override; virtual void heroBonusChanged(const CGHeroInstance * hero, const Bonus & bonus, bool gain) override;
virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) override; virtual void showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) override;
void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override; void showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) override;
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; virtual void battleStart(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool side) override;
virtual void battleEnd(const BattleResult *br) override; virtual void battleEnd(const BattleResult * br) override;
void makeTurn(); void makeTurn();
void makeTurnInternal(); void makeTurnInternal();
@@ -259,15 +264,15 @@ public:
void wander(HeroPtr h); void wander(HeroPtr h);
void setGoal(HeroPtr h, Goals::TSubgoal goal); void setGoal(HeroPtr h, Goals::TSubgoal goal);
void evaluateGoal(HeroPtr h); //evaluates goal assigned to hero, if any void evaluateGoal(HeroPtr h); //evaluates goal assigned to hero, if any
void completeGoal (Goals::TSubgoal goal); //safely removes goal from reserved hero void completeGoal(Goals::TSubgoal goal); //safely removes goal from reserved hero
void striveToQuest (const QuestInfo &q); void striveToQuest(const QuestInfo & q);
void recruitHero(const CGTownInstance * t, bool throwing = false); void recruitHero(const CGTownInstance * t, bool throwing = false);
bool isGoodForVisit(const CGObjectInstance *obj, HeroPtr h, SectorMap &sm); bool isGoodForVisit(const CGObjectInstance * obj, HeroPtr h, SectorMap & sm);
void buildStructure(const CGTownInstance * t); void buildStructure(const CGTownInstance * t);
//void recruitCreatures(const CGTownInstance * t); //void recruitCreatures(const CGTownInstance * t);
void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter); void recruitCreatures(const CGDwelling * d, const CArmedInstance * recruiter);
bool canGetArmy (const CGHeroInstance * h, const CGHeroInstance * source); //can we get any better stacks from other hero? bool canGetArmy(const CGHeroInstance * h, const CGHeroInstance * source); //can we get any better stacks from other hero?
void pickBestCreatures(const CArmedInstance * army, const CArmedInstance * source); //called when we can't find a slot for new stack void pickBestCreatures(const CArmedInstance * army, const CArmedInstance * source); //called when we can't find a slot for new stack
void pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other = nullptr); void pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other = nullptr);
void moveCreaturesToHero(const CGTownInstance * t); void moveCreaturesToHero(const CGTownInstance * t);
@@ -279,52 +284,52 @@ public:
void lostHero(HeroPtr h); //should remove all references to hero (assigned tasks and so on) void lostHero(HeroPtr h); //should remove all references to hero (assigned tasks and so on)
void waitTillFree(); void waitTillFree();
void addVisitableObj(const CGObjectInstance *obj); void addVisitableObj(const CGObjectInstance * obj);
void markObjectVisited (const CGObjectInstance *obj); void markObjectVisited(const CGObjectInstance * obj);
void reserveObject (HeroPtr h, const CGObjectInstance *obj); //TODO: reserve all objects that heroes attempt to visit void reserveObject(HeroPtr h, const CGObjectInstance * obj); //TODO: reserve all objects that heroes attempt to visit
void unreserveObject (HeroPtr h, const CGObjectInstance *obj); void unreserveObject(HeroPtr h, const CGObjectInstance * obj);
void markHeroUnableToExplore (HeroPtr h); void markHeroUnableToExplore(HeroPtr h);
void markHeroAbleToExplore (HeroPtr h); void markHeroAbleToExplore(HeroPtr h);
bool isAbleToExplore (HeroPtr h); bool isAbleToExplore(HeroPtr h);
void clearPathsInfo(); void clearPathsInfo();
void validateObject(const CGObjectInstance *obj); //checks if object is still visible and if not, removes references to it void validateObject(const CGObjectInstance * obj); //checks if object is still visible and if not, removes references to it
void validateObject(ObjectIdRef obj); //checks if object is still visible and if not, removes references to it void validateObject(ObjectIdRef obj); //checks if object is still visible and if not, removes references to it
void validateVisitableObjs(); void validateVisitableObjs();
void retrieveVisitableObjs(std::vector<const CGObjectInstance *> &out, bool includeOwned = false) const; void retrieveVisitableObjs(std::vector<const CGObjectInstance *> & out, bool includeOwned = false) const;
void retrieveVisitableObjs(); void retrieveVisitableObjs();
std::vector<const CGObjectInstance *> getFlaggedObjects() const; std::vector<const CGObjectInstance *> getFlaggedObjects() const;
const CGObjectInstance *lookForArt(int aid) const; const CGObjectInstance * lookForArt(int aid) const;
bool isAccessible(const int3 &pos); bool isAccessible(const int3 & pos);
HeroPtr getHeroWithGrail() const; HeroPtr getHeroWithGrail() const;
const CGObjectInstance *getUnvisitedObj(const std::function<bool(const CGObjectInstance *)> &predicate); const CGObjectInstance * getUnvisitedObj(const std::function<bool(const CGObjectInstance *)> & predicate);
bool isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies = false) const; bool isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies = false) const;
//optimization - use one SM for every hero call //optimization - use one SM for every hero call
std::shared_ptr<SectorMap> getCachedSectorMap(HeroPtr h); std::shared_ptr<SectorMap> getCachedSectorMap(HeroPtr h);
const CGTownInstance *findTownWithTavern() const; const CGTownInstance * findTownWithTavern() const;
bool canRecruitAnyHero(const CGTownInstance * t = NULL) const; bool canRecruitAnyHero(const CGTownInstance * t = NULL) const;
Goals::TSubgoal getGoal (HeroPtr h) const; Goals::TSubgoal getGoal(HeroPtr h) const;
bool canAct(HeroPtr h) const; bool canAct(HeroPtr h) const;
std::vector<HeroPtr> getUnblockedHeroes() const; std::vector<HeroPtr> getUnblockedHeroes() const;
HeroPtr primaryHero() const; HeroPtr primaryHero() const;
TResources freeResources() const; //owned resources minus gold reserve TResources freeResources() const; //owned resources minus gold reserve
TResources estimateIncome() const; TResources estimateIncome() const;
bool containsSavedRes(const TResources &cost) const; bool containsSavedRes(const TResources & cost) const;
void checkHeroArmy (HeroPtr h); void checkHeroArmy(HeroPtr h);
void requestSent(const CPackForServer *pack, int requestID) override; void requestSent(const CPackForServer * pack, int requestID) override;
void answerQuery(QueryID queryID, int selection); void answerQuery(QueryID queryID, int selection);
//special function that can be called ONLY from game events handling thread and will send request ASAP //special function that can be called ONLY from game events handling thread and will send request ASAP
void requestActionASAP(std::function<void()> whatToDo); void requestActionASAP(std::function<void()> whatToDo);
#if 0 #if 0
//disabled due to issue 2890 //disabled due to issue 2890
template <typename Handler> void registerGoals(Handler &h) template<typename Handler> void registerGoals(Handler & h)
{ {
//h.template registerType<Goals::AbstractGoal, Goals::BoostHero>(); //h.template registerType<Goals::AbstractGoal, Goals::BoostHero>();
h.template registerType<Goals::AbstractGoal, Goals::Build>(); h.template registerType<Goals::AbstractGoal, Goals::Build>();
@@ -349,7 +354,7 @@ public:
} }
#endif #endif
template <typename Handler> void serializeInternal(Handler &h, const int version) template<typename Handler> void serializeInternal(Handler & h, const int version)
{ {
h & knownTeleportChannels; h & knownTeleportChannels;
h & knownSubterraneanGates; h & knownSubterraneanGates;
@@ -413,8 +418,10 @@ public:
class cannotFulfillGoalException : public std::exception class cannotFulfillGoalException : public std::exception
{ {
std::string msg; std::string msg;
public: public:
explicit cannotFulfillGoalException(crstring _Message) : msg(_Message) explicit cannotFulfillGoalException(crstring _Message)
: msg(_Message)
{ {
} }
@@ -422,18 +429,21 @@ public:
{ {
}; };
const char *what() const throw () override const char * what() const throw () override
{ {
return msg.c_str(); return msg.c_str();
} }
}; };
class goalFulfilledException : public std::exception class goalFulfilledException : public std::exception
{ {
std::string msg; std::string msg;
public: public:
Goals::TSubgoal goal; Goals::TSubgoal goal;
explicit goalFulfilledException(Goals::TSubgoal Goal) : goal(Goal) explicit goalFulfilledException(Goals::TSubgoal Goal)
: goal(Goal)
{ {
msg = goal->name(); msg = goal->name();
} }
@@ -442,11 +452,10 @@ public:
{ {
}; };
const char *what() const throw () override const char * what() const throw () override
{ {
return msg.c_str(); return msg.c_str();
} }
}; };
void makePossibleUpgrades(const CArmedInstance *obj); void makePossibleUpgrades(const CArmedInstance * obj);

View File

@@ -14,19 +14,19 @@
#define strcpy_s(a, b, c) strncpy(a, c, b) #define strcpy_s(a, b, c) strncpy(a, c, b)
#endif #endif
static const char *g_cszAiName = "VCAI"; static const char * g_cszAiName = "VCAI";
extern "C" DLL_EXPORT int GetGlobalAiVersion() extern "C" DLL_EXPORT int GetGlobalAiVersion()
{ {
return AI_INTERFACE_VER; return AI_INTERFACE_VER;
} }
extern "C" DLL_EXPORT void GetAiName(char* name) extern "C" DLL_EXPORT void GetAiName(char * name)
{ {
strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName); strcpy_s(name, strlen(g_cszAiName) + 1, g_cszAiName);
} }
extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> &out) extern "C" DLL_EXPORT void GetNewAI(std::shared_ptr<CGlobalAI> & out)
{ {
out = std::make_shared<VCAI>(); out = std::make_shared<VCAI>();
} }