1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Fuzzy rework

This commit is contained in:
Andrii Danylchenko 2023-05-14 09:17:15 +03:00
parent 38a98387e4
commit b1ca663eb6
4 changed files with 93 additions and 94 deletions

View File

@ -49,7 +49,8 @@ EvaluationContext::EvaluationContext(const Nullkiller * ai)
turn(0),
strategicalValue(0),
evaluator(ai),
enemyHeroDangerRatio(0)
enemyHeroDangerRatio(0),
armyGrowth(0)
{
}
@ -64,6 +65,7 @@ void PriorityEvaluator::initVisitTile()
std::string str = std::string((char *)file.first.get(), file.second);
engine = fl::FllImporter().fromString(str);
armyLossPersentageVariable = engine->getInputVariable("armyLoss");
armyGrowthVariable = engine->getInputVariable("armyGrowth");
heroRoleVariable = engine->getInputVariable("heroRole");
dangerVariable = engine->getInputVariable("danger");
turnVariable = engine->getInputVariable("turn");
@ -164,7 +166,7 @@ uint64_t getCreatureBankArmyReward(const CGObjectInstance * target, const CGHero
return result;
}
uint64_t getDwellingScore(CCallback * cb, const CGObjectInstance * target, bool checkGold)
uint64_t getDwellingArmyValue(CCallback * cb, const CGObjectInstance * target, bool checkGold)
{
auto dwelling = dynamic_cast<const CGDwelling *>(target);
uint64_t score = 0;
@ -185,6 +187,27 @@ uint64_t getDwellingScore(CCallback * cb, const CGObjectInstance * target, bool
return score;
}
uint64_t getDwellingArmyGrowth(CCallback * cb, const CGObjectInstance * target, PlayerColor myColor)
{
auto dwelling = dynamic_cast<const CGDwelling *>(target);
uint64_t score = 0;
if(dwelling->getOwner() == myColor)
return 0;
for(auto & creLevel : dwelling->creatures)
{
if(creLevel.second.size())
{
auto creature = creLevel.second.back().toCreature();
score += creature->getAIValue() * creature->getGrowth();
}
}
return score;
}
int getDwellingArmyCost(const CGObjectInstance * target)
{
auto dwelling = dynamic_cast<const CGDwelling *>(target);
@ -272,7 +295,7 @@ uint64_t RewardEvaluator::getArmyReward(
case Obj::CREATURE_GENERATOR2:
case Obj::CREATURE_GENERATOR3:
case Obj::CREATURE_GENERATOR4:
return getDwellingScore(ai->cb.get(), target, checkGold);
return getDwellingArmyValue(ai->cb.get(), target, checkGold);
case Obj::CRYPT:
case Obj::SHIPWRECK:
case Obj::SHIPWRECK_SURVIVOR:
@ -293,6 +316,44 @@ uint64_t RewardEvaluator::getArmyReward(
}
}
uint64_t RewardEvaluator::getArmyGrowth(
const CGObjectInstance * target,
const CGHeroInstance * hero,
const CCreatureSet * army) const
{
const float enemyArmyEliminationRewardRatio = 0.5f;
if(!target)
return 0;
switch(target->ID)
{
case Obj::TOWN:
{
auto town = dynamic_cast<const CGTownInstance *>(target);
auto fortLevel = town->fortLevel();
auto neutral = !town->getOwner().isValidPlayer();
auto booster = isAnotherAi(town, *ai->cb) || neutral ? 1 : 2;
if(fortLevel < CGTownInstance::CITADEL)
return town->hasFort() ? booster * 500 : 0;
else
return booster * (fortLevel == CGTownInstance::CASTLE ? 5000 : 2000);
}
case Obj::CREATURE_GENERATOR1:
case Obj::CREATURE_GENERATOR2:
case Obj::CREATURE_GENERATOR3:
case Obj::CREATURE_GENERATOR4:
return getDwellingArmyGrowth(ai->cb.get(), target, hero->getOwner());
case Obj::ARTIFACT:
// it is not supported now because hero will not sit in town on 7th day but later parts of legion may be counted as army growth as well.
return 0;
default:
return 0;
}
}
int RewardEvaluator::getGoldCost(const CGObjectInstance * target, const CGHeroInstance * hero, const CCreatureSet * army) const
{
if(!target)
@ -714,6 +775,7 @@ public:
{
evaluationContext.goldReward += evaluationContext.evaluator.getGoldReward(target, hero);
evaluationContext.armyReward += evaluationContext.evaluator.getArmyReward(target, hero, army, checkGold);
evaluationContext.armyGrowth += evaluationContext.evaluator.getArmyGrowth(target, hero, army);
evaluationContext.skillReward += evaluationContext.evaluator.getSkillReward(target, hero, evaluationContext.heroRole);
evaluationContext.strategicalValue += evaluationContext.evaluator.getStrategicalValue(target);
evaluationContext.goldCost += evaluationContext.evaluator.getGoldCost(target, hero, army);
@ -920,6 +982,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
scoutTurnDistanceVariable->setValue(evaluationContext.movementCostByRole[HeroRole::SCOUT]);
goldRewardVariable->setValue(evaluationContext.goldReward);
armyRewardVariable->setValue(evaluationContext.armyReward);
armyGrowthVariable->setValue(evaluationContext.armyGrowth);
skillRewardVariable->setValue(evaluationContext.skillReward);
dangerVariable->setValue(evaluationContext.danger);
rewardTypeVariable->setValue(rewardType);

View File

@ -33,6 +33,7 @@ public:
RewardEvaluator(const Nullkiller * ai) : ai(ai) {}
uint64_t getArmyReward(const CGObjectInstance * target, const CGHeroInstance * hero, const CCreatureSet * army, bool checkGold) const;
uint64_t getArmyGrowth(const CGObjectInstance * target, const CGHeroInstance * hero, const CCreatureSet * army) const;
int getGoldCost(const CGObjectInstance * target, const CGHeroInstance * hero, const CCreatureSet * army) const;
float getEnemyHeroStrategicalValue(const CGHeroInstance * enemy) const;
float getResourceRequirementStrength(int resType) const;
@ -54,6 +55,7 @@ struct DLL_EXPORT EvaluationContext
float closestWayRatio;
float armyLossPersentage;
float armyReward;
uint64_t armyGrowth;
int32_t goldReward;
int32_t goldCost;
float skillReward;
@ -95,6 +97,7 @@ private:
fl::InputVariable * turnVariable;
fl::InputVariable * goldRewardVariable;
fl::InputVariable * armyRewardVariable;
fl::InputVariable * armyGrowthVariable;
fl::InputVariable * dangerVariable;
fl::InputVariable * skillRewardVariable;
fl::InputVariable * strategicalValueVariable;

View File

@ -879,7 +879,7 @@ void AINodeStorage::setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes)
for(auto & hero : heroes)
{
// do not allow our own heroes in garrison to act on map
if(hero.first->getOwner() == ai->playerID && hero.first->inTownGarrison && ai->isHeroLocked(hero.first))
if(hero.first->getOwner() == ai->playerID && hero.first->inTownGarrison)
continue;
uint64_t mask = FirstActorMask << actors.size();

View File

@ -121,106 +121,39 @@ InputVariable: fear
term: LOW Triangle 0.000 0.500 1.000
term: MEDIUM Triangle 0.500 1.000 1.500
term: HIGH Ramp 1.000 1.800
InputVariable: armyGrowth
enabled: true
range: 0.000 20000.000
lock-range: false
term: NONE Ramp 100.000 0.000
term: SMALL Triangle 0.000 1000.000 3000.000
term: MEDIUM Triangle 1000.000 3000.000 8000.000
term: BIG Triangle 3000.000 8000.000 20000.000
term: HUGE Ramp 8000.000 20000.000
OutputVariable: Value
enabled: true
range: -0.500 1.500
range: -1.500 2.000
lock-range: false
aggregation: AlgebraicSum
defuzzifier: Centroid 100
default: 0.500
lock-previous: false
term: LOWEST Discrete -0.500 0.000 -0.500 1.000 -0.200 1.000 -0.200 0.000 0.200 0.000 0.200 1.000 0.500 1.000 0.500 0.000 0.500
term: BITLOW Rectangle -0.010 0.010 0.500
term: LOW Discrete -0.150 0.000 -0.150 1.000 -0.050 1.000 -0.050 0.000 0.050 0.000 0.050 1.000 0.150 1.000 0.150 0.000 0.500
term: MEDIUM Triangle 0.450 0.500 0.550 0.050
term: HIGH Discrete 0.850 0.000 0.850 1.000 0.950 1.000 0.950 0.000 1.050 0.000 1.050 1.000 1.150 1.000 1.150 0.000 0.500
term: HIGHEST Discrete 0.500 0.000 0.500 1.000 0.800 1.000 0.800 0.000 1.200 0.000 1.200 1.000 1.500 1.000 1.500 0.000 0.500
term: BITHIGH Rectangle 0.990 1.010 0.500
term: WORST Binary -1.000 -inf 0.500
term: BAD Rectangle -1.000 -0.700 0.500
term: BASE Rectangle -0.200 0.200 0.400
term: LOW Rectangle 1.110 1.190 0.320
term: HIGHEST Discrete 0.300 0.000 0.300 1.000 0.600 1.000 0.600 0.000 1.700 0.000 1.700 1.000 2.000 1.000 2.000 0.000 0.500
term: HIGH Discrete 0.600 0.000 0.600 1.000 0.850 1.000 0.850 0.000 1.450 0.000 1.450 1.000 1.700 1.000 1.700 0.000 0.400
term: BITHIGH Discrete 0.850 0.000 0.850 1.000 1.000 1.000 1.000 0.000 1.300 0.000 1.300 1.000 1.450 1.000 1.450 0.000 0.350
term: MEDIUM Discrete 1.000 0.000 1.000 1.000 1.100 1.000 1.100 0.000 1.200 0.000 1.200 1.000 1.300 1.000 1.300 0.000 0.330
RuleBlock: gold reward
enabled: true
conjunction: AlgebraicProduct
disjunction: AlgebraicSum
implication: AlgebraicProduct
activation: General
rule: if turn is NOW and mainTurnDistance is very LONG and heroRole is SCOUT then Value is LOW with 0.5
rule: if turn is NOW and mainTurnDistance is LONG and heroRole is SCOUT then Value is LOW with 0.3
rule: if turn is NOW and scoutTurnDistance is LONG and heroRole is SCOUT then Value is LOW with 0.3
rule: if turn is NOW and mainTurnDistance is LONG and heroRole is MAIN then Value is LOW with 0.3
rule: if turn is NEXT and mainTurnDistance is very LONG and heroRole is SCOUT then Value is LOW with 0.8
rule: if turn is NEXT and scoutTurnDistance is LONG and heroRole is SCOUT then Value is BITLOW
rule: if turn is NEXT and mainTurnDistance is LONG and heroRole is MAIN then Value is LOW with 0.3
rule: if turn is NEXT and mainTurnDistance is LONG and heroRole is SCOUT then Value is BITLOW with 0.3
rule: if turn is FUTURE and scoutTurnDistance is very LONG and heroRole is SCOUT then Value is LOWEST with 0.3
rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is SCOUT then Value is LOWEST with 0.5
rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is NONE then Value is LOWEST with 0.5
rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is LOW then Value is LOWEST with 0.3
rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is MEDIUM then Value is LOW with 0.5
rule: if turn is FUTURE and mainTurnDistance is very LONG and heroRole is MAIN and strategicalValue is HIGH then Value is BITLOW
rule: if turn is FUTURE and scoutTurnDistance is LONG and heroRole is SCOUT then Value is LOW
rule: if turn is FUTURE and mainTurnDistance is LONG and heroRole is MAIN then Value is LOW
rule: if turn is FUTURE and mainTurnDistance is LONG and heroRole is SCOUT then Value is LOW
rule: if scoutTurnDistance is MEDIUM and heroRole is SCOUT then Value is BITLOW
rule: if mainTurnDistance is MEDIUM then Value is BITLOW
rule: if scoutTurnDistance is LOW and heroRole is SCOUT then Value is MEDIUM
rule: if mainTurnDistance is LOW then Value is MEDIUM
rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is SCOUT and danger is not NONE and armyLoss is LOW then Value is BITHIGH
rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is SCOUT and danger is NONE then Value is HIGH with 0.7
rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if goldReward is HIGH and goldPreasure is HIGH and heroRole is MAIN and danger is NONE then Value is BITHIGH
rule: if goldReward is MEDIUM and goldPreasure is HIGH and heroRole is SCOUT and danger is NONE then Value is HIGH
rule: if goldReward is MEDIUM and goldPreasure is HIGH and armyLoss is LOW and heroRole is SCOUT and danger is not NONE then Value is MEDIUM
rule: if goldReward is MEDIUM and heroRole is MAIN and danger is NONE and rewardType is SINGLE then Value is BITLOW
rule: if goldReward is MEDIUM and goldPreasure is HIGH and armyLoss is LOW and heroRole is MAIN and danger is not NONE then Value is BITHIGH
rule: if goldReward is LOW and goldPreasure is HIGH and heroRole is SCOUT and armyLoss is LOW then Value is BITHIGH
rule: if goldReward is LOW and heroRole is MAIN and danger is not NONE and rewardType is SINGLE and armyLoss is LOW then Value is BITLOW
rule: if goldReward is LOW and heroRole is MAIN and danger is NONE and rewardType is SINGLE then Value is LOW
rule: if goldReward is LOWEST and heroRole is MAIN and danger is NONE and rewardType is SINGLE then Value is LOWEST
rule: if armyReward is HIGH and heroRole is SCOUT and danger is not NONE and armyLoss is LOW then Value is HIGH with 0.5
rule: if armyReward is HIGH and heroRole is SCOUT and danger is NONE then Value is HIGHEST
rule: if armyReward is HIGH and heroRole is MAIN and rewardType is MIXED and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if armyReward is HIGH and heroRole is MAIN and rewardType is SINGLE and mainTurnDistance is LOWEST then Value is HIGHEST
rule: if armyReward is HIGH and heroRole is MAIN and rewardType is SINGLE and danger is NONE and fear is not HIGH then Value is HIGH
rule: if armyReward is HIGH and heroRole is MAIN and rewardType is SINGLE and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if armyReward is MEDIUM and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST with 0.5
rule: if armyReward is MEDIUM and heroRole is MAIN and danger is NONE then Value is BITHIGH
rule: if armyReward is MEDIUM and heroRole is MAIN and danger is NONE and mainTurnDistance is LOWEST then Value is HIGH with 0.2
rule: if armyReward is MEDIUM and heroRole is SCOUT and danger is NONE then Value is HIGHEST with 0.5
rule: if armyReward is LOW and heroRole is SCOUT and danger is NONE then Value is HIGH
rule: if armyReward is LOW and heroRole is MAIN and danger is not NONE and armyLoss is LOW then Value is HIGH
rule: if armyReward is LOW and heroRole is MAIN and danger is NONE then Value is BITLOW with 0.5
rule: if armyReward is LOW and heroRole is MAIN and danger is NONE and mainTurnDistance is LOWEST then Value is HIGH
rule: if skillReward is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH
rule: if skillReward is MEDIUM and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is BITHIGH
rule: if skillReward is MEDIUM and heroRole is MAIN and rewardType is MIXED and armyLoss is LOW and fear is not HIGH then Value is HIGH with 0.5
rule: if skillReward is HIGH and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if skillReward is MEDIUM and heroRole is SCOUT then Value is LOWEST
rule: if skillReward is HIGH and heroRole is SCOUT then Value is LOWEST
rule: if strategicalValue is LOW and heroRole is MAIN and armyLoss is LOW then Value is BITHIGH
rule: if strategicalValue is LOWEST and heroRole is MAIN and armyLoss is LOW then Value is LOW
rule: if strategicalValue is LOW and heroRole is SCOUT and armyLoss is LOW and fear is not HIGH then Value is HIGH with 0.5
rule: if strategicalValue is MEDIUM and heroRole is SCOUT and danger is NONE and fear is not HIGH then Value is HIGH
rule: if strategicalValue is HIGH and heroRole is SCOUT and danger is NONE and fear is not HIGH then Value is HIGHEST with 0.5
rule: if strategicalValue is HIGH and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if strategicalValue is HIGH and heroRole is MAIN and armyLoss is MEDIUM and fear is not HIGH then Value is HIGH
rule: if strategicalValue is MEDIUM and heroRole is MAIN and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if rewardType is NONE then Value is LOWEST
rule: if armyLoss is HIGH and strategicalValue is not HIGH and heroRole is MAIN then Value is LOWEST
rule: if armyLoss is HIGH and strategicalValue is HIGH and heroRole is MAIN then Value is LOW
rule: if armyLoss is HIGH and heroRole is SCOUT then Value is LOWEST
rule: if heroRole is SCOUT and closestHeroRatio is LOW then Value is LOW
rule: if heroRole is SCOUT and closestHeroRatio is LOWEST then Value is LOWEST
rule: if heroRole is MAIN and danger is NONE and skillReward is NONE and rewardType is SINGLE and closestHeroRatio is LOW then Value is LOW
rule: if heroRole is MAIN and danger is NONE and skillReward is NONE and rewardType is SINGLE and closestHeroRatio is LOWEST then Value is LOWEST
rule: if heroRole is MAIN and danger is not NONE and armyLoss is LOW then Value is BITHIGH with 0.2
rule: if heroRole is SCOUT then Value is BITLOW
rule: if goldCost is not NONE and goldReward is NONE and goldPreasure is HIGH then Value is LOWEST
rule: if turn is NOW then Value is LOW with 0.3
rule: if turn is not NOW then Value is LOW with 0.4
rule: if goldPreasure is HIGH and goldReward is HIGH and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if goldPreasure is HIGH and goldReward is MEDIUM and heroRole is MAIN and danger is not NONE and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if goldPreasure is HIGH and goldReward is HIGH and heroRole is SCOUT and danger is NONE and armyLoss is LOW and fear is not HIGH then Value is HIGHEST
rule: if goldPreasure is HIGH and goldReward is MEDIUM and heroRole is SCOUT and danger is NONE and armyLoss is LOW and fear is not HIGH then Value is HIGH
rule: if goldPreasure is HIGH and goldReward is LOW and heroRole is SCOUT and armyLoss is LOW then Value is BITHIGH
rule: if goldPreasure is HIGH and goldReward is LOW and heroRole is SCOUT and scoutTurnDistance is LOW and armyLoss is LOW then Value is HIGH with 0.5
rule: if fear is MEDIUM then Value is LOW
rule: if fear is HIGH then Value is LOWEST
rule: if heroRole is MAIN then Value is BASE
rule: if heroRole is SCOUT then Value is BASE
rule: if heroRole is MAIN and armyGrowth is HUGE then Value is HIGH
rule: if heroRole is MAIN and armyGrowth is BIG then Value is BITHIGH
rule: if heroRole is MAIN and strategicalValue is HIGH then Value is HIGHEST