浏览代码

CPathfinder: separate teleporter exits and neighbour tile code

This way code that handle real neighbour tiles is more readable and teleport exits don't have to go via all checks they ignore anyway.
ArseniyShestakov 10 年之前
父节点
当前提交
13c2b5e2d8
共有 2 个文件被更改,包括 41 次插入27 次删除
  1. 39 26
      lib/CGameState.cpp
  2. 2 1
      lib/CGameState.h

+ 39 - 26
lib/CGameState.cpp

@@ -3300,13 +3300,33 @@ void CPathfinder::initializeGraph()
 	}
 	}
 }
 }
 
 
-void CPathfinder::getNeighbours(const int3 &coord, bool noTeleportExcludes)
+void CPathfinder::getNeighbours(const int3 &coord)
 {
 {
+	neighbours.clear();
 	ct = &gs->map->getTile(coord);
 	ct = &gs->map->getTile(coord);
 // Will be needed for usage outside of calculatePaths
 // Will be needed for usage outside of calculatePaths
 //	if(!cp)
 //	if(!cp)
 //		cp = getNode(coord);
 //		cp = getNode(coord);
 
 
+	std::vector<int3> tiles;
+	gs->getNeighbours(*ct, coord, tiles, boost::logic::indeterminate, !cp->land);
+	sTileObj = ct->topVisitableObj(coord == CGHeroInstance::convertPosition(hero->pos, false));
+	if(sTileObj)
+	{
+		for(int3 tile: tiles)
+		{
+			if(canMoveBetween(tile, sTileObj->visitablePos()))
+				neighbours.push_back(tile);
+		}
+	}
+	else
+		vstd::concatenate(neighbours, tiles);
+}
+
+void CPathfinder::getTeleportExits(bool noTeleportExcludes)
+{
+	assert(sTileObj);
+
 	neighbours.clear();
 	neighbours.clear();
 	auto isAllowedTeleportEntrance = [&](const CGTeleport * obj) -> bool
 	auto isAllowedTeleportEntrance = [&](const CGTeleport * obj) -> bool
 	{
 	{
@@ -3328,7 +3348,6 @@ void CPathfinder::getNeighbours(const int3 &coord, bool noTeleportExcludes)
 		return false;
 		return false;
 	};
 	};
 
 
-	sTileObj = ct->topVisitableObj(coord == CGHeroInstance::convertPosition(hero->pos, false));
 	sTileTeleport = dynamic_cast<const CGTeleport *>(sTileObj);
 	sTileTeleport = dynamic_cast<const CGTeleport *>(sTileObj);
 	if(isAllowedTeleportEntrance(sTileTeleport))
 	if(isAllowedTeleportEntrance(sTileTeleport))
 	{
 	{
@@ -3339,19 +3358,6 @@ void CPathfinder::getNeighbours(const int3 &coord, bool noTeleportExcludes)
 				neighbours.push_back(obj->visitablePos());
 				neighbours.push_back(obj->visitablePos());
 		}
 		}
 	}
 	}
-
-	std::vector<int3> neighbour_tiles;
-	gs->getNeighbours(*ct, coord, neighbour_tiles, boost::logic::indeterminate, !cp->land);
-	if(sTileObj)
-	{
-		for(int3 neighbour_tile: neighbour_tiles)
-		{
-			if(canMoveBetween(neighbour_tile, sTileObj->visitablePos()))
-				neighbours.push_back(neighbour_tile);
-		}
-	}
-	else
-		vstd::concatenate(neighbours, neighbour_tiles);
 }
 }
 
 
 void CPathfinder::calculatePaths()
 void CPathfinder::calculatePaths()
@@ -3406,13 +3412,11 @@ void CPathfinder::calculatePaths()
 			dp = getNode(neighbour);
 			dp = getNode(neighbour);
 			dt = &gs->map->getTile(neighbour);
 			dt = &gs->map->getTile(neighbour);
 			destTopVisObjID = dt->topVisitableId();
 			destTopVisObjID = dt->topVisitableId();
