1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge pull request #530 from dydzio0614/objRemovalFix

Extend objectRemoved callback to check parent goals and resource manager
This commit is contained in:
DjWarmonger 2019-01-07 19:00:06 +01:00 committed by GitHub
commit efc53e8f8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 39 deletions

View File

@ -88,6 +88,11 @@ bool AIhelper::hasTasksLeft() const
return resourceManager->hasTasksLeft(); return resourceManager->hasTasksLeft();
} }
bool AIhelper::removeOutdatedObjectives(std::function<bool(const Goals::TSubgoal&)> predicate)
{
return resourceManager->removeOutdatedObjectives(predicate);
}
bool AIhelper::canAfford(const TResources & cost) const bool AIhelper::canAfford(const TResources & cost) const
{ {
return resourceManager->canAfford(cost); return resourceManager->canAfford(cost);

View File

@ -47,6 +47,7 @@ public:
Goals::TSubgoal whatToDo() const override; Goals::TSubgoal whatToDo() const override;
bool containsObjective(Goals::TSubgoal goal) const; bool containsObjective(Goals::TSubgoal goal) const;
bool hasTasksLeft() const override; bool hasTasksLeft() const override;
bool removeOutdatedObjectives(std::function<bool(const Goals::TSubgoal &)> predicate) override;
bool getBuildingOptions(const CGTownInstance * t) override; bool getBuildingOptions(const CGTownInstance * t) override;
BuildingID getMaxPossibleGoldBuilding(const CGTownInstance * t); BuildingID getMaxPossibleGoldBuilding(const CGTownInstance * t);

View File

@ -232,22 +232,12 @@ bool ResourceManager::notifyGoalCompleted(Goals::TSubgoal goal)
if (goal->invalid()) if (goal->invalid())
logAi->warn("Attempt to complete Invalid goal"); logAi->warn("Attempt to complete Invalid goal");
bool removedGoal = false; std::function<bool(const Goals::TSubgoal &)> equivalentGoalsCheck = [goal](const Goals::TSubgoal & x) -> bool
while (true) {
{ //unfortunatelly we can't use remove_if on heap return x == goal || x->fulfillsMe(goal);
auto it = boost::find_if(queue, [goal](const ResourceObjective & ro) -> bool };
{
return ro.goal == goal || ro.goal->fulfillsMe (goal); bool removedGoal = removeOutdatedObjectives(equivalentGoalsCheck);
});
if(it != queue.end()) //removed at least one
{
logAi->debug("Removing goal %s from ResourceManager.", it->goal->name());
queue.erase(queue.s_handle_from_iterator(it));
removedGoal = true;
}
else //found nothing more to remove
break;
}
dumpToLog(); dumpToLog();
@ -315,6 +305,27 @@ bool ResourceManager::hasTasksLeft() const
return !queue.empty(); return !queue.empty();
} }
bool ResourceManager::removeOutdatedObjectives(std::function<bool(const Goals::TSubgoal &)> predicate)
{
bool removedAnything = false;
while(true)
{ //unfortunately we can't use remove_if on heap
auto it = boost::find_if(queue, [&](const ResourceObjective & ro) -> bool
{
predicate(ro.goal);
});
if(it != queue.end()) //removed at least one
{
logAi->debug("Removing goal %s from ResourceManager.", it->goal->name());
queue.erase(queue.s_handle_from_iterator(it));
removedAnything = true;
}
else //found nothing more to remove
break;
}
return removedAnything;
}
TResources ResourceManager::reservedResources() const TResources ResourceManager::reservedResources() const
{ {
TResources res; TResources res;

View File

@ -52,7 +52,7 @@ public:
virtual Goals::TSubgoal whatToDo(TResources &res, Goals::TSubgoal goal) = 0; virtual Goals::TSubgoal whatToDo(TResources &res, Goals::TSubgoal goal) = 0;
virtual bool containsObjective(Goals::TSubgoal goal) const = 0; virtual bool containsObjective(Goals::TSubgoal goal) const = 0;
virtual bool hasTasksLeft() const = 0; virtual bool hasTasksLeft() const = 0;
private: virtual bool removeOutdatedObjectives(std::function<bool(const Goals::TSubgoal &)> predicate) = 0; //remove ResourceObjectives from queue if ResourceObjective->goal meets specific criteria
virtual bool notifyGoalCompleted(Goals::TSubgoal goal) = 0; virtual bool notifyGoalCompleted(Goals::TSubgoal goal) = 0;
}; };
@ -82,6 +82,7 @@ public:
Goals::TSubgoal whatToDo(TResources & res, Goals::TSubgoal goal); //can we afford this goal or need to CollectRes? Goals::TSubgoal whatToDo(TResources & res, Goals::TSubgoal goal); //can we afford this goal or need to CollectRes?
bool containsObjective(Goals::TSubgoal goal) const; bool containsObjective(Goals::TSubgoal goal) const;
bool hasTasksLeft() const override; bool hasTasksLeft() const override;
bool removeOutdatedObjectives(std::function<bool(const Goals::TSubgoal &)> predicate) override;
protected: //not-const actions only for AI protected: //not-const actions only for AI
virtual void reserveResoures(const TResources & res, Goals::TSubgoal goal = Goals::TSubgoal()); virtual void reserveResoures(const TResources & res, Goals::TSubgoal goal = Goals::TSubgoal());

