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

Nullkiller: turn limit for main heroes

This commit is contained in:
Andrii Danylchenko 2021-05-16 15:01:34 +03:00 committed by Andrii Danylchenko
parent 1f83569868
commit 0ffc7c3b94
8 changed files with 48 additions and 18 deletions

View File

@ -104,6 +104,7 @@ Goals::TTask Nullkiller::choseBestTask(Goals::TSubgoal behavior, int decompositi
void Nullkiller::resetAiState()
{
scanDepth = ScanDepth::SMALL;
playerID = ai->playerID;
lockedHeroes.clear();
dangerHitMap->reset();
@ -140,6 +141,11 @@ void Nullkiller::updateAiState(int pass)
cfg.useHeroChain = true;
cfg.scoutTurnDistanceLimit = SCOUT_TURN_DISTANCE_LIMIT;
if(scanDepth != ScanDepth::FULL)
{
cfg.mainTurnDistanceLimit = MAIN_TURN_DISTANCE_LIMIT * ((int)scanDepth + 1);
}
pathfinder->updatePaths(activeHeroes, cfg);
armyManager->update();
@ -215,6 +221,20 @@ void Nullkiller::makeTurn()
}
Goals::TTask bestTask = choseBestTask(bestTasks);
HeroPtr hero = bestTask->getHero();
if(bestTask->priority < NEXT_SCAN_MIN_PRIORITY
&& hero.validAndSet()
&& heroManager->getHeroRole(hero) == HeroRole::MAIN
&& scanDepth != ScanDepth::FULL)
{
logAi->trace(
"Goal %s has too low priority %f so increasing scan depth",
bestTask->toString(),
bestTask->priority);
scanDepth = (ScanDepth)((int)scanDepth + 1);
continue;
}
if(bestTask->priority < MIN_PRIORITY)
{

View File

@ -21,6 +21,7 @@
const float MAX_GOLD_PEASURE = 0.3f;
const float MIN_PRIORITY = 0.01f;
const float NEXT_SCAN_MIN_PRIORITY = 0.4f;
enum class HeroLockedReason
{
@ -33,12 +34,22 @@ enum class HeroLockedReason
HERO_CHAIN = 3
};
enum class ScanDepth
{
SMALL = 0,
MEDIUM = 1,
FULL = 2
};
class Nullkiller
{
private:
const CGHeroInstance * activeHero;
int3 targetTile;
std::map<const CGHeroInstance *, HeroLockedReason> lockedHeroes;
ScanDepth scanDepth;
public:
std::unique_ptr<DangerHitMapAnalyzer> dangerHitMap;

View File

@ -74,7 +74,6 @@ namespace Goals
public:
bool operator==(const TSubgoal & rhs) const;
bool operator<(const TSubgoal & rhs) const;
//TODO: serialize?
};
typedef std::shared_ptr<ITask> TTask;
@ -108,7 +107,6 @@ namespace Goals
const CGTownInstance *town; VSETTER(CGTownInstance *, town)
int bid; VSETTER(int, bid)
TSubgoal parent; VSETTER(TSubgoal, parent)
//EvaluationContext evaluationContext; VSETTER(EvaluationContext, evaluationContext)
AbstractGoal(EGoals goal = EGoals::INVALID)
: goalType(goal), hero()
@ -185,6 +183,7 @@ namespace Goals
//TODO: make accept work for std::shared_ptr... somehow
virtual void accept(VCAI * ai) = 0; //unhandled goal will report standard error
virtual std::string toString() const = 0;
virtual HeroPtr getHero() const = 0;
virtual ~ITask() {}
};
}

View File

@ -97,10 +97,9 @@ namespace Goals
return *((T *)this);
}
virtual bool isElementar() const override
{
return true;
}
virtual bool isElementar() const override { return true; }
virtual HeroPtr getHero() const override { return hero; }
};
class DLL_EXPORT Invalid : public ElementarGoal<Invalid>

View File

@ -108,7 +108,8 @@ void AINodeStorage::clear()
heroChainPass = EHeroChainPass::INITIAL;
heroChainTurn = 0;
heroChainMaxTurns = 1;
scoutTurnDistanceLimit = 255;
turnDistanceLimit[HeroRole::MAIN] = 255;
turnDistanceLimit[HeroRole::SCOUT] = 255;
}
const AIPathNode * AINodeStorage::getAINode(const CGPathNode * node) const
@ -703,15 +704,10 @@ bool AINodeStorage::isDistanceLimitReached(const PathNodeInfo & source, CDestina
auto aiNode = getAINode(destination.node);
if(heroChainPass == EHeroChainPass::FINAL)
if(heroChainPass != EHeroChainPass::CHAIN
&& destination.node->turns > turnDistanceLimit[aiNode->actor->heroRole])
{
if(aiNode->actor->heroRole == HeroRole::SCOUT && destination.node->turns > scoutTurnDistanceLimit)
return true;
}
else if(heroChainPass == EHeroChainPass::INITIAL)
{
if(aiNode->actor->heroRole == HeroRole::SCOUT && destination.node->turns > scoutTurnDistanceLimit)
return true;
return true;
}
return false;

View File

@ -13,6 +13,7 @@
#define PATHFINDER_TRACE_LEVEL 0
#define AI_TRACE_LEVEL 0
#define SCOUT_TURN_DISTANCE_LIMIT 3
#define MAIN_TURN_DISTANCE_LIMIT 5
#include "../../../lib/CPathfinder.h"
#include "../../../lib/mapObjects/CGHeroInstance.h"
@ -147,7 +148,7 @@ private:
int heroChainTurn;
int heroChainMaxTurns;
PlayerColor playerID;
uint8_t scoutTurnDistanceLimit;
uint8_t turnDistanceLimit[2];
public:
/// more than 1 chain layer for each hero allows us to have more than 1 path to each tile so we can chose more optimal one.
@ -204,7 +205,8 @@ public:
std::vector<AIPath> getChainInfo(const int3 & pos, bool isOnLand) const;
bool isTileAccessible(const HeroPtr & hero, const int3 & pos, const EPathfindingLayer layer) const;
void setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes);
void setScoutTurnDistanceLimit(uint8_t distanceLimit) { scoutTurnDistanceLimit = distanceLimit; }
void setScoutTurnDistanceLimit(uint8_t distanceLimit) { turnDistanceLimit[HeroRole::SCOUT] = distanceLimit; }
void setMainTurnDistanceLimit(uint8_t distanceLimit) { turnDistanceLimit[HeroRole::MAIN] = distanceLimit; }
void setTownsAndDwellings(
const std::vector<const CGTownInstance *> & towns,
const std::set<const CGObjectInstance *> & visitableObjs);

View File

@ -56,6 +56,7 @@ void AIPathfinder::updatePaths(std::map<const CGHeroInstance *, HeroRole> heroes
storage->clear();
storage->setHeroes(heroes);
storage->setScoutTurnDistanceLimit(pathfinderSettings.scoutTurnDistanceLimit);
storage->setMainTurnDistanceLimit(pathfinderSettings.mainTurnDistanceLimit);
if(pathfinderSettings.useHeroChain)
{

View File

@ -19,10 +19,12 @@ struct PathfinderSettings
{
bool useHeroChain;
uint8_t scoutTurnDistanceLimit;
uint8_t mainTurnDistanceLimit;
PathfinderSettings()
:useHeroChain(false),
scoutTurnDistanceLimit(255)
scoutTurnDistanceLimit(255),
mainTurnDistanceLimit(255)
{ }
};