From c470945db7d8ba4ce3f7d57b71bfa2205014fb3d Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Sat, 22 Nov 2014 16:40:28 +1300 Subject: [PATCH 1/3] Remove vestigial direction-sorting machinery from PathSearch --- OpenRA.Mods.RA/Move/PathSearch.cs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/OpenRA.Mods.RA/Move/PathSearch.cs b/OpenRA.Mods.RA/Move/PathSearch.cs index ce23ab2b60..bdfed9a183 100755 --- a/OpenRA.Mods.RA/Move/PathSearch.cs +++ b/OpenRA.Mods.RA/Move/PathSearch.cs @@ -33,7 +33,6 @@ namespace OpenRA.Mods.RA.Move MobileInfo mobileInfo; Func customCost; Func customBlock; - Pair[] nextDirections; int laneBias = 1; public PathSearch(World world, MobileInfo mobileInfo, Actor self) @@ -46,7 +45,6 @@ namespace OpenRA.Mods.RA.Move Queue = new PriorityQueue(); Considered = new HashSet(); MaxCost = 0; - nextDirections = CVec.directions.Select(d => new Pair(d, 0)).ToArray(); } public static PathSearch Search(World world, MobileInfo mi, Actor self, bool checkForBlocked) @@ -170,10 +168,11 @@ namespace OpenRA.Mods.RA.Move // This current cell is ok; check all immediate directions: Considered.Add(p.Location); - for (var i = 0; i < nextDirections.Length; ++i) + var directions = CVec.directions; + + for (var i = 0; i < directions.Length; ++i) { - var d = nextDirections[i].First; - nextDirections[i].Second = int.MaxValue; + var d = directions[i]; var newHere = p.Location + d; @@ -239,7 +238,6 @@ namespace OpenRA.Mods.RA.Move hereCell.MinCost = newCost; CellInfo[newHere] = hereCell; - nextDirections[i].Second = newCost + est; Queue.Add(new PathDistance(newCost + est, newHere)); if (newCost > MaxCost) @@ -248,8 +246,6 @@ namespace OpenRA.Mods.RA.Move Considered.Add(newHere); } - // Sort to prefer the cheaper direction: - // Array.Sort(nextDirections, (a, b) => a.Second.CompareTo(b.Second)); return p.Location; } From f4e5c63408bd2c98e76de86e5a980b560df7e45c Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Sat, 22 Nov 2014 17:06:55 +1300 Subject: [PATCH 2/3] Pathfinder: Only consider useful neighbors Depending on the direction we came from, many neighbors are completely useless. This is the first step to implementing the ideas in 'Jump Point Search' V2: Added comment describing what the array is for. --- OpenRA.Mods.RA/Move/PathSearch.cs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/OpenRA.Mods.RA/Move/PathSearch.cs b/OpenRA.Mods.RA/Move/PathSearch.cs index bdfed9a183..42d10a37f5 100755 --- a/OpenRA.Mods.RA/Move/PathSearch.cs +++ b/OpenRA.Mods.RA/Move/PathSearch.cs @@ -138,6 +138,32 @@ namespace OpenRA.Mods.RA.Move return this; } + // Sets of neighbors for each incoming direction. These exclude the neighbors which are guaranteed + // to be reached more cheaply by a path through our parent cell which does not include the current cell. + // For horizontal/vertical directions, the set is the three cells 'ahead'. For diagonal directions, the set + // is the three cells ahead, plus the two cells to the side, which we cannot exclude without knowing if + // the cell directly between them and our parent is passable. + static CVec[][] DirectedNeighbors = { + new CVec[] { new CVec(-1, -1), new CVec(0, -1), new CVec(1, -1), new CVec(-1, 0), new CVec(-1, 1) }, + new CVec[] { new CVec(-1, -1), new CVec(0, -1), new CVec(1, -1) }, + new CVec[] { new CVec(-1, -1), new CVec(0, -1), new CVec(1, -1), new CVec(1, 0), new CVec(1, 1) }, + new CVec[] { new CVec(-1, -1), new CVec(-1, 0), new CVec(-1, 1) }, + CVec.directions, + new CVec[] { new CVec(1, -1), new CVec(1, 0), new CVec(1, 1) }, + new CVec[] { new CVec(-1, -1), new CVec(-1, 0), new CVec(-1, 1), new CVec(0, 1), new CVec(1, 1) }, + new CVec[] { new CVec(-1, 1), new CVec(0, 1), new CVec(1, 1) }, + new CVec[] { new CVec(1, -1), new CVec(1, 0), new CVec(-1, 1), new CVec(0, 1), new CVec(1, 1) }, + }; + + static CVec[] GetNeighbors(CPos p, CPos prev) + { + var dx = p.X - prev.X; + var dy = p.Y - prev.Y; + var index = dy * 3 + dx + 4; + + return DirectedNeighbors[index]; + } + public CPos Expand(World world) { var p = Queue.Pop(); @@ -165,10 +191,10 @@ namespace OpenRA.Mods.RA.Move return p.Location; } - // This current cell is ok; check all immediate directions: + // This current cell is ok; check useful immediate directions: Considered.Add(p.Location); - var directions = CVec.directions; + var directions = GetNeighbors(p.Location, pCell.Path); for (var i = 0; i < directions.Length; ++i) { From 68309af233ec5e0cdcd74cb76d381f25ce30afc5 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Sat, 22 Nov 2014 17:29:43 +1300 Subject: [PATCH 3/3] Remove enemy territory avoidance in FindResources. This is called from the inner loop of the pathfinder, so cannot afford to do actor queries etc. It also didn't have the desired effect -- harvesters still wander through enemy territory even with the bias. Just rip it out for a perf win. --- OpenRA.Mods.RA/Activities/FindResources.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/OpenRA.Mods.RA/Activities/FindResources.cs b/OpenRA.Mods.RA/Activities/FindResources.cs index e044143931..eca23337fc 100755 --- a/OpenRA.Mods.RA/Activities/FindResources.cs +++ b/OpenRA.Mods.RA/Activities/FindResources.cs @@ -52,13 +52,8 @@ namespace OpenRA.Mods.RA.Activities var searchRadiusSquared = searchRadius * searchRadius; // Find harvestable resources nearby: - // Avoid enemy territory: - // TODO: calculate weapons ranges of units and factor those in instead of hard-coding 8. var path = self.World.WorldActor.Trait().FindPath( PathSearch.Search(self.World, mobileInfo, self, true) - .WithCustomCost(loc => self.World.FindActorsInCircle(self.World.Map.CenterOfCell(loc), WRange.FromCells(8)) - .Where(u => !u.Destroyed && self.Owner.Stances[u.Owner] == Stance.Enemy) - .Sum(u => Math.Max(0, 64 - (loc - u.Location).LengthSquared))) .WithHeuristic(loc => { // Avoid this cell: