浏览代码

CPathsInfo: rework nodes multi_array allocation

ArseniyShestakov 10 年之前
父节点
当前提交
d76b2b7ca8
共有 2 个文件被更改,包括 47 次插入32 次删除
  1. 38 26
      lib/CPathfinder.cpp
  2. 9 6
      lib/CPathfinder.h

+ 38 - 26
lib/CPathfinder.cpp

@@ -566,14 +566,15 @@ void CPathfinder::initializeGraph()
 	auto updateNode = [&](int3 pos, ELayer layer, const TerrainTile * tinfo, bool blockNotAccessible)
 	{
 		auto node = out.getNode(pos, layer);
-		node->reset();
 
 		auto accessibility = evaluateAccessibility(pos, tinfo);
 		/// TODO: Probably this shouldn't be handled by initializeGraph
 		if(blockNotAccessible
 			&& (accessibility != CGPathNode::ACCESSIBLE || tinfo->terType == ETerrainType::WATER))
+		{
 			accessibility = CGPathNode::BLOCKED;
-		node->accessible = accessibility;
+		}
+		node->update(pos, layer, accessibility);
 	};
 
 	int3 pos;
@@ -823,8 +824,8 @@ int CPathfinderHelper::getMovementCost(const CGHeroInstance * h, const int3 & ds
 	return getMovementCost(h, h->visitablePos(), dst, h->movement);
 }
 
-CGPathNode::CGPathNode(int3 Coord, ELayer Layer)
-	: coord(Coord), layer(Layer)
+CGPathNode::CGPathNode()
+	: coord(int3(-1, -1, -1)), layer(ELayer::WRONG)
 {
 	reset();
 }
@@ -839,6 +840,19 @@ void CGPathNode::reset()
 	action = UNKNOWN;
 }
 
+void CGPathNode::update(const int3 & Coord, const ELayer Layer, const EAccessibility Accessible)
+{
+	if(layer == ELayer::WRONG)
+	{
+		coord = Coord;
+		layer = Layer;
+	}
+	else
+		reset();
+
+	accessible = Accessible;
+}
+
 bool CGPathNode::reachable() const
 {
 	return turns < 255;
@@ -870,63 +884,61 @@ CPathsInfo::CPathsInfo(const int3 & Sizes)
 {
 	hero = nullptr;
 	nodes.resize(boost::extents[sizes.x][sizes.y][sizes.z][ELayer::NUM_LAYERS]);
-	for(int i = 0; i < sizes.x; i++)
-		for(int j = 0; j < sizes.y; j++)
-			for(int z = 0; z < sizes.z; z++)
-				for(int l = 0; l < ELayer::NUM_LAYERS; l++)
-					nodes[i][j][z][l] = new CGPathNode(int3(i, j, z), static_cast<ELayer>(l));
 }
 
 CPathsInfo::~CPathsInfo()
 {
 }
 
-const CGPathNode * CPathsInfo::getPathInfo(const int3 & tile, const ELayer layer) const
+const CGPathNode * CPathsInfo::getPathInfo(const int3 & tile) const
 {
-	boost::unique_lock<boost::mutex> pathLock(pathMx);
+	assert(vstd::iswithin(tile.x, 0, sizes.x));
+	assert(vstd::iswithin(tile.y, 0, sizes.y));
+	assert(vstd::iswithin(tile.z, 0, sizes.z));
 
-	if(tile.x >= sizes.x || tile.y >= sizes.y || tile.z >= sizes.z || layer >= ELayer::NUM_LAYERS)
-		return nullptr;
-	return getNode(tile, layer);
+	boost::unique_lock<boost::mutex> pathLock(pathMx);
+	return getNode(tile);
 }
 
-bool CPathsInfo::getPath(CGPath & out, const int3 & dst, const ELayer layer) const
+bool CPathsInfo::getPath(CGPath & out, const int3 & dst) const
 {
 	boost::unique_lock<boost::mutex> pathLock(pathMx);
 
 	out.nodes.clear();
-	const CGPathNode * curnode = getNode(dst, layer);
+	const CGPathNode * curnode = getNode(dst);
 	if(!curnode->theNodeBefore)
 		return false;
 
 	while(curnode)
 	{
-		CGPathNode cpn = * curnode;
+		const CGPathNode cpn = * curnode;
 		curnode = curnode->theNodeBefore;
 		out.nodes.push_back(cpn);
 	}
 	return true;
 }
 
-int CPathsInfo::getDistance(const int3 & tile, const ELayer layer) const
+int CPathsInfo::getDistance(const int3 & tile) const
 {
 	boost::unique_lock<boost::mutex> pathLock(pathMx);
 
 	CGPath ret;
-	if(getPath(ret, tile, layer))
+	if(getPath(ret, tile))
 		return ret.nodes.size();
 	else
 		return 255;
 }
 
-CGPathNode * CPathsInfo::getNode(const int3 & coord, const ELayer layer) const
+const CGPathNode * CPathsInfo::getNode(const int3 & coord) const
 {
-	if(layer != ELayer::AUTO)
-		return nodes[coord.x][coord.y][coord.z][layer];
-
-	auto landNode = nodes[coord.x][coord.y][coord.z][ELayer::LAND];
-	if(landNode->theNodeBefore)
+	auto landNode = &nodes[coord.x][coord.y][coord.z][ELayer::LAND];
+	if(landNode->reachable())
 		return landNode;
 	else
-		return nodes[coord.x][coord.y][coord.z][ELayer::SAIL];
+		return &nodes[coord.x][coord.y][coord.z][ELayer::SAIL];
+}
+
+CGPathNode * CPathsInfo::getNode(const int3 & coord, const ELayer layer)
+{
+	return &nodes[coord.x][coord.y][coord.z][layer];
 }

+ 9 - 6
lib/CPathfinder.h

@@ -55,8 +55,9 @@ struct DLL_LINKAGE CGPathNode
 	ELayer layer;
 	ENodeAction action;
 
-	CGPathNode(int3 Coord, ELayer Layer);
+	CGPathNode();
 	void reset();
+	void update(const int3 & Coord, const ELayer Layer, const EAccessibility Accessible);
 	bool reachable() const;
 };
 
@@ -78,14 +79,16 @@ struct DLL_LINKAGE CPathsInfo
 	const CGHeroInstance * hero;
 	int3 hpos;
 	int3 sizes;
-	boost::multi_array<CGPathNode *, 4> nodes; //[w][h][level][layer]
+	boost::multi_array<CGPathNode, 4> nodes; //[w][h][level][layer]
 
 	CPathsInfo(const int3 & Sizes);
 	~CPathsInfo();
-	const CGPathNode * getPathInfo(const int3 & tile, const ELayer layer = ELayer::AUTO) const;
-	bool getPath(CGPath & out, const int3 & dst, const ELayer layer = ELayer::AUTO) const;
-	int getDistance(const int3 & tile, const ELayer layer = ELayer::AUTO) const;
-	CGPathNode * getNode(const int3 & coord, const ELayer layer) const;
+	const CGPathNode * getPathInfo(const int3 & tile) const;
+	bool getPath(CGPath & out, const int3 & dst) const;
+	int getDistance(const int3 & tile) const;
+	const CGPathNode * getNode(const int3 & coord) const;
+
+	CGPathNode * getNode(const int3 & coord, const ELayer layer);
 };
 
 class CPathfinder : private CGameInfoCallback