浏览代码

fix: skip pass and priority pass if hero is not valid anymore to as extra checks for lost heroes

Mircea TheHonestCTO 3 月之前
父节点
当前提交
2e49d6aca9

+ 4 - 4
AI/Nullkiller2/AIUtility.cpp

@@ -95,14 +95,14 @@ const CGHeroInstance * HeroPtr::getUnverified() const
 	return hero;
 }
 
-bool HeroPtr::verify() const
+bool HeroPtr::verify(const bool verbose) const
 {
 	// TODO: check if these all assertions every time we get info about hero affect efficiency
 	// behave terribly when attempting unauthorized access to hero that is not ours (or was lost)
 
 	if(hero)
 	{
-		const auto *obj = cpsic->getObj(hero->id);
+		const auto *obj = cpsic->getObj(hero->id, verbose);
 		//const bool owned = obj && obj->tempOwner == ai->playerID;
 
 		if(!obj)
@@ -123,9 +123,9 @@ const CGHeroInstance * HeroPtr::operator->() const
 }
 
 // Should be called before using the hero inside this HeroPtr, that's the point of this
-bool HeroPtr::isVerified() const
+bool HeroPtr::isVerified(const bool verbose) const
 {
-	return verify();
+	return verify(verbose);
 }
 
 // enforces isVerified()

+ 2 - 2
AI/Nullkiller2/AIUtility.h

@@ -79,7 +79,7 @@ struct DLL_EXPORT HeroPtr
 private:
 	const CGHeroInstance * hero;
 	std::shared_ptr<CPlayerSpecificInfoCallback> cpsic;
-	bool verify() const;
+	bool verify(bool verbose = true) const;
 
 public:
 	explicit HeroPtr(const CGHeroInstance * input, std::shared_ptr<CPlayerSpecificInfoCallback> cpsic);
@@ -102,7 +102,7 @@ public:
 	std::string nameOrDefault() const;
 	const CGHeroInstance * get() const;
 	const CGHeroInstance * getUnverified() const;
-	bool isVerified() const;
+	bool isVerified(bool verbose = true) const;
 };
 
 enum BattleState

+ 18 - 10
AI/Nullkiller2/Engine/Nullkiller.cpp

@@ -460,17 +460,22 @@ void Nullkiller::makeTurn()
 				continue;
 			}
 
-#if NK2AI_TRACE_LEVEL >= 1
 			logAi->info("Pass %d: Performing prio %d task %s with prio: %d", i, prioOfTask, selectedTask->toString(), selectedTask->priority);
-#endif
 
-			if(!executeTask(selectedTask))
+			if(HeroPtr heroPtr(selectedTask->getHero(), cc); selectedTask->getHero() && !heroPtr.isVerified(false))
 			{
-				if(hasAnySuccess)
-					break;
-				return;
+				logAi->warn("Nullkiller::makeTurn Skipping pass due to unverified hero: %s", heroPtr.nameOrDefault());
+			}
+			else
+			{
+				if(!executeTask(selectedTask))
+				{
+					if(hasAnySuccess)
+						break;
+					return;
+				}
+				hasAnySuccess = true;
 			}
-			hasAnySuccess = true;
 		}
 
 		hasAnySuccess |= handleTrading();
@@ -509,13 +514,16 @@ bool Nullkiller::updateStateAndExecutePriorityPass(Goals::TGoalVec & tempResults
 		{
 			logAi->info("Pass %d: Performing priorityPass %d task %s with prio: %d", passIndex, i, bestPrioPassTask->toString(), bestPrioPassTask->priority);
 
-			if(!executeTask(bestPrioPassTask))
+			if(HeroPtr heroPtr(bestPrioPassTask->getHero(), cc); bestPrioPassTask->getHero() && !heroPtr.isVerified(false))
+			{
+				logAi->warn("Nullkiller::updateStateAndExecutePriorityPass Skipping priorityPass due to unverified hero: %s", heroPtr.nameOrDefault());
+			}
+			else if(!executeTask(bestPrioPassTask))
 			{
 				logAi->warn("Task failed to execute");
 				return false;
 			}
 
-			// TODO: Mircea: Might want to consider calling it before executeTask just in case
 			updateState();
 		}
 		else
@@ -555,7 +563,7 @@ HeroRole Nullkiller::getTaskRole(const Goals::TTask & task) const
 	return heroRole;
 }
 
