1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-25 21:38:59 +02:00

- Fixes for Quest Guard and goal completion, in particular For Sale map (#894)

- Fixes for ally players handling by AI
This commit is contained in:
DjWarmonger 2013-12-24 22:01:16 +00:00
parent 0c3ccda922
commit a8539b2b28
3 changed files with 50 additions and 43 deletions

View File

@ -258,7 +258,17 @@ TSubgoal GetObj::whatToDoToAchieve()
if(!obj)
return sptr (Goals::Explore());
int3 pos = obj->visitablePos();
return sptr (Goals::VisitTile(pos).sethero(hero)); //we must visit object with same hero, if any
if (hero)
{
if (ai->isAccessibleForHero(pos, hero))
return sptr (Goals::VisitTile(pos).sethero(hero));
}
else
{
if (isReachable(obj))
return sptr (Goals::VisitTile(pos).sethero(hero)); //we must visit object with same hero, if any
}
return sptr (Goals::ClearWayTo(pos).sethero(hero));
}
float GetObj::importanceWhenLocked() const
@ -266,10 +276,9 @@ float GetObj::importanceWhenLocked() const
return 3;
}
bool GetObj::fulfillsMe (shared_ptr<VisitTile> goal)
bool GetObj::fulfillsMe (TSubgoal goal)
{
if (cb->getObj(ObjectInstanceID(objid))->visitablePos() == goal->tile)
if (goal->goalType == Goals::VISIT_TILE && cb->getObj(ObjectInstanceID(objid))->visitablePos() == goal->tile)
return true;
else
return false;
@ -305,9 +314,9 @@ float VisitHero::importanceWhenLocked() const
return 4;
}
bool VisitHero::fulfillsMe (shared_ptr<VisitTile> goal)
bool VisitHero::fulfillsMe (TSubgoal goal)
{
if (cb->getObj(ObjectInstanceID(objid))->visitablePos() == goal->tile)
if (goal->goalType == Goals::VISIT_TILE && cb->getObj(ObjectInstanceID(objid))->visitablePos() == goal->tile)
return true;
else
return false;
@ -355,18 +364,24 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
ret.push_back (sptr (Goals::FindObj (Obj::KEYMASTER, cb->getTile(tileToHit)->visitableObjects.back()->subID)));
}
////FIXME: this code shouldn't be necessary
//if(tileToHit == tile)
//{
// logAi->errorStream() << boost::format("Very strange, tile to hit is %s and tile is also %s, while hero %s is at %s\n")
// % tileToHit % tile % h->name % h->visitablePos();
// throw cannotFulfillGoalException("Retrieving first tile to hit failed (probably)!");
//}
auto topObj = backOrNull(cb->getVisitableObjs(tileToHit));
if(topObj && topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
if(topObj)
{
logAi->errorStream() << boost::format("%s stands in the way of %s.\n") % topObj->getHoverText() % h->getHoverText();
if (topObj->ID == Obj::HERO && cb->getPlayerRelations(h->tempOwner, topObj->tempOwner) != PlayerRelations::ENEMIES)
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 (shouldVisit(h, topObj))
{
//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)));
}
else
{
//TODO: we should be able to return apriopriate quest here (VCAI::striveToQuest)
logAi->debugStream() << "Quest guard blocks the way to " + tile();
}
}
}
else
ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
@ -375,7 +390,10 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
ret.push_back (sptr (Goals::RecruitHero()));
if (ret.empty())
throw cannotFulfillGoalException("There is no known way to clear the way to tile " + tile());
{
logAi->warnStream() << "There is no known way to clear the way to tile " + tile();
throw goalFulfilledException (sptr(*this)); //make sure asigned hero gets unlocked
}
return ret;
}
@ -642,7 +660,7 @@ TSubgoal CollectRes::whatToDoToAchieve()
}
}
}
return sptr (Goals::Invalid()); //FIXME: unused?
return sptr (setisElementar(true)); //all the conditions for trade are met
}
float CollectRes::importanceWhenLocked() const
@ -916,5 +934,3 @@ float CGoal<T>::accept (FuzzyHelper * f)
{
return f->evaluate(static_cast<T&>(*this)); //casting enforces template instantiation
}

View File

