mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-26 08:41:13 +02:00
- Fixed some more cases when heroes could block each other
- More generous checking of complete goals and their dependencies
This commit is contained in:
parent
b0bdfff117
commit
54c52869cf
@ -191,7 +191,7 @@ TSubgoal FindObj::whatToDoToAchieve()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (o && isReachable(o))
|
||||
if (o && isReachable(o)) //we don't use isAccessibleForHero as we don't know which hero it is
|
||||
return sptr (Goals::GetObj(o->id.getNum()));
|
||||
else
|
||||
return sptr (Goals::Explore());
|
||||
@ -210,6 +210,14 @@ TSubgoal GetObj::whatToDoToAchieve()
|
||||
return sptr (Goals::VisitTile(pos));
|
||||
}
|
||||
|
||||
bool GetObj::fulfillsMe (shared_ptr<VisitTile> goal)
|
||||
{
|
||||
if (cb->getObj(ObjectInstanceID(objid))->visitablePos() == goal->tile)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string VisitHero::completeMessage() const
|
||||
{
|
||||
return "hero " + hero.get()->name + " visited hero " + boost::lexical_cast<std::string>(objid);
|
||||
@ -231,6 +239,14 @@ TSubgoal VisitHero::whatToDoToAchieve()
|
||||
return sptr (Goals::Invalid());
|
||||
}
|
||||
|
||||
bool VisitHero::fulfillsMe (shared_ptr<VisitTile> goal)
|
||||
{
|
||||
if (cb->getObj(ObjectInstanceID(objid))->visitablePos() == goal->tile)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
TSubgoal GetArtOfType::whatToDoToAchieve()
|
||||
{
|
||||
TSubgoal alternativeWay = CGoal::lookForArtSmart(aid); //TODO: use
|
||||
@ -718,7 +734,7 @@ TSubgoal GatherArmy::whatToDoToAchieve()
|
||||
{
|
||||
if(!t->visitingHero && howManyReinforcementsCanGet(hero,t))
|
||||
{
|
||||
if(isReachable(t) && !vstd::contains (ai->townVisitsThisWeek[hero], t))
|
||||
if (ai->isAccessibleForHero(t->pos, hero) && !vstd::contains (ai->townVisitsThisWeek[hero], t))
|
||||
townsReachable.push_back(t);
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ class VCAI;
|
||||
namespace Goals
|
||||
{
|
||||
struct AbstractGoal;
|
||||
class VisitTile;
|
||||
typedef std::shared_ptr<Goals::AbstractGoal> TSubgoal;
|
||||
typedef std::vector<TSubgoal> TGoalVec;
|
||||
|
||||
@ -108,6 +109,14 @@ public:
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool fulfillsMe (Goals::TSubgoal goal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual bool fulfillsMe (shared_ptr<VisitTile> goal)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//template <typename Handler> void serialize(Handler &h, const int version)
|
||||
@ -259,6 +268,7 @@ public:
|
||||
GetObj(int Objid) : CGoal(Goals::GET_OBJ) {objid = Objid;};
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
bool operator== (GetObj &g) {return g.objid == objid;}
|
||||
bool fulfillsMe (shared_ptr<VisitTile> goal) override;
|
||||
std::string completeMessage() const override;
|
||||
};
|
||||
class FindObj : public CGoal<FindObj>
|
||||
@ -278,6 +288,7 @@ public:
|
||||
VisitHero(int hid) : CGoal (Goals::VISIT_HERO){objid = hid;};
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
bool operator== (VisitHero &g) {return g.objid == objid;}
|
||||
bool fulfillsMe (shared_ptr<VisitTile> goal) override;
|
||||
std::string completeMessage() const override;
|
||||
};
|
||||
class GetArtOfType : public CGoal<GetArtOfType>
|
||||
|
@ -259,7 +259,8 @@ void VCAI::heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visi
|
||||
markObjectVisited (visitedObj);
|
||||
erase_if_present(reservedObjs, visitedObj); //unreserve objects
|
||||
erase_if_present(reservedHeroesMap[visitor], visitedObj);
|
||||
completeGoal (sptr(Goals::GetObj(visitedObj->id.getNum()).sethero(visitor))); //we don't need to visit in anymore
|
||||
completeGoal (sptr(Goals::GetObj(visitedObj->id.getNum()).sethero(visitor))); //we don't need to visit it anymore
|
||||
//TODO: what if we visited one-time visitable object that was reserved by another hero (shouldn't, but..)
|
||||
}
|
||||
|
||||
status.heroVisit(visitedObj, start);
|
||||
@ -1083,7 +1084,7 @@ std::vector<const CGObjectInstance *> VCAI::getPossibleDestinations(HeroPtr h)
|
||||
std::vector<const CGObjectInstance *> possibleDestinations;
|
||||
for(const CGObjectInstance *obj : visitableObjs)
|
||||
{
|
||||
if(cb->getPathInfo(obj->visitablePos())->reachable() && !obj->wasVisited(playerID) &&
|
||||
if(isAccessibleForHero(obj->visitablePos(), h) && !obj->wasVisited(playerID) &&
|
||||
(obj->tempOwner != playerID || isWeeklyRevisitable(obj))) //flag or get weekly resources / creatures
|
||||
possibleDestinations.push_back(obj);
|
||||
}
|
||||
@ -1122,8 +1123,15 @@ void VCAI::wander(HeroPtr h)
|
||||
while(1)
|
||||
{
|
||||
validateVisitableObjs();
|
||||
std::vector <ObjectIdRef> dests;
|
||||
range::copy(reservedHeroesMap[h], std::back_inserter(dests));
|
||||
std::vector <ObjectIdRef> dests, tmp;
|
||||
|
||||
range::copy(reservedHeroesMap[h], std::back_inserter(tmp)); //visit our reserved objects first
|
||||
for (auto obj : tmp)
|
||||
{
|
||||
if (isAccessibleForHero (obj->visitablePos(), h)) //even nearby objects could be blocked by other heroes :(
|
||||
dests.push_back(obj); //can't use lambda for member function :(
|
||||
}
|
||||
|
||||
if (!dests.size())
|
||||
range::copy(getPossibleDestinations(h), std::back_inserter(dests));
|
||||
|
||||
@ -1140,7 +1148,7 @@ void VCAI::wander(HeroPtr h)
|
||||
{
|
||||
if(!t->visitingHero && howManyReinforcementsCanGet(h,t) && !vstd::contains(townVisitsThisWeek[h], t))
|
||||
{
|
||||
if(isReachable(t))
|
||||
if (isAccessibleForHero (t->visitablePos(), h))
|
||||
townsReachable.push_back(t);
|
||||
else
|
||||
townsNotReachable.push_back(t);
|
||||
@ -1243,9 +1251,9 @@ void VCAI::completeGoal (Goals::TSubgoal goal)
|
||||
{
|
||||
for (auto p : lockedHeroes)
|
||||
{
|
||||
if (p.second == goal)
|
||||
if (p.second == goal || p.second->fulfillsMe(goal)) //we could have fulfilled goals of other heroes by chance
|
||||
{
|
||||
logAi->debugStream() << boost::format("%s") % goal->completeMessage();
|
||||
logAi->debugStream() << boost::format("%s") % p.second->completeMessage();
|
||||
lockedHeroes.erase (lockedHeroes.find(p.first)); //is it safe?
|
||||
}
|
||||
}
|
||||
@ -1688,16 +1696,6 @@ void VCAI::endTurn()
|
||||
logAi->debugStream() << "Player " << static_cast<int>(playerID.getNum()) << " ended turn";
|
||||
}
|
||||
|
||||
bool VCAI::fulfillsGoal (Goals::TSubgoal goal, Goals::TSubgoal mainGoal)
|
||||
{
|
||||
if (mainGoal->goalType == Goals::GET_OBJ && goal->goalType == Goals::VISIT_TILE) //deduce that GET_OBJ was completed by visiting object's tile
|
||||
{ //TODO: more universal mechanism
|
||||
if (cb->getObj(ObjectInstanceID(mainGoal->objid))->visitablePos() == goal->tile)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VCAI::striveToGoal(Goals::TSubgoal ultimateGoal)
|
||||
{
|
||||
if (ultimateGoal->invalid())
|
||||
@ -1783,7 +1781,7 @@ Goals::TSubgoal VCAI::striveToGoalInternal(Goals::TSubgoal ultimateGoal, bool on
|
||||
catch(goalFulfilledException &e)
|
||||
{
|
||||
completeGoal (goal);
|
||||
if (fulfillsGoal (goal, ultimateGoal) || maxGoals > 98) //completed goal was main goal //TODO: find better condition
|
||||
if (ultimateGoal->fulfillsMe(goal) || maxGoals > 98) //completed goal was main goal //TODO: find better condition
|
||||
return sptr(Goals::Invalid());
|
||||
}
|
||||
catch(std::exception &e)
|
||||
|
@ -239,7 +239,6 @@ public:
|
||||
void setGoal(HeroPtr h, Goals::TSubgoal goal);
|
||||
void completeGoal (Goals::TSubgoal goal); //safely removes goal from reserved hero
|
||||
void striveToQuest (const QuestInfo &q);
|
||||
bool fulfillsGoal (Goals::TSubgoal goal, Goals::TSubgoal mainGoal);
|
||||
|
||||
void recruitHero(const CGTownInstance * t, bool throwing = false);
|
||||
std::vector<const CGObjectInstance *> getPossibleDestinations(HeroPtr h);
|
||||
|
Loading…
Reference in New Issue
Block a user