mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
#2983б #2910 and a few other bugs fixed
This commit is contained in:
parent
49c872e4ec
commit
cf213a5acf
@ -523,7 +523,7 @@ creInfo infoFromDC(const dwellingContent & dc)
|
||||
return ci;
|
||||
}
|
||||
|
||||
ui64 howManyReinforcementsCanBuy(HeroPtr h, const CGTownInstance * t)
|
||||
ui64 howManyReinforcementsCanBuy(HeroPtr h, const CGDwelling * t)
|
||||
{
|
||||
ui64 aivalue = 0;
|
||||
|
||||
|
@ -179,7 +179,7 @@ bool compareMovement(HeroPtr lhs, HeroPtr rhs);
|
||||
bool compareHeroStrength(HeroPtr h1, HeroPtr h2);
|
||||
bool compareArmyStrength(const CArmedInstance * a1, const CArmedInstance * a2);
|
||||
bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2);
|
||||
ui64 howManyReinforcementsCanBuy(HeroPtr h, const CGTownInstance * t);
|
||||
ui64 howManyReinforcementsCanBuy(HeroPtr h, const CGDwelling * t);
|
||||
ui64 howManyReinforcementsCanGet(HeroPtr h, const CGTownInstance * t);
|
||||
int3 whereToExplore(HeroPtr h);
|
||||
uint32_t distanceToTile(const CGHeroInstance * hero, int3 pos);
|
||||
|
@ -19,8 +19,13 @@ extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
Goals::TSubgoal FuzzyHelper::chooseSolution(Goals::TGoalVec vec)
|
||||
{
|
||||
if(vec.empty()) //no possibilities found
|
||||
if(vec.empty())
|
||||
{
|
||||
logAi->debug("FuzzyHelper found no goals. Returning Goals::Invalid.");
|
||||
|
||||
//no possibilities found
|
||||
return sptr(Goals::Invalid());
|
||||
}
|
||||
|
||||
//a trick to switch between heroes less often - calculatePaths is costly
|
||||
auto sortByHeroes = [](const Goals::TSubgoal & lhs, const Goals::TSubgoal & rhs) -> bool
|
||||
@ -38,7 +43,17 @@ Goals::TSubgoal FuzzyHelper::chooseSolution(Goals::TGoalVec vec)
|
||||
{
|
||||
return lhs->priority < rhs->priority;
|
||||
};
|
||||
return *boost::max_element(vec, compareGoals);
|
||||
|
||||
for(auto goal : vec)
|
||||
{
|
||||
logAi->debug("FuzzyHelper evaluated goal %s, priority=%i", goal->name(), goal->priority);
|
||||
}
|
||||
|
||||
Goals::TSubgoal result = *boost::max_element(vec, compareGoals);
|
||||
|
||||
logAi->debug("FuzzyHelper returned goal %s, priority=%i", result->name(), result->priority);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
|
||||
|
@ -163,6 +163,9 @@ bool Goals::AbstractGoal::operator==(AbstractGoal & g)
|
||||
return (town == g.town && bid == g.bid); //build specific structure in specific town
|
||||
break;
|
||||
|
||||
case BUY_ARMY:
|
||||
return town == g.town;
|
||||
|
||||
//no check atm
|
||||
case COLLECT_RES:
|
||||
case TRADE: //TODO
|
||||
@ -1441,14 +1444,16 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
ret.push_back(sptr(Goals::VisitTile(pos).sethero(hero)));
|
||||
}
|
||||
//buy army in town
|
||||
if (!t->visitingHero || t->visitingHero != hero.get(true))
|
||||
if (!t->visitingHero || t->visitingHero == hero.get(true))
|
||||
{
|
||||
ui32 val = std::min<ui32>(value, howManyReinforcementsCanBuy(hero, t));
|
||||
if (val)
|
||||
{
|
||||
auto goal = sptr(Goals::BuyArmy(t, val).sethero(hero));
|
||||
if (!ai->ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice
|
||||
if(!ai->ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice
|
||||
ret.push_back(goal);
|
||||
else
|
||||
logAi->debug("Can not buy army, because of ai->ah->containsObjective");
|
||||
}
|
||||
}
|
||||
//build dwelling
|
||||
@ -1460,6 +1465,8 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
auto goal = sptr(BuildThis(bid.get(), t).setpriority(priority));
|
||||
if (!ai->ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice
|
||||
ret.push_back(goal);
|
||||
else
|
||||
logAi->debug("Can not build a structure, because of ai->ah->containsObjective");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1501,15 +1508,21 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
if(relationToOwner == PlayerRelations::SAME_PLAYER)
|
||||
{
|
||||
auto dwelling = dynamic_cast<const CGDwelling *>(obj);
|
||||
for(auto & creLevel : dwelling->creatures)
|
||||
|
||||
ui32 val = std::min<ui32>(value, howManyReinforcementsCanBuy(hero, dwelling));
|
||||
|
||||
if(val)
|
||||
{
|
||||
if(creLevel.first)
|
||||
for(auto & creLevel : dwelling->creatures)
|
||||
{
|
||||
for(auto & creatureID : creLevel.second)
|
||||
if(creLevel.first)
|
||||
{
|
||||
auto creature = VLC->creh->creatures[creatureID];
|
||||
if(ai->ah->freeResources().canAfford(creature->cost))
|
||||
objs.push_back(obj); //TODO: reserve resources?
|
||||
for(auto & creatureID : creLevel.second)
|
||||
{
|
||||
auto creature = VLC->creh->creatures[creatureID];
|
||||
if(ai->ah->freeResources().canAfford(creature->cost))
|
||||
objs.push_back(obj); //TODO: reserve resources?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +172,8 @@ Goals::TSubgoal ResourceManager::whatToDo() const //suggest any goal
|
||||
|
||||
Goals::TSubgoal ResourceManager::whatToDo(TResources &res, Goals::TSubgoal goal)
|
||||
{
|
||||
logAi->trace("ResourceManager: checking goal %s which requires resources %s", goal->name(), res.toString());
|
||||
|
||||
TResources accumulatedResources;
|
||||
auto allResources = cb->getResourceAmount();
|
||||
|
||||
@ -181,19 +183,38 @@ Goals::TSubgoal ResourceManager::whatToDo(TResources &res, Goals::TSubgoal goal)
|
||||
for (auto it = queue.ordered_begin(); it != queue.ordered_end(); it++)
|
||||
{
|
||||
accumulatedResources += it->resources;
|
||||
if (!accumulatedResources.canBeAfforded(allResources)) //can't afford
|
||||
return collectResourcesForOurGoal(ro);
|
||||
|
||||
logAi->trace(
|
||||
"ResourceManager: checking goal %s, accumulatedResources=%s, available=%s",
|
||||
it->goal->name(),
|
||||
accumulatedResources.toString(),
|
||||
allResources.toString());
|
||||
|
||||
if(!accumulatedResources.canBeAfforded(allResources))
|
||||
{
|
||||
//can't afford
|
||||
break;
|
||||
}
|
||||
else //can afford all goals up to this point
|
||||
{
|
||||
if (it->goal == goal)
|
||||
if(it->goal == goal)
|
||||
{
|
||||
logAi->debug("ResourceManager: can afford goal %s", goal->name());
|
||||
return goal; //can afford immediately
|
||||
}
|
||||
}
|
||||
}
|
||||
return collectResourcesForOurGoal(ro); //fallback, ever needed?
|
||||
|
||||
logAi->debug("ResourceManager: can not afford goal %s", goal->name());
|
||||
|
||||
return collectResourcesForOurGoal(ro);
|
||||
}
|
||||
|
||||
bool ResourceManager::containsObjective(Goals::TSubgoal goal) const
|
||||
{
|
||||
logAi->trace("Entering ResourceManager.containsObjective goal=%s", goal->name());
|
||||
dumpToLog();
|
||||
|
||||
//TODO: unit tests for once
|
||||
for (auto objective : queue)
|
||||
{
|
||||
@ -205,6 +226,8 @@ bool ResourceManager::containsObjective(Goals::TSubgoal goal) const
|
||||
|
||||
bool ResourceManager::notifyGoalCompleted(Goals::TSubgoal goal)
|
||||
{
|
||||
logAi->trace("Entering ResourceManager.notifyGoalCompleted goal=%s", goal->name());
|
||||
|
||||
if (goal->invalid())
|
||||
logAi->warn("Attempt to complete Invalid goal");
|
||||
|
||||
@ -215,15 +238,18 @@ bool ResourceManager::notifyGoalCompleted(Goals::TSubgoal goal)
|
||||
{
|
||||
return ro.goal == goal || ro.goal->fulfillsMe (goal);
|
||||
});
|
||||
if (it != queue.end()) //removed at least one
|
||||
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
|
||||
return removedGoal;
|
||||
break;
|
||||
}
|
||||
|
||||
dumpToLog();
|
||||
|
||||
return removedGoal;
|
||||
}
|
||||
|
||||
@ -248,10 +274,21 @@ bool ResourceManager::updateGoal(Goals::TSubgoal goal)
|
||||
return false;
|
||||
}
|
||||
|
||||
void ResourceManager::dumpToLog() const
|
||||
{
|
||||
for(auto it = queue.ordered_begin(); it != queue.ordered_end(); it++)
|
||||
{
|
||||
logAi->trace("ResourceManager contains goal %s which requires resources %s", it->goal->name(), it->resources.toString());
|
||||
}
|
||||
}
|
||||
|
||||
bool ResourceManager::tryPush(const ResourceObjective & o)
|
||||
{
|
||||
auto goal = o.goal;
|
||||
|
||||
logAi->trace("ResourceManager: Trying to add goal %s which requires resources %s", goal->name(), o.resources.toString());
|
||||
dumpToLog();
|
||||
|
||||
auto it = boost::find_if(queue, [goal](const ResourceObjective & ro) -> bool
|
||||
{
|
||||
return ro.goal == goal;
|
||||
|
@ -102,6 +102,8 @@ private:
|
||||
|
||||
boost::heap::binomial_heap<ResourceObjective> queue;
|
||||
|
||||
void dumpToLog() const;
|
||||
|
||||
//TODO: register?
|
||||
template<typename Handler> void serializeInternal(Handler & h, const int version)
|
||||
{
|
||||
|
@ -933,6 +933,8 @@ void VCAI::mainLoop()
|
||||
}
|
||||
}
|
||||
|
||||
logAi->trace("Main loop: selecting best elementar goal");
|
||||
|
||||
//now choose one elementar goal to realize
|
||||
Goals::TGoalVec possibleGoals(elementarGoals.begin(), elementarGoals.end()); //copy to vector
|
||||
Goals::TSubgoal goalToRealize = sptr(Goals::Invalid());
|
||||
@ -2205,7 +2207,7 @@ void VCAI::tryRealize(Goals::BuyArmy & g)
|
||||
});
|
||||
|
||||
vstd::amin(ci.count, res / ci.cre->cost); //max count we can afford
|
||||
if (ci.count > 0)
|
||||
if (ci.count > 0 && t->getUpperArmy()->getSlotFor(ci.creID) != SlotID())
|
||||
{
|
||||
cb->recruitCreatures(t, t->getUpperArmy(), ci.creID, ci.count, ci.level);
|
||||
valueBought += ci.count * ci.cre->AIValue;
|
||||
@ -2379,6 +2381,13 @@ void VCAI::striveToGoal(Goals::TSubgoal basicGoal)
|
||||
|
||||
Goals::TSubgoal VCAI::decomposeGoal(Goals::TSubgoal ultimateGoal)
|
||||
{
|
||||
if(ultimateGoal->isElementar)
|
||||
{
|
||||
logAi->warn("Trying to decompose elementar goal %s", ultimateGoal->name());
|
||||
|
||||
return ultimateGoal;
|
||||
}
|
||||
|
||||
const int searchDepth = 30;
|
||||
const int searchDepth2 = searchDepth - 2;
|
||||
Goals::TSubgoal abstractGoal = sptr(Goals::Invalid());
|
||||
|
Loading…
Reference in New Issue
Block a user