-
 			useEmbarkCost = 0; //0 - usual movement; 1 - embark; 2 - disembark
 			useEmbarkCost = 0; //0 - usual movement; 1 - embark; 2 - disembark
 			const bool destIsGuardian = sourceGuardPosition == neighbour;
 			const bool destIsGuardian = sourceGuardPosition == neighbour;
 
 
-			dTileTeleport = dynamic_cast<const CGTeleport*>(dt->topVisitableObj());
 			if(!goodForLandSeaTransition()
 			if(!goodForLandSeaTransition()
-			   || (!canMoveBetween(cp->coord, dp->coord) && !CGTeleport::isConnected(sTileTeleport, dTileTeleport))
+			   || !canMoveBetween(cp->coord, dp->coord)
 			   || dp->accessible == CGPathNode::BLOCKED)
 			   || dp->accessible == CGPathNode::BLOCKED)
 			{
 			{
 				continue;
 				continue;
@@ -3423,10 +3427,6 @@ void CPathfinder::calculatePaths()
 				guardedSource = false;
 				guardedSource = false;
 
 
 			int cost = gs->getMovementCost(hero, cp->coord, dp->coord, flying, 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(CGTeleport::isConnected(sTileTeleport, dTileTeleport))
-				cost = 0;
-
 			int remains = movement - cost;
 			int remains = movement - cost;
 			if(useEmbarkCost)
 			if(useEmbarkCost)
 			{
 			{
@@ -3467,10 +3467,6 @@ void CPathfinder::calculatePaths()
 						return true; // For now we'll walways allos transit for teleports
 						return true; // For now we'll walways allos transit for teleports
 					if(useEmbarkCost && allowEmbarkAndDisembark)
 					if(useEmbarkCost && allowEmbarkAndDisembark)
 						return true;
 						return true;
-					if(gs->isTeleportEntrancePassable(dTileTeleport, hero->tempOwner))
-						return true; // Always add entry teleport with non-dummy channel
-					if(CGTeleport::isConnected(sTileTeleport, dTileTeleport))
-						return true; // Always add exit points of teleport
 					if(guardedDst && !guardedSource)
 					if(guardedDst && !guardedSource)
 						return true; // Can step into a hostile tile once
 						return true; // Can step into a hostile tile once
 
 
@@ -3481,6 +3477,23 @@ void CPathfinder::calculatePaths()
 					mq.push_back(dp);
 					mq.push_back(dp);
 			}
 			}
 		} //neighbours loop
 		} //neighbours loop
+
+		//just add all passable teleport exits
+		if(sTileObj)
+		{
+			getTeleportExits();
+			for(auto & neighbour : neighbours)
+			{
+				dp = getNode(neighbour);
+				if (dp->turns == 0xff)
+				{
+					dp->moveRemains = movement;
+					dp->turns = turn;
+					dp->theNodeBefore = cp;
+					mq.push_back(dp);
+				}
+			}
+		}
 	} //queue loop
 	} //queue loop
 }
 }
 
 

+ 2 - 1
lib/CGameState.h

@@ -308,7 +308,8 @@ private:
 	void initializeGraph();
 	void initializeGraph();
 	bool goodForLandSeaTransition(); //checks if current move will be between sea<->land. If so, checks it legality (returns false if movement is not possible) and sets useEmbarkCost
 	bool goodForLandSeaTransition(); //checks if current move will be between sea<->land. If so, checks it legality (returns false if movement is not possible) and sets useEmbarkCost
 
 
-	void getNeighbours(const int3 &coord, bool noTeleportExcludes = false);
+	void getNeighbours(const int3 &coord);
+	void getTeleportExits(bool noTeleportExcludes = false);
 
 
 	CGPathNode::EAccessibility evaluateAccessibility(const TerrainTile *tinfo) const;
 	CGPathNode::EAccessibility evaluateAccessibility(const TerrainTile *tinfo) const;
 	bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)
 	bool canMoveBetween(const int3 &a, const int3 &b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility)