1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-17 01:32:21 +02:00

Nullkiller: fix file headers, move fuzzy config to ai folder

This commit is contained in:
Andrii Danylchenko
2021-05-15 22:04:26 +03:00
committed by Andrii Danylchenko
parent 1d561b9882
commit ada76a5603
20 changed files with 412 additions and 284 deletions

View File

@ -1,3 +1,12 @@
/*
* Behavior.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 #pragma once
#include "../VCAI.h" #include "../VCAI.h"
@ -7,4 +16,4 @@ class Behavior
public: public:
virtual Goals::TGoalVec getTasks() = 0; virtual Goals::TGoalVec getTasks() = 0;
virtual std::string toString() const = 0; virtual std::string toString() const = 0;
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Goals.cpp, part of VCMI engine * BuyArmyBehavior.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
@ -73,4 +73,4 @@ Goals::TGoalVec BuyArmyBehavior::getTasks()
} }
return tasks; return tasks;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Goals.h, part of VCMI engine * BuyArmyBehavior.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *

View File

@ -1,12 +1,12 @@
/* /*
* Goals.cpp, part of VCMI engine * CaptureObjectsBehavior.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
* License: GNU General Public License v2.0 or later * License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder * Full text of license available in license.txt file, in main folder
* *
*/ */
#include "StdInc.h" #include "StdInc.h"
#include "../VCAI.h" #include "../VCAI.h"
#include "../Engine/Nullkiller.h" #include "../Engine/Nullkiller.h"

View File

@ -1,12 +1,12 @@
/* /*
* Goals.h, part of VCMI engine * CaptureObjectsBehavior.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
* License: GNU General Public License v2.0 or later * License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder * Full text of license available in license.txt file, in main folder
* *
*/ */
#pragma once #pragma once
#include "lib/VCMI_Lib.h" #include "lib/VCMI_Lib.h"

View File

