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:
committed by
ArseniyShestakov
parent
2ede3783dd
commit
25dea1a599
@@ -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;
|
||||||
|
@@ -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);
|
||||||
};
|
};
|
||||||
|
@@ -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,49 +409,53 @@ 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);
|
||||||
tilePriority = 5;
|
tilePriority = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vt.strengthRatio->setValue(strengthRatio);
|
vt.strengthRatio->setValue(strengthRatio);
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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
435
AI/VCAI/Goals.h
435
AI/VCAI/Goals.h
@@ -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());}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
1420
AI/VCAI/VCAI.cpp
1420
AI/VCAI/VCAI.cpp
File diff suppressed because it is too large
Load Diff
165
AI/VCAI/VCAI.h
165
AI/VCAI/VCAI.h
@@ -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);
|
||||||
|
|
||||||
|
@@ -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>();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user