-bool Nullkiller::executeTask(const Goals::TTask & task)
+bool Nullkiller::executeTask(const Goals::TTask & task) const
 {
 	auto start = std::chrono::high_resolution_clock::now();
 	std::string taskDescr = task->toString();

+ 1 - 1
AI/Nullkiller2/Engine/Nullkiller.h

@@ -148,7 +148,7 @@ private:
 	void decompose(Goals::TGoalVec & results, const Goals::TSubgoal& behavior, int decompositionMaxDepth) const;
 	Goals::TTask choseBestTask(Goals::TGoalVec & tasks) const;
 	Goals::TTaskVec buildPlan(Goals::TGoalVec & tasks, int priorityTier) const;
-	bool executeTask(const Goals::TTask & task);
+	bool executeTask(const Goals::TTask & task) const;
 	bool areAffectedObjectsPresent(const Goals::TTask & task) const;
 	HeroRole getTaskRole(const Goals::TTask & task) const;
 	void tracePlayerStatus(bool beginning) const;

+ 2 - 2
AI/Nullkiller2/Pathfinding/AINodeStorage.cpp

@@ -1429,10 +1429,10 @@ void AINodeStorage::calculateChainInfo(std::vector<AIPath> & paths, const int3 &
 			continue;
 		}
 
-		if(HeroPtr heroPtr(node.actor->hero, aiNk->cc); !heroPtr.isVerified())
+		if(HeroPtr heroPtr(node.actor->hero, aiNk->cc); !heroPtr.isVerified(false))
 		{
 #if NK2AI_TRACE_LEVEL >= 1
-			logAi->warn("AINodeStorage::calculateChainInfo Skipping unverified hero: %s", heroPtr.nameOrDefault());
+			logAi->warn("AINodeStorage::calculateChainInfo Skipping path due to unverified hero: %s", heroPtr.nameOrDefault());
 #endif
 			continue;
 		}

+ 3 - 4
lib/callback/CGameInfoCallback.cpp

@@ -111,17 +111,16 @@ TurnTimerInfo CGameInfoCallback::getPlayerTurnTime(PlayerColor color) const
 /*                                                                      */
 /************************************************************************/
 
-const CGObjectInstance* CGameInfoCallback::getObj(ObjectInstanceID objid, bool verbose) const
+const CGObjectInstance * CGameInfoCallback::getObj(const ObjectInstanceID objId, const bool verbose) const
 {
-	const CGObjectInstance * ret = MapInfoCallback::getObj(objid, verbose);
-
+	const CGObjectInstance * ret = MapInfoCallback::getObj(objId, verbose);
 	if(!ret)
 		return nullptr;
 
 	if(getPlayerID().has_value() && !isVisibleFor(ret, *getPlayerID()) && ret->tempOwner != getPlayerID())
 	{
 		if(verbose)
-			logGlobal->error("Cannot get object with id %d. Object is not visible.", objid.getNum());
+			logGlobal->error("Cannot get object with id %d. Object is not visible.", objId.getNum());
 		return nullptr;
 	}
 

+ 1 - 1
lib/callback/CGameInfoCallback.h

@@ -61,7 +61,7 @@ public:
 	const CArtifactSet * getArtSet(const ArtifactLocation & loc) const;
 
 	//objects
-	const CGObjectInstance * getObj(ObjectInstanceID objid, bool verbose = true) const override;
+	const CGObjectInstance * getObj(ObjectInstanceID objId, bool verbose = true) const override;
 	std::vector<const CGObjectInstance *> getBlockingObjs(int3 pos) const;
 	std::vector<const CGObjectInstance *> getVisitableObjs(int3 pos, bool verbose = true) const;
 	std::vector<const CGObjectInstance *> getAllVisitableObjs() const;

+ 5 - 5
lib/callback/MapInfoCallback.cpp

@@ -22,19 +22,19 @@ VCMI_LIB_NAMESPACE_BEGIN
 
 MapInfoCallback::~MapInfoCallback() = default;
 
-const CGObjectInstance * MapInfoCallback::getObj(ObjectInstanceID objid, bool verbose) const
+const CGObjectInstance * MapInfoCallback::getObj(const ObjectInstanceID objId, const bool verbose) const
 {
-	if(!objid.hasValue())
+	if(!objId.hasValue())
 	{
 		if(verbose)
-			logGlobal->error("Cannot get object with id %d. No such object", objid.getNum());
+			logGlobal->error("Cannot get object with id %d. No such object", objId.getNum());
 		return nullptr;
 	}
 
-	const CGObjectInstance * ret = getMapConstPtr()->getObject(objid);
+	const CGObjectInstance * ret = getMapConstPtr()->getObject(objId);
 	if(!ret && verbose)
 	{
-		logGlobal->error("Cannot get object with id %d. Object was removed", objid.getNum());
+		logGlobal->error("Cannot get object with id %d. Object was removed", objId.getNum());
 		return nullptr;
 	}
 

+ 1 - 1
lib/callback/MapInfoCallback.h

@@ -23,7 +23,7 @@ protected:
 public:
 	virtual ~MapInfoCallback();
 
-	const CGObjectInstance * getObj(ObjectInstanceID objid, bool verbose = true) const override;
+	const CGObjectInstance * getObj(ObjectInstanceID objId, bool verbose = true) const override;
 	const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const override;
 	const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const override;
 	const CGHeroInstance * getHero(ObjectInstanceID objid) const override;