Browse Source

Extra cache for search area

Tomasz Zieliński 1 năm trước cách đây
mục cha
commit
d31789e745
3 tập tin đã thay đổi với 53 bổ sung9 xóa
  1. 32 0
      lib/rmg/Zone.cpp
  2. 1 0
      lib/rmg/Zone.h
  3. 20 9
      lib/rmg/modificators/ObjectManager.cpp

+ 32 - 0
lib/rmg/Zone.cpp

@@ -177,6 +177,38 @@ rmg::Path Zone::searchPath(const rmg::Area & src, bool onlyStraight, const std::
 	return resultPath;
 }
 
+rmg::Path Zone::searchPath(const rmg::Area & src, bool onlyStraight, const rmg::Area & searchArea) const
+///connect current tile to any other free tile within searchArea
+{
+	auto movementCost = [this](const int3 & s, const int3 & d)
+	{
+		if(map.isFree(d))
+			return 1;
+		else if (map.isPossible(d))
+			return 2;
+		return 3;
+	};
+
+	rmg::Path freePath(searchArea);
+	rmg::Path resultPath(searchArea);
+	freePath.connect(dAreaFree);
+
+	//connect to all pieces
+	auto goals = connectedAreas(src, onlyStraight);
+	for(auto & goal : goals)
+	{
+		auto path = freePath.search(goal, onlyStraight, movementCost);
+		if(path.getPathArea().empty())
+			return rmg::Path::invalid();
+
+		freePath.connect(path.getPathArea());
+		resultPath.connect(path.getPathArea());
+	}
+
+	return resultPath;
+}
+
+
 rmg::Path Zone::searchPath(const int3 & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter) const
 ///connect current tile to any other free tile within zone
 {

+ 1 - 0
lib/rmg/Zone.h

@@ -66,6 +66,7 @@ public:
 	void connectPath(const rmg::Path & path);
 	rmg::Path searchPath(const rmg::Area & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter = AREA_NO_FILTER) const;
 	rmg::Path searchPath(const int3 & src, bool onlyStraight, const std::function<bool(const int3 &)> & areafilter = AREA_NO_FILTER) const;
+	rmg::Path searchPath(const rmg::Area & src, bool onlyStraight, const rmg::Area & searchArea) const;
 
 	TModificators getModificators();
 

+ 20 - 9
lib/rmg/modificators/ObjectManager.cpp

@@ -95,7 +95,7 @@ void ObjectManager::updateDistances(std::function<ui32(const int3 & tile)> dista
 {
 	RecursiveLock lock(externalAccessMutex);
 	tilesByDistance.clear();
-	for (auto tile : zone.areaPossible().getTiles()) //don't need to mark distance for not possible tiles
+	for (const auto & tile : zone.areaPossible().getTiles()) //don't need to mark distance for not possible tiles
 	{
 		ui32 d = distanceFunction(tile);
 		map.setNearestObjectDistance(tile, std::min(static_cast<float>(d), map.getNearestObjectDistance(tile)));
@@ -305,6 +305,7 @@ rmg::Path ObjectManager::placeAndConnectObject(const rmg::Area & searchArea, rmg
 {
 	int3 pos;
 	auto possibleArea = searchArea;
+	auto cachedArea = zone.areaPossible() + zone.freePaths();
 	while(true)
 	{
 		pos = findPlaceForObject(possibleArea, obj, weightFunction, optimizer);
@@ -322,21 +323,31 @@ rmg::Path ObjectManager::placeAndConnectObject(const rmg::Area & searchArea, rmg
 			accessibleArea.add(obj.instances().back()->getPosition(true));
 		}
 
-		auto path = zone.searchPath(accessibleArea, onlyStraight, [&obj, isGuarded](const int3 & t)
+		rmg::Area subArea;
+		if (isGuarded)
 		{
-			if(isGuarded)
+			const auto & guardedArea = obj.instances().back()->getAccessibleArea();
+			const auto & unguardedArea = obj.getAccessibleArea(isGuarded);
+			subArea = cachedArea.getSubarea([guardedArea, unguardedArea, obj](const int3 & t)
 			{
-				const auto & guardedArea = obj.instances().back()->getAccessibleArea();
-				const auto & unguardedArea = obj.getAccessibleArea(isGuarded);
 				if(unguardedArea.contains(t) && !guardedArea.contains(t))
 					return false;
 				
 				//guard position is always target
 				if(obj.instances().back()->getPosition(true) == t)
 					return true;
-			}
-			return !obj.getArea().contains(t);
-		});
+
+				return !obj.getArea().contains(t);
+			});
+		}
+		else
+		{
+			subArea = cachedArea.getSubarea([obj](const int3 & t)
+			{
+				return !obj.getArea().contains(t);
+			});
+		}
+		auto path = zone.searchPath(accessibleArea, onlyStraight, cachedArea);
 		
 		if(path.valid())
 		{
@@ -670,7 +681,7 @@ bool ObjectManager::addGuard(rmg::Object & object, si32 strength, bool zoneGuard
 		return false;
 	
 	// Prefer non-blocking tiles, if any
-	auto entrableTiles = object.getEntrableArea().getTiles();
+	const auto & entrableTiles = object.getEntrableArea().getTiles();
 	int3 entrableTile(-1, -1, -1);
 	if (entrableTiles.empty())
 	{