1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

- A complete solutions for reserved adventure objects

- AI won't get stuck at School of War / School of Magic when no money
This commit is contained in:
DjWarmonger 2012-03-29 18:26:06 +00:00
parent 3cf4ebc163
commit 81367ef6d5
3 changed files with 100 additions and 8 deletions

View File

@ -555,6 +555,8 @@ void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visi
{ {
visitedObject = const_cast<CGObjectInstance *>(visitedObj); // remember the object and wait for return visitedObject = const_cast<CGObjectInstance *>(visitedObj); // remember the object and wait for return
markObjectVisited (visitedObj); markObjectVisited (visitedObj);
remove_if_present(reservedObjs, visitedObj); //unreserve objects
remove_if_present(reservedHeroesMap[visitor], visitedObj);
} }
} }
@ -1114,6 +1116,9 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(const CGHero
if (!shouldVisit(h, obj)) if (!shouldVisit(h, obj))
return true; return true;
if (vstd::contains(reservedObjs, obj)) //does checking for our own reserved objects make sense? here?
return true;
return false; return false;
}),possibleDestinations.end()); }),possibleDestinations.end());
@ -1125,18 +1130,74 @@ void VCAI::wander(const CGHeroInstance * h)
{ {
while(1) while(1)
{ {
auto dests = getPossibleDestinations(h); std::vector <const CGObjectInstance *> dests (reservedHeroesMap[h].begin(), reservedHeroesMap[h].end()); //copy constructor
if (!dests.size())
dests = getPossibleDestinations(h);
if(!dests.size()) if(!dests.size())
{ {
PNLOG("Nowhere more to go...\n"); auto compareReinforcements = [h](const CGTownInstance *lhs, const CGTownInstance *rhs) -> bool
setGoal (h, INVALID); {
break; return howManyReinforcementsCanGet(h, lhs) < howManyReinforcementsCanGet(h, rhs);
};
std::vector<const CGTownInstance *> townsReachable;
std::vector<const CGTownInstance *> townsNotReachable;
BOOST_FOREACH(const CGTownInstance *t, cb->getTownsInfo())
{
if(!t->visitingHero && howManyReinforcementsCanGet(h,t) && !vstd::contains(townVisitsThisWeek[h], t))
{
if(isReachable(t))
townsReachable.push_back(t);
else
townsNotReachable.push_back(t);
}
}
if(townsReachable.size())
{
boost::sort(townsReachable, compareReinforcements);
dests.push_back(townsReachable.back());
}
else if(townsNotReachable.size())
{
boost::sort(townsNotReachable, compareReinforcements);
//TODO pick the truly best
const CGTownInstance *t = townsNotReachable.back();
BNLOG("%s can't reach any town, we'll try to make our way to %s at %s", h->name % t->name % t->visitablePos());
int3 pos1 = h->pos;
striveToGoal(CGoal(CLEAR_WAY_TO).settile(t->visitablePos()).sethero(h));
if (pos1 == h->pos && h == primaryHero()) //hero can't move
{
if(cb->getResourceAmount(Res::GOLD) >= HERO_GOLD_COST && cb->getHeroesInfo().size() < ALLOWED_ROAMING_HEROES && cb->getAvailableHeroes(t).size())
recruitHero(t);
}
break;
}
else if(cb->getResourceAmount(Res::GOLD) >= HERO_GOLD_COST)
{
std::vector<const CGTownInstance *> towns = cb->getTownsInfo();
erase_if(towns, [](const CGTownInstance *t) -> bool
{
BOOST_FOREACH(const CGHeroInstance *h, cb->getHeroesInfo())
if(!t->getArmyStrength() || howManyReinforcementsCanGet(h, t))
return true;
return false;
});
boost::sort(towns, compareArmyStrength);
if(towns.size())
recruitHero(towns.back());
break;
}
else
{
PNLOG("Nowhere more to go...\n");
break;
}
} }
const CGObjectInstance * obj = dests.front(); const CGObjectInstance * obj = dests.front();
if(!goVisitObj(obj, h)) if(!goVisitObj(obj, h))
{ {
BNLOG("Hero %s apparently used all MPs (%d left)\n", h->name % h->movement); BNLOG("Hero %s apparently used all MPs (%d left)\n", h->name % h->movement);
markObjectVisited(obj); //reserve that object - we predict it will be reached soon reserveObject(h, obj); //reserve that object - we predict it will be reached soon
setGoal(h, CGoal(VISIT_TILE).sethero(h).settile(obj->visitablePos())); setGoal(h, CGoal(VISIT_TILE).sethero(h).settile(obj->visitablePos()));
break; break;
} }
@ -1194,6 +1255,12 @@ void VCAI::markObjectVisited (const CGObjectInstance *obj)
alreadyVisited.push_back(obj); alreadyVisited.push_back(obj);
} }
void VCAI::reserveObject (const CGHeroInstance * h, const CGObjectInstance *obj)
{
reservedObjs.push_back(obj);
reservedHeroesMap[h].insert(obj);
}
void VCAI::validateVisitableObjs() void VCAI::validateVisitableObjs()
{ {
std::vector<const CGObjectInstance *> hlp; std::vector<const CGObjectInstance *> hlp;
@ -1355,9 +1422,15 @@ bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h)
cb->moveHero(h,CGHeroInstance::convertPosition(endpos, true)); cb->moveHero(h,CGHeroInstance::convertPosition(endpos, true));
waitTillFree(); //movement may cause battle or blocking dialog waitTillFree(); //movement may cause battle or blocking dialog
boost::this_thread::interruption_point(); boost::this_thread::interruption_point();
if(h->tempOwner != playerID) //we lost hero if(h->tempOwner != playerID) //we lost hero - remove all tasks assigned to him/her
{ {
remove_if_present(lockedHeroes, h); remove_if_present(lockedHeroes, h);
BOOST_FOREACH (auto obj, reservedHeroesMap[h])
{
remove_if_present(reservedObjs, obj); //unreserve all objects for that hero
}
remove_if_present(reservedHeroesMap, h);
throw std::runtime_error("Hero was lost!"); //we need to throw, otherwise hero will be assigned to sth again throw std::runtime_error("Hero was lost!"); //we need to throw, otherwise hero will be assigned to sth again
break; break;
} }
@ -1366,7 +1439,9 @@ bool VCAI::moveHeroToTile(int3 dst, const CGHeroInstance * h)
ret = !i; ret = !i;
} }
if (visitedObject) //we step into something interesting if (visitedObject) //we step into something interesting
{
performObjectInteraction (visitedObject, h); performObjectInteraction (visitedObject, h);
}
if(h->tempOwner == playerID) //lost hero after last move if(h->tempOwner == playerID) //lost hero after last move
cb->recalculatePaths(); cb->recalculatePaths();
@ -2524,8 +2599,6 @@ bool isWeeklyRevisitable (const CGObjectInstance * obj)
bool shouldVisit (const CGHeroInstance * h, const CGObjectInstance * obj) bool shouldVisit (const CGHeroInstance * h, const CGObjectInstance * obj)
{ {
if (obj->wasVisited(h))
return false;
switch (obj->ID) switch (obj->ID)
{ {
case Obj::CREATURE_GENERATOR1: case Obj::CREATURE_GENERATOR1:
@ -2548,7 +2621,20 @@ bool shouldVisit (const CGHeroInstance * h, const CGObjectInstance * obj)
case Obj::WHIRLPOOL: case Obj::WHIRLPOOL:
//TODO: mehcanism for handling monoliths //TODO: mehcanism for handling monoliths
return false; return false;
case Obj::SCHOOL_OF_MAGIC:
case Obj::SCHOOL_OF_WAR:
{
TResources myRes = ai->myCb->getResourceAmount();
if (myRes[Res::GOLD] - GOLD_RESERVE < 1000)
return false;
}
case Obj::LIBRARY_OF_ENLIGHTENMENT:
return h->level >= 12;
} }
if (obj->wasVisited(h))
return false;
return true; return true;
} }

View File

@ -157,9 +157,11 @@ public:
std::map<const CGHeroInstance *, std::vector<const CGTownInstance *> > townVisitsThisWeek; std::map<const CGHeroInstance *, std::vector<const CGTownInstance *> > townVisitsThisWeek;
std::map<const CGHeroInstance *, CGoal> lockedHeroes; //TODO: allow non-elementar objectives std::map<const CGHeroInstance *, CGoal> lockedHeroes; //TODO: allow non-elementar objectives
std::map<const CGHeroInstance *, std::set<const CGObjectInstance *> > reservedHeroesMap; //objects reserved by specific heroes
std::vector<const CGObjectInstance *> visitableObjs; std::vector<const CGObjectInstance *> visitableObjs;
std::vector<const CGObjectInstance *> alreadyVisited; std::vector<const CGObjectInstance *> alreadyVisited;
std::vector<const CGObjectInstance *> reservedObjs; //to be visited by specific hero
TResources saving; TResources saving;
@ -266,6 +268,7 @@ public:
void addVisitableObj(const CGObjectInstance *obj); void addVisitableObj(const CGObjectInstance *obj);
void markObjectVisited (const CGObjectInstance *obj); void markObjectVisited (const CGObjectInstance *obj);
void reserveObject (const CGHeroInstance * h, const CGObjectInstance *obj);
//void removeVisitableObj(const CGObjectInstance *obj); //void removeVisitableObj(const CGObjectInstance *obj);
void validateVisitableObjs(); void validateVisitableObjs();
void retreiveVisitableObjs(std::vector<const CGObjectInstance *> &out, bool includeOwned = false) const; void retreiveVisitableObjs(std::vector<const CGObjectInstance *> &out, bool includeOwned = false) const;

View File

@ -180,9 +180,11 @@ namespace Obj
DERELICT_SHIP = 24, DERELICT_SHIP = 24,
DRAGON_UTOPIA = 25, DRAGON_UTOPIA = 25,
GARRISON = 33, GARRISON = 33,
LIBRARY_OF_ENLIGHTENMENT = 41,
MONOLITH1 = 43, MONOLITH1 = 43,
MONOLITH2 = 44, MONOLITH2 = 44,
MONOLITH3 = 45, MONOLITH3 = 45,
SCHOOL_OF_MAGIC = 47,
MINE = 53, MINE = 53,
MONSTER = 54, MONSTER = 54,
OBELISK = 57, OBELISK = 57,
@ -192,6 +194,7 @@ namespace Obj
STABLES = 94, STABLES = 94,
TRADING_POST = 99, TRADING_POST = 99,
SUBTERRANEAN_GATE = 103, SUBTERRANEAN_GATE = 103,
SCHOOL_OF_WAR = 107,
WHIRLPOOL = 111, WHIRLPOOL = 111,
BORDER_GATE = 212, BORDER_GATE = 212,
GARRISON2 = 219, GARRISON2 = 219,