Sfoglia il codice sorgente

Some nontrivial optimizations based on profiling results:
- Movement bonuses will be calculated ONCE per pathfinder loop
- Goals will be sorted by hero to reduce number of calculatePaths calls

DjWarmonger 11 anni fa
parent
commit
a64df5718f
6 ha cambiato i file con 27 aggiunte e 12 eliminazioni
  1. 8 1
      AI/VCAI/Fuzzy.cpp
  2. 1 1
      AI/VCAI/VCAI.cpp
  3. 1 1
      CCallback.cpp
  4. 15 7
      lib/CGameState.cpp
  5. 1 1
      lib/CGameState.h
  6. 1 1
      server/CGameHandler.cpp

+ 8 - 1
AI/VCAI/Fuzzy.cpp

@@ -319,6 +319,13 @@ Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
 	if (vec.empty()) //no possibilities found
 		return sptr(Goals::Invalid());
 
+	//a trick to switch between heroes less often - calculatePaths is costly
+	auto sortByHeroes = [](const Goals::TSubgoal & lhs, const Goals::TSubgoal & rhs) -> bool
+	{
+		return lhs->hero.h < rhs->hero.h;
+	};
+	boost::sort (vec, sortByHeroes);
+
 	for (auto g : vec)
 	{
 		setPriority(g);
@@ -328,8 +335,8 @@ Goals::TSubgoal FuzzyHelper::chooseSolution (Goals::TGoalVec vec)
 	{
 		return lhs->priority < rhs->priority;
 	};
-
 	boost::sort (vec, compareGoals);
+
 	return vec.back();
 }
 

+ 1 - 1
AI/VCAI/VCAI.cpp

