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

View File

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

View File

@@ -460,10 +460,14 @@ 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(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(hasAnySuccess)
@@ -472,6 +476,7 @@ void Nullkiller::makeTurn()
}
hasAnySuccess = true;
}
}
hasAnySuccess |= handleTrading();
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);
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();

View File

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

View File

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

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

View File

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

View File

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

View File

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