mirror of
https://github.com/vcmi/vcmi.git
synced 2024-11-24 08:32:34 +02:00
Nullkiller: refactoring and stabilization of gather army & clusterization
This commit is contained in:
parent
1fdf0de75d
commit
35a1167f3d
@ -241,7 +241,6 @@ void ObjectClusterizer::clusterize()
|
||||
continue;
|
||||
}
|
||||
|
||||
bool directlyAccessible = false;
|
||||
std::set<const CGHeroInstance *> heroesProcessed;
|
||||
|
||||
for(auto & path : paths)
|
||||
@ -292,44 +291,33 @@ void ObjectClusterizer::clusterize()
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Path added to cluster %s%s", blocker->getObjectName(), blocker->visitablePos().toString());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
directlyAccessible = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
directlyAccessible = true;
|
||||
}
|
||||
|
||||
heroesProcessed.insert(path.targetHero);
|
||||
}
|
||||
|
||||
if(directlyAccessible)
|
||||
{
|
||||
AIPath & shortestPath = paths.front();
|
||||
float priority = ai->priorityEvaluator->evaluate(Goals::sptr(Goals::ExecuteHeroChain(shortestPath, obj)));
|
||||
float priority = ai->priorityEvaluator->evaluate(Goals::sptr(Goals::ExecuteHeroChain(path, obj)));
|
||||
|
||||
if(priority < MIN_PRIORITY)
|
||||
continue;
|
||||
|
||||
bool interestingObject = shortestPath.turn() <= 2 || priority > 0.5f;
|
||||
|
||||
bool interestingObject = path.turn() <= 2 || priority > 0.5f;
|
||||
|
||||
if(interestingObject)
|
||||
{
|
||||
nearObjects.addObject(obj, shortestPath, priority);
|
||||
nearObjects.addObject(obj, path, priority);
|
||||
}
|
||||
else
|
||||
{
|
||||
farObjects.addObject(obj, shortestPath, priority);
|
||||
farObjects.addObject(obj, path, priority);
|
||||
}
|
||||
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Path %s added to %s objects. Turn: %d, priority: %f",
|
||||
shortestPath.toString(),
|
||||
path.toString(),
|
||||
interestingObject ? "near" : "far",
|
||||
shortestPath.turn(),
|
||||
path.turn(),
|
||||
priority);
|
||||
#endif
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "../VCAI.h"
|
||||
#include "../Engine/Nullkiller.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../Goals/UnlockCluster.h"
|
||||
#include "../Markers/UnlockCluster.h"
|
||||
#include "../Goals/Composition.h"
|
||||
#include "../Behaviors/CaptureObjectsBehavior.h"
|
||||
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include "../VCAI.h"
|
||||
#include "../Engine/Nullkiller.h"
|
||||
#include "../Goals/ExecuteHeroChain.h"
|
||||
#include "../Goals/Composition.h"
|
||||
#include "../Markers/HeroExchange.h"
|
||||
#include "../Markers/ArmyUpgrade.h"
|
||||
#include "GatherArmyBehavior.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "lib/mapping/CMap.h" //for victory conditions
|
||||
@ -73,7 +76,6 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
}
|
||||
|
||||
auto paths = ai->nullkiller->pathfinder->getPathInfo(pos);
|
||||
std::vector<std::shared_ptr<ExecuteHeroChain>> waysToVisitObj;
|
||||
|
||||
#if AI_TRACE_LEVEL >= 1
|
||||
logAi->trace("Found %d paths", paths.size());
|
||||
@ -87,15 +89,6 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
|
||||
if(path.containsHero(hero)) continue;
|
||||
|
||||
if(path.getFirstBlockedAction())
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
// TODO: decomposition
|
||||
logAi->trace("Ignore path. Action is blocked.");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ai->nullkiller->dangerHitMap->enemyCanKillOurHeroesAlongThePath(path))
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
@ -104,15 +97,35 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
continue;
|
||||
}
|
||||
|
||||
float armyValue = (float)ai->nullkiller->armyManager->howManyReinforcementsCanGet(hero, path.heroArmy) / hero->getArmyStrength();
|
||||
if(ai->nullkiller->arePathHeroesLocked(path))
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Ignore path because of locked hero");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
HeroExchange heroExchange(hero, path);
|
||||
|
||||
float armyValue = (float)heroExchange.getReinforcementArmyStrength() / hero->getArmyStrength();
|
||||
|
||||
// avoid transferring very small amount of army
|
||||
if(armyValue < 0.1f)
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Army value is too small.");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// avoid trying to move bigger army to the weaker one.
|
||||
if(armyValue > 0.5f)
|
||||
if(armyValue > 1)
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Army value is too large.");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
auto danger = path.getTotalDanger();
|
||||
|
||||
@ -131,26 +144,28 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const CGHeroInstance * her
|
||||
|
||||
if(isSafe)
|
||||
{
|
||||
auto newWay = std::make_shared<ExecuteHeroChain>(path, hero);
|
||||
Composition composition;
|
||||
ExecuteHeroChain exchangePath(path, hero);
|
||||
|
||||
newWay->strategicalValue = armyValue;
|
||||
waysToVisitObj.push_back(newWay);
|
||||
exchangePath.closestWayRatio = 1;
|
||||
|
||||
composition.addNext(heroExchange);
|
||||
composition.addNext(exchangePath);
|
||||
|
||||
auto blockedAction = path.getFirstBlockedAction();
|
||||
|
||||
if(blockedAction)
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Action is blocked. Considering decomposition.");
|
||||
#endif
|
||||
composition.addNext(blockedAction->decompose(path.targetHero));
|
||||
}
|
||||
|
||||
tasks.push_back(sptr(composition));
|
||||
}
|
||||
}
|
||||
|
||||
if(waysToVisitObj.empty())
|
||||
return tasks;
|
||||
|
||||
for(auto way : waysToVisitObj)
|
||||
{
|
||||
if(ai->nullkiller->arePathHeroesLocked(way->getPath()))
|
||||
continue;
|
||||
|
||||
way->closestWayRatio = 1;
|
||||
|
||||
tasks.push_back(sptr(*way));
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
||||
@ -184,6 +199,14 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ai->nullkiller->arePathHeroesLocked(path))
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
logAi->trace("Ignore path because of locked hero");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
if(path.getFirstBlockedAction())
|
||||
{
|
||||
#if AI_TRACE_LEVEL >= 2
|
||||
@ -224,27 +247,13 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const CGTownInstance * upgrader)
|
||||
|
||||
if(isSafe)
|
||||
{
|
||||
auto newWay = std::make_shared<ExecuteHeroChain>(path, upgrader);
|
||||
ExecuteHeroChain newWay(path, upgrader);
|
||||
|
||||
newWay.closestWayRatio = 1;
|
||||
|
||||
newWay->strategicalValue = armyValue;
|
||||
newWay->goldCost = upgrade.upgradeCost[Res::GOLD];
|
||||
|
||||
waysToVisitObj.push_back(newWay);
|
||||
tasks.push_back(sptr(Composition().addNext(ArmyUpgrade(path, upgrader, upgrade)).addNext(newWay)));
|
||||
}
|
||||
}
|
||||
|
||||
if(waysToVisitObj.empty())
|
||||
return tasks;
|
||||
|
||||
for(auto way : waysToVisitObj)
|
||||
{
|
||||
if(ai->nullkiller->arePathHeroesLocked(way->getPath()))
|
||||
continue;
|
||||
|
||||
way->closestWayRatio = 1;
|
||||
|
||||
tasks.push_back(sptr(*way));
|
||||
}
|
||||
|
||||
return tasks;
|
||||
}
|
||||
|
@ -24,17 +24,17 @@ set(VCAI_SRCS
|
||||
Goals/BuildBoat.cpp
|
||||
Goals/BuildThis.cpp
|
||||
Goals/DismissHero.cpp
|
||||
Goals/GatherTroops.cpp
|
||||
Goals/BuyArmy.cpp
|
||||
Goals/AdventureSpellCast.cpp
|
||||
Goals/CollectRes.cpp
|
||||
Goals/Trade.cpp
|
||||
Goals/RecruitHero.cpp
|
||||
Goals/UnlockCluster.cpp
|
||||
Goals/DigAtTile.cpp
|
||||
Goals/GetArtOfType.cpp
|
||||
Goals/ExecuteHeroChain.cpp
|
||||
Goals/ExchangeSwapTownHeroes.cpp
|
||||
Goals/CompleteQuest.cpp
|
||||
Markers/ArmyUpgrade.cpp
|
||||
Markers/HeroExchange.cpp
|
||||
Markers/UnlockCluster.cpp
|
||||
Engine/Nullkiller.cpp
|
||||
Engine/PriorityEvaluator.cpp
|
||||
Analyzers/DangerHitMapAnalyzer.cpp
|
||||
@ -47,7 +47,6 @@ set(VCAI_SRCS
|
||||
Behaviors/StartupBehavior.cpp
|
||||
Behaviors/BuildingBehavior.cpp
|
||||
Behaviors/GatherArmyBehavior.cpp
|
||||
Behaviors/CompleteQuestBehavior.cpp
|
||||
Behaviors/ClusterBehavior.cpp
|
||||
main.cpp
|
||||
VCAI.cpp
|
||||
@ -81,18 +80,18 @@ set(VCAI_HEADERS
|
||||
Goals/BuildBoat.h
|
||||
Goals/BuildThis.h
|
||||
Goals/DismissHero.h
|
||||
Goals/GatherTroops.h
|
||||
Goals/BuyArmy.h
|
||||
Goals/AdventureSpellCast.h
|
||||
Goals/CollectRes.h
|
||||
Goals/Trade.h
|
||||
Goals/UnlockCluster.h
|
||||
Goals/RecruitHero.h
|
||||
Goals/DigAtTile.h
|
||||
Goals/GetArtOfType.h
|
||||
Goals/ExecuteHeroChain.h
|
||||
Goals/ExchangeSwapTownHeroes.h
|
||||
Goals/CompleteQuest.h
|
||||
Goals/Goals.h
|
||||
Markers/ArmyUpgrade.h
|
||||
Markers/HeroExchange.h
|
||||
Markers/UnlockCluster.h
|
||||
Engine/Nullkiller.h
|
||||
Engine/PriorityEvaluator.h
|
||||
Analyzers/DangerHitMapAnalyzer.h
|
||||
@ -105,7 +104,6 @@ set(VCAI_HEADERS
|
||||
Behaviors/StartupBehavior.h
|
||||
Behaviors/BuildingBehavior.h
|
||||
Behaviors/GatherArmyBehavior.h
|
||||
Behaviors/CompleteQuestBehavior.h
|
||||
Behaviors/ClusterBehavior.h
|
||||
VCAI.h
|
||||
)
|
||||
|
@ -20,8 +20,10 @@
|
||||
#include "../../../CCallback.h"
|
||||
#include "../../../lib/filesystem/Filesystem.h"
|
||||
#include "../Goals/ExecuteHeroChain.h"
|
||||
#include "../Goals/UnlockCluster.h"
|
||||
#include "../Markers/UnlockCluster.h"
|
||||
#include "../Goals/BuildThis.h"
|
||||
#include "../Markers/HeroExchange.h"
|
||||
#include "../Markers/ArmyUpgrade.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
|
||||
@ -456,6 +458,38 @@ int32_t RewardEvaluator::getGoldReward(const CGObjectInstance * target, const CG
|
||||
}
|
||||
}
|
||||
|
||||
class HeroExchangeEvaluator : public IEvaluationContextBuilder
|
||||
{
|
||||
public:
|
||||
virtual void buildEvaluationContext(EvaluationContext & evaluationContext, Goals::TSubgoal task) const override
|
||||
{
|
||||
if(task->goalType != Goals::HERO_EXCHANGE)
|
||||
return;
|
||||
|
||||
Goals::HeroExchange & heroExchange = dynamic_cast<Goals::HeroExchange &>(*task);
|
||||
|
||||
uint64_t armyStrength = heroExchange.getReinforcementArmyStrength();
|
||||
|
||||
evaluationContext.strategicalValue += 0.5f * armyStrength / heroExchange.hero.get()->getArmyStrength();
|
||||
}
|
||||
};
|
||||
|
||||
class ArmyUpgradeEvaluator : public IEvaluationContextBuilder
|
||||
{
|
||||
public:
|
||||
virtual void buildEvaluationContext(EvaluationContext & evaluationContext, Goals::TSubgoal task) const override
|
||||
{
|
||||
if(task->goalType != Goals::ARMY_UPGRADE)
|
||||
return;
|
||||
|
||||
Goals::ArmyUpgrade & armyUpgrade = dynamic_cast<Goals::ArmyUpgrade &>(*task);
|
||||
|
||||
uint64_t upgradeValue = armyUpgrade.getUpgradeValue();
|
||||
|
||||
evaluationContext.armyReward += upgradeValue;
|
||||
}
|
||||
};
|
||||
|
||||
class ExecuteHeroChainEvaluationContextBuilder : public IEvaluationContextBuilder
|
||||
{
|
||||
public:
|
||||
@ -610,6 +644,7 @@ PriorityEvaluator::PriorityEvaluator(const Nullkiller * ai)
|
||||
evaluationContextBuilders.push_back(std::make_shared<ExecuteHeroChainEvaluationContextBuilder>());
|
||||
evaluationContextBuilders.push_back(std::make_shared<BuildThisEvaluationContextBuilder>());
|
||||
evaluationContextBuilders.push_back(std::make_shared<ClusterEvaluationContextBuilder>());
|
||||
evaluationContextBuilders.push_back(std::make_shared<HeroExchangeEvaluator>());
|
||||
}
|
||||
|
||||
EvaluationContext PriorityEvaluator::buildEvaluationContext(Goals::TSubgoal goal) const
|
||||
@ -628,7 +663,6 @@ EvaluationContext PriorityEvaluator::buildEvaluationContext(Goals::TSubgoal goal
|
||||
|
||||
for(auto subgoal : parts)
|
||||
{
|
||||
context.strategicalValue += subgoal->strategicalValue;
|
||||
context.goldCost += subgoal->goldCost;
|
||||
|
||||
for(auto builder : evaluationContextBuilders)
|
||||
|
@ -63,7 +63,9 @@ namespace Goals
|
||||
DISMISS_HERO,
|
||||
COMPOSITION,
|
||||
CLUSTER_BEHAVIOR,
|
||||
UNLOCK_CLUSTER
|
||||
UNLOCK_CLUSTER,
|
||||
HERO_EXCHANGE,
|
||||
ARMY_UPGRADE
|
||||
};
|
||||
|
||||
class DLL_EXPORT TSubgoal : public std::shared_ptr<AbstractGoal>
|
||||
@ -96,7 +98,6 @@ namespace Goals
|
||||
public:
|
||||
bool isAbstract; VSETTER(bool, isAbstract)
|
||||
int value; VSETTER(int, value)
|
||||
float strategicalValue; VSETTER(float, strategicalValue)
|
||||
ui64 goldCost; VSETTER(ui64, goldCost)
|
||||
int resID; VSETTER(int, resID)
|
||||
int objid; VSETTER(int, objid)
|
||||
@ -119,7 +120,6 @@ namespace Goals
|
||||
tile = int3(-1, -1, -1);
|
||||
town = nullptr;
|
||||
bid = -1;
|
||||
strategicalValue = 0;
|
||||
goldCost = 0;
|
||||
}
|
||||
virtual ~AbstractGoal() {}
|
||||
|
@ -1,85 +0,0 @@
|
||||
/*
|
||||
* ClearWayTo.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "ClearWayTo.h"
|
||||
#include "Explore.h"
|
||||
#include "RecruitHero.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../FuzzyHelper.h"
|
||||
#include "../AIhelper.h"
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool ClearWayTo::operator==(const ClearWayTo & other) const
|
||||
{
|
||||
return other.hero.h == hero.h && other.tile == tile;
|
||||
}
|
||||
|
||||
TSubgoal ClearWayTo::whatToDoToAchieve()
|
||||
{
|
||||
assert(cb->isInTheMap(tile)); //set tile
|
||||
if(!cb->isVisible(tile))
|
||||
{
|
||||
logAi->error("Clear way should be used with visible tiles!");
|
||||
return sptr(Explore());
|
||||
}
|
||||
|
||||
return (fh->chooseSolution(getAllPossibleSubgoals()));
|
||||
}
|
||||
|
||||
bool ClearWayTo::fulfillsMe(TSubgoal goal)
|
||||
{
|
||||
if (goal->goalType == VISIT_TILE)
|
||||
{
|
||||
if (!hero || hero == goal->hero)
|
||||
return tile == goal->tile;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TGoalVec ClearWayTo::getAllPossibleSubgoals()
|
||||
{
|
||||
TGoalVec ret;
|
||||
|
||||
std::vector<const CGHeroInstance *> heroes;
|
||||
if(hero)
|
||||
heroes.push_back(hero.h);
|
||||
else
|
||||
heroes = cb->getHeroesInfo();
|
||||
|
||||
for(auto h : heroes)
|
||||
{
|
||||
//TODO: handle clearing way to allied heroes that are blocked
|
||||
//if ((hero && hero->visitablePos() == tile && hero == *h) || //we can't free the way ourselves
|
||||
// h->visitablePos() == tile) //we are already on that tile! what does it mean?
|
||||
// continue;
|
||||
|
||||
//if our hero is trapped, make sure we request clearing the way from OUR perspective
|
||||
|
||||
vstd::concatenate(ret, ai->ah->howToVisitTile(h, tile));
|
||||
}
|
||||
|
||||
if(ret.empty() && ai->canRecruitAnyHero())
|
||||
ret.push_back(sptr(RecruitHero()));
|
||||
|
||||
if(ret.empty())
|
||||
{
|
||||
logAi->warn("There is no known way to clear the way to tile %s", tile.toString());
|
||||
throw goalFulfilledException(sptr(ClearWayTo(tile))); //make sure asigned hero gets unlocked
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* ClearWayTo.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT ClearWayTo : public CGoal<ClearWayTo>
|
||||
{
|
||||
public:
|
||||
ClearWayTo()
|
||||
: CGoal(Goals::CLEAR_WAY_TO)
|
||||
{
|
||||
}
|
||||
ClearWayTo(int3 Tile)
|
||||
: CGoal(Goals::CLEAR_WAY_TO)
|
||||
{
|
||||
tile = Tile;
|
||||
priority = 5;
|
||||
}
|
||||
ClearWayTo(int3 Tile, HeroPtr h)
|
||||
: CGoal(Goals::CLEAR_WAY_TO)
|
||||
{
|
||||
tile = Tile;
|
||||
hero = h;
|
||||
priority = 5;
|
||||
}
|
||||
TGoalVec getAllPossibleSubgoals() override;
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
bool fulfillsMe(TSubgoal goal) override;
|
||||
virtual bool operator==(const ClearWayTo & other) const override;
|
||||
};
|
||||
}
|
@ -1,191 +0,0 @@
|
||||
/*
|
||||
* CollectRes.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "Goals.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
#include "../../../lib/StringConstants.h"
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool CollectRes::operator==(const CollectRes & other) const
|
||||
{
|
||||
return resID == other.resID;
|
||||
}
|
||||
|
||||
//TGoalVec CollectRes::getAllPossibleSubgoals()
|
||||
//{
|
||||
// TGoalVec ret;
|
||||
//
|
||||
//auto givesResource = [this](const CGObjectInstance * obj) -> bool
|
||||
//{
|
||||
// //TODO: move this logic to object side
|
||||
// //TODO: remember mithril exists
|
||||
// //TODO: water objects
|
||||
// //TODO: Creature banks
|
||||
|
||||
// //return false first from once-visitable, before checking if they were even visited
|
||||
// switch (obj->ID.num)
|
||||
// {
|
||||
// case Obj::TREASURE_CHEST:
|
||||
// return resID == Res::GOLD;
|
||||
// break;
|
||||
// case Obj::RESOURCE:
|
||||
// return obj->subID == resID;
|
||||
// break;
|
||||
// case Obj::MINE:
|
||||
// return (obj->subID == resID &&
|
||||
// (cb->getPlayerRelations(obj->tempOwner, ai->playerID) == PlayerRelations::ENEMIES)); //don't capture our mines
|
||||
// break;
|
||||
// case Obj::CAMPFIRE:
|
||||
// return true; //contains all resources
|
||||
// break;
|
||||
// case Obj::WINDMILL:
|
||||
// switch (resID)
|
||||
// {
|
||||
// case Res::GOLD:
|
||||
// case Res::WOOD:
|
||||
// return false;
|
||||
// }
|
||||
// break;
|
||||
// case Obj::WATER_WHEEL:
|
||||
// if (resID != Res::GOLD)
|
||||
// return false;
|
||||
// break;
|
||||
// case Obj::MYSTICAL_GARDEN:
|
||||
// if ((resID != Res::GOLD) && (resID != Res::GEMS))
|
||||
// return false;
|
||||
// break;
|
||||
// case Obj::LEAN_TO:
|
||||
// case Obj::WAGON:
|
||||
// if (resID != Res::GOLD)
|
||||
// return false;
|
||||
// break;
|
||||
// default:
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
// return !vstd::contains(ai->alreadyVisited, obj); //for weekly / once visitable
|
||||
//};
|
||||
|
||||
//std::vector<const CGObjectInstance *> objs;
|
||||
//for (auto obj : ai->visitableObjs)
|
||||
//{
|
||||
// if (givesResource(obj))
|
||||
// objs.push_back(obj);
|
||||
//}
|
||||
//for (auto h : cb->getHeroesInfo())
|
||||
//{
|
||||
// std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects
|
||||
|
||||
// for (auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero
|
||||
// {
|
||||
// if (givesResource(obj))
|
||||
// ourObjs.push_back(obj);
|
||||
// }
|
||||
|
||||
// for (auto obj : ourObjs)
|
||||
// {
|
||||
// auto waysToGo = ai->ah->howToVisitObj(h, ObjectIdRef(obj));
|
||||
|
||||
// vstd::concatenate(ret, waysToGo);
|
||||
// }
|
||||
//}
|
||||
// return ret;
|
||||
//}
|
||||
|
||||
//TSubgoal CollectRes::whatToDoToAchieve()
|
||||
//{
|
||||
// auto goals = getAllPossibleSubgoals();
|
||||
// auto trade = whatToDoToTrade();
|
||||
// if (!trade->invalid())
|
||||
// goals.push_back(trade);
|
||||
//
|
||||
// return sptr(Invalid()); //we can always do that
|
||||
//}
|
||||
|
||||
TSubgoal CollectRes::whatToDoToTrade()
|
||||
{
|
||||
//std::vector<const IMarket *> markets;
|
||||
|
||||
//std::vector<const CGObjectInstance *> visObjs;
|
||||
//ai->retrieveVisitableObjs(visObjs, true);
|
||||
//for (const CGObjectInstance * obj : visObjs)
|
||||
//{
|
||||
// if (const IMarket * m = IMarket::castFrom(obj, false))
|
||||
// {
|
||||
// if (obj->ID == Obj::TOWN && obj->tempOwner == ai->playerID && m->allowsTrade(EMarketMode::RESOURCE_RESOURCE))
|
||||
// markets.push_back(m);
|
||||
// else if (obj->ID == Obj::TRADING_POST)
|
||||
// markets.push_back(m);
|
||||
// }
|
||||
//}
|
||||
|
||||
//boost::sort(markets, [](const IMarket * m1, const IMarket * m2) -> bool
|
||||
//{
|
||||
// return m1->getMarketEfficiency() < m2->getMarketEfficiency();
|
||||
//});
|
||||
|
||||
//markets.erase(boost::remove_if(markets, [](const IMarket * market) -> bool
|
||||
//{
|
||||
// if (!(market->o->ID == Obj::TOWN && market->o->tempOwner == ai->playerID))
|
||||
// {
|
||||
// if (!ai->isAccessible(market->o->visitablePos()))
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
//}), markets.end());
|
||||
|
||||
//if (!markets.size())
|
||||
//{
|
||||
// for (const CGTownInstance * t : cb->getTownsInfo())
|
||||
// {
|
||||
// if (cb->canBuildStructure(t, BuildingID::MARKETPLACE) == EBuildingState::ALLOWED)
|
||||
// return sptr(BuildThis(BuildingID::MARKETPLACE, t).setpriority(2));
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// const IMarket * m = markets.back();
|
||||
// //attempt trade at back (best prices)
|
||||
// int howManyCanWeBuy = 0;
|
||||
// for (Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, 1))
|
||||
// {
|
||||
// if (i == resID)
|
||||
// continue;
|
||||
// int toGive = -1, toReceive = -1;
|
||||
// m->getOffer(i, resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE);
|
||||
// assert(toGive > 0 && toReceive > 0);
|
||||
// howManyCanWeBuy += toReceive * (ai->ah->freeResources()[i] / toGive);
|
||||
// }
|
||||
|
||||
// if (howManyCanWeBuy >= value)
|
||||
// {
|
||||
// auto backObj = cb->getTopObj(m->o->visitablePos()); //it'll be a hero if we have one there; otherwise marketplace
|
||||
// assert(backObj);
|
||||
// auto objid = m->o->id.getNum();
|
||||
// if (backObj->tempOwner != ai->playerID) //top object not owned
|
||||
// {
|
||||
// return sptr(VisitObj(objid)); //just go there
|
||||
// }
|
||||
// else //either it's our town, or we have hero there
|
||||
// {
|
||||
// return sptr(Trade(resID, value, objid).setisElementar(true)); //we can do this immediately
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
return sptr(Invalid()); //cannot trade
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* CollectRes.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT CollectRes : public CGoal<CollectRes>
|
||||
{
|
||||
public:
|
||||
CollectRes()
|
||||
: CGoal(Goals::COLLECT_RES)
|
||||
{
|
||||
}
|
||||
CollectRes(int rid, int val)
|
||||
: CGoal(Goals::COLLECT_RES)
|
||||
{
|
||||
resID = rid;
|
||||
value = val;
|
||||
}
|
||||
/*TGoalVec getAllPossibleSubgoals() override;
|
||||
TSubgoal whatToDoToAchieve() override;*/
|
||||
TSubgoal whatToDoToTrade();
|
||||
virtual bool operator==(const CollectRes & other) const override;
|
||||
};
|
||||
}
|
@ -8,8 +8,8 @@
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "CompleteQuestBehavior.h"
|
||||
#include "CaptureObjectsBehavior.h"
|
||||
#include "CompleteQuest.h"
|
||||
#include "../Behaviors/CaptureObjectsBehavior.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
@ -26,23 +26,6 @@ std::string CompleteQuest::toString() const
|
||||
|
||||
TGoalVec CompleteQuest::decompose() const
|
||||
{
|
||||
/*TGoalVec solutions;
|
||||
|
||||
auto quests = cb->getMyQuests();
|
||||
|
||||
for(auto & q : quests)
|
||||
{
|
||||
if(q.quest->missionType == CQuest::MISSION_NONE
|
||||
|| q.quest->progress == CQuest::COMPLETE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
vstd::concatenate(solutions, getQuestTasks());
|
||||
}
|
||||
|
||||
return solutions;*/
|
||||
|
||||
if(q.obj && (q.obj->ID == Obj::BORDER_GATE || q.obj->ID == Obj::BORDERGUARD))
|
||||
{
|
||||
return missionKeymaster();
|
@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Conquer.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "Goals.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../AIhelper.h"
|
||||
#include "../FuzzyHelper.h"
|
||||
#include "../ResourceManager.h"
|
||||
#include "../BuildingManager.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
#include "../../../lib/StringConstants.h"
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool Conquer::operator==(const Conquer & other) const
|
||||
{
|
||||
return other.hero.h == hero.h;
|
||||
}
|
||||
|
||||
TSubgoal Conquer::whatToDoToAchieve()
|
||||
{
|
||||
logAi->trace("Entering goal CONQUER");
|
||||
|
||||
return fh->chooseSolution(getAllPossibleSubgoals());
|
||||
}
|
||||
|
||||
TGoalVec Conquer::getAllPossibleSubgoals()
|
||||
{
|
||||
TGoalVec ret;
|
||||
|
||||
auto conquerable = [](const CGObjectInstance * obj) -> bool
|
||||
{
|
||||
if(cb->getPlayerRelations(ai->playerID, obj->tempOwner) == PlayerRelations::ENEMIES)
|
||||
{
|
||||
switch(obj->ID.num)
|
||||
{
|
||||
case Obj::TOWN:
|
||||
case Obj::HERO:
|
||||
case Obj::CREATURE_GENERATOR1:
|
||||
case Obj::MINE: //TODO: check ai->knownSubterraneanGates
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
std::vector<const CGObjectInstance *> objs;
|
||||
for(auto obj : ai->visitableObjs)
|
||||
{
|
||||
if(conquerable(obj))
|
||||
objs.push_back(obj);
|
||||
}
|
||||
|
||||
for(auto h : cb->getHeroesInfo())
|
||||
{
|
||||
std::vector<const CGObjectInstance *> ourObjs(objs); //copy common objects
|
||||
|
||||
for(auto obj : ai->reservedHeroesMap[h]) //add objects reserved by this hero
|
||||
{
|
||||
if(conquerable(obj))
|
||||
ourObjs.push_back(obj);
|
||||
}
|
||||
for(auto obj : ourObjs)
|
||||
{
|
||||
auto waysToGo = ai->ah->howToVisitObj(h, ObjectIdRef(obj));
|
||||
|
||||
vstd::concatenate(ret, waysToGo);
|
||||
}
|
||||
}
|
||||
if(!objs.empty() && ai->canRecruitAnyHero()) //probably no point to recruit hero if we see no objects to capture
|
||||
ret.push_back(sptr(RecruitHero()));
|
||||
|
||||
if(ret.empty())
|
||||
ret.push_back(sptr(Explore())); //we need to find an enemy
|
||||
return ret;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Conquer.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT Conquer : public CGoal<Conquer>
|
||||
{
|
||||
public:
|
||||
Conquer()
|
||||
: CGoal(Goals::CONQUER)
|
||||
{
|
||||
priority = 10;
|
||||
}
|
||||
TGoalVec getAllPossibleSubgoals() override;
|
||||
TSubgoal whatToDoToAchieve() override;
|
||||
virtual bool operator==(const Conquer & other) const override;
|
||||
};
|
||||
}
|
@ -1,432 +0,0 @@
|
||||
/*
|
||||
* Explore.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "Goals.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../AIhelper.h"
|
||||
#include "../FuzzyHelper.h"
|
||||
#include "../ResourceManager.h"
|
||||
#include "../BuildingManager.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
#include "../../../lib/StringConstants.h"
|
||||
#include "../../../lib/CPlayerState.h"
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
struct ExplorationHelper
|
||||
{
|
||||
HeroPtr hero;
|
||||
int sightRadius;
|
||||
float bestValue;
|
||||
TSubgoal bestGoal;
|
||||
VCAI * aip;
|
||||
CCallback * cbp;
|
||||
const TeamState * ts;
|
||||
int3 ourPos;
|
||||
bool allowDeadEndCancellation;
|
||||
bool allowGatherArmy;
|
||||
|
||||
ExplorationHelper(HeroPtr h, bool gatherArmy)
|
||||
{
|
||||
cbp = cb.get();
|
||||
aip = ai.get();
|
||||
hero = h;
|
||||
ts = cbp->getPlayerTeam(ai->playerID);
|
||||
sightRadius = hero->getSightRadius();
|
||||
bestGoal = sptr(Goals::Invalid());
|
||||
bestValue = 0;
|
||||
ourPos = h->convertPosition(h->pos, false);
|
||||
allowDeadEndCancellation = true;
|
||||
allowGatherArmy = gatherArmy;
|
||||
}
|
||||
|
||||
void scanSector(int scanRadius)
|
||||
{
|
||||
for(int x = ourPos.x - scanRadius; x <= ourPos.x + scanRadius; x++)
|
||||
{
|
||||
for(int y = ourPos.y - scanRadius; y <= ourPos.y + scanRadius; y++)
|
||||
{
|
||||
int3 tile = int3(x, y, ourPos.z);
|
||||
|
||||
if(cbp->isInTheMap(tile) && ts->fogOfWarMap[tile.x][tile.y][tile.z])
|
||||
{
|
||||
scanTile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scanMap()
|
||||
{
|
||||
int3 mapSize = cbp->getMapSize();
|
||||
int perimeter = 2 * sightRadius * (mapSize.x + mapSize.y);
|
||||
|
||||
std::vector<int3> from;
|
||||
std::vector<int3> to;
|
||||
|
||||
from.reserve(perimeter);
|
||||
to.reserve(perimeter);
|
||||
|
||||
foreach_tile_pos([&](const int3 & pos)
|
||||
{
|
||||
if(ts->fogOfWarMap[pos.x][pos.y][pos.z])
|
||||
{
|
||||
bool hasInvisibleNeighbor = false;
|
||||
|
||||
foreach_neighbour(cbp, pos, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(!ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
{
|
||||
hasInvisibleNeighbor = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(hasInvisibleNeighbor)
|
||||
from.push_back(pos);
|
||||
}
|
||||
});
|
||||
|
||||
logAi->debug("Exploration scan visible area perimeter for hero %s", hero.name);
|
||||
|
||||
for(const int3 & tile : from)
|
||||
{
|
||||
scanTile(tile);
|
||||
}
|
||||
|
||||
if(!bestGoal->invalid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
allowDeadEndCancellation = false;
|
||||
|
||||
for(int i = 0; i < sightRadius; i++)
|
||||
{
|
||||
getVisibleNeighbours(from, to);
|
||||
vstd::concatenate(from, to);
|
||||
vstd::removeDuplicates(from);
|
||||
}
|
||||
|
||||
logAi->debug("Exploration scan all possible tiles for hero %s", hero.name);
|
||||
|
||||
for(const int3 & tile : from)
|
||||
{
|
||||
scanTile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
void scanTile(const int3 & tile)
|
||||
{
|
||||
if(tile == ourPos
|
||||
|| !aip->ah->isTileAccessible(hero, tile)) //shouldn't happen, but it does
|
||||
return;
|
||||
|
||||
int tilesDiscovered = howManyTilesWillBeDiscovered(tile);
|
||||
if(!tilesDiscovered)
|
||||
return;
|
||||
|
||||
auto waysToVisit = aip->ah->howToVisitTile(hero, tile, allowGatherArmy);
|
||||
for(auto goal : waysToVisit)
|
||||
{
|
||||
if(goal->evaluationContext.movementCost <= 0.0) // should not happen
|
||||
continue;
|
||||
|
||||
float ourValue = (float)tilesDiscovered * tilesDiscovered / goal->evaluationContext.movementCost;
|
||||
|
||||
if(ourValue > bestValue) //avoid costly checks of tiles that don't reveal much
|
||||
{
|
||||
auto obj = cb->getTopObj(tile);
|
||||
|
||||
// picking up resources does not yield any exploration at all.
|
||||
// if it blocks the way to some explorable tile AIPathfinder will take care of it
|
||||
if(obj && obj->blockVisit)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isSafeToVisit(hero, tile))
|
||||
{
|
||||
bestGoal = goal;
|
||||
bestValue = ourValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getVisibleNeighbours(const std::vector<int3> & tiles, std::vector<int3> & out) const
|
||||
{
|
||||
for(const int3 & tile : tiles)
|
||||
{
|
||||
foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour)
|
||||
{
|
||||
if(ts->fogOfWarMap[neighbour.x][neighbour.y][neighbour.z])
|
||||
{
|
||||
out.push_back(neighbour);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
int howManyTilesWillBeDiscovered(
|
||||
const int3 & pos) const
|
||||
{
|
||||
int ret = 0;
|
||||
for(int x = pos.x - sightRadius; x <= pos.x + sightRadius; x++)
|
||||
{
|
||||
for(int y = pos.y - sightRadius; y <= pos.y + sightRadius; y++)
|
||||
{
|
||||
int3 npos = int3(x, y, pos.z);
|
||||
if(cbp->isInTheMap(npos)
|
||||
&& pos.dist2d(npos) - 0.5 < sightRadius
|
||||
&& !ts->fogOfWarMap[npos.x][npos.y][npos.z])
|
||||
{
|
||||
if(allowDeadEndCancellation
|
||||
&& !hasReachableNeighbor(npos))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool hasReachableNeighbor(const int3 &pos) const
|
||||
{
|
||||
for(crint3 dir : int3::getDirs())
|
||||
{
|
||||
int3 tile = pos + dir;
|
||||
if(cbp->isInTheMap(tile))
|
||||
{
|
||||
auto isAccessible = aip->ah->isTileAccessible(hero, tile);
|
||||
|
||||
if(isAccessible)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool Explore::operator==(const Explore & other) const
|
||||
{
|
||||
return other.hero.h == hero.h && other.allowGatherArmy == allowGatherArmy;
|
||||
}
|
||||
|
||||
TSubgoal Explore::whatToDoToAchieve()
|
||||
{
|
||||
return sptr(Goals::Invalid());
|
||||
}
|
||||
|
||||
TGoalVec Explore::getAllPossibleSubgoals()
|
||||
{
|
||||
TGoalVec ret;
|
||||
std::vector<const CGHeroInstance *> heroes;
|
||||
|
||||
if(hero)
|
||||
{
|
||||
heroes.push_back(hero.h);
|
||||
}
|
||||
else
|
||||
{
|
||||
//heroes = ai->getUnblockedHeroes();
|
||||
heroes = cb->getHeroesInfo();
|
||||
vstd::erase_if(heroes, [](const HeroPtr h)
|
||||
{
|
||||
if(ai->getGoal(h)->goalType == EXPLORE) //do not reassign hero who is already explorer
|
||||
return true;
|
||||
|
||||
if(!ai->isAbleToExplore(h))
|
||||
return true;
|
||||
|
||||
return !h->movement; //saves time, immobile heroes are useless anyway
|
||||
});
|
||||
}
|
||||
|
||||
//try to use buildings that uncover map
|
||||
std::vector<const CGObjectInstance *> objs;
|
||||
for(auto obj : ai->visitableObjs)
|
||||
{
|
||||
if(!vstd::contains(ai->alreadyVisited, obj))
|
||||
{
|
||||
switch(obj->ID.num)
|
||||
{
|
||||
case Obj::REDWOOD_OBSERVATORY:
|
||||
case Obj::PILLAR_OF_FIRE:
|
||||
case Obj::CARTOGRAPHER:
|
||||
objs.push_back(obj);
|
||||
break;
|
||||
case Obj::MONOLITH_ONE_WAY_ENTRANCE:
|
||||
case Obj::MONOLITH_TWO_WAY:
|
||||
case Obj::SUBTERRANEAN_GATE:
|
||||
auto tObj = dynamic_cast<const CGTeleport *>(obj);
|
||||
assert(ai->knownTeleportChannels.find(tObj->channel) != ai->knownTeleportChannels.end());
|
||||
if(TeleportChannel::IMPASSABLE != ai->knownTeleportChannels[tObj->channel]->passability)
|
||||
objs.push_back(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(obj->ID.num)
|
||||
{
|
||||
case Obj::MONOLITH_TWO_WAY:
|
||||
case Obj::SUBTERRANEAN_GATE:
|
||||
auto tObj = dynamic_cast<const CGTeleport *>(obj);
|
||||
if(TeleportChannel::IMPASSABLE == ai->knownTeleportChannels[tObj->channel]->passability)
|
||||
break;
|
||||
for(auto exit : ai->knownTeleportChannels[tObj->channel]->exits)
|
||||
{
|
||||
if(!cb->getObj(exit))
|
||||
{ // Always attempt to visit two-way teleports if one of channel exits is not visible
|
||||
objs.push_back(obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto h : heroes)
|
||||
{
|
||||
for(auto obj : objs) //double loop, performance risk?
|
||||
{
|
||||
auto waysToVisitObj = ai->ah->howToVisitObj(h, obj, allowGatherArmy);
|
||||
|
||||
vstd::concatenate(ret, waysToVisitObj);
|
||||
}
|
||||
|
||||
TSubgoal goal = exploreNearestNeighbour(h);
|
||||
|
||||
if(!goal->invalid())
|
||||
{
|
||||
ret.push_back(goal);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret.empty())
|
||||
{
|
||||
for(auto h : heroes)
|
||||
{
|
||||
logAi->trace("Exploration searching for a new point for hero %s", h->name);
|
||||
|
||||
TSubgoal goal = explorationNewPoint(h);
|
||||
|
||||
if(goal->invalid())
|
||||
{
|
||||
ai->markHeroUnableToExplore(h); //there is no freely accessible tile, do not poll this hero anymore
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.push_back(goal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//we either don't have hero yet or none of heroes can explore
|
||||
if((!hero || ret.empty()) && ai->canRecruitAnyHero())
|
||||
ret.push_back(sptr(RecruitHero()));
|
||||
|
||||
if(ret.empty())
|
||||
{
|
||||
throw goalFulfilledException(sptr(Explore().sethero(hero)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
TSubgoal Explore::explorationBestNeighbour(int3 hpos, HeroPtr h) const
|
||||
{
|
||||
ExplorationHelper scanResult(h, allowGatherArmy);
|
||||
|
||||
for(crint3 dir : int3::getDirs())
|
||||
{
|
||||
int3 tile = hpos + dir;
|
||||
if(cb->isInTheMap(tile))
|
||||
{
|
||||
scanResult.scanTile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
return scanResult.bestGoal;
|
||||
}
|
||||
|
||||
|
||||
TSubgoal Explore::explorationNewPoint(HeroPtr h) const
|
||||
{
|
||||
ExplorationHelper scanResult(h, allowGatherArmy);
|
||||
|
||||
scanResult.scanSector(10);
|
||||
|
||||
if(!scanResult.bestGoal->invalid())
|
||||
{
|
||||
return scanResult.bestGoal;
|
||||
}
|
||||
|
||||
scanResult.scanMap();
|
||||
|
||||
return scanResult.bestGoal;
|
||||
}
|
||||
|
||||
|
||||
TSubgoal Explore::exploreNearestNeighbour(HeroPtr h) const
|
||||
{
|
||||
TimeCheck tc("where to explore");
|
||||
int3 hpos = h->visitablePos();
|
||||
|
||||
//look for nearby objs -> visit them if they're close enough
|
||||
const int DIST_LIMIT = 3;
|
||||
const float COST_LIMIT = .2; //todo: fine tune
|
||||
|
||||
std::vector<const CGObjectInstance *> nearbyVisitableObjs;
|
||||
for(int x = hpos.x - DIST_LIMIT; x <= hpos.x + DIST_LIMIT; ++x) //get only local objects instead of all possible objects on the map
|
||||
{
|
||||
for(int y = hpos.y - DIST_LIMIT; y <= hpos.y + DIST_LIMIT; ++y)
|
||||
{
|
||||
for(auto obj : cb->getVisitableObjs(int3(x, y, hpos.z), false))
|
||||
{
|
||||
if(ai->isGoodForVisit(obj, h, COST_LIMIT))
|
||||
{
|
||||
nearbyVisitableObjs.push_back(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(nearbyVisitableObjs.size())
|
||||
{
|
||||
vstd::removeDuplicates(nearbyVisitableObjs); //one object may occupy multiple tiles
|
||||
boost::sort(nearbyVisitableObjs, CDistanceSorter(h.get()));
|
||||
|
||||
TSubgoal pickupNearestObj = fh->chooseSolution(ai->ah->howToVisitObj(h, nearbyVisitableObjs.back(), false));
|
||||
|
||||
if(!pickupNearestObj->invalid())
|
||||
{
|
||||
return pickupNearestObj;
|
||||
}
|
||||
}
|
||||
|
||||
//check if nearby tiles allow us to reveal anything - this is quick
|
||||
return explorationBestNeighbour(hpos, h);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
///*
|
||||
//* Explore.h, part of VCMI engine
|
||||
//*
|
||||
//* Authors: listed in file AUTHORS in main folder
|
||||
//*
|
||||
//* License: GNU General Public License v2.0 or later
|
||||
//* Full text of license available in license.txt file, in main folder
|
||||
//*
|
||||
//*/
|
||||
//#pragma once
|
||||
//
|
||||
//#include "CGoal.h"
|
||||
//
|
||||
//struct HeroPtr;
|
||||
//class VCAI;
|
||||
//class FuzzyHelper;
|
||||
//
|
||||
//namespace Goals
|
||||
//{
|
||||
// struct ExplorationHelper;
|
||||
//
|
||||
// class DLL_EXPORT Explore : public CGoal<Explore>
|
||||
// {
|
||||
// private:
|
||||
// bool allowGatherArmy;
|
||||
//
|
||||
// public:
|
||||
// Explore(bool allowGatherArmy)
|
||||
// : CGoal(Goals::EXPLORE), allowGatherArmy(allowGatherArmy)
|
||||
// {
|
||||
// priority = 1;
|
||||
// }
|
||||
//
|
||||
// Explore()
|
||||
// : Explore(true)
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// Explore(HeroPtr h)
|
||||
// : CGoal(Goals::EXPLORE)
|
||||
// {
|
||||
// hero = h;
|
||||
// priority = 1;
|
||||
// }
|
||||
// TGoalVec getAllPossibleSubgoals() override;
|
||||
// TSubgoal whatToDoToAchieve() override;
|
||||
// virtual bool operator==(const Explore & other) const override;
|
||||
//
|
||||
// private:
|
||||
// TSubgoal exploreNearestNeighbour(HeroPtr h) const;
|
||||
// TSubgoal explorationNewPoint(HeroPtr h) const;
|
||||
// TSubgoal explorationBestNeighbour(int3 hpos, HeroPtr h) const;
|
||||
// void explorationScanTile(const int3 & tile, ExplorationHelper & scanResult) const;
|
||||
// bool hasReachableNeighbor(const int3 &pos, HeroPtr hero, CCallback * cbp, VCAI * vcai) const;
|
||||
//
|
||||
// void getVisibleNeighbours(
|
||||
// const std::vector<int3> & tiles,
|
||||
// std::vector<int3> & out,
|
||||
// CCallback * cbp,
|
||||
// const TeamState * ts) const;
|
||||
//
|
||||
// int howManyTilesWillBeDiscovered(const int3 & pos, ExplorationHelper & scanResult) const;
|
||||
// };
|
||||
//}
|
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* GatherTroops.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "Goals.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
#include "../../../lib/StringConstants.h"
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool GatherTroops::operator==(const GatherTroops & other) const
|
||||
{
|
||||
return objid == other.objid;
|
||||
}
|
||||
|
||||
int GatherTroops::getCreaturesCount(const CArmedInstance * army)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for(auto stack : army->Slots())
|
||||
{
|
||||
if(objid == stack.second->getCreatureID().num)
|
||||
{
|
||||
count += stack.second->count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
//
|
||||
//TSubgoal GatherTroops::whatToDoToAchieve()
|
||||
//{
|
||||
// logAi->trace("Entering GatherTroops::whatToDoToAchieve");
|
||||
//
|
||||
// auto heroes = cb->getHeroesInfo(true);
|
||||
//
|
||||
// for(auto hero : heroes)
|
||||
// {
|
||||
// if(getCreaturesCount(hero) >= this->value)
|
||||
// {
|
||||
// logAi->trace("Completing GATHER_TROOPS by hero %s", hero->name);
|
||||
//
|
||||
// throw goalFulfilledException(sptr(*this));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return sptr(Invalid());
|
||||
//}
|
||||
|
||||
//
|
||||
//TGoalVec GatherTroops::getAllPossibleSubgoals()
|
||||
//{
|
||||
// TGoalVec solutions;
|
||||
|
||||
//for(const CGTownInstance * t : cb->getTownsInfo())
|
||||
//{
|
||||
// int count = getCreaturesCount(t->getUpperArmy());
|
||||
|
||||
// if(count >= this->value)
|
||||
// {
|
||||
// if(t->visitingHero)
|
||||
// {
|
||||
// solutions.push_back(sptr(VisitObj(t->id.getNum()).sethero(t->visitingHero.get())));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// vstd::concatenate(solutions, ai->ah->howToVisitObj(t));
|
||||
// }
|
||||
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// auto creature = VLC->creh->creatures[objid];
|
||||
// if(t->subID == creature->faction) //TODO: how to force AI to build unupgraded creatures? :O
|
||||
// {
|
||||
// auto creatures = vstd::tryAt(t->town->creatures, creature->level - 1);
|
||||
// if(!creatures)
|
||||
// continue;
|
||||
|
||||
// int upgradeNumber = vstd::find_pos(*creatures, creature->idNumber);
|
||||
// if(upgradeNumber < 0)
|
||||
// continue;
|
||||
|
||||
// BuildingID bid(BuildingID::DWELL_FIRST + creature->level - 1 + upgradeNumber * GameConstants::CREATURES_PER_TOWN);
|
||||
// if(t->hasBuilt(bid) && ai->ah->freeResources().canAfford(creature->cost)) //this assumes only creatures with dwellings are assigned to faction
|
||||
// {
|
||||
// solutions.push_back(sptr(BuyArmy(t, creature->AIValue * this->value).setobjid(objid)));
|
||||
// }
|
||||
// /*else //disable random building requests for now - this code needs to know a lot of town/resource context to do more good than harm
|
||||
// {
|
||||
// return sptr(BuildThis(bid, t).setpriority(priority));
|
||||
// }*/
|
||||
// }
|
||||
//}
|
||||
|
||||
//for(auto obj : ai->visitableObjs)
|
||||
//{
|
||||
// auto d = dynamic_cast<const CGDwelling *>(obj);
|
||||
|
||||
// if(!d || obj->ID == Obj::TOWN)
|
||||
// continue;
|
||||
|
||||
// for(auto creature : d->creatures)
|
||||
// {
|
||||
// if(creature.first) //there are more than 0 creatures avaliabe
|
||||
// {
|
||||
// for(auto type : creature.second)
|
||||
// {
|
||||
// if(type == objid && ai->ah->freeResources().canAfford(VLC->creh->creatures[type]->cost))
|
||||
// vstd::concatenate(solutions, ai->ah->howToVisitObj(obj));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//CreatureID creID = CreatureID(objid);
|
||||
|
||||
//vstd::erase_if(solutions, [&](TSubgoal goal)->bool
|
||||
//{
|
||||
// return goal->hero && !goal->hero->getSlotFor(creID).validSlot() && !goal->hero->getFreeSlot().validSlot();
|
||||
//});
|
||||
|
||||
// return solutions;
|
||||
// //TODO: exchange troops between heroes
|
||||
//}
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* GatherTroops.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT GatherTroops : public CGoal<GatherTroops>
|
||||
{
|
||||
public:
|
||||
GatherTroops()
|
||||
: CGoal(Goals::GATHER_TROOPS)
|
||||
{
|
||||
}
|
||||
GatherTroops(int type, int val)
|
||||
: CGoal(Goals::GATHER_TROOPS)
|
||||
{
|
||||
objid = type;
|
||||
value = val;
|
||||
}
|
||||
virtual bool operator==(const GatherTroops & other) const override;
|
||||
|
||||
private:
|
||||
int getCreaturesCount(const CArmedInstance * army);
|
||||
};
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* GetArtOfType.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "GetArtOfType.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool GetArtOfType::operator==(const GetArtOfType & other) const
|
||||
{
|
||||
return other.hero.h == hero.h && other.objid == objid;
|
||||
}
|
||||
//
|
||||
//TSubgoal GetArtOfType::whatToDoToAchieve()
|
||||
//{
|
||||
// return sptr(FindObj(Obj::ARTIFACT, aid));
|
||||
//}
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* GetArtOfType.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT GetArtOfType : public CGoal<GetArtOfType>
|
||||
{
|
||||
public:
|
||||
GetArtOfType()
|
||||
: CGoal(Goals::GET_ART_TYPE)
|
||||
{
|
||||
}
|
||||
GetArtOfType(int type)
|
||||
: CGoal(Goals::GET_ART_TYPE)
|
||||
{
|
||||
aid = type;
|
||||
}
|
||||
virtual bool operator==(const GetArtOfType & other) const override;
|
||||
};
|
||||
}
|
@ -14,10 +14,7 @@
|
||||
#include "BuildBoat.h"
|
||||
#include "BuildThis.h"
|
||||
#include "BuyArmy.h"
|
||||
#include "GatherTroops.h"
|
||||
#include "Trade.h"
|
||||
#include "CollectRes.h"
|
||||
#include "RecruitHero.h"
|
||||
#include "GetArtOfType.h"
|
||||
#include "DigAtTile.h"
|
||||
#include "AdventureSpellCast.h"
|
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* VisitHero.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "VisitHero.h"
|
||||
#include "Invalid.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../AIhelper.h"
|
||||
#include "../FuzzyHelper.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool VisitHero::operator==(const VisitHero & other) const
|
||||
{
|
||||
return other.hero.h == hero.h && other.objid == objid;
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* VisitHero.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#error not used
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT VisitHero : public CGoal<VisitHero>
|
||||
{
|
||||
public:
|
||||
VisitHero()
|
||||
: CGoal(Goals::VISIT_HERO)
|
||||
{
|
||||
}
|
||||
VisitHero(int hid)
|
||||
: CGoal(Goals::VISIT_HERO)
|
||||
{
|
||||
objid = hid;
|
||||
}
|
||||
virtual bool operator==(const VisitHero & other) const override;
|
||||
};
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* VisitObj.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "Goals.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../AIhelper.h"
|
||||
#include "../FuzzyHelper.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
#include "../../../lib/StringConstants.h"
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool VisitObj::operator==(const VisitObj & other) const
|
||||
{
|
||||
return other.hero.h == hero.h && other.objid == objid;
|
||||
}
|
||||
|
||||
VisitObj::VisitObj(int Objid)
|
||||
: CGoal(VISIT_OBJ)
|
||||
{
|
||||
objid = Objid;
|
||||
auto obj = ai->myCb->getObjInstance(ObjectInstanceID(objid));
|
||||
if(obj)
|
||||
tile = obj->visitablePos();
|
||||
else
|
||||
logAi->error("VisitObj constructed with invalid object instance %d", Objid);
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* VisitObj.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#error not used
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT VisitObj : public CGoal<VisitObj> //this goal was previously known as GetObj
|
||||
{
|
||||
public:
|
||||
VisitObj() = delete; // empty constructor not allowed
|
||||
VisitObj(int Objid);
|
||||
|
||||
virtual bool operator==(const VisitObj & other) const override;
|
||||
};
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* VisitTile.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "Goals.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../AIUtility.h"
|
||||
#include "../AIhelper.h"
|
||||
#include "../FuzzyHelper.h"
|
||||
#include "../../../lib/mapping/CMap.h" //for victory conditions
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
#include "../../../lib/StringConstants.h"
|
||||
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool VisitTile::operator==(const VisitTile & other) const
|
||||
{
|
||||
return other.hero.h == hero.h && other.tile == tile;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* VisitTile.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#error not used
|
||||
|
||||
#include "CGoal.h"
|
||||
|
||||
struct HeroPtr;
|
||||
class VCAI;
|
||||
class FuzzyHelper;
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT VisitTile : public CGoal<VisitTile>
|
||||
//tile, in conjunction with hero elementar; assumes tile is reachable
|
||||
{
|
||||
public:
|
||||
VisitTile() {} // empty constructor not allowed
|
||||
|
||||
VisitTile(int3 Tile)
|
||||
: CGoal(Goals::VISIT_TILE)
|
||||
{
|
||||
tile = Tile;
|
||||
}
|
||||
virtual bool operator==(const VisitTile & other) const override;
|
||||
};
|
||||
}
|
36
AI/Nullkiller/Markers/ArmyUpgrade.cpp
Normal file
36
AI/Nullkiller/Markers/ArmyUpgrade.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* ArmyUpgrade.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "ArmyUpgrade.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../Engine/Nullkiller.h"
|
||||
#include "../AIUtility.h"
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
ArmyUpgrade::ArmyUpgrade(const AIPath & upgradePath, const CGObjectInstance * upgrader, const ArmyUpgradeInfo & upgrade)
|
||||
: CGoal(Goals::ARMY_UPGRADE), upgrader(upgrader), upgradeValue(upgrade.upgradeValue),
|
||||
initialValue(upgradePath.heroArmy->getArmyStrength()), goldCost(upgrade.upgradeCost[Res::GOLD])
|
||||
{
|
||||
sethero(upgradePath.targetHero);
|
||||
}
|
||||
|
||||
bool ArmyUpgrade::operator==(const ArmyUpgrade & other) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string ArmyUpgrade::toString() const
|
||||
{
|
||||
return "Army upgrade at " + upgrader->getObjectName() + upgrader->visitablePos().toString();
|
||||
}
|
35
AI/Nullkiller/Markers/ArmyUpgrade.h
Normal file
35
AI/Nullkiller/Markers/ArmyUpgrade.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* ArmyUpgrade.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../Goals/CGoal.h"
|
||||
#include "../Pathfinding/AINodeStorage.h"
|
||||
#include "../Analyzers/ArmyManager.h"
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT ArmyUpgrade : public CGoal<ArmyUpgrade>
|
||||
{
|
||||
private:
|
||||
const CGObjectInstance * upgrader;
|
||||
uint64_t initialValue;
|
||||
uint64_t upgradeValue;
|
||||
uint64_t goldCost;
|
||||
|
||||
public:
|
||||
ArmyUpgrade(const AIPath & upgradePath, const CGObjectInstance * upgrader, const ArmyUpgradeInfo & upgrade);
|
||||
|
||||
virtual bool operator==(const ArmyUpgrade & other) const override;
|
||||
virtual std::string toString() const override;
|
||||
|
||||
uint64_t getUpgradeValue() const { return upgradeValue; }
|
||||
uint64_t getInitialArmyValue() const { return initialValue; }
|
||||
};
|
||||
}
|
36
AI/Nullkiller/Markers/HeroExchange.cpp
Normal file
36
AI/Nullkiller/Markers/HeroExchange.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* HeroExchange.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
#include "HeroExchange.h"
|
||||
#include "../VCAI.h"
|
||||
#include "../Engine/Nullkiller.h"
|
||||
#include "../AIUtility.h"
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
|
||||
using namespace Goals;
|
||||
|
||||
bool HeroExchange::operator==(const HeroExchange & other) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string HeroExchange::toString() const
|
||||
{
|
||||
return "Hero exchange " + exchangePath.toString();
|
||||
}
|
||||
|
||||
uint64_t HeroExchange::getReinforcementArmyStrength() const
|
||||
{
|
||||
uint64_t armyValue = ai->nullkiller->armyManager->howManyReinforcementsCanGet(hero.get(), exchangePath.heroArmy);
|
||||
|
||||
return armyValue;
|
||||
}
|
34
AI/Nullkiller/Markers/HeroExchange.h
Normal file
34
AI/Nullkiller/Markers/HeroExchange.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* HeroExchange.h, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../Goals/CGoal.h"
|
||||
#include "../Pathfinding/AINodeStorage.h"
|
||||
|
||||
namespace Goals
|
||||
{
|
||||
class DLL_EXPORT HeroExchange : public CGoal<HeroExchange>
|
||||
{
|
||||
private:
|
||||
AIPath exchangePath;
|
||||
|
||||
public:
|
||||
HeroExchange(const CGHeroInstance * targetHero, const AIPath & exchangePath)
|
||||
: CGoal(Goals::HERO_EXCHANGE), exchangePath(exchangePath)
|
||||
{
|
||||
sethero(targetHero);
|
||||
}
|
||||
|
||||
virtual bool operator==(const HeroExchange & other) const override;
|
||||
virtual std::string toString() const override;
|
||||
|
||||
uint64_t getReinforcementArmyStrength() const;
|
||||
};
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "CGoal.h"
|
||||
#include "../Goals/CGoal.h"
|
||||
#include "../Analyzers/ObjectClusterizer.h"
|
||||
|
||||
|
@ -1112,10 +1112,10 @@ AIPath::AIPath()
|
||||
|
||||
std::shared_ptr<const SpecialAction> AIPath::getFirstBlockedAction() const
|
||||
{
|
||||
for(auto node : nodes)
|
||||
for(auto node = nodes.rbegin(); node != nodes.rend(); node++)
|
||||
{
|
||||
if(node.specialAction && node.actionIsBlocked)
|
||||
return node.specialAction;
|
||||
if(node->specialAction && node->actionIsBlocked)
|
||||
return node->specialAction;
|
||||
}
|
||||
|
||||
return std::shared_ptr<const SpecialAction>();
|
||||
|
@ -11,7 +11,7 @@
|
||||
#pragma once
|
||||
|
||||
#define PATHFINDER_TRACE_LEVEL 0
|
||||
#define AI_TRACE_LEVEL 0
|
||||
#define AI_TRACE_LEVEL 2
|
||||
#define SCOUT_TURN_DISTANCE_LIMIT 3
|
||||
|
||||
#include "../../../lib/CPathfinder.h"
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "StdInc.h"
|
||||
#include "BattleAction.h"
|
||||
#include "../../VCAI.h"
|
||||
#include "../../Behaviors/CompleteQuestBehavior.h"
|
||||
#include "../../Goals/CompleteQuest.h"
|
||||
#include "../../../../lib/mapping/CMap.h" //for victory conditions
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
|
Loading…
Reference in New Issue
Block a user