mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-25 21:38:59 +02:00
nkai: fix freezes
This commit is contained in:
parent
c93bb0a502
commit
6490c65490
@ -229,6 +229,31 @@ const CGHeroInstance * HeroManager::findHeroWithGrail() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const CGHeroInstance * HeroManager::findWeakHeroToDismiss(uint64_t armyLimit) const
|
||||
{
|
||||
const CGHeroInstance * weakestHero = nullptr;
|
||||
auto myHeroes = ai->cb->getHeroesInfo();
|
||||
|
||||
for(auto existingHero : myHeroes)
|
||||
{
|
||||
if(ai->isHeroLocked(existingHero)
|
||||
|| existingHero->getArmyStrength() >armyLimit
|
||||
|| getHeroRole(existingHero) == HeroRole::MAIN
|
||||
|| existingHero->movementPointsRemaining()
|
||||
|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!weakestHero || weakestHero->getFightingStrength() > existingHero->getFightingStrength())
|
||||
{
|
||||
weakestHero = existingHero;
|
||||
}
|
||||
}
|
||||
|
||||
return weakestHero;
|
||||
}
|
||||
|
||||
SecondarySkillScoreMap::SecondarySkillScoreMap(std::map<SecondarySkill, float> scoreMap)
|
||||
:scoreMap(scoreMap)
|
||||
{
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
virtual bool canRecruitHero(const CGTownInstance * t = nullptr) const = 0;
|
||||
virtual bool heroCapReached() const = 0;
|
||||
virtual const CGHeroInstance * findHeroWithGrail() const = 0;
|
||||
virtual const CGHeroInstance * findWeakHeroToDismiss(uint64_t armyLimit) const = 0;
|
||||
};
|
||||
|
||||
class DLL_EXPORT ISecondarySkillRule
|
||||
@ -74,6 +75,7 @@ public:
|
||||
bool canRecruitHero(const CGTownInstance * t = nullptr) const override;
|
||||
bool heroCapReached() const override;
|
||||
const CGHeroInstance * findHeroWithGrail() const override;
|
||||
const CGHeroInstance * findWeakHeroToDismiss(uint64_t armyLimit) const override;
|
||||
|
||||
private:
|
||||
float evaluateFightingStrength(const CGHeroInstance * hero) const;
|
||||
|
@ -121,16 +121,31 @@ bool handleGarrisonHeroFromPreviousTurn(const CGTownInstance * town, Goals::TGoa
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!town->visitingHero && cb->getHeroCount(ai->playerID, false) < GameConstants::MAX_HEROES_PER_PLAYER)
|
||||
if(!town->visitingHero)
|
||||
{
|
||||
logAi->trace(
|
||||
"Extracting hero %s from garrison of town %s",
|
||||
town->garrisonHero->getNameTranslated(),
|
||||
town->getNameTranslated());
|
||||
if(cb->getHeroCount(ai->playerID, false) < GameConstants::MAX_HEROES_PER_PLAYER)
|
||||
{
|
||||
logAi->trace(
|
||||
"Extracting hero %s from garrison of town %s",
|
||||
town->garrisonHero->getNameTranslated(),
|
||||
town->getNameTranslated());
|
||||
|
||||
tasks.push_back(Goals::sptr(Goals::ExchangeSwapTownHeroes(town, nullptr).setpriority(5)));
|
||||
tasks.push_back(Goals::sptr(Goals::ExchangeSwapTownHeroes(town, nullptr).setpriority(5)));
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else if(ai->nullkiller->heroManager->getHeroRole(town->garrisonHero.get()) == HeroRole::MAIN)
|
||||
{
|
||||
auto armyDismissLimit = 1000;
|
||||
auto heroToDismiss = ai->nullkiller->heroManager->findWeakHeroToDismiss(armyDismissLimit);
|
||||
|
||||
if(heroToDismiss)
|
||||
{
|
||||
tasks.push_back(Goals::sptr(Goals::DismissHero(heroToDismiss).setpriority(5)));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -141,14 +156,6 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
logAi->trace("Evaluating defence for %s", town->getNameTranslated());
|
||||
|
||||
auto treatNode = ai->nullkiller->dangerHitMap->getObjectTreat(town);
|
||||
|
||||
if(!treatNode.fastestDanger.hero)
|
||||
{
|
||||
logAi->trace("No treat found for town %s", town->getNameTranslated());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<HitMapInfo> treats = ai->nullkiller->dangerHitMap->getTownTreats(town);
|
||||
|
||||
treats.push_back(treatNode.fastestDanger); // no guarantee that fastest danger will be there
|
||||
@ -157,6 +164,13 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!treatNode.fastestDanger.hero)
|
||||
{
|
||||
logAi->trace("No treat found for town %s", town->getNameTranslated());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t reinforcement = ai->nullkiller->armyManager->howManyReinforcementsCanBuy(town->getUpperArmy(), town);
|
||||
|
||||
@ -224,11 +238,6 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
||||
if(path.getHeroStrength() < townDefenseStrength)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(town->visitingHero)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(path.turn() <= treat.turn - 2)
|
||||
{
|
||||
@ -440,27 +449,10 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
|
||||
}
|
||||
else if(ai->nullkiller->heroManager->heroCapReached())
|
||||
{
|
||||
const CGHeroInstance * weakestHero = nullptr;
|
||||
heroToDismiss = ai->nullkiller->heroManager->findWeakHeroToDismiss(hero->getArmyStrength());
|
||||
|
||||
for(auto existingHero : myHeroes)
|
||||
{
|
||||
if(ai->nullkiller->isHeroLocked(existingHero)
|
||||
|| existingHero->getArmyStrength() > hero->getArmyStrength()
|
||||
|| ai->nullkiller->heroManager->getHeroRole(existingHero) == HeroRole::MAIN
|
||||
|| existingHero->movementPointsRemaining()
|
||||
|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
|
||||
continue;
|
||||
|
||||
if(!weakestHero || weakestHero->getFightingStrength() > existingHero->getFightingStrength())
|
||||
{
|
||||
weakestHero = existingHero;
|
||||
}
|
||||
}
|
||||
|
||||
if(!weakestHero)
|
||||
if(!heroToDismiss)
|
||||
continue;
|
||||
|
||||
heroToDismiss = weakestHero;
|
||||
}
|
||||
|
||||
TGoalVec sequence;
|
||||
|
@ -592,7 +592,6 @@ int32_t getArmyCost(const CArmedInstance * army)
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Gets aproximated reward in gold. Daily income is multiplied by 5
|
||||
int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CGHeroInstance * hero) const
|
||||
{
|
||||
if(!target)
|
||||
@ -713,9 +712,6 @@ public:
|
||||
|
||||
auto strategicalValue = evaluationContext.evaluator.getStrategicalValue(town);
|
||||
|
||||
if(evaluationContext.evaluator.ai->buildAnalyzer->getDevelopmentInfo().size() == 1)
|
||||
vstd::amax(evaluationContext.strategicalValue, 10.0);
|
||||
|
||||
float multiplier = 1;
|
||||
|
||||
if(treat.turn < defendTown.getTurn())
|
||||
@ -736,7 +732,12 @@ public:
|
||||
|
||||
evaluationContext.armyGrowth += armyGrowth * multiplier;
|
||||
evaluationContext.goldReward += dailyIncome * 5 * multiplier;
|
||||
evaluationContext.addNonCriticalStrategicalValue(1.7f * multiplier * strategicalValue);
|
||||
|
||||
if(evaluationContext.evaluator.ai->buildAnalyzer->getDevelopmentInfo().size() == 1)
|
||||
vstd::amax(evaluationContext.strategicalValue, 2.5f * multiplier * strategicalValue);
|
||||
else
|
||||
evaluationContext.addNonCriticalStrategicalValue(1.7f * multiplier * strategicalValue);
|
||||
|
||||
vstd::amax(evaluationContext.danger, defendTown.getTreat().danger);
|
||||
addTileDanger(evaluationContext, town->visitablePos(), defendTown.getTurn(), defendTown.getDefenceStrength());
|
||||
}
|
||||
|
@ -171,6 +171,10 @@ RuleBlock: basic
|
||||
rule: if heroRole is SCOUT and turn is NEXT and mainTurnDistance is LONG then Value is BAD
|
||||
rule: if heroRole is SCOUT and turn is NOW and scoutTurnDistance is LONG then Value is BAD
|
||||
rule: if heroRole is SCOUT and turn is NOW and scoutTurnDistance is MEDIUM then Value is BAD with 0.3
|
||||
rule: if heroRole is SCOUT and fear is HIGH then Value is BAD with 0.8
|
||||
rule: if heroRole is SCOUT and fear is MEDIUM then Value is BAD with 0.5
|
||||
rule: if heroRole is MAIN and fear is HIGH then Value is BAD with 0.5
|
||||
rule: if heroRole is MAIN and fear is MEDIUM then Value is BAD with 0.2
|
||||
RuleBlock: strategicalValue
|
||||
enabled: true
|
||||
conjunction: AlgebraicProduct
|
||||
@ -205,7 +209,8 @@ RuleBlock: strategicalValue
|
||||
rule: if heroRole is SCOUT and strategicalValue is LOW and danger is NONE and scoutTurnDistance is MEDIUM and fear is not HIGH then Value is SMALL
|
||||
rule: if armyLoss is HIGH and strategicalValue is LOW then Value is BAD
|
||||
rule: if armyLoss is HIGH and strategicalValue is MEDIUM then Value is BAD with 0.7
|
||||
rule: if strategicalValue is CRITICAL then Value is CRITICAL
|
||||
rule: if strategicalValue is CRITICAL and heroRole is MAIN then Value is CRITICAL
|
||||
rule: if strategicalValue is CRITICAL and heroRole is SCOUT then Value is CRITICAL with 0.7
|
||||
RuleBlock: armyReward
|
||||
enabled: true
|
||||
conjunction: AlgebraicProduct
|
||||
@ -220,6 +225,14 @@ RuleBlock: armyReward
|
||||
rule: if heroRole is MAIN and armyReward is MEDIUM and mainTurnDistance is LONG and fear is not HIGH then Value is MEDIUM
|
||||
rule: if heroRole is MAIN and armyReward is LOW and mainTurnDistance is LOW and fear is not HIGH then Value is MEDIUM
|
||||
rule: if heroRole is MAIN and armyReward is LOW and mainTurnDistance is MEDIUM and fear is not HIGH then Value is SMALL
|
||||
rule: if heroRole is SCOUT and armyReward is HIGH and danger is NONE and scoutTurnDistance is LOW and fear is not HIGH then Value is HIGH
|
||||
rule: if heroRole is SCOUT and armyReward is HIGH and danger is NONE and scoutTurnDistance is MEDIUM and fear is not HIGH then Value is HIGH with 0.7
|
||||
rule: if heroRole is SCOUT and armyReward is HIGH and danger is NONE and scoutTurnDistance is LONG and fear is not HIGH then Value is BITHIGH
|
||||
rule: if heroRole is SCOUT and armyReward is MEDIUM and danger is NONE and scoutTurnDistance is LOW then Value is HIGH with 0.7
|
||||
rule: if heroRole is SCOUT and armyReward is MEDIUM and danger is NONE and scoutTurnDistance is MEDIUM and fear is not HIGH then Value is BITHIGH
|
||||
rule: if heroRole is SCOUT and armyReward is MEDIUM and danger is NONE and scoutTurnDistance is LONG and fear is not HIGH then Value is MEDIUM
|
||||
rule: if heroRole is SCOUT and armyReward is LOW and danger is NONE and scoutTurnDistance is LOW and fear is not HIGH then Value is MEDIUM
|
||||
rule: if heroRole is SCOUT and armyReward is LOW and danger is NONE and scoutTurnDistance is MEDIUM and fear is not HIGH then Value is SMALL
|
||||
RuleBlock: gold
|
||||
enabled: true
|
||||
conjunction: AlgebraicProduct
|
||||
|
Loading…
x
Reference in New Issue
Block a user