@ -1,5 +1,5 @@
/* /*
* Goals.cpp, part of VCMI engine * RecruitHeroBehavior.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
@ -43,156 +43,3 @@ Goals::TGoalVec RecruitHeroBehavior::getTasks()
return tasks; return tasks;
} }
std::string StartupBehavior::toString() const
{
return "Startup";
}
const AIPath getShortestPath(const CGTownInstance * town, const std::vector<AIPath> & paths)
{
auto shortestPath = *vstd::minElementByFun(paths, [town](const AIPath & path) -> float
{
if(town->garrisonHero && path.targetHero == town->garrisonHero.get())
return 1;
return path.movementCost();
});
return shortestPath;
}
const CGHeroInstance * getNearestHero(const CGTownInstance * town)
{
auto paths = ai->ah->getPathsToTile(town->visitablePos());
if(paths.empty())
return nullptr;
auto shortestPath = getShortestPath(town, paths);
if(shortestPath.nodes.size() > 1
|| shortestPath.targetHero->visitablePos().dist2dSQ(town->visitablePos()) > 4
|| town->garrisonHero && shortestPath.targetHero == town->garrisonHero.get())
return nullptr;
return shortestPath.targetHero;
}
bool needToRecruitHero(const CGTownInstance * startupTown)
{
if(!ai->canRecruitAnyHero(startupTown))
return false;
if(!startupTown->garrisonHero && !startupTown->visitingHero)
return false;
auto heroToCheck = startupTown->garrisonHero ? startupTown->garrisonHero.get() : startupTown->visitingHero.get();
auto paths = cb->getPathsInfo(heroToCheck);
for(auto obj : ai->visitableObjs)
{
if(obj->ID == Obj::RESOURCE && obj->subID == Res::GOLD
|| obj->ID == Obj::TREASURE_CHEST
|| obj->ID == Obj::CAMPFIRE
|| obj->ID == Obj::WATER_WHEEL)
{
auto path = paths->getPathInfo(obj->visitablePos());
if(path->accessible == CGPathNode::BLOCKVIS && path->turns != 255)
{
return true;
}
}
}
return false;
}
Goals::TGoalVec StartupBehavior::getTasks()
{
Goals::TGoalVec tasks;
auto towns = cb->getTownsInfo();
if(!towns.size())
return tasks;
const CGTownInstance * startupTown = towns.front();
bool canRecruitHero = needToRecruitHero(startupTown);
if(towns.size() > 1)
{
startupTown = *vstd::maxElementByFun(towns, [](const CGTownInstance * town) -> float
{
auto closestHero = getNearestHero(town);
if(!closestHero)
return 0;
return ai->ah->evaluateHero(closestHero);
});
}
auto closestHero = getNearestHero(startupTown);
if(closestHero)
{
if(!startupTown->visitingHero)
{
if(ai->ah->howManyReinforcementsCanGet(startupTown->getUpperArmy(), closestHero) > 200)
{
auto paths = ai->ah->getPathsToTile(startupTown->visitablePos());
if(paths.size())
{
auto path = getShortestPath(startupTown, paths);
tasks.push_back(Goals::sptr(Goals::ExecuteHeroChain(path, startupTown).setpriority(100)));
}
}
}
else
{
auto visitingHero = startupTown->visitingHero.get();
auto visitingHeroScore = ai->ah->evaluateHero(visitingHero);
if(startupTown->garrisonHero)
{
auto garrisonHero = startupTown->garrisonHero.get();
auto garrisonHeroScore = ai->ah->evaluateHero(garrisonHero);
if(visitingHeroScore > garrisonHeroScore
|| ai->ah->getHeroRole(garrisonHero) == HeroRole::SCOUT && ai->ah->getHeroRole(visitingHero) == HeroRole::MAIN)
{
if(canRecruitHero || ai->ah->howManyReinforcementsCanGet(visitingHero, garrisonHero) > 200)
{
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(startupTown, visitingHero).setpriority(100)));
}
}
else if(ai->ah->howManyReinforcementsCanGet(garrisonHero, visitingHero) > 200)
{
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(startupTown, garrisonHero).setpriority(100)));
}
}
else if(canRecruitHero)
{
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(startupTown, visitingHero).setpriority(100)));
}
}
}
if(tasks.empty() && canRecruitHero && !startupTown->visitingHero)
{
tasks.push_back(Goals::sptr(Goals::RecruitHero()));
}
if(tasks.empty() && towns.size())
{
for(const CGTownInstance * town : towns)
{
if(town->garrisonHero && town->garrisonHero->movement)
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(town, nullptr).setpriority(0.0001f)));
}
}
return tasks;
}

View File

@ -1,5 +1,5 @@
/* /*
* Goals.h, part of VCMI engine * RecruitHeroBehavior.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
@ -23,15 +23,3 @@ public:
virtual Goals::TGoalVec getTasks() override; virtual Goals::TGoalVec getTasks() override;
virtual std::string toString() const override; virtual std::string toString() const override;
}; };
class StartupBehavior : public Behavior
{
public:
StartupBehavior()
{
}
virtual Goals::TGoalVec getTasks() override;
virtual std::string toString() const override;
};

View File

@ -0,0 +1,178 @@
/*
* StartupBehavior.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 "StartupBehavior.h"
#include "../VCAI.h"
#include "../AIhelper.h"
#include "../AIUtility.h"
#include "../Goals/RecruitHero.h"
#include "../Goals/ExecuteHeroChain.h"
#include "../Goals/ExchangeSwapTownHeroes.h"
#include "lib/mapping/CMap.h" //for victory conditions
#include "lib/CPathfinder.h"
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<VCAI> ai;
extern FuzzyHelper * fh;
using namespace Goals;
std::string StartupBehavior::toString() const
{
return "Startup";
}
const AIPath getShortestPath(const CGTownInstance * town, const std::vector<AIPath> & paths)
{
auto shortestPath = *vstd::minElementByFun(paths, [town](const AIPath & path) -> float
{
if(town->garrisonHero && path.targetHero == town->garrisonHero.get())
return 1;
return path.movementCost();
});
return shortestPath;
}
const CGHeroInstance * getNearestHero(const CGTownInstance * town)
{
auto paths = ai->ah->getPathsToTile(town->visitablePos());
if(paths.empty())
return nullptr;
auto shortestPath = getShortestPath(town, paths);
if(shortestPath.nodes.size() > 1
|| shortestPath.targetHero->visitablePos().dist2dSQ(town->visitablePos()) > 4
|| town->garrisonHero && shortestPath.targetHero == town->garrisonHero.get())
return nullptr;
return shortestPath.targetHero;
}
bool needToRecruitHero(const CGTownInstance * startupTown)
{
if(!ai->canRecruitAnyHero(startupTown))
return false;
if(!startupTown->garrisonHero && !startupTown->visitingHero)
return false;
auto heroToCheck = startupTown->garrisonHero ? startupTown->garrisonHero.get() : startupTown->visitingHero.get();
auto paths = cb->getPathsInfo(heroToCheck);
for(auto obj : ai->visitableObjs)
{
if(obj->ID == Obj::RESOURCE && obj->subID == Res::GOLD
|| obj->ID == Obj::TREASURE_CHEST
|| obj->ID == Obj::CAMPFIRE
|| obj->ID == Obj::WATER_WHEEL)
{
auto path = paths->getPathInfo(obj->visitablePos());
if(path->accessible == CGPathNode::BLOCKVIS && path->turns != 255)
{
return true;
}
}
}
return false;
}
Goals::TGoalVec StartupBehavior::getTasks()
{
Goals::TGoalVec tasks;
auto towns = cb->getTownsInfo();
if(!towns.size())
return tasks;
const CGTownInstance * startupTown = towns.front();
bool canRecruitHero = needToRecruitHero(startupTown);
if(towns.size() > 1)
{
startupTown = *vstd::maxElementByFun(towns, [](const CGTownInstance * town) -> float
{
auto closestHero = getNearestHero(town);
if(!closestHero)
return 0;
return ai->ah->evaluateHero(closestHero);
});
}
auto closestHero = getNearestHero(startupTown);
if(closestHero)
{
if(!startupTown->visitingHero)
{
if(ai->ah->howManyReinforcementsCanGet(startupTown->getUpperArmy(), closestHero) > 200)
{
auto paths = ai->ah->getPathsToTile(startupTown->visitablePos());
if(paths.size())
{
auto path = getShortestPath(startupTown, paths);
tasks.push_back(Goals::sptr(Goals::ExecuteHeroChain(path, startupTown).setpriority(100)));
}
}
}
else
{
auto visitingHero = startupTown->visitingHero.get();
auto visitingHeroScore = ai->ah->evaluateHero(visitingHero);
if(startupTown->garrisonHero)
{
auto garrisonHero = startupTown->garrisonHero.get();
auto garrisonHeroScore = ai->ah->evaluateHero(garrisonHero);
if(visitingHeroScore > garrisonHeroScore
|| ai->ah->getHeroRole(garrisonHero) == HeroRole::SCOUT && ai->ah->getHeroRole(visitingHero) == HeroRole::MAIN)
{
if(canRecruitHero || ai->ah->howManyReinforcementsCanGet(visitingHero, garrisonHero) > 200)
{
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(startupTown, visitingHero).setpriority(100)));
}
}
else if(ai->ah->howManyReinforcementsCanGet(garrisonHero, visitingHero) > 200)
{
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(startupTown, garrisonHero).setpriority(100)));
}
}
else if(canRecruitHero)
{
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(startupTown, visitingHero).setpriority(100)));
}
}
}
if(tasks.empty() && canRecruitHero && !startupTown->visitingHero)
{
tasks.push_back(Goals::sptr(Goals::RecruitHero()));
}
if(tasks.empty() && towns.size())
{
for(const CGTownInstance * town : towns)
{
if(town->garrisonHero && town->garrisonHero->movement)
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(town, nullptr).setpriority(0.0001f)));
}
}
return tasks;
}

View File

@ -0,0 +1,26 @@
/*
* StartupBehavior.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 "lib/VCMI_Lib.h"
#include "Behavior.h"
#include "../AIUtility.h"
class StartupBehavior : public Behavior
{
public:
StartupBehavior()
{
}
virtual Goals::TGoalVec getTasks() override;
virtual std::string toString() const override;
};

View File

@ -47,6 +47,7 @@ set(VCAI_SRCS
Goals/FindObj.cpp Goals/FindObj.cpp
Goals/CompleteQuest.cpp Goals/CompleteQuest.cpp
Goals/ExecuteHeroChain.cpp Goals/ExecuteHeroChain.cpp
Goals/ExchangeSwapTownHeroes.cpp
Engine/Nullkiller.cpp Engine/Nullkiller.cpp
Engine/PriorityEvaluator.cpp Engine/PriorityEvaluator.cpp
Engine/DangerHitMapAnalyzer.cpp Engine/DangerHitMapAnalyzer.cpp
@ -54,6 +55,7 @@ set(VCAI_SRCS
Behaviors/CaptureObjectsBehavior.cpp Behaviors/CaptureObjectsBehavior.cpp
Behaviors/RecruitHeroBehavior.cpp Behaviors/RecruitHeroBehavior.cpp
Behaviors/BuyArmyBehavior.cpp Behaviors/BuyArmyBehavior.cpp
Behaviors/StartupBehavior.cpp
main.cpp main.cpp
VCAI.cpp VCAI.cpp
) )
@ -110,6 +112,7 @@ set(VCAI_HEADERS
Goals/FindObj.h Goals/FindObj.h
Goals/CompleteQuest.h Goals/CompleteQuest.h
Goals/ExecuteHeroChain.h Goals/ExecuteHeroChain.h
Goals/ExchangeSwapTownHeroes.h
Goals/Goals.h Goals/Goals.h
Engine/Nullkiller.h Engine/Nullkiller.h
Engine/PriorityEvaluator.h Engine/PriorityEvaluator.h
@ -118,6 +121,7 @@ set(VCAI_HEADERS
Behaviors/CaptureObjectsBehavior.h Behaviors/CaptureObjectsBehavior.h
Behaviors/RecruitHeroBehavior.h Behaviors/RecruitHeroBehavior.h
Behaviors/BuyArmyBehavior.h Behaviors/BuyArmyBehavior.h
Behaviors/StartupBehavior.h
VCAI.h VCAI.h
) )

View File

@ -1,3 +1,12 @@
/*
* DangerHitMapAnalyzer.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 "StdInc.h"
#include "DangerHitMapAnalyzer.h" #include "DangerHitMapAnalyzer.h"
@ -62,4 +71,4 @@ uint64_t DangerHitMapAnalyzer::enemyCanKillOurHeroesAlongThePath(const AIPath &
return info.fastestDanger.turn <= turn && !isSafeToVisit(path.targetHero, path.heroArmy, info.fastestDanger.danger) return info.fastestDanger.turn <= turn && !isSafeToVisit(path.targetHero, path.heroArmy, info.fastestDanger.danger)
|| info.maximumDanger.turn <= turn && !isSafeToVisit(path.targetHero, path.heroArmy, info.maximumDanger.danger); || info.maximumDanger.turn <= turn && !isSafeToVisit(path.targetHero, path.heroArmy, info.maximumDanger.danger);
} }

View File

@ -1,3 +1,12 @@
/*
* DangerHitMapAnalyzer.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 #pragma once
#include "../VCAI.h" #include "../VCAI.h"
@ -35,4 +44,4 @@ private:
public: public:
void updateHitMap(); void updateHitMap();
uint64_t enemyCanKillOurHeroesAlongThePath(const AIPath & path) const; uint64_t enemyCanKillOurHeroesAlongThePath(const AIPath & path) const;
}; };

View File

@ -1,3 +1,12 @@
/*
* Nullkiller.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 "StdInc.h"
#include "Nullkiller.h" #include "Nullkiller.h"
#include "../VCAI.h" #include "../VCAI.h"
@ -5,6 +14,7 @@
#include "../Behaviors/CaptureObjectsBehavior.h" #include "../Behaviors/CaptureObjectsBehavior.h"
#include "../Behaviors/RecruitHeroBehavior.h" #include "../Behaviors/RecruitHeroBehavior.h"
#include "../Behaviors/BuyArmyBehavior.h" #include "../Behaviors/BuyArmyBehavior.h"
#include "../Behaviors/StartupBehavior.h"
#include "../Goals/Invalid.h" #include "../Goals/Invalid.h"
extern boost::thread_specific_ptr<CCallback> cb; extern boost::thread_specific_ptr<CCallback> cb;
@ -122,4 +132,4 @@ void Nullkiller::makeTurn()
return; return;
} }
} }
} }

View File

@ -1,3 +1,12 @@
/*
* Nullkiller.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 #pragma once
#include "PriorityEvaluator.h" #include "PriorityEvaluator.h"
@ -27,4 +36,4 @@ private:
void updateAiState(); void updateAiState();
Goals::TSubgoal choseBestTask(std::shared_ptr<Behavior> behavior) const; Goals::TSubgoal choseBestTask(std::shared_ptr<Behavior> behavior) const;
Goals::TSubgoal choseBestTask(Goals::TGoalVec & tasks) const; Goals::TSubgoal choseBestTask(Goals::TGoalVec & tasks) const;
}; };

View File

@ -1,11 +1,11 @@
/* /*
* Fuzzy.cpp, part of VCMI engine * PriorityEvaluator.cpp, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
* License: GNU General Public License v2.0 or later * License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder * Full text of license available in license.txt file, in main folder
* *
*/ */
#include "StdInc.h" #include "StdInc.h"
#include "PriorityEvaluator.h" #include "PriorityEvaluator.h"
@ -46,7 +46,7 @@ PriorityEvaluator::~PriorityEvaluator()
void PriorityEvaluator::initVisitTile() void PriorityEvaluator::initVisitTile()
{ {
auto file = CResourceHandler::get()->load(ResourceID("config/ai-priorities.txt"))->readAll(); auto file = CResourceHandler::get()->load(ResourceID("config/ai/object-priorities.txt"))->readAll();
std::string str = std::string((char *)file.first.get(), file.second); std::string str = std::string((char *)file.first.get(), file.second);
engine = fl::FllImporter().fromString(str); engine = fl::FllImporter().fromString(str);
armyLossPersentageVariable = engine->getInputVariable("armyLoss"); armyLossPersentageVariable = engine->getInputVariable("armyLoss");

View File

@ -1,11 +1,11 @@
/* /*
* Fuzzy.h, part of VCMI engine * PriorityEvaluator.h, part of VCMI engine
* *
* Authors: listed in file AUTHORS in main folder * Authors: listed in file AUTHORS in main folder
* *
* License: GNU General Public License v2.0 or later * License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder * Full text of license available in license.txt file, in main folder
* *
*/ */
#pragma once #pragma once
#include "fl/Headers.h" #include "fl/Headers.h"

View File

@ -0,0 +1,81 @@
/*
* ExchangeSwapTownHeroes.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 "ExchangeSwapTownHeroes.h"
#include "ExecuteHeroChain.h"
#include "../VCAI.h"
#include "../FuzzyHelper.h"
#include "../AIhelper.h"
#include "../../../lib/mapping/CMap.h" //for victory conditions
#include "../../../lib/CPathfinder.h"
#include "../Engine/Nullkiller.h"
extern boost::thread_specific_ptr<CCallback> cb;
extern boost::thread_specific_ptr<VCAI> ai;
extern FuzzyHelper * fh;
using namespace Goals;
ExchangeSwapTownHeroes::ExchangeSwapTownHeroes(const CGTownInstance * town, const CGHeroInstance * garrisonHero)
:CGoal(Goals::EXCHANGE_SWAP_TOWN_HEROES), town(town), garrisonHero(garrisonHero)
{
}
std::string ExchangeSwapTownHeroes::name() const
{
return "Exchange and swap heroes of " + town->name;
}
std::string ExchangeSwapTownHeroes::completeMessage() const
{
return "Exchange and swap heroes of " + town->name + " compelete";
}
bool ExchangeSwapTownHeroes::operator==(const ExchangeSwapTownHeroes & other) const
{
return town == other.town;
}
TSubgoal ExchangeSwapTownHeroes::whatToDoToAchieve()
{
return iAmElementar();
}
void ExchangeSwapTownHeroes::accept(VCAI * ai)
{
if(!garrisonHero)
{
if(!town->garrisonHero)
throw cannotFulfillGoalException("Invalid configuration. There is no hero in town garrison.");
cb->swapGarrisonHero(town);
ai->buildArmyIn(town);
ai->nullkiller->unlockHero(town->visitingHero.get());
logAi->debug("Extracted hero %s from garrison of %s", town->visitingHero->name, town->name);
return;
}
if(town->visitingHero && town->visitingHero.get() != garrisonHero)
cb->swapGarrisonHero(town);
ai->moveHeroToTile(town->visitablePos(), garrisonHero);
cb->swapGarrisonHero(town); // selected hero left in garrison with strongest army
ai->nullkiller->lockHero(town->garrisonHero.get());
if(town->visitingHero)
{
ai->nullkiller->unlockHero(town->visitingHero.get());
makePossibleUpgrades(town->visitingHero);
}
logAi->debug("Put hero %s to garrison of %s", town->garrisonHero->name, town->name);
}

View File

@ -0,0 +1,36 @@
/*
* ExchangeSwapTownHeroes.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"
namespace Goals
{
class DLL_EXPORT ExchangeSwapTownHeroes : public CGoal<ExchangeSwapTownHeroes>
{
private:
const CGTownInstance * town;
const CGHeroInstance * garrisonHero;
public:
ExchangeSwapTownHeroes(const CGTownInstance * town, const CGHeroInstance * garrisonHero = nullptr);
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
void accept(VCAI * ai) override;
std::string name() const override;
std::string completeMessage() const override;
virtual bool operator==(const ExchangeSwapTownHeroes & other) const override;
};
}

View File

@ -117,61 +117,4 @@ std::string ExecuteHeroChain::name() const
std::string ExecuteHeroChain::completeMessage() const std::string ExecuteHeroChain::completeMessage() const
{ {
return "Hero chain completed"; return "Hero chain completed";
}
ExchangeSwapTownHeroes::ExchangeSwapTownHeroes(const CGTownInstance * town, const CGHeroInstance * garrisonHero)
:CGoal(Goals::EXCHANGE_SWAP_TOWN_HEROES), town(town), garrisonHero(garrisonHero)
{
}
std::string ExchangeSwapTownHeroes::name() const
{
return "Exchange and swap heroes of " + town->name;
}
std::string ExchangeSwapTownHeroes::completeMessage() const
{
return "Exchange and swap heroes of " + town->name + " compelete";
}
bool ExchangeSwapTownHeroes::operator==(const ExchangeSwapTownHeroes & other) const
{
return town == other.town;
}
TSubgoal ExchangeSwapTownHeroes::whatToDoToAchieve()
{
return iAmElementar();
}
void ExchangeSwapTownHeroes::accept(VCAI * ai)
{
if(!garrisonHero)
{
if(!town->garrisonHero)
throw cannotFulfillGoalException("Invalid configuration. There is no hero in town garrison.");
cb->swapGarrisonHero(town);
ai->buildArmyIn(town);
ai->nullkiller->unlockHero(town->visitingHero.get());
logAi->debug("Extracted hero %s from garrison of %s", town->visitingHero->name, town->name);
return;
}
if(town->visitingHero && town->visitingHero.get() != garrisonHero)
cb->swapGarrisonHero(town);
ai->moveHeroToTile(town->visitablePos(), garrisonHero);
cb->swapGarrisonHero(town); // selected hero left in garrison with strongest army
ai->nullkiller->lockHero(town->garrisonHero.get());
if(town->visitingHero)
{
ai->nullkiller->unlockHero(town->visitingHero.get());
makePossibleUpgrades(town->visitingHero);
}
logAi->debug("Put hero %s to garrison of %s", town->garrisonHero->name, town->name);
} }

View File

@ -33,25 +33,4 @@ namespace Goals
std::string completeMessage() const override; std::string completeMessage() const override;
virtual bool operator==(const ExecuteHeroChain & other) const override; virtual bool operator==(const ExecuteHeroChain & other) const override;
}; };
class DLL_EXPORT ExchangeSwapTownHeroes : public CGoal<ExchangeSwapTownHeroes>
{
private:
const CGTownInstance * town;
const CGHeroInstance * garrisonHero;
public:
ExchangeSwapTownHeroes(const CGTownInstance * town, const CGHeroInstance * garrisonHero = nullptr);
TGoalVec getAllPossibleSubgoals() override
{
return TGoalVec();
}
TSubgoal whatToDoToAchieve() override;
void accept(VCAI * ai) override;
std::string name() const override;
std::string completeMessage() const override;
virtual bool operator==(const ExchangeSwapTownHeroes & other) const override;
};
} }