mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-21 12:06:49 +02:00
- Implemented serialization of Goals. Loaded games work, at least.
- Attempts to add Subterranean Gates to SectorMap - Extensive use of ClearWayTo goal.
This commit is contained in:
parent
8a9f2781c2
commit
b0b0249524
@ -480,6 +480,32 @@ float FuzzyHelper::evaluate (Goals::GatherArmy & g)
|
|||||||
float army = g.hero->getArmyStrength();
|
float army = g.hero->getArmyStrength();
|
||||||
return g.value / std::max(g.value - army, 1000.0f);
|
return g.value / std::max(g.value - army, 1000.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float FuzzyHelper::evaluate (Goals::ClearWayTo & g)
|
||||||
|
{
|
||||||
|
if (!g.hero.h)
|
||||||
|
throw cannotFulfillGoalException("ClearWayTo called without hero!");
|
||||||
|
|
||||||
|
SectorMap sm(g.hero);
|
||||||
|
int3 t = sm.firstTileToGet(g.hero, g.tile);
|
||||||
|
|
||||||
|
if (t.valid())
|
||||||
|
{
|
||||||
|
if (isSafeToVisit(g.hero, t))
|
||||||
|
{
|
||||||
|
g.setpriority(Goals::VisitTile(g.tile).sethero(g.hero).setisAbstract(g.isAbstract).accept(this));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g.setpriority (Goals::GatherArmy(evaluateDanger(t, g.hero.h)*SAFE_ATTACK_CONSTANT).
|
||||||
|
sethero(g.hero).setisAbstract(true).accept(this));
|
||||||
|
}
|
||||||
|
return g.priority;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
float FuzzyHelper::evaluate (Goals::BuildThis & g)
|
float FuzzyHelper::evaluate (Goals::BuildThis & g)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -67,6 +67,7 @@ public:
|
|||||||
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::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);
|
||||||
|
@ -452,16 +452,28 @@ TSubgoal ClearWayTo::whatToDoToAchieve()
|
|||||||
TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||||
{
|
{
|
||||||
TGoalVec ret;
|
TGoalVec ret;
|
||||||
for (auto h : cb->getHeroesInfo())
|
|
||||||
|
std::vector<const CGHeroInstance *> heroes;
|
||||||
|
|
||||||
|
if (hero)
|
||||||
|
heroes.push_back(hero.h);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if ((hero && hero->visitablePos() == tile && hero == *h) || //we can't free the way ourselves
|
heroes = cb->getHeroesInfo();
|
||||||
h->visitablePos() == tile) //we are already on that tile! what does it mean?
|
}
|
||||||
continue;
|
|
||||||
|
for (auto h : heroes)
|
||||||
|
{
|
||||||
|
//TODO: handle clearing way to allied heroes that are blocked
|
||||||
|
//if ((hero && hero->visitablePos() == tile && hero == *h) || //we can't free the way ourselves
|
||||||
|
// h->visitablePos() == tile) //we are already on that tile! what does it mean?
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
//if our hero is trapped, make sure we request clearing the way from OUR perspective
|
||||||
|
|
||||||
SectorMap sm(h);
|
SectorMap sm(h);
|
||||||
|
|
||||||
int3 tileToHit = sm.firstTileToGet(hero ? hero : h, tile);
|
int3 tileToHit = sm.firstTileToGet(h, tile);
|
||||||
//if our hero is trapped, make sure we request clearing the way from OUR perspective
|
|
||||||
if (!tileToHit.valid())
|
if (!tileToHit.valid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -471,10 +483,13 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto topObj = cb->getTopObj(tileToHit);
|
auto topObj = cb->getTopObj(tileToHit);
|
||||||
if(topObj)
|
if (topObj)
|
||||||
{
|
{
|
||||||
|
if (vstd::contains(ai->reservedObjs, topObj) && !vstd::contains(ai->reservedHeroesMap[h], topObj))
|
||||||
|
continue; //do not capure object reserved by other hero
|
||||||
|
|
||||||
if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
|
if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
|
||||||
if (topObj != hero.get(true)) //the hero we wnat to free
|
if (topObj != hero.get(true)) //the hero we want to free
|
||||||
logAi->errorStream() << boost::format("%s stands in the way of %s") % topObj->getHoverText() % h->getHoverText();
|
logAi->errorStream() << boost::format("%s stands in the way of %s") % topObj->getHoverText() % h->getHoverText();
|
||||||
if (topObj->ID == Obj::QUEST_GUARD || topObj->ID == Obj::BORDERGUARD)
|
if (topObj->ID == Obj::QUEST_GUARD || topObj->ID == Obj::BORDERGUARD)
|
||||||
{
|
{
|
||||||
@ -482,6 +497,7 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
|||||||
{
|
{
|
||||||
//do NOT use VISIT_TILE, as tile with quets guard can't be visited
|
//do NOT use VISIT_TILE, as tile with quets guard can't be visited
|
||||||
ret.push_back (sptr (Goals::GetObj(topObj->id.getNum()).sethero(h)));
|
ret.push_back (sptr (Goals::GetObj(topObj->id.getNum()).sethero(h)));
|
||||||
|
continue; //do not try to visit tile or gather army
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -490,8 +506,16 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (isSafeToVisit(h, tileToHit)) //this makes sense only if tile is guarded, but there i no quest object
|
||||||
|
{
|
||||||
ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
|
ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret.push_back (sptr (Goals::GatherArmy(evaluateDanger(tileToHit, h)*SAFE_ATTACK_CONSTANT).
|
||||||
|
sethero(h).setisAbstract(true)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ai->canRecruitAnyHero())
|
if (ai->canRecruitAnyHero())
|
||||||
ret.push_back (sptr (Goals::RecruitHero()));
|
ret.push_back (sptr (Goals::RecruitHero()));
|
||||||
@ -563,10 +587,12 @@ TGoalVec Explore::getAllPossibleSubgoals()
|
|||||||
for (auto h : heroes)
|
for (auto h : heroes)
|
||||||
{
|
{
|
||||||
SectorMap sm(h);
|
SectorMap sm(h);
|
||||||
|
|
||||||
for (auto obj : objs) //double loop, performance risk?
|
for (auto obj : objs) //double loop, performance risk?
|
||||||
{
|
{
|
||||||
auto t = sm.firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
auto t = sm.firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
||||||
ai->whatToDoToReachTile(h, t, ret);
|
if (ai->canReachTile(h, t))
|
||||||
|
ret.push_back (sptr(Goals::ClearWayTo(obj->visitablePos(), h).setisAbstract(true)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int3 t = whereToExplore(h);
|
int3 t = whereToExplore(h);
|
||||||
@ -577,33 +603,14 @@ TGoalVec Explore::getAllPossibleSubgoals()
|
|||||||
else if (hero.h == h || (!hero && h == ai->primaryHero().h)) //check this only ONCE, high cost
|
else if (hero.h == h || (!hero && h == ai->primaryHero().h)) //check this only ONCE, high cost
|
||||||
{
|
{
|
||||||
t = ai->explorationDesperate(h);
|
t = ai->explorationDesperate(h);
|
||||||
ai->whatToDoToReachTile(h, t, ret);
|
if (t.valid()) //don't waste time if we are completely blocked
|
||||||
|
ret.push_back (sptr(Goals::ClearWayTo(t, h).setisAbstract(true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//we either don't have hero yet or none of heroes can explore
|
//we either don't have hero yet or none of heroes can explore
|
||||||
if ((!hero || ret.empty()) && ai->canRecruitAnyHero())
|
if ((!hero || ret.empty()) && ai->canRecruitAnyHero())
|
||||||
ret.push_back (sptr(Goals::RecruitHero()));
|
ret.push_back (sptr(Goals::RecruitHero()));
|
||||||
|
|
||||||
//if (ret.empty())
|
|
||||||
//{
|
|
||||||
// for (auto h : heroes) //this is costly function, use only when there is no other way
|
|
||||||
// {
|
|
||||||
// auto t = ai->explorationDesperate (h); //we assume that no more than one tile on the way is guarded
|
|
||||||
// if (t.valid())
|
|
||||||
// {
|
|
||||||
// if (isSafeToVisit(h, t))
|
|
||||||
// {
|
|
||||||
// ret.push_back (sptr (Goals::VisitTile(t).sethero(h)));
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// ret.push_back (sptr (Goals::GatherArmy(evaluateDanger(t, h)*SAFE_ATTACK_CONSTANT).
|
|
||||||
// sethero(h).setisAbstract(true)));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ret.empty())
|
if (ret.empty())
|
||||||
{
|
{
|
||||||
throw goalFulfilledException (sptr(Goals::Explore().sethero(hero)));
|
throw goalFulfilledException (sptr(Goals::Explore().sethero(hero)));
|
||||||
@ -886,7 +893,8 @@ TGoalVec Conquer::getAllPossibleSubgoals()
|
|||||||
for (auto obj : ourObjs) //double loop, performance risk?
|
for (auto obj : ourObjs) //double loop, performance risk?
|
||||||
{
|
{
|
||||||
auto t = sm.firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
auto t = sm.firstTileToGet(h, obj->visitablePos()); //we assume that no more than one tile on the way is guarded
|
||||||
ai->whatToDoToReachTile (h, t, ret);
|
if (ai->canReachTile(h, t))
|
||||||
|
ret.push_back (sptr(Goals::ClearWayTo(obj->visitablePos(), h).setisAbstract(true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!objs.empty() && ai->canRecruitAnyHero()) //probably no point to recruit hero if we see no objects to capture
|
if (!objs.empty() && ai->canRecruitAnyHero()) //probably no point to recruit hero if we see no objects to capture
|
||||||
|
@ -193,7 +193,7 @@ class NotLose : public CGoal<NotLose>
|
|||||||
public:
|
public:
|
||||||
NotLose() : CGoal (Goals::DO_NOT_LOSE) {priority = 100;};
|
NotLose() : CGoal (Goals::DO_NOT_LOSE) {priority = 100;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
//TSubgoal whatToDoToAchieve() override;
|
||||||
};
|
};
|
||||||
class Conquer : public CGoal<Conquer>
|
class Conquer : public CGoal<Conquer>
|
||||||
{
|
{
|
||||||
@ -221,9 +221,9 @@ class Explore : public CGoal<Explore>
|
|||||||
};
|
};
|
||||||
class GatherArmy : public CGoal<GatherArmy>
|
class GatherArmy : public CGoal<GatherArmy>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
GatherArmy() : CGoal (Goals::GATHER_ARMY){};
|
|
||||||
public:
|
public:
|
||||||
|
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;
|
||||||
@ -234,7 +234,7 @@ class BoostHero : public CGoal<BoostHero>
|
|||||||
public:
|
public:
|
||||||
BoostHero() : CGoal (Goals::INVALID){priority = -1e10;}; //TODO
|
BoostHero() : CGoal (Goals::INVALID){priority = -1e10;}; //TODO
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
//TSubgoal whatToDoToAchieve() override {return sptr(Invalid());};
|
||||||
};
|
};
|
||||||
class RecruitHero : public CGoal<RecruitHero>
|
class RecruitHero : public CGoal<RecruitHero>
|
||||||
{
|
{
|
||||||
@ -245,9 +245,9 @@ class RecruitHero : public CGoal<RecruitHero>
|
|||||||
};
|
};
|
||||||
class BuildThis : public CGoal<BuildThis>
|
class BuildThis : public CGoal<BuildThis>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
BuildThis() : CGoal (Goals::BUILD_STRUCTURE){};
|
|
||||||
public:
|
public:
|
||||||
|
BuildThis() : CGoal (Goals::BUILD_STRUCTURE){}; //FIXME: should be not allowed (private)
|
||||||
|
|
||||||
BuildThis(BuildingID Bid, const CGTownInstance *tid) : CGoal (Goals::BUILD_STRUCTURE) {bid = Bid; town = tid; priority = 5;};
|
BuildThis(BuildingID Bid, const CGTownInstance *tid) : CGoal (Goals::BUILD_STRUCTURE) {bid = Bid; town = tid; priority = 5;};
|
||||||
BuildThis(BuildingID Bid) : CGoal (Goals::BUILD_STRUCTURE) {bid = Bid; priority = 5;};
|
BuildThis(BuildingID Bid) : CGoal (Goals::BUILD_STRUCTURE) {bid = Bid; priority = 5;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
@ -255,27 +255,27 @@ public:
|
|||||||
};
|
};
|
||||||
class CollectRes : public CGoal<CollectRes>
|
class CollectRes : public CGoal<CollectRes>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
CollectRes() : CGoal (Goals::COLLECT_RES){};
|
|
||||||
public:
|
public:
|
||||||
|
CollectRes() : CGoal (Goals::COLLECT_RES){};
|
||||||
|
|
||||||
CollectRes(int rid, int val) : CGoal (Goals::COLLECT_RES) {resID = rid; value = val; priority = 2;};
|
CollectRes(int rid, int val) : CGoal (Goals::COLLECT_RES) {resID = rid; value = val; priority = 2;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
TSubgoal whatToDoToAchieve() override;
|
||||||
};
|
};
|
||||||
class GatherTroops : public CGoal<GatherTroops>
|
class GatherTroops : public CGoal<GatherTroops>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
GatherTroops() : CGoal (Goals::GATHER_TROOPS){priority = 2;};
|
|
||||||
public:
|
public:
|
||||||
|
GatherTroops() : CGoal (Goals::GATHER_TROOPS){priority = 2;};
|
||||||
|
|
||||||
GatherTroops(int type, int val) : CGoal (Goals::GATHER_TROOPS){objid = type; value = val; priority = 2;};
|
GatherTroops(int type, int val) : CGoal (Goals::GATHER_TROOPS){objid = type; value = val; priority = 2;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
TSubgoal whatToDoToAchieve() override;
|
||||||
};
|
};
|
||||||
class GetObj : public CGoal<GetObj>
|
class GetObj : public CGoal<GetObj>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
GetObj() {}; // empty constructor not allowed
|
|
||||||
public:
|
public:
|
||||||
|
GetObj() {}; // empty constructor not allowed
|
||||||
|
|
||||||
GetObj(int Objid) : CGoal(Goals::GET_OBJ) {objid = Objid; priority = 3;};
|
GetObj(int Objid) : CGoal(Goals::GET_OBJ) {objid = Objid; priority = 3;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
TSubgoal whatToDoToAchieve() override;
|
||||||
@ -285,9 +285,9 @@ public:
|
|||||||
};
|
};
|
||||||
class FindObj : public CGoal<FindObj>
|
class FindObj : public CGoal<FindObj>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
FindObj() {}; // empty constructor not allowed
|
|
||||||
public:
|
public:
|
||||||
|
FindObj() {}; // empty constructor not allowed
|
||||||
|
|
||||||
FindObj(int ID) : CGoal(Goals::FIND_OBJ) {objid = ID; priority = 1;};
|
FindObj(int ID) : CGoal(Goals::FIND_OBJ) {objid = ID; priority = 1;};
|
||||||
FindObj(int ID, int subID) : CGoal(Goals::FIND_OBJ) {objid = ID; resID = subID; priority = 1;};
|
FindObj(int ID, int subID) : CGoal(Goals::FIND_OBJ) {objid = ID; resID = subID; priority = 1;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
@ -295,9 +295,9 @@ public:
|
|||||||
};
|
};
|
||||||
class VisitHero : public CGoal<VisitHero>
|
class VisitHero : public CGoal<VisitHero>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
VisitHero() : CGoal (Goals::VISIT_HERO){};
|
|
||||||
public:
|
public:
|
||||||
|
VisitHero() : CGoal (Goals::VISIT_HERO){};
|
||||||
|
|
||||||
VisitHero(int hid) : CGoal (Goals::VISIT_HERO){objid = hid; priority = 4;};
|
VisitHero(int hid) : CGoal (Goals::VISIT_HERO){objid = hid; priority = 4;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
TSubgoal whatToDoToAchieve() override;
|
||||||
@ -307,9 +307,9 @@ public:
|
|||||||
};
|
};
|
||||||
class GetArtOfType : public CGoal<GetArtOfType>
|
class GetArtOfType : public CGoal<GetArtOfType>
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
GetArtOfType() : CGoal (Goals::GET_ART_TYPE){};
|
|
||||||
public:
|
public:
|
||||||
|
GetArtOfType() : CGoal (Goals::GET_ART_TYPE){};
|
||||||
|
|
||||||
GetArtOfType(int type) : CGoal (Goals::GET_ART_TYPE){aid = type; priority = 2;};
|
GetArtOfType(int type) : CGoal (Goals::GET_ART_TYPE){aid = type; priority = 2;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
TSubgoal whatToDoToAchieve() override;
|
||||||
@ -317,9 +317,9 @@ public:
|
|||||||
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
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
VisitTile() {}; // empty constructor not allowed
|
|
||||||
public:
|
public:
|
||||||
|
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;
|
||||||
@ -329,7 +329,10 @@ public:
|
|||||||
class ClearWayTo : public CGoal<ClearWayTo>
|
class ClearWayTo : public CGoal<ClearWayTo>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ClearWayTo() : CGoal (Goals::CLEAR_WAY_TO){};
|
||||||
|
|
||||||
ClearWayTo(int3 Tile) : CGoal (Goals::CLEAR_WAY_TO) {tile = Tile; 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.tile == tile;}
|
bool operator== (ClearWayTo &g) {return g.tile == tile;}
|
||||||
@ -337,9 +340,9 @@ public:
|
|||||||
class DigAtTile : public CGoal<DigAtTile>
|
class DigAtTile : public CGoal<DigAtTile>
|
||||||
//elementar with hero on tile
|
//elementar with hero on tile
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
DigAtTile() : CGoal (Goals::DIG_AT_TILE){};
|
|
||||||
public:
|
public:
|
||||||
|
DigAtTile() : CGoal (Goals::DIG_AT_TILE){};
|
||||||
|
|
||||||
DigAtTile(int3 Tile) : CGoal (Goals::DIG_AT_TILE) {tile = Tile; priority = 20;};
|
DigAtTile(int3 Tile) : CGoal (Goals::DIG_AT_TILE) {tile = Tile; priority = 20;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
TSubgoal whatToDoToAchieve() override;
|
||||||
@ -351,9 +354,11 @@ class CIssueCommand : public CGoal<CIssueCommand>
|
|||||||
std::function<bool()> command;
|
std::function<bool()> command;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
CIssueCommand(): CGoal(ISSUE_COMMAND){};
|
||||||
|
|
||||||
CIssueCommand(std::function<bool()> _command): CGoal(ISSUE_COMMAND), command(_command) {priority = 1e10;};
|
CIssueCommand(std::function<bool()> _command): CGoal(ISSUE_COMMAND), command(_command) {priority = 1e10;};
|
||||||
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
|
||||||
TSubgoal whatToDoToAchieve() override;
|
//TSubgoal whatToDoToAchieve() override {return sptr(Invalid());};
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -598,6 +598,8 @@ void VCAI::saveGame(COSer<CSaveFile> &h, const int version)
|
|||||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
validateVisitableObjs();
|
validateVisitableObjs();
|
||||||
|
|
||||||
|
registerGoals(h);
|
||||||
CAdventureAI::saveGame(h, version);
|
CAdventureAI::saveGame(h, version);
|
||||||
serializeInternal(h, version);
|
serializeInternal(h, version);
|
||||||
}
|
}
|
||||||
@ -606,6 +608,8 @@ void VCAI::loadGame(CISer<CLoadFile> &h, const int version)
|
|||||||
{
|
{
|
||||||
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
LOG_TRACE_PARAMS(logAi, "version '%i'", version);
|
||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
|
|
||||||
|
registerGoals(h);
|
||||||
CAdventureAI::loadGame(h, version);
|
CAdventureAI::loadGame(h, version);
|
||||||
serializeInternal(h, version);
|
serializeInternal(h, version);
|
||||||
}
|
}
|
||||||
@ -1215,24 +1219,18 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(HeroPtr h)
|
|||||||
return possibleDestinations;
|
return possibleDestinations;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VCAI::whatToDoToReachTile (const CGHeroInstance * h, int3 t, Goals::TGoalVec& vec)
|
bool VCAI::canReachTile (const CGHeroInstance * h, int3 t)
|
||||||
///TODO: possibly merge with Goals::ClearWayTo
|
|
||||||
{
|
{
|
||||||
if (t.valid())
|
if (t.valid())
|
||||||
{
|
{
|
||||||
auto obj = cb->getTopObj(t);
|
auto obj = cb->getTopObj(t);
|
||||||
if (obj && vstd::contains(ai->reservedObjs, obj) && !vstd::contains(reservedHeroesMap[h], obj))
|
if (obj && vstd::contains(ai->reservedObjs, obj) && !vstd::contains(reservedHeroesMap[h], obj))
|
||||||
return; //do not capture object reserved by another hero
|
return false; //do not capture object reserved by another hero
|
||||||
if (isSafeToVisit(h, t))
|
|
||||||
{
|
|
||||||
vec.push_back (sptr (Goals::VisitTile(t).sethero(h)));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
return true;
|
||||||
vec.push_back (sptr (Goals::GatherArmy(evaluateDanger(t, h)*SAFE_ATTACK_CONSTANT).
|
|
||||||
sethero(h).setisAbstract(true)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VCAI::canRecruitAnyHero (const CGTownInstance * t) const
|
bool VCAI::canRecruitAnyHero (const CGTownInstance * t) const
|
||||||
@ -2709,8 +2707,16 @@ void SectorMap::exploreNewSector(crint3 pos, int num)
|
|||||||
s.embarkmentPoints.push_back(neighPos);
|
s.embarkmentPoints.push_back(neighPos);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if(t->visitable && vstd::contains(ai->knownSubterraneanGates, t->visitableObjects.front()))
|
|
||||||
toVisit.push(ai->knownSubterraneanGates[t->visitableObjects.front()]->visitablePos());
|
if(t->visitable)
|
||||||
|
{
|
||||||
|
auto obj = t->visitableObjects.front();
|
||||||
|
if (vstd::contains(ai->knownSubterraneanGates, obj))
|
||||||
|
{ //not really sure what does it do, but subtrranean gates do not make one sector
|
||||||
|
toVisit.push(ai->knownSubterraneanGates[obj]->visitablePos());
|
||||||
|
s.subterraneanGates.push_back (obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2893,7 +2899,20 @@ For ship construction etc, another function (goal?) is needed
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO consider other types of connections between sectors?
|
for (auto gate : s->subterraneanGates)
|
||||||
|
{
|
||||||
|
auto gatePair = ai->knownSubterraneanGates.find(gate);
|
||||||
|
if (gatePair != ai->knownSubterraneanGates.end())
|
||||||
|
{
|
||||||
|
//check the other side of gate
|
||||||
|
Sector *neigh = &infoOnSectors[retreiveTile(gatePair->second->visitablePos())];
|
||||||
|
if(!preds[neigh]) //if we didn't come into this sector yet
|
||||||
|
{
|
||||||
|
preds[neigh] = s; //it becomes our new target sector
|
||||||
|
sq.push(neigh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!preds[dst])
|
if(!preds[dst])
|
||||||
@ -3001,10 +3020,19 @@ For ship construction etc, another function (goal?) is needed
|
|||||||
//disembark
|
//disembark
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
else
|
else //use subterranean gates
|
||||||
{
|
{
|
||||||
|
auto firstGate = boost::find_if(src->subterraneanGates, [=](const CGObjectInstance * gate) -> bool
|
||||||
|
{
|
||||||
|
return retreiveTile(gate->visitablePos()) == sectorToReach->id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(firstGate != src->subterraneanGates.end())
|
||||||
|
{
|
||||||
|
return (*firstGate)->visitablePos();
|
||||||
|
}
|
||||||
//TODO
|
//TODO
|
||||||
//transition between two land/water sectors. Monolith? Whirlpool? ...
|
//Monolith? Whirlpool? ...
|
||||||
return ret;
|
return ret;
|
||||||
//throw cannotFulfillGoalException("Land-land and water-water inter-sector transitions are not implemented!");
|
//throw cannotFulfillGoalException("Land-land and water-water inter-sector transitions are not implemented!");
|
||||||
}
|
}
|
||||||
@ -3078,19 +3106,6 @@ void SectorMap::makeParentBFS(crint3 source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
//this code is unused, as tiles on both sides of game are different sectors
|
|
||||||
|
|
||||||
//const TerrainTile *t = cb->getTile(curPos);
|
|
||||||
//if(t->topVisitableId() == Obj::SUBTERRANEAN_GATE)
|
|
||||||
//{
|
|
||||||
// //try finding the exit gate
|
|
||||||
// auto it = ai->knownSubterraneanGates.find(t->topVisitableObj());
|
|
||||||
// if (it != ai->knownSubterraneanGates.end())
|
|
||||||
// {
|
|
||||||
// const int3 outPos = it->second->visitablePos();
|
|
||||||
// parent[outPos] = curPos; //TODO: is it only one tile?
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ struct SectorMap
|
|||||||
int id;
|
int id;
|
||||||
std::vector<int3> tiles;
|
std::vector<int3> tiles;
|
||||||
std::vector<int3> embarkmentPoints; //tiles of other sectors onto which we can (dis)embark
|
std::vector<int3> embarkmentPoints; //tiles of other sectors onto which we can (dis)embark
|
||||||
|
std::vector<const CGObjectInstance *> subterraneanGates;
|
||||||
bool water; //all tiles of sector are land or water
|
bool water; //all tiles of sector are land or water
|
||||||
Sector()
|
Sector()
|
||||||
{
|
{
|
||||||
@ -180,7 +181,7 @@ public:
|
|||||||
int3 explorationBestNeighbour(int3 hpos, int radius, HeroPtr h);
|
int3 explorationBestNeighbour(int3 hpos, int radius, HeroPtr h);
|
||||||
int3 explorationNewPoint(HeroPtr h);
|
int3 explorationNewPoint(HeroPtr h);
|
||||||
int3 explorationDesperate(HeroPtr h);
|
int3 explorationDesperate(HeroPtr h);
|
||||||
void whatToDoToReachTile (const CGHeroInstance * h, int3 t, Goals::TGoalVec& vec);
|
bool canReachTile (const CGHeroInstance * h, int3 t);
|
||||||
void recruitHero();
|
void recruitHero();
|
||||||
|
|
||||||
virtual std::string getBattleAIName() const override;
|
virtual std::string getBattleAIName() const override;
|
||||||
@ -312,6 +313,29 @@ public:
|
|||||||
//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);
|
||||||
|
|
||||||
|
template <typename Handler> void registerGoals(Handler &h)
|
||||||
|
{
|
||||||
|
//h.registerType<Goals::AbstractGoal, Goals::BoostHero>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::Build>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::BuildThis>();
|
||||||
|
//h.registerType<Goals::AbstractGoal, Goals::CIssueCommand>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::ClearWayTo>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::CollectRes>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::Conquer>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::DigAtTile>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::Explore>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::FindObj>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::GatherArmy>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::GatherTroops>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::GetArtOfType>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::GetObj>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::Invalid>();
|
||||||
|
//h.registerType<Goals::AbstractGoal, Goals::NotLose>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::RecruitHero>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::VisitHero>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::VisitTile>();
|
||||||
|
h.registerType<Goals::AbstractGoal, Goals::Win>();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Handler> void serializeInternal(Handler &h, const int version)
|
template <typename Handler> void serializeInternal(Handler &h, const int version)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user