diff --git a/OpenRA.Mods.RA/Move/PathFinder.cs b/OpenRA.Mods.RA/Move/PathFinder.cs index fc899d1cc1..7c4e5524e9 100644 --- a/OpenRA.Mods.RA/Move/PathFinder.cs +++ b/OpenRA.Mods.RA/Move/PathFinder.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using OpenRA; using OpenRA.Primitives; using OpenRA.Support; using OpenRA.Traits; @@ -136,9 +137,7 @@ namespace OpenRA.Mods.RA.Move var dbg = world.WorldActor.TraitOrDefault(); if (dbg != null) - { - dbg.AddLayer(search.Considered.Select(p => new Pair(p, search.CellInfo[p.X, p.Y].MinCost)), search.MaxCost, search.Owner); - } + dbg.AddLayer(search.Considered.Select(p => new Pair(p, search.CellInfo[p].MinCost)), search.MaxCost, search.Owner); if (path != null) return path; @@ -149,15 +148,15 @@ namespace OpenRA.Mods.RA.Move } } - static List MakePath(CellInfo[,] cellInfo, CPos destination) + static List MakePath(CellLayer cellInfo, CPos destination) { var ret = new List(); var pathNode = destination; - while (cellInfo[pathNode.X, pathNode.Y].Path != pathNode) + while (cellInfo[pathNode].Path != pathNode) { ret.Add(pathNode); - pathNode = cellInfo[pathNode.X, pathNode.Y].Path; + pathNode = cellInfo[pathNode].Path; } ret.Add(pathNode); @@ -165,9 +164,8 @@ namespace OpenRA.Mods.RA.Move return ret; } - public List FindBidiPath( /* searches from both ends toward each other */ - PathSearch fromSrc, - PathSearch fromDest) + // Searches from both ends toward each other + public List FindBidiPath(PathSearch fromSrc, PathSearch fromDest) { using (new PerfSample("Pathfinder")) { @@ -181,8 +179,8 @@ namespace OpenRA.Mods.RA.Move /* make some progress on the first search */ var p = fromSrc.Expand(world); - if (fromDest.CellInfo[p.X, p.Y].Seen && - fromDest.CellInfo[p.X, p.Y].MinCost < float.PositiveInfinity) + if (fromDest.CellInfo[p].Seen && + fromDest.CellInfo[p].MinCost < float.PositiveInfinity) { path = MakeBidiPath(fromSrc, fromDest, p); break; @@ -191,8 +189,8 @@ namespace OpenRA.Mods.RA.Move /* make some progress on the second search */ var q = fromDest.Expand(world); - if (fromSrc.CellInfo[q.X, q.Y].Seen && - fromSrc.CellInfo[q.X, q.Y].MinCost < float.PositiveInfinity) + if (fromSrc.CellInfo[q].Seen && + fromSrc.CellInfo[q].MinCost < float.PositiveInfinity) { path = MakeBidiPath(fromSrc, fromDest, q); break; @@ -202,8 +200,8 @@ namespace OpenRA.Mods.RA.Move var dbg = world.WorldActor.TraitOrDefault(); if (dbg != null) { - dbg.AddLayer(fromSrc.Considered.Select(p => new Pair(p, fromSrc.CellInfo[p.X, p.Y].MinCost)), fromSrc.MaxCost, fromSrc.Owner); - dbg.AddLayer(fromDest.Considered.Select(p => new Pair(p, fromDest.CellInfo[p.X, p.Y].MinCost)), fromDest.MaxCost, fromDest.Owner); + dbg.AddLayer(fromSrc.Considered.Select(p => new Pair(p, fromSrc.CellInfo[p].MinCost)), fromSrc.MaxCost, fromSrc.Owner); + dbg.AddLayer(fromDest.Considered.Select(p => new Pair(p, fromDest.CellInfo[p].MinCost)), fromDest.MaxCost, fromDest.Owner); } if (path != null) @@ -222,19 +220,19 @@ namespace OpenRA.Mods.RA.Move var ret = new List(); var q = p; - while (ca[q.X, q.Y].Path != q) + while (ca[q].Path != q) { ret.Add(q); - q = ca[q.X, q.Y].Path; + q = ca[q].Path; } ret.Add(q); ret.Reverse(); q = p; - while (cb[q.X, q.Y].Path != q) + while (cb[q].Path != q) { - q = cb[q.X, q.Y].Path; + q = cb[q].Path; ret.Add(q); } diff --git a/OpenRA.Mods.RA/Move/PathSearch.cs b/OpenRA.Mods.RA/Move/PathSearch.cs index e34c403213..a0aec53548 100755 --- a/OpenRA.Mods.RA/Move/PathSearch.cs +++ b/OpenRA.Mods.RA/Move/PathSearch.cs @@ -10,14 +10,16 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.Linq; +using OpenRA; using OpenRA.Primitives; namespace OpenRA.Mods.RA.Move { public sealed class PathSearch : IDisposable { - public CellInfo[,] CellInfo; + public CellLayer CellInfo; public PriorityQueue Queue; public Func Heuristic; public bool CheckForBlocked; @@ -141,7 +143,7 @@ namespace OpenRA.Mods.RA.Move public CPos Expand(World world) { var p = Queue.Pop(); - while (CellInfo[p.Location.X, p.Location.Y].Seen) + while (CellInfo[p.Location].Seen) { if (Queue.Empty) return p.Location; @@ -149,7 +151,9 @@ namespace OpenRA.Mods.RA.Move p = Queue.Pop(); } - CellInfo[p.Location.X, p.Location.Y].Seen = true; + var pCell = CellInfo[p.Location]; + pCell.Seen = true; + CellInfo[p.Location] = pCell; var thisCost = mobileInfo.MovementCostForCell(world, p.Location); @@ -177,7 +181,7 @@ namespace OpenRA.Mods.RA.Move if (!world.Map.IsInMap(newHere)) continue; - if (CellInfo[newHere.X, newHere.Y].Seen) + if (CellInfo[newHere].Seen) continue; // Now we may seriously consider this direction using heuristics: @@ -224,14 +228,16 @@ namespace OpenRA.Mods.RA.Move cellCost += laneBias; } - var newCost = CellInfo[p.Location.X, p.Location.Y].MinCost + cellCost; + var newCost = CellInfo[p.Location].MinCost + cellCost; // Cost is even higher; next direction: - if (newCost > CellInfo[newHere.X, newHere.Y].MinCost) + if (newCost > CellInfo[newHere].MinCost) continue; - CellInfo[newHere.X, newHere.Y].Path = p.Location; - CellInfo[newHere.X, newHere.Y].MinCost = newCost; + var hereCell = CellInfo[newHere]; + hereCell.Path = p.Location; + hereCell.MinCost = newCost; + CellInfo[newHere] = hereCell; nextDirections[i].Second = newCost + est; Queue.Add(new PathDistance(newCost + est, newHere)); @@ -252,27 +258,28 @@ namespace OpenRA.Mods.RA.Move if (!self.World.Map.IsInMap(location)) return; - CellInfo[location.X, location.Y] = new CellInfo(0, location, false); + CellInfo[location] = new CellInfo(0, location, false); Queue.Add(new PathDistance(Heuristic(location), location)); } - static readonly Queue CellInfoPool = new Queue(); + static readonly Queue> CellInfoPool = new Queue>(); - static CellInfo[,] GetFromPool() + static CellLayer GetFromPool() { lock (CellInfoPool) return CellInfoPool.Dequeue(); } - static void PutBackIntoPool(CellInfo[,] ci) + static void PutBackIntoPool(CellLayer ci) { lock (CellInfoPool) CellInfoPool.Enqueue(ci); } - CellInfo[,] InitCellInfo() + CellLayer InitCellInfo() { - CellInfo[,] result = null; + CellLayer result = null; + var mapSize = new Size(self.World.Map.MapSize.X, self.World.Map.MapSize.Y); // HACK: Uses a static cache so that double-ended searches (which have two PathSearch instances) // can implicitly share data. The PathFinder should allocate the CellInfo array and pass it @@ -280,8 +287,7 @@ namespace OpenRA.Mods.RA.Move while (CellInfoPool.Count > 0) { var cellInfo = GetFromPool(); - if (cellInfo.GetUpperBound(0) != self.World.Map.MapSize.X - 1 || - cellInfo.GetUpperBound(1) != self.World.Map.MapSize.Y - 1) + if (cellInfo.Size != mapSize) { Log.Write("debug", "Discarding old pooled CellInfo of wrong size."); continue; @@ -292,11 +298,10 @@ namespace OpenRA.Mods.RA.Move } if (result == null) - result = new CellInfo[self.World.Map.MapSize.X, self.World.Map.MapSize.Y]; + result = new CellLayer(self.World.Map); - for (var x = 0; x < self.World.Map.MapSize.X; x++) - for (var y = 0; y < self.World.Map.MapSize.Y; y++) - result[x, y] = new CellInfo(int.MaxValue, new CPos(x, y), false); + foreach (var cell in self.World.Map.Cells) + result[cell] = new CellInfo(int.MaxValue, cell, false); return result; }