Преглед изворни кода

Pathfinding: restore gamestate usage to avoid overhead

Also when possible pass TerrainTile pointers to getMovementCost instead of using getTile.
ArseniyShestakov пре 10 година
родитељ
комит
a1fe2ebc44
3 измењених фајлова са 24 додато и 20 уклоњено
  1. 22 18
      lib/CPathfinder.cpp
  2. 1 1
      lib/CPathfinder.h
  3. 1 1
      server/CGameHandler.cpp

+ 22 - 18
lib/CPathfinder.cpp

@@ -96,7 +96,7 @@ void CPathfinder::calculatePaths()
 		cp = pq.top();
 		pq.pop();
 		cp->locked = true;
-		ct = getTile(cp->coord);
+		ct = &gs->map->getTile(cp->coord);
 		ctObj = ct->topVisitableObj(isSourceInitialPosition());
 
 		int movement = cp->moveRemains, turn = cp->turns;
@@ -111,7 +111,7 @@ void CPathfinder::calculatePaths()
 		addNeighbours();
 		for(auto & neighbour : neighbours)
 		{
-			dt = getTile(neighbour);
+			dt = &gs->map->getTile(neighbour);
 			dtObj = dt->topVisitableObj();
 			for(ELayer i = ELayer::LAND; i <= ELayer::AIR; i.advance(1))
 			{
@@ -135,7 +135,7 @@ void CPathfinder::calculatePaths()
 					continue;
 
 				destAction = getDestAction();
-				int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, movement, hlp->getTurnInfo());
+				int cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, movement, hlp->getTurnInfo());
 				int remains = movement - cost;
 				if(destAction == CGPathNode::EMBARK || destAction == CGPathNode::DISEMBARK)
 				{
@@ -148,7 +148,7 @@ void CPathfinder::calculatePaths()
 					//occurs rarely, when hero with low movepoints tries to leave the road
 					hlp->updateTurnInfo(++turnAtNextTile);
 					int moveAtNextTile = hlp->getMaxMovePoints(i);
-					cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, moveAtNextTile, hlp->getTurnInfo()); //cost must be updated, movement points changed :(
+					cost = CPathfinderHelper::getMovementCost(hero, cp->coord, dp->coord, ct, dt, moveAtNextTile, hlp->getTurnInfo()); //cost must be updated, movement points changed :(
 					remains = moveAtNextTile - cost;
 				}
 
@@ -222,7 +222,7 @@ void CPathfinder::addTeleportExits()
 				auto pos = obj->getBlockedPos();
 				for(auto p : pos)
 				{
-					if(getTile(p)->topVisitableId() == obj->ID)
+					if(gs->map->getTile(p).topVisitableId() == obj->ID)
 						neighbours.push_back(p);
 				}
 			}
@@ -511,7 +511,7 @@ bool CPathfinder::isSourceGuarded() const
 	/// - Map start with hero on guarded tile
 	/// - Dimention door used
 	/// TODO: check what happen when there is several guards
-	if(guardingCreaturePosition(cp->coord) != int3(-1, -1, -1) && !isSourceInitialPosition())
+	if(gs->guardingCreaturePosition(cp->coord).valid() && !isSourceInitialPosition())
 	{
 		return true;
 	}
