diff --git a/AI/VCAI/Fuzzy.cpp b/AI/VCAI/Fuzzy.cpp index d205e1153..1661c04b5 100644 --- a/AI/VCAI/Fuzzy.cpp +++ b/AI/VCAI/Fuzzy.cpp @@ -302,6 +302,8 @@ Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec) if (vec.empty()) //no possibilities found return sptr(Goals::Invalid()); + cachedSectorMaps.clear(); + //a trick to switch between heroes less often - calculatePaths is costly auto sortByHeroes = [](const Goals::TSubgoal & lhs, const Goals::TSubgoal & rhs) -> bool { @@ -480,8 +482,7 @@ float FuzzyHelper::evaluate (Goals::ClearWayTo & g) if (!g.hero.h) throw cannotFulfillGoalException("ClearWayTo called without hero!"); - SectorMap sm(g.hero); - int3 t = sm.firstTileToGet(g.hero, g.tile); + int3 t = getCachedSectorMap(g.hero).firstTileToGet(g.hero, g.tile); if (t.valid()) { @@ -530,3 +531,16 @@ void FuzzyHelper::setPriority (Goals::TSubgoal & g) { g->setpriority(g->accept(this)); //this enforces returned value is set } + +SectorMap& FuzzyHelper::getCachedSectorMap(HeroPtr h) +{ + auto it = cachedSectorMaps.find(h); + if (it != cachedSectorMaps.end()) + return it->second; + else + { + cachedSectorMaps[h] = SectorMap(h); + } + + return cachedSectorMaps[h]; +} diff --git a/AI/VCAI/Fuzzy.h b/AI/VCAI/Fuzzy.h index 67b77fa58..af5808301 100644 --- a/AI/VCAI/Fuzzy.h +++ b/AI/VCAI/Fuzzy.h @@ -15,6 +15,7 @@ class VCAI; class CArmedInstance; class CBank; +class SectorMap; class engineBase { @@ -54,6 +55,8 @@ class FuzzyHelper ~EvalVisitTile(); } vt; + std::map cachedSectorMaps; + public: enum RuleBlocks {BANK_DANGER, TACTICAL_ADVANTAGE, VISIT_TILE}; //blocks should be initialized in this order, which may be confusing :/ @@ -81,4 +84,7 @@ public: Goals::TSubgoal chooseSolution (Goals::TGoalVec vec); //shared_ptr chooseSolution (std::vector> & vec); + + //optimization - use one SM for every hero call + SectorMap& getCachedSectorMap (HeroPtr h); }; diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 620783e47..95dcfc9e4 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -2924,7 +2924,7 @@ bool SectorMap::markIfBlocked(ui8 &sec, crint3 pos) void SectorMap::update() { - visibleTiles = std::move(cb->getAllVisibleTiles()); + visibleTiles = cb->getAllVisibleTiles(); clear(); int curSector = 3; //0 is invisible, 1 is not explored diff --git a/AI/VCAI/VCAI.h b/AI/VCAI/VCAI.h index 851b4f74e..0f6ade208 100644 --- a/AI/VCAI/VCAI.h +++ b/AI/VCAI/VCAI.h @@ -95,7 +95,7 @@ struct SectorMap //std::vector>> pathfinderSector; std::map infoOnSectors; - unique_ptr> visibleTiles; + shared_ptr> visibleTiles; SectorMap(); SectorMap(HeroPtr h); diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index e11011635..b45be13bd 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -465,7 +465,7 @@ const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const } //TODO: typedef? -unique_ptr> CGameInfoCallback::getAllVisibleTiles() const +shared_ptr> CGameInfoCallback::getAllVisibleTiles() const { assert(player.is_initialized()); auto team = getPlayerTeam(player.get()); @@ -486,7 +486,7 @@ unique_ptr> CGameInfoCallback::getAllVisible else tileArray[x][y][z] = nullptr; } - return make_unique>(tileArray); + return make_shared>(tileArray); } EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID ) diff --git a/lib/CGameInfoCallback.h b/lib/CGameInfoCallback.h index 140c8d964..aa253a138 100644 --- a/lib/CGameInfoCallback.h +++ b/lib/CGameInfoCallback.h @@ -91,7 +91,7 @@ public: const CMapHeader * getMapHeader()const; int3 getMapSize() const; //returns size of map - z is 1 for one - level map and 2 for two level map const TerrainTile * getTile(int3 tile, bool verbose = true) const; - unique_ptr> CGameInfoCallback::getAllVisibleTiles() const; + shared_ptr> CGameInfoCallback::getAllVisibleTiles() const; bool isInTheMap(const int3 &pos) const; //town