Bring PathSearch in line with the current code style.
This commit is contained in:
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.RA.Activities
|
|||||||
|
|
||||||
var path = pathFinder.FindBidiPath(
|
var path = pathFinder.FindBidiPath(
|
||||||
PathSearch.FromPoints(self.World, mobile.Info, self, searchCells, loc, true),
|
PathSearch.FromPoints(self.World, mobile.Info, self, searchCells, loc, true),
|
||||||
PathSearch.FromPoint(self.World, mobile.Info, self, loc, targetPosition, true).InReverse()
|
PathSearch.FromPoint(self.World, mobile.Info, self, loc, targetPosition, true).Reverse()
|
||||||
);
|
);
|
||||||
|
|
||||||
inner = mobile.MoveTo(() => path);
|
inner = mobile.MoveTo(() => path);
|
||||||
|
|||||||
30
OpenRA.Mods.RA/Move/PathFinder.cs
Executable file → Normal file
30
OpenRA.Mods.RA/Move/PathFinder.cs
Executable file → Normal file
@@ -68,7 +68,7 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
var pb = FindBidiPath(
|
var pb = FindBidiPath(
|
||||||
PathSearch.FromPoint(world, mi, self, target, from, true),
|
PathSearch.FromPoint(world, mi, self, target, from, true),
|
||||||
PathSearch.FromPoint(world, mi, self, from, target, true).InReverse()
|
PathSearch.FromPoint(world, mi, self, from, target, true).Reverse()
|
||||||
);
|
);
|
||||||
|
|
||||||
CheckSanePath2(pb, from, target);
|
CheckSanePath2(pb, from, target);
|
||||||
@@ -109,7 +109,7 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
var path = FindBidiPath(
|
var path = FindBidiPath(
|
||||||
PathSearch.FromPoints(world, mi, self, tilesInRange, src, true),
|
PathSearch.FromPoints(world, mi, self, tilesInRange, src, true),
|
||||||
PathSearch.FromPoint(world, mi, self, src, targetCell, true).InReverse()
|
PathSearch.FromPoint(world, mi, self, src, targetCell, true).Reverse()
|
||||||
);
|
);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
@@ -124,12 +124,12 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
{
|
{
|
||||||
List<CPos> path = null;
|
List<CPos> path = null;
|
||||||
|
|
||||||
while (!search.queue.Empty)
|
while (!search.Queue.Empty)
|
||||||
{
|
{
|
||||||
var p = search.Expand(world);
|
var p = search.Expand(world);
|
||||||
if (search.heuristic(p) == 0)
|
if (search.Heuristic(p) == 0)
|
||||||
{
|
{
|
||||||
path = MakePath(search.cellInfo, p);
|
path = MakePath(search.CellInfo, p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,7 +137,7 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
var dbg = world.WorldActor.TraitOrDefault<PathfinderDebugOverlay>();
|
var dbg = world.WorldActor.TraitOrDefault<PathfinderDebugOverlay>();
|
||||||
if (dbg != null)
|
if (dbg != null)
|
||||||
{
|
{
|
||||||
dbg.AddLayer(search.considered.Select(p => new Pair<CPos, int>(p, search.cellInfo[p.X, p.Y].MinCost)), search.maxCost, search.owner);
|
dbg.AddLayer(search.Considered.Select(p => new Pair<CPos, int>(p, search.CellInfo[p.X, p.Y].MinCost)), search.MaxCost, search.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path != null)
|
if (path != null)
|
||||||
@@ -176,13 +176,13 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
{
|
{
|
||||||
List<CPos> path = null;
|
List<CPos> path = null;
|
||||||
|
|
||||||
while (!fromSrc.queue.Empty && !fromDest.queue.Empty)
|
while (!fromSrc.Queue.Empty && !fromDest.Queue.Empty)
|
||||||
{
|
{
|
||||||
/* make some progress on the first search */
|
/* make some progress on the first search */
|
||||||
var p = fromSrc.Expand(world);
|
var p = fromSrc.Expand(world);
|
||||||
|
|
||||||
if (fromDest.cellInfo[p.X, p.Y].Seen &&
|
if (fromDest.CellInfo[p.X, p.Y].Seen &&
|
||||||
fromDest.cellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
|
fromDest.CellInfo[p.X, p.Y].MinCost < float.PositiveInfinity)
|
||||||
{
|
{
|
||||||
path = MakeBidiPath(fromSrc, fromDest, p);
|
path = MakeBidiPath(fromSrc, fromDest, p);
|
||||||
break;
|
break;
|
||||||
@@ -191,8 +191,8 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
/* make some progress on the second search */
|
/* make some progress on the second search */
|
||||||
var q = fromDest.Expand(world);
|
var q = fromDest.Expand(world);
|
||||||
|
|
||||||
if (fromSrc.cellInfo[q.X, q.Y].Seen &&
|
if (fromSrc.CellInfo[q.X, q.Y].Seen &&
|
||||||
fromSrc.cellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
|
fromSrc.CellInfo[q.X, q.Y].MinCost < float.PositiveInfinity)
|
||||||
{
|
{
|
||||||
path = MakeBidiPath(fromSrc, fromDest, q);
|
path = MakeBidiPath(fromSrc, fromDest, q);
|
||||||
break;
|
break;
|
||||||
@@ -202,8 +202,8 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
var dbg = world.WorldActor.TraitOrDefault<PathfinderDebugOverlay>();
|
var dbg = world.WorldActor.TraitOrDefault<PathfinderDebugOverlay>();
|
||||||
if (dbg != null)
|
if (dbg != null)
|
||||||
{
|
{
|
||||||
dbg.AddLayer(fromSrc.considered.Select(p => new Pair<CPos, int>(p, fromSrc.cellInfo[p.X, p.Y].MinCost)), fromSrc.maxCost, fromSrc.owner);
|
dbg.AddLayer(fromSrc.Considered.Select(p => new Pair<CPos, int>(p, fromSrc.CellInfo[p.X, p.Y].MinCost)), fromSrc.MaxCost, fromSrc.Owner);
|
||||||
dbg.AddLayer(fromDest.considered.Select(p => new Pair<CPos, int>(p, fromDest.cellInfo[p.X, p.Y].MinCost)), fromDest.maxCost, fromDest.owner);
|
dbg.AddLayer(fromDest.Considered.Select(p => new Pair<CPos, int>(p, fromDest.CellInfo[p.X, p.Y].MinCost)), fromDest.MaxCost, fromDest.Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path != null)
|
if (path != null)
|
||||||
@@ -216,8 +216,8 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
static List<CPos> MakeBidiPath(PathSearch a, PathSearch b, CPos p)
|
static List<CPos> MakeBidiPath(PathSearch a, PathSearch b, CPos p)
|
||||||
{
|
{
|
||||||
var ca = a.cellInfo;
|
var ca = a.CellInfo;
|
||||||
var cb = b.cellInfo;
|
var cb = b.CellInfo;
|
||||||
|
|
||||||
var ret = new List<CPos>();
|
var ret = new List<CPos>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#region Copyright & License Information
|
#region Copyright & License Information
|
||||||
/*
|
/*
|
||||||
* Copyright 2007-2011 The OpenRA Developers (see AUTHORS)
|
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
* This file is part of OpenRA, which is free software. It is made
|
||||||
* available to you under the terms of the GNU General Public License
|
* available to you under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation. For more information,
|
* as published by the Free Software Foundation. For more information,
|
||||||
@@ -17,38 +17,88 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
{
|
{
|
||||||
public sealed class PathSearch : IDisposable
|
public sealed class PathSearch : IDisposable
|
||||||
{
|
{
|
||||||
World world;
|
public CellInfo[,] CellInfo;
|
||||||
public CellInfo[,] cellInfo;
|
public PriorityQueue<PathDistance> Queue;
|
||||||
public PriorityQueue<PathDistance> queue;
|
public Func<CPos, int> Heuristic;
|
||||||
public Func<CPos, int> heuristic;
|
public bool CheckForBlocked;
|
||||||
|
public Actor IgnoreBuilding;
|
||||||
|
public bool InReverse;
|
||||||
|
public HashSet<CPos> Considered;
|
||||||
|
public Player Owner { get { return self.Owner; } }
|
||||||
|
public int MaxCost;
|
||||||
|
|
||||||
|
Actor self;
|
||||||
|
MobileInfo mobileInfo;
|
||||||
Func<CPos, int> customCost;
|
Func<CPos, int> customCost;
|
||||||
Func<CPos, bool> customBlock;
|
Func<CPos, bool> customBlock;
|
||||||
public bool checkForBlocked;
|
|
||||||
public Actor ignoreBuilding;
|
|
||||||
public bool inReverse;
|
|
||||||
public HashSet<CPos> considered;
|
|
||||||
public int maxCost;
|
|
||||||
Pair<CVec, int>[] nextDirections;
|
Pair<CVec, int>[] nextDirections;
|
||||||
MobileInfo mobileInfo;
|
int laneBias = 1;
|
||||||
Actor self;
|
|
||||||
public Player owner { get { return self.Owner; } }
|
|
||||||
|
|
||||||
public PathSearch(World world, MobileInfo mobileInfo, Actor self)
|
public PathSearch(World world, MobileInfo mobileInfo, Actor self)
|
||||||
{
|
{
|
||||||
this.world = world;
|
this.self = self;
|
||||||
cellInfo = InitCellInfo();
|
CellInfo = InitCellInfo();
|
||||||
this.mobileInfo = mobileInfo;
|
this.mobileInfo = mobileInfo;
|
||||||
this.self = self;
|
this.self = self;
|
||||||
customCost = null;
|
customCost = null;
|
||||||
queue = new PriorityQueue<PathDistance>();
|
Queue = new PriorityQueue<PathDistance>();
|
||||||
considered = new HashSet<CPos>();
|
Considered = new HashSet<CPos>();
|
||||||
maxCost = 0;
|
MaxCost = 0;
|
||||||
nextDirections = CVec.directions.Select(d => new Pair<CVec, int>(d, 0)).ToArray();
|
nextDirections = CVec.directions.Select(d => new Pair<CVec, int>(d, 0)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathSearch InReverse()
|
public static PathSearch Search(World world, MobileInfo mi, Actor self, bool checkForBlocked)
|
||||||
{
|
{
|
||||||
inReverse = true;
|
var search = new PathSearch(world, mi, self)
|
||||||
|
{
|
||||||
|
CheckForBlocked = checkForBlocked
|
||||||
|
};
|
||||||
|
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PathSearch FromPoint(World world, MobileInfo mi, Actor self, CPos from, CPos target, bool checkForBlocked)
|
||||||
|
{
|
||||||
|
var search = new PathSearch(world, mi, self)
|
||||||
|
{
|
||||||
|
Heuristic = DefaultEstimator(target),
|
||||||
|
CheckForBlocked = checkForBlocked
|
||||||
|
};
|
||||||
|
|
||||||
|
search.AddInitialCell(from);
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PathSearch FromPoints(World world, MobileInfo mi, Actor self, IEnumerable<CPos> froms, CPos target, bool checkForBlocked)
|
||||||
|
{
|
||||||
|
var search = new PathSearch(world, mi, self)
|
||||||
|
{
|
||||||
|
Heuristic = DefaultEstimator(target),
|
||||||
|
CheckForBlocked = checkForBlocked
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var sl in froms)
|
||||||
|
search.AddInitialCell(sl);
|
||||||
|
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Func<CPos, int> DefaultEstimator(CPos destination)
|
||||||
|
{
|
||||||
|
return here =>
|
||||||
|
{
|
||||||
|
var diag = Math.Min(Math.Abs(here.X - destination.X), Math.Abs(here.Y - destination.Y));
|
||||||
|
var straight = Math.Abs(here.X - destination.X) + Math.Abs(here.Y - destination.Y);
|
||||||
|
|
||||||
|
// HACK: this relies on fp and cell-size assumptions.
|
||||||
|
var h = (3400 * diag / 24) + 100 * (straight - (2 * diag));
|
||||||
|
return (int)(h * 1.001);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathSearch Reverse()
|
||||||
|
{
|
||||||
|
InReverse = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,13 +110,13 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
public PathSearch WithIgnoredBuilding(Actor b)
|
public PathSearch WithIgnoredBuilding(Actor b)
|
||||||
{
|
{
|
||||||
ignoreBuilding = b;
|
IgnoreBuilding = b;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathSearch WithHeuristic(Func<CPos, int> h)
|
public PathSearch WithHeuristic(Func<CPos, int> h)
|
||||||
{
|
{
|
||||||
heuristic = h;
|
Heuristic = h;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +128,7 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
|
|
||||||
public PathSearch WithoutLaneBias()
|
public PathSearch WithoutLaneBias()
|
||||||
{
|
{
|
||||||
LaneBias = 0;
|
laneBias = 0;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,18 +138,18 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LaneBias = 1;
|
|
||||||
|
|
||||||
public CPos Expand(World world)
|
public CPos Expand(World world)
|
||||||
{
|
{
|
||||||
var p = queue.Pop();
|
var p = Queue.Pop();
|
||||||
while (cellInfo[p.Location.X, p.Location.Y].Seen)
|
while (CellInfo[p.Location.X, p.Location.Y].Seen)
|
||||||
if (queue.Empty)
|
{
|
||||||
|
if (Queue.Empty)
|
||||||
return p.Location;
|
return p.Location;
|
||||||
else
|
|
||||||
p = queue.Pop();
|
|
||||||
|
|
||||||
cellInfo[p.Location.X, p.Location.Y].Seen = true;
|
p = Queue.Pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
CellInfo[p.Location.X, p.Location.Y].Seen = true;
|
||||||
|
|
||||||
var thisCost = mobileInfo.MovementCostForCell(world, p.Location);
|
var thisCost = mobileInfo.MovementCostForCell(world, p.Location);
|
||||||
|
|
||||||
@@ -114,7 +164,7 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This current cell is ok; check all immediate directions:
|
// This current cell is ok; check all immediate directions:
|
||||||
considered.Add(p.Location);
|
Considered.Add(p.Location);
|
||||||
|
|
||||||
for (var i = 0; i < nextDirections.Length; ++i)
|
for (var i = 0; i < nextDirections.Length; ++i)
|
||||||
{
|
{
|
||||||
@@ -126,7 +176,8 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
// Is this direction flat-out unusable or already seen?
|
// Is this direction flat-out unusable or already seen?
|
||||||
if (!world.Map.IsInMap(newHere))
|
if (!world.Map.IsInMap(newHere))
|
||||||
continue;
|
continue;
|
||||||
if (cellInfo[newHere.X, newHere.Y].Seen)
|
|
||||||
|
if (CellInfo[newHere.X, newHere.Y].Seen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Now we may seriously consider this direction using heuristics:
|
// Now we may seriously consider this direction using heuristics:
|
||||||
@@ -135,18 +186,19 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
if (costHere == int.MaxValue)
|
if (costHere == int.MaxValue)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!mobileInfo.CanEnterCell(world, self, newHere, ignoreBuilding, checkForBlocked, false))
|
if (!mobileInfo.CanEnterCell(world, self, newHere, IgnoreBuilding, CheckForBlocked, false))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (customBlock != null && customBlock(newHere))
|
if (customBlock != null && customBlock(newHere))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var est = heuristic(newHere);
|
var est = Heuristic(newHere);
|
||||||
if (est == int.MaxValue)
|
if (est == int.MaxValue)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var cellCost = costHere;
|
var cellCost = costHere;
|
||||||
if (d.X * d.Y != 0) cellCost = (cellCost * 34) / 24;
|
if (d.X * d.Y != 0)
|
||||||
|
cellCost = (cellCost * 34) / 24;
|
||||||
|
|
||||||
var userCost = 0;
|
var userCost = 0;
|
||||||
if (customCost != null)
|
if (customCost != null)
|
||||||
@@ -156,105 +208,80 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
}
|
}
|
||||||
|
|
||||||
// directional bonuses for smoother flow!
|
// directional bonuses for smoother flow!
|
||||||
if (LaneBias != 0)
|
if (laneBias != 0)
|
||||||
{
|
{
|
||||||
var ux = (newHere.X + (inReverse ? 1 : 0) & 1);
|
var ux = newHere.X + (InReverse ? 1 : 0) & 1;
|
||||||
var uy = (newHere.Y + (inReverse ? 1 : 0) & 1);
|
var uy = newHere.Y + (InReverse ? 1 : 0) & 1;
|
||||||
|
|
||||||
if (ux == 0 && d.Y < 0) cellCost += LaneBias;
|
if (ux == 0 && d.Y < 0)
|
||||||
else if (ux == 1 && d.Y > 0) cellCost += LaneBias;
|
cellCost += laneBias;
|
||||||
if (uy == 0 && d.X < 0) cellCost += LaneBias;
|
else if (ux == 1 && d.Y > 0)
|
||||||
else if (uy == 1 && d.X > 0) cellCost += LaneBias;
|
cellCost += laneBias;
|
||||||
|
|
||||||
|
if (uy == 0 && d.X < 0)
|
||||||
|
cellCost += laneBias;
|
||||||
|
else if (uy == 1 && d.X > 0)
|
||||||
|
cellCost += laneBias;
|
||||||
}
|
}
|
||||||
|
|
||||||
var newCost = cellInfo[p.Location.X, p.Location.Y].MinCost + cellCost;
|
var newCost = CellInfo[p.Location.X, p.Location.Y].MinCost + cellCost;
|
||||||
|
|
||||||
// Cost is even higher; next direction:
|
// Cost is even higher; next direction:
|
||||||
if (newCost > cellInfo[newHere.X, newHere.Y].MinCost)
|
if (newCost > CellInfo[newHere.X, newHere.Y].MinCost)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cellInfo[newHere.X, newHere.Y].Path = p.Location;
|
CellInfo[newHere.X, newHere.Y].Path = p.Location;
|
||||||
cellInfo[newHere.X, newHere.Y].MinCost = newCost;
|
CellInfo[newHere.X, newHere.Y].MinCost = newCost;
|
||||||
|
|
||||||
nextDirections[i].Second = newCost + est;
|
nextDirections[i].Second = newCost + est;
|
||||||
queue.Add(new PathDistance(newCost + est, newHere));
|
Queue.Add(new PathDistance(newCost + est, newHere));
|
||||||
|
|
||||||
if (newCost > maxCost) maxCost = newCost;
|
if (newCost > MaxCost)
|
||||||
considered.Add(newHere);
|
MaxCost = newCost;
|
||||||
|
|
||||||
|
Considered.Add(newHere);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort to prefer the cheaper direction:
|
// Sort to prefer the cheaper direction:
|
||||||
//Array.Sort(nextDirections, (a, b) => a.Second.CompareTo(b.Second));
|
// Array.Sort(nextDirections, (a, b) => a.Second.CompareTo(b.Second));
|
||||||
|
|
||||||
return p.Location;
|
return p.Location;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddInitialCell(CPos location)
|
public void AddInitialCell(CPos location)
|
||||||
{
|
{
|
||||||
if (!world.Map.IsInMap(location))
|
if (!self.World.Map.IsInMap(location))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cellInfo[location.X, location.Y] = new CellInfo(0, location, false);
|
CellInfo[location.X, location.Y] = new CellInfo(0, location, false);
|
||||||
queue.Add(new PathDistance(heuristic(location), location));
|
Queue.Add(new PathDistance(Heuristic(location), location));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PathSearch Search(World world, MobileInfo mi, Actor self, bool checkForBlocked)
|
static readonly Queue<CellInfo[,]> CellInfoPool = new Queue<CellInfo[,]>();
|
||||||
{
|
|
||||||
var search = new PathSearch(world, mi, self)
|
|
||||||
{
|
|
||||||
checkForBlocked = checkForBlocked
|
|
||||||
};
|
|
||||||
return search;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PathSearch FromPoint(World world, MobileInfo mi, Actor self, CPos from, CPos target, bool checkForBlocked)
|
|
||||||
{
|
|
||||||
var search = new PathSearch(world, mi, self)
|
|
||||||
{
|
|
||||||
heuristic = DefaultEstimator(target),
|
|
||||||
checkForBlocked = checkForBlocked
|
|
||||||
};
|
|
||||||
|
|
||||||
search.AddInitialCell(from);
|
|
||||||
return search;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PathSearch FromPoints(World world, MobileInfo mi, Actor self, IEnumerable<CPos> froms, CPos target, bool checkForBlocked)
|
|
||||||
{
|
|
||||||
var search = new PathSearch(world, mi, self)
|
|
||||||
{
|
|
||||||
heuristic = DefaultEstimator(target),
|
|
||||||
checkForBlocked = checkForBlocked
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var sl in froms)
|
|
||||||
search.AddInitialCell(sl);
|
|
||||||
|
|
||||||
return search;
|
|
||||||
}
|
|
||||||
|
|
||||||
static readonly Queue<CellInfo[,]> cellInfoPool = new Queue<CellInfo[,]>();
|
|
||||||
|
|
||||||
static CellInfo[,] GetFromPool()
|
static CellInfo[,] GetFromPool()
|
||||||
{
|
{
|
||||||
lock (cellInfoPool)
|
lock (CellInfoPool)
|
||||||
return cellInfoPool.Dequeue();
|
return CellInfoPool.Dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PutBackIntoPool(CellInfo[,] ci)
|
static void PutBackIntoPool(CellInfo[,] ci)
|
||||||
{
|
{
|
||||||
lock (cellInfoPool)
|
lock (CellInfoPool)
|
||||||
cellInfoPool.Enqueue(ci);
|
CellInfoPool.Enqueue(ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
CellInfo[,] InitCellInfo()
|
CellInfo[,] InitCellInfo()
|
||||||
{
|
{
|
||||||
CellInfo[,] result = null;
|
CellInfo[,] result = null;
|
||||||
while (cellInfoPool.Count > 0)
|
|
||||||
|
// 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
|
||||||
|
// explicitly to the things that need to share it.
|
||||||
|
while (CellInfoPool.Count > 0)
|
||||||
{
|
{
|
||||||
var cellInfo = GetFromPool();
|
var cellInfo = GetFromPool();
|
||||||
if (cellInfo.GetUpperBound(0) != world.Map.MapSize.X - 1 ||
|
if (cellInfo.GetUpperBound(0) != self.World.Map.MapSize.X - 1 ||
|
||||||
cellInfo.GetUpperBound(1) != world.Map.MapSize.Y - 1)
|
cellInfo.GetUpperBound(1) != self.World.Map.MapSize.Y - 1)
|
||||||
{
|
{
|
||||||
Log.Write("debug", "Discarding old pooled CellInfo of wrong size.");
|
Log.Write("debug", "Discarding old pooled CellInfo of wrong size.");
|
||||||
continue;
|
continue;
|
||||||
@@ -265,36 +292,25 @@ namespace OpenRA.Mods.RA.Move
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (result == null)
|
if (result == null)
|
||||||
result = new CellInfo[world.Map.MapSize.X, world.Map.MapSize.Y];
|
result = new CellInfo[self.World.Map.MapSize.X, self.World.Map.MapSize.Y];
|
||||||
|
|
||||||
for (var x = 0; x < world.Map.MapSize.X; x++)
|
for (var x = 0; x < self.World.Map.MapSize.X; x++)
|
||||||
for (var y = 0; y < world.Map.MapSize.Y; y++)
|
for (var y = 0; y < self.World.Map.MapSize.Y; y++)
|
||||||
result[ x, y ] = new CellInfo( int.MaxValue, new CPos( x, y ), false );
|
result[x, y] = new CellInfo(int.MaxValue, new CPos(x, y), false);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Func<CPos, int> DefaultEstimator(CPos destination)
|
|
||||||
{
|
|
||||||
return here =>
|
|
||||||
{
|
|
||||||
var diag = Math.Min(Math.Abs(here.X - destination.X), Math.Abs(here.Y - destination.Y));
|
|
||||||
var straight = (Math.Abs(here.X - destination.X) + Math.Abs(here.Y - destination.Y));
|
|
||||||
var h = (3400 * diag / 24) + 100 * (straight - (2 * diag));
|
|
||||||
h = (int)(h * 1.001);
|
|
||||||
return h;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool disposed;
|
bool disposed;
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (disposed)
|
if (disposed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
disposed = true;
|
disposed = true;
|
||||||
|
|
||||||
PutBackIntoPool(cellInfo);
|
PutBackIntoPool(CellInfo);
|
||||||
cellInfo = null;
|
CellInfo = null;
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user