浏览代码

TurnInfo: implement internal bonus cache for most used bonuses

Bonus system even with caching add too big overhead so we'll only use it once for these bonuses.
Still I'm like it to be transparent for external code so it's a bit hacky code.
ArseniyShestakov 10 年之前
父节点
当前提交
5ae6225ebc
共有 2 个文件被更改,包括 50 次插入0 次删除
  1. 36 0
      lib/CPathfinder.cpp
  2. 14 0
      lib/CPathfinder.h

+ 36 - 0
lib/CPathfinder.cpp

@@ -709,6 +709,21 @@ bool CPathfinder::addTeleportWhirlpool(const CGWhirlpool * obj) const
 	return options.useTeleportWhirlpool && hlp->hasBonusOfType(Bonus::WHIRLPOOL_PROTECTION) && obj;
 }
 
+TurnInfo::BonusCache::BonusCache(TBonusListPtr bl)
+{
+	noTerrainPenalty.reserve(ETerrainType::ROCK);
+	for(int i = 0; i < ETerrainType::ROCK; i++)
+	{
+		noTerrainPenalty.push_back(bl->getFirst(Selector::type(Bonus::NO_TERRAIN_PENALTY).And(Selector::subtype(i))));
+	}
+
+	freeShipBoarding = bl->getFirst(Selector::type(Bonus::FREE_SHIP_BOARDING));
+	flyingMovement = bl->getFirst(Selector::type(Bonus::FLYING_MOVEMENT));
+	flyingMovementVal = bl->valOfBonuses(Selector::type(Bonus::FLYING_MOVEMENT));
+	waterWalking = bl->getFirst(Selector::type(Bonus::WATER_WALKING));
+	waterWalkingVal = bl->valOfBonuses(Selector::type(Bonus::WATER_WALKING));
+}
+
 TurnInfo::TurnInfo(const CGHeroInstance * Hero, const int turn)
 	: hero(Hero), maxMovePointsLand(-1), maxMovePointsWater(-1)
 {
@@ -716,6 +731,7 @@ TurnInfo::TurnInfo(const CGHeroInstance * Hero, const int turn)
 	cachingStr << "days_" << turn;
 
 	bonuses = hero->getAllBonuses(Selector::days(turn), nullptr, nullptr, cachingStr.str());
+	bonusCache = make_unique<BonusCache>(bonuses);
 }
 
 bool TurnInfo::isLayerAvailable(const EPathfindingLayer layer) const
@@ -740,11 +756,31 @@ bool TurnInfo::isLayerAvailable(const EPathfindingLayer layer) const
 
 bool TurnInfo::hasBonusOfType(Bonus::BonusType type, int subtype) const
 {
+	switch(type)
+	{
+	case Bonus::FREE_SHIP_BOARDING:
+		return bonusCache->freeShipBoarding;
+	case Bonus::FLYING_MOVEMENT:
+		return bonusCache->flyingMovement;
+	case Bonus::WATER_WALKING:
+		return bonusCache->waterWalking;
+	case Bonus::NO_TERRAIN_PENALTY:
+		return bonusCache->noTerrainPenalty[subtype];
+	}
+
 	return bonuses->getFirst(Selector::type(type).And(Selector::subtype(subtype)));
 }
 
 int TurnInfo::valOfBonuses(Bonus::BonusType type, int subtype) const
 {
+	switch(type)
+	{
+	case Bonus::FLYING_MOVEMENT:
+		return bonusCache->flyingMovementVal;
+	case Bonus::WATER_WALKING:
+		return bonusCache->waterWalkingVal;
+	}
+
 	return bonuses->valOfBonuses(Selector::type(type).And(Selector::subtype(subtype)));
 }
 

+ 14 - 0
lib/CPathfinder.h

@@ -209,6 +209,20 @@ private:
 
 struct DLL_LINKAGE TurnInfo
 {
+	/// This is certainly not the best design ever and certainly can be improved
+	/// Unfortunately for pathfinder that do hundreds of thousands calls onus system add too big overhead
+	struct BonusCache {
+		std::vector<bool> noTerrainPenalty;
+		bool freeShipBoarding;
+		bool flyingMovement;
+		int flyingMovementVal;
+		bool waterWalking;
+		int waterWalkingVal;
+
+		BonusCache(TBonusListPtr bonusList);
+	};
+	unique_ptr<BonusCache> bonusCache;
+
 	const CGHeroInstance * hero;
 	TBonusListPtr bonuses;
 	mutable int maxMovePointsLand;