@@ -528,7 +528,7 @@ bool CPathfinder::isDestinationGuarded(const bool ignoreAccessibility) const
 {
 	/// isDestinationGuarded is exception needed for garrisons.
 	/// When monster standing behind garrison it's visitable and guarded at the same time.
-	if(guardingCreaturePosition(dp->coord).valid()
+	if(gs->guardingCreaturePosition(dp->coord).valid()
 		&& (ignoreAccessibility || dp->accessible == CGPathNode::BLOCKVIS))
 	{
 		return true;
@@ -539,7 +539,7 @@ bool CPathfinder::isDestinationGuarded(const bool ignoreAccessibility) const
 
 bool CPathfinder::isDestinationGuardian() const
 {
-	return guardingCreaturePosition(cp->coord) == dp->coord;
+	return gs->guardingCreaturePosition(cp->coord) == dp->coord;
 }
 
 void CPathfinder::initializeGraph()
@@ -558,7 +558,7 @@ void CPathfinder::initializeGraph()
 		{
 			for(pos.z=0; pos.z < out.sizes.z; ++pos.z)
 			{
-				const TerrainTile * tinfo = getTile(pos);
+				const TerrainTile * tinfo = &gs->map->getTile(pos);
 				switch(tinfo->terType)
 				{
 				case ETerrainType::ROCK:
@@ -893,7 +893,7 @@ void CPathfinderHelper::getNeighbours(const CMap * map, const TerrainTile & srct
 	}
 }
 
-int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & src, const int3 & dst, const int remainingMovePoints, const TurnInfo * ti, const bool checkLast)
+int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & src, const int3 & dst, const TerrainTile * ct, const TerrainTile * dt, const int remainingMovePoints, const TurnInfo * ti, const bool checkLast)
 {
 	if(src == dst) //same tile
 		return 0;
@@ -901,23 +901,27 @@ int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & sr
 	if(!ti)
 		ti = new TurnInfo(h);
 
-	auto s = h->cb->getTile(src), d = h->cb->getTile(dst);
+	if(ct == nullptr || dt == nullptr)
+	{
+		ct = h->cb->getTile(src);
+		dt = h->cb->getTile(dst);
+	}
 
 	/// TODO: by the original game rules hero shouldn't be affected by terrain penalty while flying.
 	/// Also flying movement only has penalty when player moving over blocked tiles.
 	/// So if you only have base flying with 40% penalty you can still ignore terrain penalty while having zero flying penalty.
-	int ret = h->getTileCost(*d, *s, ti);
+	int ret = h->getTileCost(*dt, *ct, ti);
 	/// Unfortunately this can't be implemented yet as server don't know when player flying and when he's not.
 	/// Difference in cost calculation on client and server is much worse than incorrect cost.
 	/// So this one is waiting till server going to use pathfinder rules for path validation.
 
-	if(d->blocked && ti->hasBonusOfType(Bonus::FLYING_MOVEMENT))
+	if(dt->blocked && ti->hasBonusOfType(Bonus::FLYING_MOVEMENT))
 	{
 		ret *= (100.0 + ti->valOfBonuses(Bonus::FLYING_MOVEMENT)) / 100.0;
 	}
-	else if(d->terType == ETerrainType::WATER)
+	else if(dt->terType == ETerrainType::WATER)
 	{
-		if(h->boat && s->hasFavourableWinds() && d->hasFavourableWinds()) //Favourable Winds
+		if(h->boat && ct->hasFavourableWinds() && dt->hasFavourableWinds()) //Favourable Winds
 			ret *= 0.666;
 		else if(!h->boat && ti->hasBonusOfType(Bonus::WATER_WALKING))
 		{
@@ -941,10 +945,10 @@ int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & sr
 	{
 		std::vector<int3> vec;
 		vec.reserve(8); //optimization
-		getNeighbours(h->cb->gameState()->map, *d, dst, vec, s->terType != ETerrainType::WATER, true);
+		getNeighbours(h->cb->gameState()->map, *dt, dst, vec, ct->terType != ETerrainType::WATER, true);
 		for(auto & elem : vec)
 		{
-			int fcost = getMovementCost(h, dst, elem, left, ti, false);
+			int fcost = getMovementCost(h, dst, elem, nullptr, nullptr, left, ti, false);
 			if(fcost <= left)
 				return ret;
 		}
@@ -955,7 +959,7 @@ int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & sr
 
 int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & dst)
 {
-	return getMovementCost(h, h->visitablePos(), dst, h->movement);
+	return getMovementCost(h, h->visitablePos(), dst, nullptr, nullptr, h->movement);
 }
 
 CGPathNode::CGPathNode()

+ 1 - 1
lib/CPathfinder.h

@@ -248,7 +248,7 @@ public:
 
 	static void getNeighbours(const CMap * map, const TerrainTile & srct, const int3 & tile, std::vector<int3> & vec, const boost::logic::tribool & onLand, const bool limitCoastSailing);
 
-	static int getMovementCost(const CGHeroInstance * h, const int3 & src, const int3 & dst, const int remainingMovePoints =- 1, const TurnInfo * ti = nullptr, const bool checkLast = true);
+	static int getMovementCost(const CGHeroInstance * h, const int3 & src, const int3 & dst, const TerrainTile * ct, const TerrainTile * dt, const int remainingMovePoints =- 1, const TurnInfo * ti = nullptr, const bool checkLast = true);
 	static int getMovementCost(const CGHeroInstance * h, const int3 & dst);
 
 private:

+ 1 - 1
server/CGameHandler.cpp

@@ -1781,7 +1781,7 @@ bool CGameHandler::moveHero( ObjectInstanceID hid, int3 dst, ui8 teleporting, bo
 	auto ti = new TurnInfo(h);
 	const bool canFly = ti->hasBonusOfType(Bonus::FLYING_MOVEMENT);
 	const bool canWalkOnSea = ti->hasBonusOfType(Bonus::WATER_WALKING);
-	const int cost = CPathfinderHelper::getMovementCost(h, h->getPosition(), hmpos, h->movement, ti);
+	const int cost = CPathfinderHelper::getMovementCost(h, h->getPosition(), hmpos, nullptr, nullptr, h->movement, ti);
 
 	//it's a rock or blocked and not visitable tile
 	//OR hero is on land and dest is water and (there is not present only one object - boat)