mirror of
https://github.com/vcmi/vcmi.git
synced 2026-06-19 22:57:37 +02:00
AIhelper should be owned by AI instance.
This commit is contained in:
@@ -13,8 +13,6 @@
|
||||
#include "ResourceManager.h"
|
||||
#include "BuildingManager.h"
|
||||
|
||||
boost::thread_specific_ptr<AIhelper> ah;
|
||||
|
||||
AIhelper::AIhelper()
|
||||
{
|
||||
resourceManager.reset(new ResourceManager());
|
||||
|
||||
@@ -27,11 +27,9 @@ class DLL_EXPORT AIhelper : public IResourceManager, public IBuildingManager
|
||||
friend class VCAI;
|
||||
friend struct SetGlobalState; //mess?
|
||||
|
||||
//members are thread_specific. AIhelper is global
|
||||
std::shared_ptr<ResourceManager> resourceManager;
|
||||
std::shared_ptr<BuildingManager> buildingManager;
|
||||
//TODO: vector<IAbstractManager>
|
||||
std::shared_ptr<VCAI> ai;
|
||||
public:
|
||||
AIhelper();
|
||||
~AIhelper();
|
||||
|
||||
+15
-16
@@ -21,7 +21,6 @@
|
||||
|
||||
extern boost::thread_specific_ptr<CCallback> cb;
|
||||
extern boost::thread_specific_ptr<VCAI> ai;
|
||||
extern boost::thread_specific_ptr<AIhelper> ah;
|
||||
extern FuzzyHelper * fh;
|
||||
|
||||
using namespace Goals;
|
||||
@@ -280,7 +279,7 @@ namespace Goals
|
||||
//TODO: calculate the actual cost of units instead
|
||||
TResources price;
|
||||
price[Res::GOLD] = value * 0.4f; //some approximate value
|
||||
return ah->whatToDo(price, iAmElementar()); //buy right now or gather resources
|
||||
return ai->ah->whatToDo(price, iAmElementar()); //buy right now or gather resources
|
||||
}
|
||||
std::string BuyArmy::completeMessage() const
|
||||
{
|
||||
@@ -924,7 +923,7 @@ TSubgoal RecruitHero::whatToDoToAchieve()
|
||||
|
||||
TResources res;
|
||||
res[Res::GOLD] = GameConstants::HERO_GOLD_COST;
|
||||
return ah->whatToDo(res, iAmElementar()); //either buy immediately, or collect res
|
||||
return ai->ah->whatToDo(res, iAmElementar()); //either buy immediately, or collect res
|
||||
}
|
||||
|
||||
bool Goals::RecruitHero::operator==(AbstractGoal & g)
|
||||
@@ -1058,7 +1057,7 @@ TSubgoal BuildThis::whatToDoToAchieve()
|
||||
case EBuildingState::NO_RESOURCES:
|
||||
{
|
||||
auto res = town->town->buildings.at(BuildingID(bid))->resources;
|
||||
return ah->whatToDo(res, iAmElementar()); //realize immediately or gather resources
|
||||
return ai->ah->whatToDo(res, iAmElementar()); //realize immediately or gather resources
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1142,7 +1141,7 @@ TGoalVec Goals::CollectRes::getAllPossibleSubgoals()
|
||||
}
|
||||
for (auto obj : ourObjs)
|
||||
{
|
||||
auto pos = obj->visitablePos();
|
||||
auto pos = obj->visitablePos();
|
||||
if (ai->isTileNotReserved(h, pos)) //further decomposition and evaluation will be handled by VisitObj
|
||||
ret.push_back(sptr(Goals::VisitObj(obj->id.getNum()).sethero(h).setisAbstract(true)));
|
||||
}
|
||||
@@ -1215,7 +1214,7 @@ TSubgoal Goals::CollectRes::whatToDoToTrade()
|
||||
int toGive = -1, toReceive = -1;
|
||||
m->getOffer(i, resID, toGive, toReceive, EMarketMode::RESOURCE_RESOURCE);
|
||||
assert(toGive > 0 && toReceive > 0);
|
||||
howManyCanWeBuy += toReceive * (ah->freeResources()[i] / toGive);
|
||||
howManyCanWeBuy += toReceive * (ai->ah->freeResources()[i] / toGive);
|
||||
}
|
||||
|
||||
if (howManyCanWeBuy >= value)
|
||||
@@ -1296,7 +1295,7 @@ TSubgoal GatherTroops::whatToDoToAchieve()
|
||||
{
|
||||
for(auto type : creature.second)
|
||||
{
|
||||
if(type == objid && ah->freeResources().canAfford(VLC->creh->creatures[type]->cost))
|
||||
if(type == objid && ai->ah->freeResources().canAfford(VLC->creh->creatures[type]->cost))
|
||||
dwellings.push_back(d);
|
||||
}
|
||||
}
|
||||
@@ -1438,19 +1437,19 @@ TGoalVec Goals::Build::getAllPossibleSubgoals()
|
||||
for (const CGTownInstance * t : cb->getTownsInfo())
|
||||
{
|
||||
//start fresh with every town
|
||||
ah->getBuildingOptions(t);
|
||||
auto ib = ah->immediateBuilding();
|
||||
ai->ah->getBuildingOptions(t);
|
||||
auto ib = ai->ah->immediateBuilding();
|
||||
if (ib.is_initialized())
|
||||
{
|
||||
ret.push_back(sptr(Goals::BuildThis(ib.get().bid, t).setpriority(2))); //prioritize buildings we can build quick
|
||||
}
|
||||
else //try build later
|
||||
{
|
||||
auto eb = ah->expensiveBuilding();
|
||||
auto eb = ai->ah->expensiveBuilding();
|
||||
if (eb.is_initialized())
|
||||
{
|
||||
auto pb = eb.get(); //gather resources for any we can't afford
|
||||
auto goal = ah->whatToDo(pb.price, sptr(Goals::BuildThis(pb.bid, t).setpriority(0.5)));
|
||||
auto goal = ai->ah->whatToDo(pb.price, sptr(Goals::BuildThis(pb.bid, t).setpriority(0.5)));
|
||||
ret.push_back(goal);
|
||||
}
|
||||
}
|
||||
@@ -1520,18 +1519,18 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
if (val)
|
||||
{
|
||||
auto goal = sptr(Goals::BuyArmy(t, val).sethero(hero));
|
||||
if (!ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice
|
||||
if (!ai->ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice
|
||||
ret.push_back(goal);
|
||||
}
|
||||
}
|
||||
//build dwelling
|
||||
//TODO: plan building over multiple turns?
|
||||
//auto bid = ah->canBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(Date::DAY_OF_WEEK));
|
||||
auto bid = ah->canBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 1);
|
||||
auto bid = ai->ah->canBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 1);
|
||||
if (bid.is_initialized())
|
||||
{
|
||||
auto goal = sptr(BuildThis(bid.get(), t).setpriority(priority));
|
||||
if (!ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice
|
||||
if (!ai->ah->containsObjective(goal)) //avoid loops caused by reserving same objective twice
|
||||
ret.push_back(goal);
|
||||
}
|
||||
}
|
||||
@@ -1580,7 +1579,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
for(auto & creatureID : creLevel.second)
|
||||
{
|
||||
auto creature = VLC->creh->creatures[creatureID];
|
||||
if(ah->freeResources().canAfford(creature->cost))
|
||||
if(ai->ah->freeResources().canAfford(creature->cost))
|
||||
objs.push_back(obj); //TODO: reserve resources?
|
||||
}
|
||||
}
|
||||
@@ -1600,7 +1599,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
||||
}
|
||||
}
|
||||
|
||||
if(ai->canRecruitAnyHero() && ah->freeGold() > GameConstants::HERO_GOLD_COST) //this is not stupid in early phase of game
|
||||
if(ai->canRecruitAnyHero() && ai->ah->freeGold() > GameConstants::HERO_GOLD_COST) //this is not stupid in early phase of game
|
||||
{
|
||||
if(auto t = ai->findTownWithTavern())
|
||||
{
|
||||
|
||||
+10
-11
@@ -35,7 +35,6 @@ const double SAFE_ATTACK_CONSTANT = 1.5;
|
||||
//one thread may be turn of AI and another will be handling a side effect for AI2
|
||||
boost::thread_specific_ptr<CCallback> cb;
|
||||
boost::thread_specific_ptr<VCAI> ai;
|
||||
extern boost::thread_specific_ptr<AIhelper> ah;
|
||||
|
||||
//std::map<int, std::map<int, int> > HeroView::infosCount;
|
||||
|
||||
@@ -49,10 +48,6 @@ struct SetGlobalState
|
||||
|
||||
ai.reset(AI);
|
||||
cb.reset(AI->myCb.get());
|
||||
if (!ah.get())
|
||||
ah.reset(new AIhelper());
|
||||
ah->setAI(AI); //does this make any sense?
|
||||
ah->setCB(cb.get());
|
||||
}
|
||||
~SetGlobalState()
|
||||
{
|
||||
@@ -100,10 +95,14 @@ VCAI::VCAI()
|
||||
makingTurn = nullptr;
|
||||
destinationTeleport = ObjectInstanceID();
|
||||
destinationTeleportPos = int3(-1);
|
||||
|
||||
ah = new AIhelper();
|
||||
ah->setAI(this);
|
||||
}
|
||||
|
||||
VCAI::~VCAI()
|
||||
{
|
||||
delete ah;
|
||||
LOG_TRACE(logAi);
|
||||
finish();
|
||||
}
|
||||
@@ -447,7 +446,7 @@ void VCAI::objectRemoved(const CGObjectInstance * obj)
|
||||
|
||||
for(auto goal : ultimateGoalsFromBasic)
|
||||
vstd::erase_if(goal.second, goalErasePredicate);
|
||||
|
||||
|
||||
//TODO: Find better way to handle hero boat removal
|
||||
if(auto hero = dynamic_cast<const CGHeroInstance *>(obj))
|
||||
{
|
||||
@@ -614,7 +613,7 @@ void VCAI::init(std::shared_ptr<CCallback> CB)
|
||||
myCb = CB;
|
||||
cbc = CB;
|
||||
|
||||
ah.reset(new AIhelper());
|
||||
ah->setCB(CB.get());
|
||||
|
||||
NET_EVENT_HANDLER; //sets ah->rm->cb
|
||||
playerID = *myCb->getMyColor();
|
||||
@@ -1494,7 +1493,7 @@ void VCAI::wander(HeroPtr h)
|
||||
//end of objs empty
|
||||
|
||||
if(dests.size()) //performance improvement
|
||||
{
|
||||
{
|
||||
Goals::TGoalVec targetObjectGoals;
|
||||
for(auto destination : dests)
|
||||
{
|
||||
@@ -3083,7 +3082,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
||||
case Obj::SCHOOL_OF_MAGIC:
|
||||
case Obj::SCHOOL_OF_WAR:
|
||||
{
|
||||
if (ah->freeGold() < 1000)
|
||||
if (ai->ah->freeGold() < 1000)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -3093,7 +3092,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
||||
break;
|
||||
case Obj::TREE_OF_KNOWLEDGE:
|
||||
{
|
||||
TResources myRes = ah->freeResources();
|
||||
TResources myRes = ai->ah->freeResources();
|
||||
if(myRes[Res::GOLD] < 2000 || myRes[Res::GEMS] < 10)
|
||||
return false;
|
||||
break;
|
||||
@@ -3108,7 +3107,7 @@ bool shouldVisit(HeroPtr h, const CGObjectInstance * obj)
|
||||
//TODO: only on request
|
||||
if(ai->myCb->getHeroesInfo().size() >= VLC->modh->settings.MAX_HEROES_ON_MAP_PER_PLAYER)
|
||||
return false;
|
||||
else if(ah->freeGold() < GameConstants::HERO_GOLD_COST)
|
||||
else if(ai->ah->freeGold() < GameConstants::HERO_GOLD_COST)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
struct QuestInfo;
|
||||
|
||||
class AIhelper;
|
||||
|
||||
class AIStatus
|
||||
{
|
||||
boost::mutex mx;
|
||||
@@ -114,6 +116,8 @@ public:
|
||||
|
||||
std::unique_ptr<boost::thread> makingTurn;
|
||||
|
||||
AIhelper * ah;
|
||||
|
||||
VCAI();
|
||||
virtual ~VCAI();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user