1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-27 22:49:25 +02:00

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

This commit is contained in:
Mircea TheHonestCTO
2025-09-04 00:56:36 +02:00
parent 7a40981a95
commit 2e49d6aca9
9 changed files with 37 additions and 30 deletions

View File

@@ -95,14 +95,14 @@ const CGHeroInstance * HeroPtr::getUnverified() const
return hero; 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 // 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) // behave terribly when attempting unauthorized access to hero that is not ours (or was lost)
if(hero) 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; //const bool owned = obj && obj->tempOwner == ai->playerID;
if(!obj) 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 // 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() // enforces isVerified()

View File

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

View File

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

View File

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

View File

@@ -1429,10 +1429,10 @@ void AINodeStorage::calculateChainInfo(std::vector<AIPath> & paths, const int3 &
continue; 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 #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 #endif
continue; continue;
} }

View File

@@ -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) if(!ret)
return nullptr; return nullptr;
if(getPlayerID().has_value() && !isVisibleFor(ret, *getPlayerID()) && ret->tempOwner != getPlayerID()) if(getPlayerID().has_value() && !isVisibleFor(ret, *getPlayerID()) && ret->tempOwner != getPlayerID())
{ {
if(verbose) 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; return nullptr;
} }

View File

@@ -61,7 +61,7 @@ public:
const CArtifactSet * getArtSet(const ArtifactLocation & loc) const; const CArtifactSet * getArtSet(const ArtifactLocation & loc) const;
//objects //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 *> getBlockingObjs(int3 pos) const;
std::vector<const CGObjectInstance *> getVisitableObjs(int3 pos, bool verbose = true) const; std::vector<const CGObjectInstance *> getVisitableObjs(int3 pos, bool verbose = true) const;
std::vector<const CGObjectInstance *> getAllVisitableObjs() const; std::vector<const CGObjectInstance *> getAllVisitableObjs() const;

View File

@@ -22,19 +22,19 @@ VCMI_LIB_NAMESPACE_BEGIN
MapInfoCallback::~MapInfoCallback() = default; 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) 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; return nullptr;
} }
const CGObjectInstance * ret = getMapConstPtr()->getObject(objid); const CGObjectInstance * ret = getMapConstPtr()->getObject(objId);
if(!ret && verbose) 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; return nullptr;
} }

View File

@@ -23,7 +23,7 @@ protected:
public: public:
virtual ~MapInfoCallback(); 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 CGObjectInstance * getObjInstance(ObjectInstanceID oid) const override;
const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const override; const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const override;
const CGHeroInstance * getHero(ObjectInstanceID objid) const override; const CGHeroInstance * getHero(ObjectInstanceID objid) const override;