View File

@ -418,37 +418,36 @@ void VCAI::objectRemoved(const CGObjectInstance * obj)
for(auto h : cb->getHeroesInfo()) for(auto h : cb->getHeroesInfo())
unreserveObject(h, obj); unreserveObject(h, obj);
std::function<bool(const Goals::TSubgoal &)> checkRemovalValidity = [&](const Goals::TSubgoal & x) -> bool
vstd::erase_if(lockedHeroes, [&](const std::pair<HeroPtr, Goals::TSubgoal> & x) -> bool
{
if((x.second->goalType == Goals::VISIT_OBJ) && (x.second->objid == obj->id.getNum()))
return true;
else
return false;
});
vstd::erase_if(ultimateGoalsFromBasic, [&](const std::pair<Goals::TSubgoal, Goals::TGoalVec> & x) -> bool
{
if((x.first->goalType == Goals::VISIT_OBJ) && (x.first->objid == obj->id.getNum()))
return true;
else
return false;
});
auto goalErasePredicate = [&](const Goals::TSubgoal & x) ->bool
{ {
if((x->goalType == Goals::VISIT_OBJ) && (x->objid == obj->id.getNum())) if((x->goalType == Goals::VISIT_OBJ) && (x->objid == obj->id.getNum()))
return true; return true;
else if(x->parent && checkRemovalValidity(x->parent)) //repeat this lambda check recursively on parent goal
return true;
else else
return false; return false;
}; };
vstd::erase_if(basicGoals, goalErasePredicate); //clear VCAI / main loop caches
vstd::erase_if(goalsToAdd, goalErasePredicate); vstd::erase_if(lockedHeroes, [&](const std::pair<HeroPtr, Goals::TSubgoal> & x) -> bool
vstd::erase_if(goalsToRemove, goalErasePredicate); {
return checkRemovalValidity(x.second);
});
vstd::erase_if(ultimateGoalsFromBasic, [&](const std::pair<Goals::TSubgoal, Goals::TGoalVec> & x) -> bool
{
return checkRemovalValidity(x.first);
});
vstd::erase_if(basicGoals, checkRemovalValidity);
vstd::erase_if(goalsToAdd, checkRemovalValidity);
vstd::erase_if(goalsToRemove, checkRemovalValidity);
for(auto goal : ultimateGoalsFromBasic) for(auto goal : ultimateGoalsFromBasic)
vstd::erase_if(goal.second, goalErasePredicate); vstd::erase_if(goal.second, checkRemovalValidity);
//clear resource manager goal cache
ah->removeOutdatedObjectives(checkRemovalValidity);
//TODO: Find better way to handle hero boat removal //TODO: Find better way to handle hero boat removal
if(auto hero = dynamic_cast<const CGHeroInstance *>(obj)) if(auto hero = dynamic_cast<const CGHeroInstance *>(obj))