Browse Source

- Fixed some more cases when heroes could block each other
- More generous checking of complete goals and their dependencies

DjWarmonger 12 years ago
parent
commit
54c52869cf
4 changed files with 45 additions and 21 deletions
  1. 18 2
      AI/VCAI/Goals.cpp
  2. 11 0
      AI/VCAI/Goals.h
  3. 16 18
      AI/VCAI/VCAI.cpp
  4. 0 1
      AI/VCAI/VCAI.h

+ 18 - 2
AI/VCAI/Goals.cpp

@@ -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);
 		}
 	}

+ 11 - 0
AI/VCAI/Goals.h

@@ -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>

+ 16 - 18
AI/VCAI/VCAI.cpp

@@ -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)

+ 0 - 1
AI/VCAI/VCAI.h

@@ -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);