1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

VisitTile fuzzy logic separated from FuzzyHelper

This commit is contained in:
Dydzio 2018-08-05 19:03:25 +02:00
parent 37b2dbcbba
commit 64b7c9f036
2 changed files with 125 additions and 115 deletions

View File

@ -125,60 +125,6 @@ ui64 FuzzyHelper::estimateBankDanger(const CBank * bank)
}
float FuzzyHelper::getTacticalAdvantage(const CArmedInstance * we, const CArmedInstance * enemy)
{
float output = 1;
try
{
armyStructure ourStructure = evaluateArmyStructure(we);
armyStructure enemyStructure = evaluateArmyStructure(enemy);
ta.ourWalkers->setValue(ourStructure.walkers);
ta.ourShooters->setValue(ourStructure.shooters);
ta.ourFlyers->setValue(ourStructure.flyers);
ta.ourSpeed->setValue(ourStructure.maxSpeed);
ta.enemyWalkers->setValue(enemyStructure.walkers);
ta.enemyShooters->setValue(enemyStructure.shooters);
ta.enemyFlyers->setValue(enemyStructure.flyers);
ta.enemySpeed->setValue(enemyStructure.maxSpeed);
bool bank = dynamic_cast<const CBank *>(enemy);
if(bank)
ta.bankPresent->setValue(1);
else
ta.bankPresent->setValue(0);
const CGTownInstance * fort = dynamic_cast<const CGTownInstance *>(enemy);
if(fort)
ta.castleWalls->setValue(fort->fortLevel());
else
ta.castleWalls->setValue(0);
//engine.process(TACTICAL_ADVANTAGE);//TODO: Process only Tactical_Advantage
ta.engine.process();
output = ta.threat->getValue();
}
catch(fl::Exception & fe)
{
logAi->error("getTacticalAdvantage: %s ", fe.getWhat());
}
if(output < 0 || (output != output))
{
fl::InputVariable * tab[] = {ta.bankPresent, ta.castleWalls, ta.ourWalkers, ta.ourShooters, ta.ourFlyers, ta.ourSpeed, ta.enemyWalkers, ta.enemyShooters, ta.enemyFlyers, ta.enemySpeed};
std::string names[] = {"bankPresent", "castleWalls", "ourWalkers", "ourShooters", "ourFlyers", "ourSpeed", "enemyWalkers", "enemyShooters", "enemyFlyers", "enemySpeed" };
std::stringstream log("Warning! Fuzzy engine doesn't cover this set of parameters: ");
for(int i = 0; i < boost::size(tab); i++)
log << names[i] << ": " << tab[i]->getValue() << " ";
logAi->error(log.str());
assert(false);
}
return output;
}
float FuzzyHelper::getWanderTargetObjectValue(const CGHeroInstance & h, const ObjectIdRef & obj)
{
float distFromObject = calculateTurnDistanceInputValue(&h, obj->pos);
@ -211,7 +157,7 @@ float FuzzyHelper::getWanderTargetObjectValue(const CGHeroInstance & h, const Ob
return output;
}
TacticalAdvantage::TacticalAdvantage()
TacticalAdvantageEngine::TacticalAdvantageEngine()
{
try
{
@ -311,7 +257,61 @@ TacticalAdvantage::TacticalAdvantage()
configure();
}
TacticalAdvantage::~TacticalAdvantage()
float TacticalAdvantageEngine::getTacticalAdvantage(const CArmedInstance * we, const CArmedInstance * enemy)
{
float output = 1;
try
{
armyStructure ourStructure = evaluateArmyStructure(we);
armyStructure enemyStructure = evaluateArmyStructure(enemy);
ourWalkers->setValue(ourStructure.walkers);
ourShooters->setValue(ourStructure.shooters);
ourFlyers->setValue(ourStructure.flyers);
ourSpeed->setValue(ourStructure.maxSpeed);
enemyWalkers->setValue(enemyStructure.walkers);
enemyShooters->setValue(enemyStructure.shooters);
enemyFlyers->setValue(enemyStructure.flyers);
enemySpeed->setValue(enemyStructure.maxSpeed);
bool bank = dynamic_cast<const CBank *>(enemy);
if(bank)
bankPresent->setValue(1);
else
bankPresent->setValue(0);
const CGTownInstance * fort = dynamic_cast<const CGTownInstance *>(enemy);
if(fort)
castleWalls->setValue(fort->fortLevel());
else
castleWalls->setValue(0);
//engine.process(TACTICAL_ADVANTAGE);//TODO: Process only Tactical_Advantage
engine.process();
output = threat->getValue();
}
catch(fl::Exception & fe)
{
logAi->error("getTacticalAdvantage: %s ", fe.getWhat());
}
if(output < 0 || (output != output))
{
fl::InputVariable * tab[] = { bankPresent, castleWalls, ourWalkers, ourShooters, ourFlyers, ourSpeed, enemyWalkers, enemyShooters, enemyFlyers, enemySpeed };
std::string names[] = { "bankPresent", "castleWalls", "ourWalkers", "ourShooters", "ourFlyers", "ourSpeed", "enemyWalkers", "enemyShooters", "enemyFlyers", "enemySpeed" };
std::stringstream log("Warning! Fuzzy engine doesn't cover this set of parameters: ");
for(int i = 0; i < boost::size(tab); i++)
log << names[i] << ": " << tab[i]->getValue() << " ";
logAi->error(log.str());
assert(false);
}
return output;
}
TacticalAdvantageEngine::~TacticalAdvantageEngine()
{
//TODO: smart pointers?
delete ourWalkers;
@ -454,50 +454,7 @@ HeroMovementGoalEngineBase::~HeroMovementGoalEngineBase()
float FuzzyHelper::evaluate(Goals::VisitTile & g)
{
//we assume that hero is already set and we want to choose most suitable one for the mission
if(!g.hero)
return 0;
//assert(cb->isInTheMap(g.tile));
float turns = calculateTurnDistanceInputValue(g.hero.h, g.tile);
float missionImportance = 0;
if(vstd::contains(ai->lockedHeroes, g.hero))
missionImportance = ai->lockedHeroes[g.hero]->priority;
float strengthRatio = 10.0f; //we are much stronger than enemy
ui64 danger = evaluateDanger(g.tile, g.hero.h);
if(danger)
strengthRatio = (fl::scalar)g.hero.h->getTotalStrength() / danger;
float tilePriority = 0;
if(g.objid == -1)
{
vt.estimatedReward->setEnabled(false);
}
else if(g.objid == Obj::TOWN) //TODO: move to getObj eventually and add appropiate logic there
{
vt.estimatedReward->setEnabled(true);
tilePriority = 5;
}
try
{
vt.strengthRatio->setValue(strengthRatio);
vt.heroStrength->setValue((fl::scalar)g.hero->getTotalStrength() / ai->primaryHero()->getTotalStrength());
vt.turnDistance->setValue(turns);
vt.missionImportance->setValue(missionImportance);
vt.estimatedReward->setValue(tilePriority);
vt.engine.process();
//engine.process(VISIT_TILE); //TODO: Process only Visit_Tile
g.priority = vt.value->getValue();
}
catch(fl::Exception & fe)
{
logAi->error("evaluate VisitTile: %s", fe.getWhat());
}
assert(g.priority >= 0);
return g.priority;
return visitTileEngine.evaluate(g);
}
float FuzzyHelper::evaluate(Goals::VisitHero & g)
{
@ -616,11 +573,60 @@ EvalWanderTargetObject::~EvalWanderTargetObject()
delete objectValue;
}
EvalVisitTile::EvalVisitTile()
VisitTileEngine::VisitTileEngine() //so far no VisitTile-specific variables that are not shared with HeroMovementGoalEngineBase
{
configure();
}
EvalVisitTile::~EvalVisitTile()
VisitTileEngine::~VisitTileEngine()
{
}
float VisitTileEngine::evaluate(Goals::AbstractGoal & goal)
{
auto g = dynamic_cast<Goals::VisitTile &>(goal);
//we assume that hero is already set and we want to choose most suitable one for the mission
if(!g.hero)
return 0;
//assert(cb->isInTheMap(g.tile));
float turns = calculateTurnDistanceInputValue(g.hero.h, g.tile);
float missionImportanceData = 0;
if(vstd::contains(ai->lockedHeroes, g.hero))
missionImportanceData = ai->lockedHeroes[g.hero]->priority;
float strengthRatioData = 10.0f; //we are much stronger than enemy
ui64 danger = evaluateDanger(g.tile, g.hero.h);
if(danger)
strengthRatioData = (fl::scalar)g.hero.h->getTotalStrength() / danger;
float tilePriority = 0;
if(g.objid == -1)
{
estimatedReward->setEnabled(false);
}
else if(g.objid == Obj::TOWN) //TODO: move to getObj eventually and add appropiate logic there
{
estimatedReward->setEnabled(true);
tilePriority = 5;
}
try
{
strengthRatio->setValue(strengthRatioData);
heroStrength->setValue((fl::scalar)g.hero->getTotalStrength() / ai->primaryHero()->getTotalStrength());
turnDistance->setValue(turns);
missionImportance->setValue(missionImportanceData);
estimatedReward->setValue(tilePriority);
engine.process();
//engine.process(VISIT_TILE); //TODO: Process only Visit_Tile
g.priority = value->getValue();
}
catch(fl::Exception & fe)
{
logAi->error("evaluate VisitTile: %s", fe.getWhat());
}
assert(g.priority >= 0);
return g.priority;
}

View File

@ -23,23 +23,25 @@ public:
fl::RuleBlock rules;
engineBase();
void configure();
virtual void configure();
void addRule(const std::string & txt);
};
class TacticalAdvantage : public engineBase
class TacticalAdvantageEngine : public engineBase
{
public:
TacticalAdvantage();
TacticalAdvantageEngine();
fl::InputVariable * ourWalkers, *ourShooters, *ourFlyers, *enemyWalkers, *enemyShooters, *enemyFlyers;
fl::InputVariable * ourSpeed, *enemySpeed;
fl::InputVariable * bankPresent;
fl::InputVariable * castleWalls;
fl::OutputVariable * threat;
~TacticalAdvantage();
float getTacticalAdvantage(const CArmedInstance * we, const CArmedInstance * enemy); //returns factor how many times enemy is stronger than us
~TacticalAdvantageEngine();
};
class HeroMovementGoalEngineBase : public engineBase //abstract class for hero visiting goals, allows evaluating newly added elementar objectives with appropiately broad context data
class HeroMovementGoalEngineBase : public engineBase
{
public:
HeroMovementGoalEngineBase();
@ -49,17 +51,20 @@ public:
fl::InputVariable * missionImportance;
fl::InputVariable * estimatedReward;
fl::OutputVariable * value;
virtual float evaluate(Goals::AbstractGoal & goal) = 0;
~HeroMovementGoalEngineBase();
protected:
float calculateTurnDistanceInputValue(const CGHeroInstance * h, int3 tile) const;
};
class EvalVisitTile : public HeroMovementGoalEngineBase
class VisitTileEngine : public HeroMovementGoalEngineBase
{
public:
EvalVisitTile();
~EvalVisitTile();
VisitTileEngine();
~VisitTileEngine();
float evaluate(Goals::AbstractGoal & goal) override;
};
class EvalWanderTargetObject : public HeroMovementGoalEngineBase //designed for use with VCAI::wander()
@ -74,11 +79,11 @@ class FuzzyHelper
{
friend class VCAI;
TacticalAdvantage ta;
TacticalAdvantageEngine tacticalAdvantageEngine;
EvalVisitTile vt;
VisitTileEngine visitTileEngine;
EvalWanderTargetObject wanderTarget;
EvalWanderTargetObject wanderTargetEngine;
public:
float evaluate(Goals::Explore & g);
@ -96,8 +101,7 @@ public:
float evaluate(Goals::AbstractGoal & g);
void setPriority(Goals::TSubgoal & g);
ui64 estimateBankDanger(const CBank * bank);
float getTacticalAdvantage(const CArmedInstance * we, const CArmedInstance * enemy); //returns factor how many times enemy is stronger than us
ui64 estimateBankDanger(const CBank * bank); //TODO: move to another class?
float getWanderTargetObjectValue(const CGHeroInstance & h, const ObjectIdRef & obj);
Goals::TSubgoal chooseSolution(Goals::TGoalVec vec);