mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-11 11:31:52 +02:00
Nullkiller AI: add strategical value fuzzy variable
This commit is contained in:
parent
e6eb9ccc03
commit
66ed1a2901
@ -35,7 +35,7 @@ Goals::TGoalVec RecruitHeroBehavior::getTasks()
|
||||
|
||||
for(auto town : towns)
|
||||
{
|
||||
if(!town->garrisonHero && ai->canRecruitAnyHero(town))
|
||||
if(!town->garrisonHero && !town->visitingHero && ai->canRecruitAnyHero(town))
|
||||
{
|
||||
if(cb->getHeroesInfo().size() < cb->getTownsInfo().size() + 1
|
||||
|| cb->getResourceAmount(Res::GOLD) > 10000)
|
||||
|
@ -16,8 +16,14 @@ extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
void DangerHitMapAnalyzer::updateHitMap()
|
||||
{
|
||||
if(upToDate)
|
||||
return;
|
||||
|
||||
upToDate = true;
|
||||
|
||||
auto mapSize = cb->getMapSize();
|
||||
hitMap.resize(boost::extents[mapSize.x][mapSize.y][mapSize.z]);
|
||||
enemyHeroAccessibleObjects.clear();
|
||||
|
||||
std::map<PlayerColor, std::vector<HeroPtr>> heroes;
|
||||
|
||||
@ -62,6 +68,17 @@ void DangerHitMapAnalyzer::updateHitMap()
|
||||
node.fastestDanger.turn = turn;
|
||||
node.fastestDanger.hero = path.targetHero;
|
||||
}
|
||||
|
||||
if(turn == 0)
|
||||
{
|
||||
auto objects = cb->getVisitableObjs(pos, false);
|
||||
|
||||
for(auto obj : objects)
|
||||
{
|
||||
if(cb->getPlayerRelations(obj->tempOwner, ai->playerID) != PlayerRelations::ENEMIES)
|
||||
enemyHeroAccessibleObjects[path.targetHero].insert(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -77,10 +94,29 @@ uint64_t DangerHitMapAnalyzer::enemyCanKillOurHeroesAlongThePath(const AIPath &
|
||||
|| info.maximumDanger.turn <= turn && !isSafeToVisit(path.targetHero, path.heroArmy, info.maximumDanger.danger);
|
||||
}
|
||||
|
||||
const HitMapNode & DangerHitMapAnalyzer::getObjectTreat(const CGObjectInstance * town) const
|
||||
const HitMapNode & DangerHitMapAnalyzer::getObjectTreat(const CGObjectInstance * obj) const
|
||||
{
|
||||
auto tile = town->visitablePos();
|
||||
auto tile = obj->visitablePos();
|
||||
const HitMapNode & info = hitMap[tile.x][tile.y][tile.z];
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
const std::set<const CGObjectInstance *> empty = {};
|
||||
|
||||
const std::set<const CGObjectInstance *> & DangerHitMapAnalyzer::getOneTurnAccessibleObjects(const CGHeroInstance * enemy) const
|
||||
{
|
||||
auto result = enemyHeroAccessibleObjects.find(enemy);
|
||||
|
||||
if(result == enemyHeroAccessibleObjects.end())
|
||||
{
|
||||
return empty;
|
||||
}
|
||||
|
||||
return result->second;
|
||||
}
|
||||
|
||||
void DangerHitMapAnalyzer::reset()
|
||||
{
|
||||
upToDate = false;
|
||||
}
|
||||
|
@ -42,10 +42,13 @@ class DangerHitMapAnalyzer
|
||||
{
|
||||
private:
|
||||
boost::multi_array<HitMapNode, 3> hitMap;
|
||||
std::map<const CGHeroInstance *, int> enemyHeroTreatMAp;
|
||||
std::map<const CGHeroInstance *, std::set<const CGObjectInstance *>> enemyHeroAccessibleObjects;
|
||||
bool upToDate;
|
||||
|
||||
public:
|
||||
void updateHitMap();
|
||||
uint64_t enemyCanKillOurHeroesAlongThePath(const AIPath & path) const;
|
||||
const HitMapNode & getObjectTreat(const CGObjectInstance * town) const;
|
||||
const HitMapNode & getObjectTreat(const CGObjectInstance * obj) const;
|
||||
const std::set<const CGObjectInstance *> & getOneTurnAccessibleObjects(const CGHeroInstance * enemy) const;
|
||||
void reset();
|
||||
};
|
||||
|
@ -67,12 +67,13 @@ void Nullkiller::resetAiState()
|
||||
{
|
||||
lockedHeroes.clear();
|
||||
|
||||
dangerHitMap->updateHitMap();
|
||||
dangerHitMap->reset();
|
||||
}
|
||||
|
||||
void Nullkiller::updateAiState()
|
||||
{
|
||||
ai->validateVisitableObjs();
|
||||
dangerHitMap->updateHitMap();
|
||||
|
||||
// TODO: move to hero manager
|
||||
auto activeHeroes = ai->getMyHeroes();
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "../../../lib/filesystem/Filesystem.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIhelper.h"
|
||||
#include "../Engine/Nullkiller.h"
|
||||
|
||||
#define MIN_AI_STRENGHT (0.5f) //lower when combat AI gets smarter
|
||||
#define UNGUARDED_OBJECT (100.0f) //we consider unguarded objects 100 times weaker than us
|
||||
@ -58,6 +59,7 @@ void PriorityEvaluator::initVisitTile()
|
||||
skillRewardVariable = engine->getInputVariable("skillReward");
|
||||
rewardTypeVariable = engine->getInputVariable("rewardType");
|
||||
closestHeroRatioVariable = engine->getInputVariable("closestHeroRatio");
|
||||
strategicalValueVariable = engine->getInputVariable("strategicalValue");
|
||||
value = engine->getOutputVariable("Value");
|
||||
}
|
||||
|
||||
@ -190,6 +192,40 @@ uint64_t getArmyReward(const CGObjectInstance * target, const CGHeroInstance * h
|
||||
}
|
||||
}
|
||||
|
||||
float getStrategicalValue(const CGObjectInstance * target);
|
||||
|
||||
float getEnemyHeroStrategicalValue(const CGHeroInstance * enemy)
|
||||
{
|
||||
auto objectsUnderTreat = ai->nullkiller->dangerHitMap->getOneTurnAccessibleObjects(enemy);
|
||||
float objectValue = 0;
|
||||
|
||||
for(auto obj : objectsUnderTreat)
|
||||
{
|
||||
objectValue += getStrategicalValue(obj);
|
||||
}
|
||||
|
||||
return objectValue + enemy->level / 15.0f;
|
||||
}
|
||||
|
||||
float getStrategicalValue(const CGObjectInstance * target)
|
||||
{
|
||||
if(!target)
|
||||
return 0;
|
||||
|
||||
switch(target->ID)
|
||||
{
|
||||
case Obj::TOWN:
|
||||
return target->tempOwner == PlayerColor::NEUTRAL ? 0.5 : 1;
|
||||
|
||||
case Obj::HERO:
|
||||
return cb->getPlayerRelations(target->tempOwner, ai->playerID) == PlayerRelations::ENEMIES
|
||||
? getEnemyHeroStrategicalValue(dynamic_cast<const CGHeroInstance *>(target))
|
||||
: 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
float evaluateWitchHutSkillScore(const CGWitchHut * hut, const CGHeroInstance * hero, HeroRole role)
|
||||
{
|
||||
if(!hut->wasVisited(hero->tempOwner))
|
||||
@ -336,8 +372,9 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
|
||||
bool checkGold = danger == 0;
|
||||
uint64_t armyReward = getArmyReward(target, hero, checkGold);
|
||||
float skillReward = getSkillReward(target, hero, heroRole);
|
||||
float strategicalValue = getStrategicalValue(target);
|
||||
double result = 0;
|
||||
int rewardType = (goldReward > 0 ? 1 : 0) + (armyReward > 0 ? 1 : 0) + (skillReward > 0 ? 1 : 0);
|
||||
int rewardType = (goldReward > 0 ? 1 : 0) + (armyReward > 0 ? 1 : 0) + (skillReward > 0 ? 1 : 0) + (strategicalValue > 0 ? 1 : 0);
|
||||
|
||||
try
|
||||
{
|
||||
@ -350,6 +387,7 @@ float PriorityEvaluator::evaluate(Goals::TSubgoal task)
|
||||
dangerVariable->setValue(danger);
|
||||
rewardTypeVariable->setValue(rewardType);
|
||||
closestHeroRatioVariable->setValue(task->evaluationContext.closestWayRatio);
|
||||
strategicalValueVariable->setValue(strategicalValue);
|
||||
|
||||
engine->process();
|
||||
//engine.process(VISIT_TILE); //TODO: Process only Visit_Tile
|
||||
|
@ -35,6 +35,7 @@ private:
|
||||
fl::InputVariable * armyRewardVariable;
|
||||
fl::InputVariable * dangerVariable;
|
||||
fl::InputVariable * skillRewardVariable;
|
||||
fl::InputVariable * strategicalValueVariable;
|
||||
fl::InputVariable * rewardTypeVariable;
|
||||
fl::InputVariable * closestHeroRatioVariable;
|
||||
fl::OutputVariable * value;
|
||||
|
@ -1750,6 +1750,11 @@ void VCAI::addVisitableObj(const CGObjectInstance * obj)
|
||||
auto teleportObj = dynamic_cast<const CGTeleport *>(obj);
|
||||
if(teleportObj)
|
||||
CGTeleport::addToChannel(knownTeleportChannels, teleportObj);
|
||||
|
||||
if(obj->ID == Obj::HERO && cb->getPlayerRelations(obj->tempOwner, playerID) == PlayerRelations::ENEMIES)
|
||||
{
|
||||
if(nullkiller) nullkiller->dangerHitMap->reset();
|
||||
}
|
||||
}
|
||||
|
||||
const CGObjectInstance * VCAI::lookForArt(int aid) const
|
||||
|
Loading…
x
Reference in New Issue
Block a user