Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/NosCore.PathFinder/NosCore.PathFinder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<RepositoryUrl>https://github.com/NosCoreIO/NosCore.PathFinder.git</RepositoryUrl>
<PackageIconUrl></PackageIconUrl>
<PackageTags>nostale, noscore, nostale private server source, nostale emulator</PackageTags>
<Version>2.1.0</Version>
<Version>2.1.1</Version>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Description>NosCore's PathFinder</Description>
<PackageLicenseExpression></PackageLicenseExpression>
Expand Down
6 changes: 3 additions & 3 deletions src/NosCore.PathFinder/Pathfinder/GoalBasedPathfinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public GoalBasedPathfinder(IMapGrid mapGrid, IHeuristic heuristic)

public GoalBasedPathfinder(IMapGrid mapGrid, IHeuristic heuristic, BrushFire brushfire) : this(mapGrid, heuristic)
{
BrushFirecache.Set(brushfire.Origin, brushfire, DateTimeOffset.Now.AddSeconds(10));
BrushFirecache.Set((mapGrid, brushfire.Origin), brushfire, DateTimeOffset.Now.AddSeconds(10));
}

public IEnumerable<(short X, short Y)> FindPath((short X, short Y) start, (short X, short Y) end)
Expand All @@ -39,10 +39,10 @@ public GoalBasedPathfinder(IMapGrid mapGrid, IHeuristic heuristic, BrushFire bru
return list;
}

if (!BrushFirecache.TryGetValue(end, out BrushFire brushFire))
if (!BrushFirecache.TryGetValue((_mapGrid, end), out BrushFire brushFire))
{
brushFire = _mapGrid.LoadBrushFire(end, _heuristic);
BrushFirecache.Set(end, brushFire, DateTimeOffset.Now.AddSeconds(10));
BrushFirecache.Set((_mapGrid, end), brushFire, DateTimeOffset.Now.AddSeconds(10));
}

if (!brushFire.Distances.ContainsKey(start))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,16 @@ public JumpPointSearchPathfinder(IMapGrid mapGrid, IHeuristic heuristic)

public IEnumerable<(short X, short Y)> FindPath((short X, short Y) start, (short X, short Y) end)
{
if (Cache.TryGetValue((start, end), out IEnumerable<(short X, short Y)>? cachedList))
// Keyed by grid too: the cache is shared by every pathfinder instance, one per map.
if (Cache.TryGetValue((_mapGrid, start, end), out IEnumerable<(short X, short Y)>? cachedList))
{
return cachedList ?? Array.Empty<(short X, short Y)>();
}

var path = BuildFullPath(GetJumpList(start, end).ToList());
for (var i = 0; i < path.Count; i++)
{
Cache.Set((path[i], end), path.Skip(i), DateTimeOffset.Now.AddSeconds(10));
Cache.Set((_mapGrid, path[i], end), path.Skip(i + 1), DateTimeOffset.Now.AddSeconds(10));
}
return path;
}
Expand Down
46 changes: 46 additions & 0 deletions test/NosCore.PathFinder.Tests/JumpPointSearchPathfinderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,51 @@ public void Test_JumpPointSearchPathfinder()

TestHelper.VerifyFile("jump-point-search-pathfinder.png", image, listPixel, "Jump Point Search Pathfinder (break at walls)");
}

[TestMethod]
public void ACachedPathStartsOnTheFirstStepLikeAFreshOne()
{
var pathfinder = new JumpPointSearchPathfinder(Walled(new[]
{
new byte[] { 0, 0, 0, 0, 0, 0 },
}), new OctileDistanceHeuristic());
var fresh = pathfinder.FindPath((1, 1), (6, 1)).ToList();

var cached = pathfinder.FindPath(fresh[0], (6, 1)).ToList();

CollectionAssert.AreEqual(fresh.Skip(1).ToList(), cached);
}

[TestMethod]
public void TwoMapsDoNotShareCachedPaths()
{
var open = new JumpPointSearchPathfinder(Walled(new[]
{
new byte[] { 0, 0, 0, 0, 0 },
new byte[] { 0, 0, 0, 0, 0 },
}), new OctileDistanceHeuristic());
var blocked = new JumpPointSearchPathfinder(Walled(new[]
{
new byte[] { 0, 0, 1, 0, 0 },
new byte[] { 0, 0, 0, 0, 0 },
}), new OctileDistanceHeuristic());

var straight = open.FindPath((1, 1), (5, 1)).ToList();
var around = blocked.FindPath(straight[0], (5, 1)).ToList();

Assert.Contains(((short)3, (short)1), straight);
Assert.DoesNotContain(((short)3, (short)1), around, "the blocked map must not reuse the open map's path through its wall");
Assert.AreEqual(((short)5, (short)1), around.Last());
}

private static TestMap Walled(byte[][] inside)
{
var width = inside[0].Length + 2;
var wall = Enumerable.Repeat((byte)1, width).ToArray();
return new TestMap(new[] { wall }
.Concat(inside.Select(row => new byte[] { 1 }.Concat(row).Append((byte)1).ToArray()))
.Append(wall)
.ToArray());
}
}
}
Loading