@ -116,15 +116,10 @@ public:
{
return false;
}
virtual bool fulfillsMe (Goals::TSubgoal goal)
virtual bool fulfillsMe (Goals::TSubgoal goal) //TODO: multimethod instead of type check
{
return false;
}
virtual bool fulfillsMe (shared_ptr<VisitTile> goal)
{
return false;
}
//template <typename Handler> void serialize(Handler &h, const int version)
//{
@ -301,7 +296,7 @@ public:
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
TSubgoal whatToDoToAchieve() override;
bool operator== (GetObj &g) {return g.objid == objid;}
bool fulfillsMe (shared_ptr<VisitTile> goal) override;
bool fulfillsMe (TSubgoal goal) override;
std::string completeMessage() const override;
float importanceWhenLocked() const override;
};
@ -325,7 +320,7 @@ public:
TGoalVec getAllPossibleSubgoals() override {return TGoalVec();};
TSubgoal whatToDoToAchieve() override;
bool operator== (VisitHero &g) {return g.objid == objid;}
bool fulfillsMe (shared_ptr<VisitTile> goal) override;
bool fulfillsMe (TSubgoal goal) override;
std::string completeMessage() const override;
float importanceWhenLocked() const override;
};

View File

@ -1153,7 +1153,7 @@ bool VCAI::isGoodForVisit(const CGObjectInstance *obj, HeroPtr h)
const int3 pos = obj->visitablePos();
if (isAccessibleForHero(obj->visitablePos(), h) &&
!obj->wasVisited(playerID) &&
(obj->tempOwner != playerID || isWeeklyRevisitable(obj)) && //flag or get weekly resources / creatures
(cb->getPlayerRelations(ai->playerID, obj->tempOwner) == PlayerRelations::ENEMIES || isWeeklyRevisitable(obj)) && //flag or get weekly resources / creatures
isSafeToVisit(h, pos) &&
shouldVisit(h, obj) &&
!vstd::contains(alreadyVisited, obj) &&
@ -1505,7 +1505,9 @@ bool VCAI::isAccessibleForHero(const int3 & pos, HeroPtr h, bool includeAllies /
{ //don't visit tile occupied by allied hero
for (auto obj : cb->getVisitableObjs(pos))
{
if (obj->ID == Obj::HERO && obj->tempOwner == h->tempOwner && obj != h.get())
if (obj->ID == Obj::HERO &&
cb->getPlayerRelations(ai->playerID, obj->tempOwner) != PlayerRelations::ENEMIES &&
obj != h.get())
return false;
}
}
@ -1614,7 +1616,6 @@ void VCAI::tryRealize(Goals::RecruitHero & g)
void VCAI::tryRealize(Goals::VisitTile & g)
{
//cb->recalculatePaths();
if(!g.hero->movement)
throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
if(g.tile == g.hero->visitablePos() && cb->getVisitableObjs(g.hero->visitablePos()).size() < 2)
@ -1623,15 +1624,10 @@ void VCAI::tryRealize(Goals::VisitTile & g)
% g.hero->name % g.tile;
throw goalFulfilledException (sptr(g));
}
//if(!g.isBlockedBorderGate(g.tile))
//{
if (ai->moveHeroToTile(g.tile, g.hero.get()))
{
throw goalFulfilledException (sptr(g));
}
//}
//else
// throw cannotFulfillGoalException("There's a blocked gate!, we should never be here"); //CLEAR_WAY_TO should get keymaster tent
if (ai->moveHeroToTile(g.tile, g.hero.get()))
{
throw goalFulfilledException (sptr(g));
}
}
void VCAI::tryRealize(Goals::VisitHero & g)
@ -1953,7 +1949,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
{
if (q.quest->checkQuest(heroes.front())) //it doesn't matter which hero it is
{
striveToGoal (sptr(Goals::VisitTile(q.tile)));
striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum())));
}
else
{
@ -1975,7 +1971,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
if (obj)
striveToGoal (sptr(Goals::GetObj(obj->id.getNum())));
else
striveToGoal (sptr(Goals::VisitTile(q.tile))); //visit seer hut
striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum()))); //visit seer hut
break;
}
case CQuest::MISSION_PRIMARY_STAT:
@ -2002,7 +1998,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
{
if (q.quest->checkQuest(hero))
{
striveToGoal (sptr(Goals::VisitTile(q.tile).sethero(hero))); //TODO: causes infinite loop :/
striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum()).sethero(hero))); //TODO: causes infinite loop :/
return;
}
}