瀏覽代碼

Cache SectorMaps to evaluate multiple goals -> huge performance boost

DjWarmonger 10 年之前
父節點
當前提交
1c14dbf7b2
共有 6 個文件被更改,包括 27 次插入7 次删除
  1. 16 2
      AI/VCAI/Fuzzy.cpp
  2. 6 0
      AI/VCAI/Fuzzy.h
  3. 1 1
      AI/VCAI/VCAI.cpp
  4. 1 1
      AI/VCAI/VCAI.h
  5. 2 2
      lib/CGameInfoCallback.cpp
  6. 1 1
      lib/CGameInfoCallback.h

+ 16 - 2
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];
+}

+ 6 - 0
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 <HeroPtr, SectorMap> 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<AbstractGoal> chooseSolution (std::vector<shared_ptr<AbstractGoal>> & vec);
+
+	//optimization - use one SM for every hero call
+	SectorMap& getCachedSectorMap (HeroPtr h);
 };

+ 1 - 1
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

+ 1 - 1
AI/VCAI/VCAI.h

@@ -95,7 +95,7 @@ struct SectorMap
 	//std::vector<std::vector<std::vector<unsigned char>>> pathfinderSector;
 
 	std::map<int, Sector> infoOnSectors;
-	unique_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
+	shared_ptr<boost::multi_array<TerrainTile*, 3>> visibleTiles;
 
 	SectorMap();
 	SectorMap(HeroPtr h);

+ 2 - 2
lib/CGameInfoCallback.cpp

@@ -465,7 +465,7 @@ const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
 }
 
 //TODO: typedef?
-unique_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
+shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const
 {
 	assert(player.is_initialized());
 	auto team = getPlayerTeam(player.get());
@@ -486,7 +486,7 @@ unique_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisible
 				else
 					tileArray[x][y][z] = nullptr;
 			}
-	return make_unique<boost::multi_array<TerrainTile*, 3>>(tileArray);
+	return make_shared<boost::multi_array<TerrainTile*, 3>>(tileArray);
 }
 
 EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID )

+ 1 - 1
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<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const;
+	shared_ptr<boost::multi_array<TerrainTile*, 3>> CGameInfoCallback::getAllVisibleTiles() const;
 	bool isInTheMap(const int3 &pos) const;
 
 	//town