diff --git a/AI/VCAI/AIhelper.cpp b/AI/VCAI/AIhelper.cpp index b769fbe1f..44e38c533 100644 --- a/AI/VCAI/AIhelper.cpp +++ b/AI/VCAI/AIhelper.cpp @@ -13,8 +13,6 @@ #include "ResourceManager.h" #include "BuildingManager.h" -boost::thread_specific_ptr ah; - AIhelper::AIhelper() { resourceManager.reset(new ResourceManager()); diff --git a/AI/VCAI/AIhelper.h b/AI/VCAI/AIhelper.h index 82bf83426..944ce53d3 100644 --- a/AI/VCAI/AIhelper.h +++ b/AI/VCAI/AIhelper.h @@ -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; std::shared_ptr buildingManager; //TODO: vector - std::shared_ptr ai; public: AIhelper(); ~AIhelper(); diff --git a/AI/VCAI/Goals.cpp b/AI/VCAI/Goals.cpp index 7abded806..6f04ea885 100644 --- a/AI/VCAI/Goals.cpp +++ b/AI/VCAI/Goals.cpp @@ -21,7 +21,6 @@ extern boost::thread_specific_ptr cb; extern boost::thread_specific_ptr ai; -extern boost::thread_specific_ptr 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(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(Date::DAY_OF_WEEK)); - auto bid = ah->canBuildAnyStructure(t, std::vector(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 1); + auto bid = ai->ah->canBuildAnyStructure(t, std::vector(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()) { diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index c2b226d16..924dedf51 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -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 cb; boost::thread_specific_ptr ai; -extern boost::thread_specific_ptr ah; //std::map > 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(obj)) { @@ -614,7 +613,7 @@ void VCAI::init(std::shared_ptr 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; } diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index a16c495d4..90be9119b 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -28,6 +28,8 @@ struct QuestInfo; +class AIhelper; + class AIStatus { boost::mutex mx; @@ -114,6 +116,8 @@ public: std::unique_ptr makingTurn; + AIhelper * ah; + VCAI(); virtual ~VCAI();