diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index e0cc610688..e8f0c5ddd5 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -504,7 +504,7 @@
-
+
diff --git a/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs b/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs
index 57fb3c3cad..fab51285a3 100644
--- a/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs
+++ b/OpenRA.Mods.Common/Pathfinder/BasePathSearch.cs
@@ -18,18 +18,11 @@ namespace OpenRA.Mods.Common.Pathfinder
{
public interface IPathSearch
{
- string Id { get; }
-
///
/// The Graph used by the A*
///
IGraph Graph { get; }
- ///
- /// The open queue where nodes that are worth to consider are stored by their estimator
- ///
- IPriorityQueue OpenQueue { get; }
-
///
/// Stores the analyzed nodes by the expand function
///
@@ -64,6 +57,7 @@ namespace OpenRA.Mods.Common.Pathfinder
/// Whether the location is a target
bool IsTarget(CPos location);
+ bool CanExpand { get; }
CPos Expand();
}
@@ -71,44 +65,13 @@ namespace OpenRA.Mods.Common.Pathfinder
{
public IGraph Graph { get; set; }
- // The Id of a Pathsearch is computed by its properties.
- // So two PathSearch instances with the same parameters will
- // Compute the same Id. This is used for caching purposes.
- public string Id
- {
- get
- {
- if (string.IsNullOrEmpty(id))
- {
- var builder = new StringBuilder();
- builder.Append(Graph.Actor.ActorID);
- while (!startPoints.Empty)
- {
- var startpoint = startPoints.Pop();
- builder.Append(startpoint.X);
- builder.Append(startpoint.Y);
- builder.Append(Graph[startpoint].EstimatedTotal);
- }
-
- builder.Append(Graph.InReverse);
- if (Graph.IgnoredActor != null) builder.Append(Graph.IgnoredActor.ActorID);
- builder.Append(Graph.LaneBias);
-
- id = builder.ToString();
- }
-
- return id;
- }
- }
-
- public IPriorityQueue OpenQueue { get; protected set; }
+ protected IPriorityQueue OpenQueue { get; private set; }
public abstract IEnumerable> Considered { get; }
public Player Owner { get { return Graph.Actor.Owner; } }
public int MaxCost { get; protected set; }
public bool Debug { get; set; }
- string id;
protected Func heuristic;
protected Func isGoal;
@@ -117,13 +80,13 @@ namespace OpenRA.Mods.Common.Pathfinder
// points considered and their Heuristics to reach
// the target. It pretty match identifies, in conjunction of the Actor,
// a deterministic set of calculations
- protected IPriorityQueue startPoints;
+ protected readonly IPriorityQueue StartPoints;
protected BasePathSearch(IGraph graph)
{
Graph = graph;
- OpenQueue = new PriorityQueue(new PositionComparer(Graph));
- startPoints = new PriorityQueue(new PositionComparer(Graph));
+ OpenQueue = new PriorityQueue(GraphConnection.ConnectionCostComparer);
+ StartPoints = new PriorityQueue(GraphConnection.ConnectionCostComparer);
Debug = false;
MaxCost = 0;
}
@@ -198,6 +161,7 @@ namespace OpenRA.Mods.Common.Pathfinder
return isGoal(location);
}
+ public bool CanExpand { get { return !OpenQueue.Empty; } }
public abstract CPos Expand();
}
}
diff --git a/OpenRA.Mods.Common/Pathfinder/CellInfo.cs b/OpenRA.Mods.Common/Pathfinder/CellInfo.cs
index 57f3e9329e..a8112bc343 100644
--- a/OpenRA.Mods.Common/Pathfinder/CellInfo.cs
+++ b/OpenRA.Mods.Common/Pathfinder/CellInfo.cs
@@ -57,22 +57,4 @@ namespace OpenRA.Mods.Common.Pathfinder
EstimatedTotal = estimatedTotal;
}
}
-
- ///
- /// Compares two nodes according to their estimations
- ///
- public class PositionComparer : IComparer
- {
- readonly IGraph graph;
-
- public PositionComparer(IGraph graph)
- {
- this.graph = graph;
- }
-
- public int Compare(CPos x, CPos y)
- {
- return Math.Sign(graph[x].EstimatedTotal - graph[y].EstimatedTotal);
- }
- }
}
diff --git a/OpenRA.Mods.Common/Pathfinder/PathFinderCacheDecorator.cs b/OpenRA.Mods.Common/Pathfinder/PathFinderUnitPathCacheDecorator.cs
similarity index 71%
rename from OpenRA.Mods.Common/Pathfinder/PathFinderCacheDecorator.cs
rename to OpenRA.Mods.Common/Pathfinder/PathFinderUnitPathCacheDecorator.cs
index f4fad6cf99..1aeaf768ac 100644
--- a/OpenRA.Mods.Common/Pathfinder/PathFinderCacheDecorator.cs
+++ b/OpenRA.Mods.Common/Pathfinder/PathFinderUnitPathCacheDecorator.cs
@@ -16,14 +16,14 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Pathfinder
{
///
- /// A decorator used to cache the pathfinder (Decorator design pattern)
+ /// A decorator used to cache FindUnitPath and FindUnitPathToRange (Decorator design pattern)
///
- public class PathFinderCacheDecorator : IPathFinder
+ public class PathFinderUnitPathCacheDecorator : IPathFinder
{
readonly IPathFinder pathFinder;
readonly ICacheStorage> cacheStorage;
- public PathFinderCacheDecorator(IPathFinder pathFinder, ICacheStorage> cacheStorage)
+ public PathFinderUnitPathCacheDecorator(IPathFinder pathFinder, ICacheStorage> cacheStorage)
{
this.pathFinder = pathFinder;
this.cacheStorage = cacheStorage;
@@ -68,37 +68,13 @@ namespace OpenRA.Mods.Common.Pathfinder
public List FindPath(IPathSearch search)
{
using (new PerfSample("Pathfinder"))
- {
- var key = "FindPath" + search.Id;
- var cachedPath = cacheStorage.Retrieve(key);
-
- if (cachedPath != null)
- return cachedPath;
-
- var pb = pathFinder.FindPath(search);
-
- cacheStorage.Store(key, pb);
-
- return pb;
- }
+ return pathFinder.FindPath(search);
}
public List FindBidiPath(IPathSearch fromSrc, IPathSearch fromDest)
{
using (new PerfSample("Pathfinder"))
- {
- var key = "FindBidiPath" + fromSrc.Id + fromDest.Id;
- var cachedPath = cacheStorage.Retrieve(key);
-
- if (cachedPath != null)
- return cachedPath;
-
- var pb = pathFinder.FindBidiPath(fromSrc, fromDest);
-
- cacheStorage.Store(key, pb);
-
- return pb;
- }
+ return pathFinder.FindBidiPath(fromSrc, fromDest);
}
}
}
diff --git a/OpenRA.Mods.Common/Pathfinder/PathGraph.cs b/OpenRA.Mods.Common/Pathfinder/PathGraph.cs
index 3204b5282e..268e1331c2 100644
--- a/OpenRA.Mods.Common/Pathfinder/PathGraph.cs
+++ b/OpenRA.Mods.Common/Pathfinder/PathGraph.cs
@@ -47,6 +47,18 @@ namespace OpenRA.Mods.Common.Pathfinder
public struct GraphConnection
{
+ public static readonly CostComparer ConnectionCostComparer = CostComparer.Instance;
+
+ public sealed class CostComparer : IComparer
+ {
+ public static readonly CostComparer Instance = new CostComparer();
+ CostComparer() { }
+ public int Compare(GraphConnection x, GraphConnection y)
+ {
+ return x.Cost.CompareTo(y.Cost);
+ }
+ }
+
public readonly CPos Destination;
public readonly int Cost;
diff --git a/OpenRA.Mods.Common/Pathfinder/PathSearch.cs b/OpenRA.Mods.Common/Pathfinder/PathSearch.cs
index 254317d030..c4f5355f7d 100644
--- a/OpenRA.Mods.Common/Pathfinder/PathSearch.cs
+++ b/OpenRA.Mods.Common/Pathfinder/PathSearch.cs
@@ -84,9 +84,11 @@ namespace OpenRA.Mods.Common.Pathfinder
protected override void AddInitialCell(CPos location)
{
- Graph[location] = new CellInfo(0, heuristic(location), location, CellStatus.Open);
- OpenQueue.Add(location);
- startPoints.Add(location);
+ var cost = heuristic(location);
+ Graph[location] = new CellInfo(0, cost, location, CellStatus.Open);
+ var connection = new GraphConnection(location, cost);
+ OpenQueue.Add(connection);
+ StartPoints.Add(connection);
considered.AddLast(new Pair(location, 0));
}
@@ -99,7 +101,7 @@ namespace OpenRA.Mods.Common.Pathfinder
/// The most promising node of the iteration
public override CPos Expand()
{
- var currentMinNode = OpenQueue.Pop();
+ var currentMinNode = OpenQueue.Pop().Destination;
var currentCell = Graph[currentMinNode];
Graph[currentMinNode] = new CellInfo(currentCell.CostSoFar, currentCell.EstimatedTotal, currentCell.PreviousPos, CellStatus.Closed);
@@ -128,10 +130,11 @@ namespace OpenRA.Mods.Common.Pathfinder
else
hCost = heuristic(neighborCPos);
- Graph[neighborCPos] = new CellInfo(gCost, gCost + hCost, currentMinNode, CellStatus.Open);
+ var estimatedCost = gCost + hCost;
+ Graph[neighborCPos] = new CellInfo(gCost, estimatedCost, currentMinNode, CellStatus.Open);
if (neighborCell.Status != CellStatus.Open)
- OpenQueue.Add(neighborCPos);
+ OpenQueue.Add(new GraphConnection(neighborCPos, estimatedCost));
if (Debug)
{
diff --git a/OpenRA.Mods.Common/Traits/World/PathFinder.cs b/OpenRA.Mods.Common/Traits/World/PathFinder.cs
index 70e71fcfc6..405f2b2a28 100644
--- a/OpenRA.Mods.Common/Traits/World/PathFinder.cs
+++ b/OpenRA.Mods.Common/Traits/World/PathFinder.cs
@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Common.Traits
{
public object Create(ActorInitializer init)
{
- return new PathFinderCacheDecorator(new PathFinder(init.World), new PathCacheStorage(init.World));
+ return new PathFinderUnitPathCacheDecorator(new PathFinder(init.World), new PathCacheStorage(init.World));
}
}
@@ -121,7 +121,7 @@ namespace OpenRA.Mods.Common.Traits
List path = null;
- while (!search.OpenQueue.Empty)
+ while (search.CanExpand)
{
var p = search.Expand();
if (search.IsTarget(p))
@@ -156,7 +156,7 @@ namespace OpenRA.Mods.Common.Traits
fromDest.Debug = true;
}
- while (!fromSrc.OpenQueue.Empty && !fromDest.OpenQueue.Empty)
+ while (fromSrc.CanExpand && fromDest.CanExpand)
{
// make some progress on the first search
var p = fromSrc.Expand();