@@ -1252,6 +1252,7 @@ bool VCAI::canRecruitAnyHero (const CGTownInstance * t) const
 
 void VCAI::wander(HeroPtr h)
 {
+	cb->setSelection(*h);
 	//unclaim objects that are now dangerous for us
 	auto reservedObjsSetCopy = reservedHeroesMap[h];
 	for (auto obj : reservedObjsSetCopy)
@@ -2189,7 +2190,6 @@ void VCAI::performTypicalActions()
 	{
         logAi->debugStream() << boost::format("Looking into %s, MP=%d") % h->name.c_str() % h->movement;
 		makePossibleUpgrades(*h);
-		cb->setSelection(*h);
 		try
 		{
 			wander(h);

+ 1 - 1
CCallback.cpp

@@ -353,7 +353,7 @@ bool CCallback::getPath2( int3 dest, CGPath &ret )
 
 int CCallback::getMovementCost(const CGHeroInstance * hero, int3 dest)
 {
-	return gs->getMovementCost(hero, hero->visitablePos(), dest, hero->movement);
+	return gs->getMovementCost(hero, hero->visitablePos(), dest, hero->hasBonusOfType (Bonus::FLYING_MOVEMENT), hero->movement);
 }
 
 void CCallback::recalculatePaths()

+ 15 - 7
lib/CGameState.cpp

@@ -2127,7 +2127,7 @@ void CGameState::getNeighbours(const TerrainTile &srct, int3 tile, std::vector<i
 	}
 }
 
-int CGameState::getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, int remainingMovePoints, bool checkLast)
+int CGameState::getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, bool flying, int remainingMovePoints, bool checkLast)
 {
 	if(src == dest) //same tile
 		return 0;
@@ -2138,7 +2138,7 @@ int CGameState::getMovementCost(const CGHeroInstance *h, const int3 &src, const
 	//get basic cost
 	int ret = h->getTileCost(d,s);
 
-	if(d.blocked && h->hasBonusOfType(Bonus::FLYING_MOVEMENT))
+	if(d.blocked && flying)
 	{
 		bool freeFlying = h->getBonusesCount(Selector::typeSubtype(Bonus::FLYING_MOVEMENT, 1)) > 0;
 
@@ -2174,7 +2174,7 @@ int CGameState::getMovementCost(const CGHeroInstance *h, const int3 &src, const
         getNeighbours(d, dest, vec, s.terType != ETerrainType::WATER, true);
 		for(auto & elem : vec)
 		{
-			int fcost = getMovementCost(h,dest,elem,left,false);
+			int fcost = getMovementCost(h,dest, elem, flying, left, false);
 			if(fcost <= left)
 			{
 				return ret;
@@ -3369,6 +3369,14 @@ void CPathfinder::calculatePaths(int3 src /*= int3(-1,-1,-1)*/, int movement /*=
 		src = hero->getPosition(false);
 	if(movement < 0)
 		movement = hero->movement;
+	bool flying = hero->hasBonusOfType(Bonus::FLYING_MOVEMENT);
+	int maxMovePointsLand = hero->maxMovePoints(true);
+	int maxMovePointsWater = hero->maxMovePoints(false);
+
+	auto maxMovePoints = [&](CGPathNode *cp) -> int
+	{
+		return cp->land ? maxMovePointsLand : maxMovePointsWater;
+	};
 
 	out.hero = hero;
 	out.hpos = src;
@@ -3402,7 +3410,7 @@ void CPathfinder::calculatePaths(int3 src /*= int3(-1,-1,-1)*/, int movement /*=
 		int movement = cp->moveRemains, turn = cp->turns;
 		if(!movement)
 		{
-			movement = hero->maxMovePoints(cp->land);
+			movement = maxMovePoints(cp);
 			turn++;
 		}
 
@@ -3454,7 +3462,7 @@ void CPathfinder::calculatePaths(int3 src /*= int3(-1,-1,-1)*/, int movement /*=
             if(cp->accessible == CGPathNode::VISITABLE && guardedSource && cp->theNodeBefore->land && ct->topVisitableId() == Obj::BOAT)
 				guardedSource = false;
 
-			int cost = gs->getMovementCost(hero, cp->coord, dp->coord, movement);
+			int cost = gs->getMovementCost(hero, cp->coord, dp->coord, flying, movement);
 
 			//special case -> moving from src Subterranean gate to dest gate -> it's free
 			if(subterraneanEntry && destTopVisObjID == Obj::SUBTERRANEAN_GATE && cp->coord.z != dp->coord.z)
@@ -3472,8 +3480,8 @@ void CPathfinder::calculatePaths(int3 src /*= int3(-1,-1,-1)*/, int movement /*=
 			{
 				//occurs rarely, when hero with low movepoints tries to leave the road
 				turnAtNextTile++;
-				int moveAtNextTile = hero->maxMovePoints(cp->land);
-				cost = gs->getMovementCost(hero, cp->coord, dp->coord, moveAtNextTile); //cost must be updated, movement points changed :(
+				int moveAtNextTile = maxMovePoints(cp);
+				cost = gs->getMovementCost(hero, cp->coord, dp->coord, flying, moveAtNextTile); //cost must be updated, movement points changed :(
 				remains = moveAtNextTile - cost;
 			}
 

+ 1 - 1
lib/CGameState.h

@@ -451,7 +451,7 @@ public:
 	bool isVisible(const CGObjectInstance *obj, boost::optional<PlayerColor> player);
 
 	void getNeighbours(const TerrainTile &srct, int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand, bool limitCoastSailing);
-	int getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, int remainingMovePoints=-1, bool checkLast=true);
+	int getMovementCost(const CGHeroInstance *h, const int3 &src, const int3 &dest, bool flying, int remainingMovePoints=-1, bool checkLast=true);
 	int getDate(Date::EDateType mode=Date::DAY) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
 
 	// ----- getters, setters -----

+ 1 - 1
server/CGameHandler.cpp

@@ -1666,7 +1666,7 @@ bool CGameHandler::moveHero( ObjectInstanceID hid, int3 dst, ui8 teleporting, Pl
 	}
 
 	const TerrainTile t = *gs->getTile(hmpos);
-	const int cost = gs->getMovementCost(h, h->getPosition(), hmpos, h->movement);
+	const int cost = gs->getMovementCost(h, h->getPosition(), hmpos, h->hasBonusOfType(Bonus::FLYING_MOVEMENT), h->movement);
 	const int3 guardPos = gs->guardingCreaturePosition(hmpos);
 
 	const bool embarking = !h->boat && !t.visitableObjects.empty() && t.visitableObjects.back()->ID == Obj::BOAT;