Ver código fonte

- Fixes for Quest Guard and goal completion, in particular For Sale map (#894)
- Fixes for ally players handling by AI

DjWarmonger 12 anos atrás
pai
commit
a8539b2b28
3 arquivos alterados com 50 adições e 43 exclusões
  1. 36 20
      AI/VCAI/Goals.cpp
  2. 3 8
      AI/VCAI/Goals.h
  3. 11 15
      AI/VCAI/VCAI.cpp

+ 36 - 20
AI/VCAI/Goals.cpp

@@ -258,7 +258,17 @@ TSubgoal GetObj::whatToDoToAchieve()
 	if(!obj)
 	if(!obj)
 		return sptr (Goals::Explore());
 		return sptr (Goals::Explore());
 	int3 pos = obj->visitablePos();
 	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
 float GetObj::importanceWhenLocked() const
@@ -266,10 +276,9 @@ float GetObj::importanceWhenLocked() const
 	return 3;
 	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;
 		return true;
 	else
 	else
 		return false;
 		return false;
@@ -305,9 +314,9 @@ float VisitHero::importanceWhenLocked() const
 	return 4;
 	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;
 		return true;
 	else
 	else
 		return false;
 		return false;
@@ -355,18 +364,24 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
 			ret.push_back  (sptr (Goals::FindObj (Obj::KEYMASTER, cb->getTile(tileToHit)->visitableObjects.back()->subID)));
 			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));
 		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
 		else
 			ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
 			ret.push_back (sptr (Goals::VisitTile(tileToHit).sethero(h)));
@@ -375,7 +390,10 @@ TGoalVec ClearWayTo::getAllPossibleSubgoals()
 		ret.push_back (sptr (Goals::RecruitHero()));
 		ret.push_back (sptr (Goals::RecruitHero()));
 
 
 	if (ret.empty())
 	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;
 	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
 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
 	return f->evaluate(static_cast<T&>(*this)); //casting enforces template instantiation
 }
 }
-
-

+ 3 - 8
AI/VCAI/Goals.h

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

+ 11 - 15
AI/VCAI/VCAI.cpp

@@ -1153,7 +1153,7 @@ bool VCAI::isGoodForVisit(const CGObjectInstance *obj, HeroPtr h)
 	const int3 pos = obj->visitablePos();
 	const int3 pos = obj->visitablePos();
 	if (isAccessibleForHero(obj->visitablePos(), h) &&
 	if (isAccessibleForHero(obj->visitablePos(), h) &&
 			!obj->wasVisited(playerID) &&
 			!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) &&
 			isSafeToVisit(h, pos) &&
 			shouldVisit(h, obj) &&
 			shouldVisit(h, obj) &&
 			!vstd::contains(alreadyVisited, 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
 	{ //don't visit tile occupied by allied hero
 		for (auto obj : cb->getVisitableObjs(pos))
 		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;
 				return false;
 		}
 		}
 	}
 	}
@@ -1614,7 +1616,6 @@ void VCAI::tryRealize(Goals::RecruitHero & g)
 
 
 void VCAI::tryRealize(Goals::VisitTile & g)
 void VCAI::tryRealize(Goals::VisitTile & g)
 {
 {
-	//cb->recalculatePaths();
 	if(!g.hero->movement)
 	if(!g.hero->movement)
 		throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
 		throw cannotFulfillGoalException("Cannot visit tile: hero is out of MPs!");
 	if(g.tile == g.hero->visitablePos()  &&  cb->getVisitableObjs(g.hero->visitablePos()).size() < 2)
 	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;
 												% g.hero->name % g.tile;
 		throw goalFulfilledException (sptr(g));
 		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)
 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
 					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
 					else
 					{
 					{
@@ -1975,7 +1971,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
 				if (obj)
 				if (obj)
 					striveToGoal (sptr(Goals::GetObj(obj->id.getNum())));
 					striveToGoal (sptr(Goals::GetObj(obj->id.getNum())));
 				else
 				else
-					striveToGoal (sptr(Goals::VisitTile(q.tile))); //visit seer hut
+					striveToGoal (sptr(Goals::GetObj(q.obj->id.getNum()))); //visit seer hut
 				break;
 				break;
 			}
 			}
 			case CQuest::MISSION_PRIMARY_STAT:
 			case CQuest::MISSION_PRIMARY_STAT:
@@ -2002,7 +1998,7 @@ void VCAI::striveToQuest (const QuestInfo &q)
 				{
 				{
 					if (q.quest->checkQuest(hero))
 					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;
 						return;
 					}
 					}
 				}
 				}