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<VCAI> ai;
extern FuzzyHelper *fh;
extern FuzzyHelper * fh;
//extern static const int3 dirs[8];
@@ -32,27 +32,29 @@ const CGObjectInstance * ObjectIdRef::operator->() const
return cb->getObj(id, false);
}
ObjectIdRef::operator const CGObjectInstance*() const
ObjectIdRef::operator const CGObjectInstance *() const
{
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;
}
HeroPtr::HeroPtr(const CGHeroInstance *H)
HeroPtr::HeroPtr(const CGHeroInstance * H)
{
if(!H)
{
@@ -63,7 +65,6 @@ HeroPtr::HeroPtr(const CGHeroInstance *H)
h = H;
name = h->name;
hid = H->id;
// infosCount[ai->playerID][hid]++;
}
@@ -76,11 +77,11 @@ HeroPtr::HeroPtr()
HeroPtr::~HeroPtr()
{
// if(hid >= 0)
// infosCount[ai->playerID][hid]--;
// if(hid >= 0)
// infosCount[ai->playerID][hid]--;
}
bool HeroPtr::operator<(const HeroPtr &rhs) const
bool HeroPtr::operator<(const HeroPtr & rhs) const
{
return hid < rhs.hid;
}
@@ -126,55 +127,59 @@ const CGHeroInstance * HeroPtr::operator*() const
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
// callback pointer is thread-specific and slow to retrieve -> read map size only once
int3 mapSize = cb->getMapSize();
for(int i = 0; i < mapSize.x; i++)
{
for(int j = 0; j < mapSize.y; j++)
{
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();
for(int i = 0; i < mapSize.x; i++)
{
for(int j = 0; j < mapSize.y; j++)
{
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
for(const int3 &dir : int3::getDirs())
for(const int3 & dir : int3::getDirs())
{
const int3 n = pos + dir;
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;
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()),
*rn = ai->myCb->getPathsInfo(hero)->getPathInfo(rhs->visitablePos());
const CGPathNode * ln = ai->myCb->getPathsInfo(hero)->getPathInfo(lhs->visitablePos());
const CGPathNode * rn = ai->myCb->getPathsInfo(hero)->getPathInfo(rhs->visitablePos());
if(ln->turns != rn->turns)
return ln->turns < rn->turns;
@@ -189,11 +194,12 @@ bool compareMovement(HeroPtr lhs, HeroPtr rhs)
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)
return 190000000; //MUCH
ui64 objectDanger = 0, guardDanger = 0;
ui64 objectDanger = 0;
ui64 guardDanger = 0;
auto visObjs = cb->getVisitableObjs(tile);
if(visObjs.size())
@@ -207,62 +213,64 @@ ui64 evaluateDanger(crint3 tile)
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)
return 190000000; //MUCH
ui64 objectDanger = 0, guardDanger = 0;
ui64 objectDanger = 0;
ui64 guardDanger = 0;
auto visitableObjects = cb->getVisitableObjs(tile);
// 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>))
{
vstd::erase_if(visitableObjects, [](const CGObjectInstance * obj)
{
return !objWithID<Obj::HERO>(obj);
});
}
if(const CGObjectInstance * dangerousObject = vstd::backOrNull(visitableObjects))
{
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!
auto armedObj = dynamic_cast<const CArmedInstance*>(dangerousObject);
if (armedObj)
auto armedObj = dynamic_cast<const CArmedInstance *>(dangerousObject);
if(armedObj)
{
float tacticalAdvantage = fh->getTacticalAdvantage(visitor, armedObj);
objectDanger *= tacticalAdvantage; //this line tends to go infinite for allied towns (?)
}
}
if (dangerousObject->ID == Obj::SUBTERRANEAN_GATE)
{ //check guard on the other side of the gate
if(dangerousObject->ID == Obj::SUBTERRANEAN_GATE)
{
//check guard on the other side of the gate
auto it = ai->knownSubterraneanGates.find(dangerousObject);
if (it != ai->knownSubterraneanGates.end())
if(it != ai->knownSubterraneanGates.end())
{
auto guards = cb->getGuardingCreatures(it->second->visitablePos());
for (auto cre : guards)
for(auto cre : guards)
{
vstd::amax (guardDanger, evaluateDanger(cre) *
fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance*>(cre)));
vstd::amax(guardDanger, evaluateDanger(cre) * fh->getTacticalAdvantage(visitor, dynamic_cast<const CArmedInstance *>(cre)));
}
}
}
}
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
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
return 0;
@@ -270,64 +278,65 @@ ui64 evaluateDanger(const CGObjectInstance *obj)
switch(obj->ID)
{
case Obj::HERO:
{
InfoAboutHero iah;
cb->getHeroInfo(obj, iah);
return iah.army.getStrength();
}
{
InfoAboutHero iah;
cb->getHeroInfo(obj, iah);
return iah.army.getStrength();
}
case Obj::TOWN:
case Obj::GARRISON: case Obj::GARRISON2: //garrison
{
InfoAboutTown iat;
cb->getTownInfo(obj, iat);
return iat.army.getStrength();
}
case Obj::GARRISON:
case Obj::GARRISON2:
{
InfoAboutTown iat;
cb->getTownInfo(obj, iat);
return iat.army.getStrength();
}
case Obj::MONSTER:
{
//TODO!!!!!!!!
const CGCreature *cre = dynamic_cast<const CGCreature*>(obj);
return cre->getArmyStrength();
}
{
//TODO!!!!!!!!
const CGCreature * cre = dynamic_cast<const CGCreature *>(obj);
return cre->getArmyStrength();
}
case Obj::CREATURE_GENERATOR1:
case Obj::CREATURE_GENERATOR4:
{
const CGDwelling *d = dynamic_cast<const CGDwelling*>(obj);
return d->getArmyStrength();
}
{
const CGDwelling * d = dynamic_cast<const CGDwelling *>(obj);
return d->getArmyStrength();
}
case Obj::MINE:
case Obj::ABANDONED_MINE:
{
const CArmedInstance * a = dynamic_cast<const CArmedInstance*>(obj);
return a->getArmyStrength();
}
{
const CArmedInstance * a = dynamic_cast<const CArmedInstance *>(obj);
return a->getArmyStrength();
}
case Obj::CRYPT: //crypt
case Obj::CREATURE_BANK: //crebank
case Obj::DRAGON_UTOPIA:
case Obj::SHIPWRECK: //shipwreck
case Obj::DERELICT_SHIP: //derelict ship
// case Obj::PYRAMID:
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj));
return fh->estimateBankDanger(dynamic_cast<const CBank *>(obj));
case Obj::PYRAMID:
{
if(obj->subID == 0)
return fh->estimateBankDanger (dynamic_cast<const CBank *>(obj));
else
return 0;
}
{
if(obj->subID == 0)
return fh->estimateBankDanger(dynamic_cast<const CBank *>(obj));
else
return 0;
}
default:
return 0;
}
}
bool compareDanger(const CGObjectInstance *lhs, const CGObjectInstance *rhs)
bool compareDanger(const CGObjectInstance * lhs, const CGObjectInstance * rhs)
{
return evaluateDanger(lhs) < evaluateDanger(rhs);
}
bool isSafeToVisit(HeroPtr h, crint3 tile)
{
const ui64 heroStrength = h->getTotalStrength(),
dangerStrength = evaluateDanger(tile, *h);
const ui64 heroStrength = h->getTotalStrength();
const ui64 dangerStrength = evaluateDanger(tile, *h);
if(dangerStrength)
{
if(heroStrength / SAFE_ATTACK_CONSTANT > dangerStrength)
@@ -336,23 +345,33 @@ bool isSafeToVisit(HeroPtr h, crint3 tile)
return true;
}
else
{
return false;
}
}
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
return !t->blocked
|| (!fromWater && t->visitableObjects.size() == 1 && t->topVisitableId() == Obj::BOAT);
//do not try to board when in water sector
// TODO: Such information should be provided by pathfinder
// Tile must be free or with unoccupied boat
if(!t->blocked)
{
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)
{
TimeCheck tc ("where to explore");
TimeCheck tc("where to explore");
int radius = h->getSightRadius();
int3 hpos = h->visitablePos();
@@ -361,22 +380,24 @@ int3 whereToExplore(HeroPtr h)
//look for nearby objs -> visit them if they're close enouh
const int DIST_LIMIT = 3;
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();
CGPath p;
ai->myCb->getPathsInfo(h.get())->getPath(p, op);
if (p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT)
if (ai->isGoodForVisit(obj, h, *sm))
if(p.nodes.size() && p.endPos() == op && p.nodes.size() <= DIST_LIMIT)
{
if(ai->isGoodForVisit(obj, h, *sm))
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()));
if(nearbyVisitableObjs.size())
return nearbyVisitableObjs.back()->visitablePos();
@@ -385,7 +406,7 @@ int3 whereToExplore(HeroPtr h)
{
return ai->explorationBestNeighbour(hpos, radius, h);
}
catch(cannotFulfillGoalException &e)
catch(cannotFulfillGoalException & e)
{
//perform exhaustive search
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
{
return cb->getTile(tileToHit)->topVisitableId() == Obj::BORDER_GATE &&
(dynamic_cast <const CGKeys *>(cb->getTile(tileToHit)->visitableObjects.back()))->wasMyColorVisited (ai->playerID);
if(cb->getTile(tileToHit)->topVisitableId() != Obj::BORDER_GATE)
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 (obj->blockVisit) //we can't stand on that object
if(auto obj = cb->getTopObj(pos))
{
if(obj->blockVisit) //we can't stand on that object
return true;
}
return false;
}
int howManyTilesWillBeDiscovered(const int3 &pos, int radious, CCallback * cbp)
{ //TODO: do not explore dead-end boundaries
int howManyTilesWillBeDiscovered(const int3 & pos, int radious, CCallback * cbp)
{
//TODO: do not explore dead-end boundaries
int ret = 0;
for(int x = pos.x - radious; x <= pos.x + radious; x++)
{
for(int y = pos.y - radious; y <= pos.y + radious; y++)
{
int3 npos = int3(x,y,pos.z);
if(cbp->isInTheMap(npos) && pos.dist2d(npos) - 0.5 < radious && !cbp->isVisible(npos))
int3 npos = int3(x, y, pos.z);
if(cbp->isInTheMap(npos) && pos.dist2d(npos) - 0.5 < radious && !cbp->isVisible(npos))
{
if (!boundaryBetweenTwoPoints (pos, npos, cbp))
if(!boundaryBetweenTwoPoints(pos, npos, cbp))
ret++;
}
}
@@ -425,21 +451,21 @@ int howManyTilesWillBeDiscovered(const int3 &pos, int radious, CCallback * cbp)
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 xMax = std::max (pos1.x, pos2.x);
int yMin = std::min (pos1.y, pos2.y);
int yMax = std::max (pos1.y, pos2.y);
int xMin = std::min(pos1.x, pos2.x);
int xMax = std::max(pos1.x, pos2.x);
int yMin = std::min(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
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;
}
}
@@ -452,9 +478,9 @@ int howManyTilesWillBeDiscovered(int radious, int3 pos, crint3 dir)
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)
{
@@ -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;
int freeHeroSlots = GameConstants::ARMY_SIZE - h->stacksCount();
@@ -478,11 +504,11 @@ ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance *t)
else
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();
});
for (auto & stack : boost::adaptors::reverse(toMove))
for(auto & stack : boost::adaptors::reverse(toMove))
{
if(freeHeroSlots)
{
@@ -500,12 +526,12 @@ bool compareHeroStrength(HeroPtr h1, HeroPtr h2)
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();
}
bool compareArtifacts(const CArtifactInstance *a1, const CArtifactInstance *a2)
bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2)
{
auto art1 = a1->artType;
auto art2 = a2->artType;

View File

@@ -20,8 +20,8 @@
class CCallback;
typedef const int3& crint3;
typedef const std::string& crstring;
typedef const int3 & crint3;
typedef const std::string & crstring;
const int GOLD_MINE_PRODUCTION = 1000, WOOD_ORE_MINE_PRODUCTION = 2, RESOURCE_MINE_PRODUCTION = 1;
const int ACTUAL_RESOURCE_COUNT = 7;
@@ -36,7 +36,7 @@ extern const int GOLD_RESERVE;
struct HeroPtr
{
const CGHeroInstance *h;
const CGHeroInstance * h;
ObjectInstanceID hid;
public:
@@ -44,7 +44,7 @@ public:
HeroPtr();
HeroPtr(const CGHeroInstance *H);
HeroPtr(const CGHeroInstance * H);
~HeroPtr();
operator bool() const
@@ -52,15 +52,15 @@ public:
return validAndSet();
}
bool operator<(const HeroPtr &rhs) const;
const CGHeroInstance *operator->() const;
const CGHeroInstance *operator*() const; //not that consistent with -> but all interfaces use CGHeroInstance*, so it's convenient
bool operator<(const HeroPtr & rhs) const;
const CGHeroInstance * operator->() const;
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;
template <typename Handler> void serialize(Handler &h, const int version)
template<typename Handler> void serialize(Handler & h, const int version)
{
h & this->h;
h & hid;
@@ -82,16 +82,16 @@ struct ObjectIdRef
{
ObjectInstanceID id;
const CGObjectInstance *operator->() const;
const CGObjectInstance * operator->() const;
operator const CGObjectInstance *() const;
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;
}
@@ -101,13 +101,14 @@ struct TimeCheck
{
CStopWatch time;
std::string txt;
TimeCheck(crstring TXT) : txt(TXT)
TimeCheck(crstring TXT)
: txt(TXT)
{
}
~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
{
std::function<void()> foo;
AtScopeExit(const std::function<void()> &FOO) : foo(FOO)
AtScopeExit(const std::function<void()> & FOO)
: foo(FOO)
{}
~AtScopeExit()
{
@@ -126,48 +128,50 @@ struct AtScopeExit
class ObjsVector : public std::vector<ObjectIdRef>
{
private:
};
template<int id>
bool objWithID(const CGObjectInstance *obj)
bool objWithID(const CGObjectInstance * obj)
{
return obj->ID == id;
}
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_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_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_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
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);
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 isBlockVisitObj(const int3 &pos);
bool isBlockVisitObj(const int3 & pos);
bool isWeeklyRevisitable (const CGObjectInstance * obj);
bool shouldVisit (HeroPtr h, const CGObjectInstance * obj);
bool isWeeklyRevisitable(const CGObjectInstance * obj);
bool shouldVisit(HeroPtr h, const CGObjectInstance * obj);
ui64 evaluateDanger(const CGObjectInstance *obj);
ui64 evaluateDanger(crint3 tile, const CGHeroInstance *visitor);
ui64 evaluateDanger(const CGObjectInstance * obj);
ui64 evaluateDanger(crint3 tile, const CGHeroInstance * visitor);
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 compareHeroStrength(HeroPtr h1, HeroPtr h2);
bool compareArmyStrength(const CArmedInstance *a1, const CArmedInstance *a2);
bool compareArtifacts(const CArtifactInstance *a1, const CArtifactInstance *a2);
ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance *t);
bool compareArmyStrength(const CArmedInstance * a1, const CArmedInstance * a2);
bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2);
ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance * t);
int3 whereToExplore(HeroPtr h);
class CDistanceSorter
{
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 CGTownInstance;
//using namespace Goals;
FuzzyHelper *fh;
FuzzyHelper * fh;
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<VCAI> ai;
@@ -47,7 +45,7 @@ void engineBase::configure()
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));
}
@@ -58,7 +56,7 @@ struct armyStructure
ui32 maxSpeed;
};
armyStructure evaluateArmyStructure (const CArmedInstance * army)
armyStructure evaluateArmyStructure(const CArmedInstance * army)
{
ui64 totalStrenght = army->getArmyStrength();
double walkersStrenght = 0;
@@ -69,17 +67,17 @@ armyStructure evaluateArmyStructure (const CArmedInstance * army)
for(auto s : army->Slots())
{
bool walker = true;
if (s.second->type->hasBonusOfType(Bonus::SHOOTER))
if(s.second->type->hasBonusOfType(Bonus::SHOOTER))
{
shootersStrenght += s.second->getPower();
walker = false;
}
if (s.second->type->hasBonusOfType(Bonus::FLYING))
if(s.second->type->hasBonusOfType(Bonus::FLYING))
{
flyersStrenght += s.second->getPower();
walker = false;
}
if (walker)
if(walker)
walkersStrenght += s.second->getPower();
vstd::amax(maxSpeed, s.second->type->valOfBonuses(Bonus::STACKS_SPEED));
@@ -106,7 +104,6 @@ void FuzzyHelper::initTacticalAdvantage()
{
try
{
ta.ourShooters = new fl::InputVariable("OurShooters");
ta.ourWalkers = new fl::InputVariable("OurWalkers");
ta.ourFlyers = new fl::InputVariable("OurFlyers");
@@ -115,12 +112,12 @@ void FuzzyHelper::initTacticalAdvantage()
ta.enemyFlyers = new fl::InputVariable("EnemyFlyers");
//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
};
for (auto val : helper)
for(auto val : helper)
{
ta.engine.addInputVariable(val);
val->addTerm(new fl::Ramp("FEW", 0.6, 0.0));
@@ -133,7 +130,7 @@ void FuzzyHelper::initTacticalAdvantage()
helper = {ta.ourSpeed, ta.enemySpeed};
for (auto val : helper)
for(auto val : helper)
{
ta.engine.addInputVariable(val);
val->addTerm(new fl::Ramp("LOW", 6.5, 3));
@@ -145,27 +142,26 @@ void FuzzyHelper::initTacticalAdvantage()
ta.castleWalls = new fl::InputVariable("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);
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);
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);
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->setRange(CGTownInstance::NONE, CGTownInstance::CASTLE);
}
ta.bankPresent = new fl::InputVariable("Bank");
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);
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->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");
}
catch (fl::Exception & pe)
catch(fl::Exception & pe)
{
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
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;
ui8 totalChance = 0;
for (auto config : bankInfo->getPossibleGuards())
for(auto config : bankInfo->getPossibleGuards())
{
totalStrength += config.second.totalStrength * 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;
try
@@ -240,17 +236,15 @@ float FuzzyHelper::getTacticalAdvantage (const CArmedInstance *we, const CArmedI
ta.enemyFlyers->setValue(enemyStructure.flyers);
ta.enemySpeed->setValue(enemyStructure.maxSpeed);
bool bank = dynamic_cast<const CBank*> (enemy);
if (bank)
bool bank = dynamic_cast<const CBank *>(enemy);
if(bank)
ta.bankPresent->setValue(1);
else
ta.bankPresent->setValue(0);
const CGTownInstance * fort = dynamic_cast<const CGTownInstance*> (enemy);
if (fort)
{
const CGTownInstance * fort = dynamic_cast<const CGTownInstance *>(enemy);
if(fort)
ta.castleWalls->setValue(fort->fortLevel());
}
else
ta.castleWalls->setValue(0);
@@ -258,18 +252,18 @@ float FuzzyHelper::getTacticalAdvantage (const CArmedInstance *we, const CArmedI
ta.engine.process();
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::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() << " ";
logAi->error(log.str());
assert(false);
@@ -296,9 +290,9 @@ FuzzyHelper::TacticalAdvantage::~TacticalAdvantage()
//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());
ai->cachedSectorMaps.clear();
@@ -308,9 +302,9 @@ Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
{
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);
}
@@ -319,16 +313,16 @@ Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
{
return lhs->priority < rhs->priority;
};
boost::sort (vec, compareGoals);
boost::sort(vec, compareGoals);
return vec.back();
}
float FuzzyHelper::evaluate (Goals::Explore & g)
float FuzzyHelper::evaluate(Goals::Explore & g)
{
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
}
@@ -354,8 +348,8 @@ void FuzzyHelper::initVisitTile()
vt.value->setMinimum(0);
vt.value->setMaximum(5);
std::vector<fl::InputVariable*> helper = {vt.strengthRatio, vt.heroStrength, vt.turnDistance, vt.missionImportance, vt.estimatedReward};
for (auto val : helper)
std::vector<fl::InputVariable *> helper = {vt.strengthRatio, vt.heroStrength, vt.turnDistance, vt.missionImportance, vt.estimatedReward};
for(auto val : helper)
{
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("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
vt.heroStrength->addTerm(new fl::Ramp("LOW", 0.2, 0));
@@ -386,11 +380,11 @@ void FuzzyHelper::initVisitTile()
vt.estimatedReward->setRange(0.0, 5.0);
//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::Triangle("MEDIUM", 2, 3)); //can't be center of mass :/
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
vt.addRule("if strengthRatio is HIGH and heroStrength is LOW then Value is very HIGH");
@@ -415,49 +409,53 @@ void FuzzyHelper::initVisitTile()
vt.addRule("if estimatedReward is HIGH then Value is very HIGH");
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
if (!g.hero)
if(!g.hero)
return 0;
//assert(cb->isInTheMap(g.tile));
float turns = 0;
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;
}
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;
else
turns = 1 + (fl::scalar)(distance - g.hero->movement) / g.hero->maxMovePoints(true); //bool on land?
}
float missionImportance = 0;
if (vstd::contains(ai->lockedHeroes, g.hero))
if(vstd::contains(ai->lockedHeroes, g.hero))
missionImportance = ai->lockedHeroes[g.hero]->priority;
float strengthRatio = 10.0f; //we are much stronger than enemy
ui64 danger = evaluateDanger (g.tile, g.hero.h);
if (danger)
ui64 danger = evaluateDanger(g.tile, g.hero.h);
if(danger)
strengthRatio = (fl::scalar)g.hero.h->getTotalStrength() / danger;
float tilePriority = 0;
if(g.objid == -1)
{
vt.estimatedReward->setEnabled(false);
}
else if(g.objid == Obj::TOWN) //TODO: move to getObj eventually and add appropiate logic there
{
vt.estimatedReward->setEnabled(true);
tilePriority = 5;
}
try
{
vt.strengthRatio->setValue(strengthRatio);
@@ -470,41 +468,41 @@ float FuzzyHelper::evaluate (Goals::VisitTile & g)
//engine.process(VISIT_TILE); //TODO: Process only Visit_Tile
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;
}
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
if (!obj)
if(!obj)
return -100; //hero died in the meantime
//TODO: consider direct copy (constructor?)
g.setpriority(Goals::VisitTile(obj->visitablePos()).sethero(g.hero).setisAbstract(g.isAbstract).accept(this));
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 lack, the less important goal
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
}
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!");
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));
}
@@ -520,32 +518,32 @@ float FuzzyHelper::evaluate (Goals::ClearWayTo & g)
}
float FuzzyHelper::evaluate (Goals::BuildThis & g)
float FuzzyHelper::evaluate(Goals::BuildThis & g)
{
return 1;
}
float FuzzyHelper::evaluate (Goals::DigAtTile & g)
float FuzzyHelper::evaluate(Goals::DigAtTile & g)
{
return 0;
}
float FuzzyHelper::evaluate (Goals::CollectRes & g)
float FuzzyHelper::evaluate(Goals::CollectRes & g)
{
return 0;
}
float FuzzyHelper::evaluate (Goals::Build & g)
float FuzzyHelper::evaluate(Goals::Build & g)
{
return 0;
}
float FuzzyHelper::evaluate (Goals::Invalid & g)
float FuzzyHelper::evaluate(Goals::Invalid & g)
{
return -1e10;
}
float FuzzyHelper::evaluate (Goals::AbstractGoal & g)
float FuzzyHelper::evaluate(Goals::AbstractGoal & g)
{
logAi->warn("Cannot evaluate goal %s", g.name());
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
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -21,12 +21,12 @@ class FuzzyHelper;
namespace Goals
{
class AbstractGoal;
class VisitTile;
typedef std::shared_ptr<Goals::AbstractGoal> TSubgoal;
typedef std::vector<TSubgoal> TGoalVec;
class AbstractGoal;
class VisitTile;
typedef std::shared_ptr<Goals::AbstractGoal> TSubgoal;
typedef std::vector<TSubgoal> TGoalVec;
enum EGoals
enum EGoals
{
INVALID = -1,
WIN, DO_NOT_LOSE, CONQUER, BUILD, //build needs to get a real reasoning
@@ -78,7 +78,8 @@ public:
const CGTownInstance *town; VSETTER(CGTownInstance *, town)
int bid; VSETTER(int, bid)
AbstractGoal (EGoals goal = INVALID) : goalType (goal)
AbstractGoal(EGoals goal = INVALID)
: goalType (goal)
{
priority = 0;
isElementar = false;
@@ -91,35 +92,47 @@ public:
town = nullptr;
bid = -1;
}
virtual ~AbstractGoal(){};
virtual ~AbstractGoal(){}
//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 TGoalVec getAllPossibleSubgoals() {TGoalVec vec; return vec;};
virtual TSubgoal whatToDoToAchieve() {return sptr(AbstractGoal());};
virtual AbstractGoal * clone() const
{
return const_cast<AbstractGoal *>(this);
}
virtual TGoalVec getAllPossibleSubgoals()
{
return TGoalVec();
}
virtual TSubgoal whatToDoToAchieve()
{
return sptr(AbstractGoal());
}
EGoals goalType;
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;
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 tryRecruitHero();
///Visitor pattern
//TODO: make accept work for std::shared_ptr... somehow
virtual void accept (VCAI * ai); //unhandled goal will report standard error
virtual float accept (FuzzyHelper * f);
virtual void accept(VCAI * ai); //unhandled goal will report standard error
virtual float accept(FuzzyHelper * f);
virtual bool operator== (AbstractGoal &g);
virtual bool fulfillsMe (Goals::TSubgoal goal) //TODO: multimethod instead of type check
virtual bool operator==(AbstractGoal & g);
virtual bool fulfillsMe(Goals::TSubgoal goal) //TODO: multimethod instead of type check
{
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 & isElementar;
@@ -136,10 +149,10 @@ public:
}
};
template <typename T> class CGoal : public AbstractGoal
template<typename T> class CGoal : public AbstractGoal
{
public:
CGoal<T> (EGoals goal = INVALID) : AbstractGoal (goal)
CGoal<T>(EGoals goal = INVALID) : AbstractGoal(goal)
{
priority = 0;
isElementar = false;
@@ -164,12 +177,12 @@ public:
OSETTER(CGTownInstance *, town)
OSETTER(int, bid)
void accept (VCAI * ai) override;
float accept (FuzzyHelper * f) override;
void accept(VCAI * ai) override;
float accept(FuzzyHelper * f) 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()
{
@@ -178,9 +191,9 @@ public:
ptr.reset(clone());
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 & value & resID & objid & aid & tile & hero & town & bid;
}
@@ -188,189 +201,403 @@ public:
class Invalid : public CGoal<Invalid>
{
public:
Invalid() : CGoal (Goals::INVALID) {priority = -1e10;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
public:
Invalid()
: CGoal(Goals::INVALID)
{
priority = -1e10;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
};
class Win : public CGoal<Win>
{
public:
Win() : CGoal (Goals::WIN) {priority = 100;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
public:
Win()
: CGoal(Goals::WIN)
{
priority = 100;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
};
class NotLose : public CGoal<NotLose>
{
public:
NotLose() : CGoal (Goals::DO_NOT_LOSE) {priority = 100;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
public:
NotLose()
: CGoal(Goals::DO_NOT_LOSE)
{
priority = 100;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
//TSubgoal whatToDoToAchieve() override;
};
class Conquer : public CGoal<Conquer>
{
public:
Conquer() : CGoal (Goals::CONQUER) {priority = 10;};
public:
Conquer()
: CGoal(Goals::CONQUER)
{
priority = 10;
}
TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override;
};
class Build : public CGoal<Build>
{
public:
Build() : CGoal (Goals::BUILD) {priority = 1;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
public:
Build()
: CGoal(Goals::BUILD)
{
priority = 1;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
};
class Explore : public CGoal<Explore>
{
public:
Explore() : CGoal (Goals::EXPLORE){priority = 1;};
Explore(HeroPtr h) : CGoal (Goals::EXPLORE){hero = h; priority = 1;};
public:
Explore()
: CGoal(Goals::EXPLORE)
{
priority = 1;
}
Explore(HeroPtr h)
: CGoal(Goals::EXPLORE)
{
hero = h;
priority = 1;
}
TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override;
std::string completeMessage() const override;
bool fulfillsMe (TSubgoal goal) override;
bool fulfillsMe(TSubgoal goal) override;
};
class GatherArmy : public CGoal<GatherArmy>
{
public:
GatherArmy() : CGoal (Goals::GATHER_ARMY){};
GatherArmy(int val) : CGoal (Goals::GATHER_ARMY){value = val; priority = 2.5;};
GatherArmy()
: CGoal(Goals::GATHER_ARMY)
{
}
GatherArmy(int val)
: CGoal(Goals::GATHER_ARMY)
{
value = val;
priority = 2.5;
}
TGoalVec getAllPossibleSubgoals() override;
TSubgoal whatToDoToAchieve() override;
std::string completeMessage() const override;
};
class BoostHero : public CGoal<BoostHero>
{
public:
BoostHero() : CGoal (Goals::INVALID){priority = -1e10;}; //TODO
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
public:
BoostHero()
: CGoal(Goals::INVALID)
{
priority = -1e10; //TODO
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
//TSubgoal whatToDoToAchieve() override {return sptr(Invalid());};
};
class RecruitHero : public CGoal<RecruitHero>
{
public:
RecruitHero() : CGoal (Goals::RECRUIT_HERO){priority = 1;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
public:
RecruitHero()
: CGoal(Goals::RECRUIT_HERO)
{
priority = 1;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
};
class BuildThis : public CGoal<BuildThis>
{
public:
BuildThis() : CGoal (Goals::BUILD_STRUCTURE){}; //FIXME: should be not allowed (private)
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();};
BuildThis()
: CGoal(Goals::BUILD_STRUCTURE)
{
//FIXME: should be not allowed (private)
}
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;
};
class CollectRes : public CGoal<CollectRes>
{
public:
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();};
public:
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();
};
TSubgoal whatToDoToAchieve() override;
};
class GatherTroops : public CGoal<GatherTroops>
{
public:
GatherTroops() : CGoal (Goals::GATHER_TROOPS){priority = 2;};
GatherTroops(int type, int val) : CGoal (Goals::GATHER_TROOPS){objid = type; value = val; priority = 2;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
GatherTroops()
: CGoal(Goals::GATHER_TROOPS)
{
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;
};
class GetObj : public CGoal<GetObj>
{
public:
GetObj() {}; // empty constructor not allowed
GetObj() {} // empty constructor not allowed
GetObj(int Objid) : CGoal(Goals::GET_OBJ) {objid = Objid; priority = 3;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
GetObj(int Objid)
: CGoal(Goals::GET_OBJ)
{
objid = Objid;
priority = 3;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
bool operator== (GetObj &g) {return g.objid == objid;}
bool fulfillsMe (TSubgoal goal) override;
bool operator==(GetObj & g)
{
return g.objid == objid;
}
bool fulfillsMe(TSubgoal goal) override;
std::string completeMessage() const override;
};
class FindObj : public CGoal<FindObj>
{
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, int subID) : CGoal(Goals::FIND_OBJ) {objid = ID; resID = subID; priority = 1;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
FindObj(int ID)
: CGoal(Goals::FIND_OBJ)
{
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;
};
class VisitHero : public CGoal<VisitHero>
{
public:
VisitHero() : CGoal (Goals::VISIT_HERO){};
VisitHero(int hid) : CGoal (Goals::VISIT_HERO){objid = hid; priority = 4;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
VisitHero()
: CGoal(Goals::VISIT_HERO)
{
}
VisitHero(int hid)
: CGoal(Goals::VISIT_HERO)
{
objid = hid;
priority = 4;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
bool operator== (VisitHero &g) { return g.goalType == goalType && g.objid == objid; }
bool fulfillsMe (TSubgoal goal) override;
bool operator==(VisitHero & g)
{
return g.goalType == goalType && g.objid == objid;
}
bool fulfillsMe(TSubgoal goal) override;
std::string completeMessage() const override;
};
class GetArtOfType : public CGoal<GetArtOfType>
{
public:
GetArtOfType() : CGoal (Goals::GET_ART_TYPE){};
GetArtOfType(int type) : CGoal (Goals::GET_ART_TYPE){aid = type; priority = 2;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
GetArtOfType()
: CGoal(Goals::GET_ART_TYPE)
{
}
GetArtOfType(int type)
: CGoal(Goals::GET_ART_TYPE)
{
aid = type;
priority = 2;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
};
class VisitTile : public CGoal<VisitTile>
//tile, in conjunction with hero elementar; assumes tile is reachable
{
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;
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;
};
};
class ClearWayTo : public CGoal<ClearWayTo>
{
public:
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()
: 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;
}
TGoalVec getAllPossibleSubgoals() 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>
//elementar with hero on tile
{
public:
DigAtTile() : CGoal (Goals::DIG_AT_TILE){};
DigAtTile(int3 Tile) : CGoal (Goals::DIG_AT_TILE) {tile = Tile; priority = 20;};
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
DigAtTile()
: CGoal(Goals::DIG_AT_TILE)
{
}
DigAtTile(int3 Tile)
: CGoal(Goals::DIG_AT_TILE)
{
tile = Tile;
priority = 20;
}
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
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>
{
std::function<bool()> command;
public:
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());};
public:
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());}
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,7 @@ class AIStatus
BattleState battle;
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::vector<const CGObjectInstance*> objectsBeingVisited;
std::vector<const CGObjectInstance *> objectsBeingVisited;
bool ongoingHeroMovement;
bool ongoingChannelProbing; // true if AI currently explore bidirectional teleport channel exits
@@ -58,10 +58,10 @@ public:
bool haveTurn();
void attemptedAnsweringQuery(QueryID queryID, int answerRequestID);
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 & 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
{
@@ -98,7 +103,7 @@ struct SectorMap
//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
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(HeroPtr h);
@@ -107,12 +112,12 @@ struct SectorMap
void exploreNewSector(crint3 pos, int num, CCallback * cbp);
void write(crstring fname);
bool markIfBlocked(TSectorID &sec, crint3 pos, const TerrainTile *t);
bool markIfBlocked(TSectorID &sec, crint3 pos);
bool markIfBlocked(TSectorID & sec, crint3 pos, const TerrainTile * t);
bool markIfBlocked(TSectorID & sec, crint3 pos);
TSectorID & retrieveTile(crint3 pos);
TSectorID & retrieveTileN(TSectorArray & vectors, const int3 & pos);
const TSectorID & retrieveTileN(const TSectorArray &vectors, const int3 &pos);
TerrainTile* getTile(crint3 pos) const;
const TSectorID & retrieveTileN(const TSectorArray & vectors, const int3 & pos);
TerrainTile * getTile(crint3 pos) const;
std::vector<const CGObjectInstance *> getNearbyObjs(HeroPtr h, bool sectorsAround);
void makeParentBFS(crint3 source);
@@ -128,25 +133,25 @@ public:
//try build an unbuilt structure in maxDays at most (0 = indefinite)
/*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
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);
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);
//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;
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel> > knownTeleportChannels;
std::map<TeleportChannelID, std::shared_ptr<TeleportChannel>> knownTeleportChannels;
std::map<const CGObjectInstance *, const CGObjectInstance *> knownSubterraneanGates;
ObjectInstanceID destinationTeleport;
int3 destinationTeleportPos;
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::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, 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
//sets are faster to search, also do not contain duplicates
@@ -154,7 +159,7 @@ public:
std::set<const CGObjectInstance *> alreadyVisited;
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;
@@ -191,62 +196,62 @@ public:
virtual void init(std::shared_ptr<CCallback> CB) 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 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 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 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 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 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;
virtual void saveGame(BinarySerializer & h, const int version) override; //saving
virtual void loadGame(BinaryDeserializer & h, const int version) override; //loading
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 heroInGarrisonChange(const CGTownInstance *town) override;
virtual void heroInGarrisonChange(const CGTownInstance * town) override;
virtual void centerView(int3 pos, int focusTime) override;
virtual void tileHidden(const std::unordered_set<int3, ShashInt3> &pos) override;
virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override;
virtual void artifactAssembled(const ArtifactLocation &al) override;
virtual void showTavernWindow(const CGObjectInstance *townOrTavern) override;
virtual void showThievesGuildWindow (const CGObjectInstance * obj) override;
virtual void tileHidden(const std::unordered_set<int3, ShashInt3> & pos) override;
virtual void artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) override;
virtual void artifactAssembled(const ArtifactLocation & al) override;
virtual void showTavernWindow(const CGObjectInstance * townOrTavern) override;
virtual void showThievesGuildWindow(const CGObjectInstance * obj) override;
virtual void playerBlocked(int reason, bool start) 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 artifactPut(const ArtifactLocation &al) override;
virtual void artifactRemoved(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 availableArtifactsChanged(const CGBlackMarket *bm = nullptr) override;
virtual void heroVisitsTown(const CGHeroInstance* hero, const CGTownInstance * town) override;
virtual void tileRevealed(const std::unordered_set<int3, ShashInt3> &pos) override;
virtual void artifactPut(const ArtifactLocation & al) override;
virtual void artifactRemoved(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 availableArtifactsChanged(const CGBlackMarket * bm = nullptr) override;
virtual void heroVisitsTown(const CGHeroInstance * hero, const CGTownInstance * town) override;
virtual void tileRevealed(const std::unordered_set<int3, ShashInt3> & pos) override;
virtual void heroExchangeStarted(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID query) 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 garrisonsChanged(ObjectInstanceID id1, ObjectInstanceID id2) override;
virtual void newObject(const CGObjectInstance * obj) override;
virtual void showHillFortWindow(const CGObjectInstance *object, const CGHeroInstance *visitor) override;
virtual void playerBonusChanged(const Bonus &bonus, bool gain) override;
virtual void heroCreated(const CGHeroInstance*) override;
virtual void showHillFortWindow(const CGObjectInstance * object, const CGHeroInstance * visitor) override;
virtual void playerBonusChanged(const Bonus & bonus, bool gain) override;
virtual void heroCreated(const CGHeroInstance *) 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 requestRealized(PackageApplied *pa) override;
virtual void showInfoDialog(const std::string & text, const std::vector<Component> & components, int soundID) override;
virtual void requestRealized(PackageApplied * pa) override;
virtual void receivedResource() override;
virtual void objectRemoved(const CGObjectInstance *obj) override;
virtual void showUniversityWindow(const IMarket *market, const CGHeroInstance *visitor) override;
virtual void objectRemoved(const CGObjectInstance * obj) override;
virtual void showUniversityWindow(const IMarket * market, const CGHeroInstance * visitor) override;
virtual void heroManaPointsChanged(const CGHeroInstance * hero) override;
virtual void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) override;
virtual void battleResultsApplied() override;
virtual void objectPropertyChanged(const SetObjectProperty * sop) 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 showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) 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 showMarketWindow(const IMarket * market, const CGHeroInstance * visitor) 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 battleEnd(const BattleResult *br) 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;
void makeTurn();
void makeTurnInternal();
@@ -259,15 +264,15 @@ public:
void wander(HeroPtr h);
void setGoal(HeroPtr h, Goals::TSubgoal goal);
void evaluateGoal(HeroPtr h); //evaluates goal assigned to hero, if any
void completeGoal (Goals::TSubgoal goal); //safely removes goal from reserved hero
void striveToQuest (const QuestInfo &q);
void completeGoal(Goals::TSubgoal goal); //safely removes goal from reserved hero
void striveToQuest(const QuestInfo & q);
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 recruitCreatures(const CGTownInstance * t);
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 pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * other = nullptr);
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 waitTillFree();
void addVisitableObj(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 unreserveObject (HeroPtr h, const CGObjectInstance *obj);
void addVisitableObj(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 unreserveObject(HeroPtr h, const CGObjectInstance * obj);
void markHeroUnableToExplore (HeroPtr h);
void markHeroAbleToExplore (HeroPtr h);
bool isAbleToExplore (HeroPtr h);
void markHeroUnableToExplore(HeroPtr h);
void markHeroAbleToExplore(HeroPtr h);
bool isAbleToExplore(HeroPtr h);
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 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();
std::vector<const CGObjectInstance *> getFlaggedObjects() const;
const CGObjectInstance *lookForArt(int aid) const;
bool isAccessible(const int3 &pos);
const CGObjectInstance * lookForArt(int aid) const;
bool isAccessible(const int3 & pos);
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;
//optimization - use one SM for every hero call
std::shared_ptr<SectorMap> getCachedSectorMap(HeroPtr h);
const CGTownInstance *findTownWithTavern() const;
const CGTownInstance * findTownWithTavern() 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;
std::vector<HeroPtr> getUnblockedHeroes() const;
HeroPtr primaryHero() const;
TResources freeResources() const; //owned resources minus gold reserve
TResources estimateIncome() const;
bool containsSavedRes(const TResources &cost) const;
void checkHeroArmy (HeroPtr h);
bool containsSavedRes(const TResources & cost) const;
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);
//special function that can be called ONLY from game events handling thread and will send request ASAP
void requestActionASAP(std::function<void()> whatToDo);
#if 0
//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::Build>();
@@ -349,7 +354,7 @@ public:
}
#endif
template <typename Handler> void serializeInternal(Handler &h, const int version)
template<typename Handler> void serializeInternal(Handler & h, const int version)
{
h & knownTeleportChannels;
h & knownSubterraneanGates;
@@ -413,8 +418,10 @@ public:
class cannotFulfillGoalException : public std::exception
{
std::string msg;
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();
}
};
class goalFulfilledException : public std::exception
{
std::string msg;
public:
Goals::TSubgoal goal;
explicit goalFulfilledException(Goals::TSubgoal Goal) : goal(Goal)
explicit goalFulfilledException(Goals::TSubgoal Goal)
: goal(Goal)
{
msg = goal->name();
}
@@ -442,11 +452,10 @@ public:
{
};
const char *what() const throw () override
const char * what() const throw () override
{
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)
#endif
static const char *g_cszAiName = "VCAI";
static const char * g_cszAiName = "VCAI";
extern "C" DLL_EXPORT int GetGlobalAiVersion()
{
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);
}
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>();
}