|
|
@@ -60,19 +60,7 @@ public class Map
|
|
|
public void BuildGraph()
|
|
|
{
|
|
|
var startTile = At(_start)!;
|
|
|
- _root = BuildPath(startTile, Neighbors(startTile).Single().Position.Subtract(startTile.Position));
|
|
|
-
|
|
|
- // Assert that we have no cycles in the graph
|
|
|
- var seen = new HashSet<PathNode>();
|
|
|
- foreach (var n in BreadthFirst())
|
|
|
- {
|
|
|
- if (seen.Contains(n))
|
|
|
- {
|
|
|
- throw new Exception("There is a cycle in the graph");
|
|
|
- }
|
|
|
-
|
|
|
- seen.Add(n);
|
|
|
- }
|
|
|
+ _root = BuildPath(startTile, Neighbors(startTile).Single().Position.Subtract(startTile.Position), new Dictionary<Vec, PathNode>());
|
|
|
}
|
|
|
|
|
|
public int LongestPath()
|
|
|
@@ -87,12 +75,12 @@ public class Map
|
|
|
var (current, length) = queue.Dequeue();
|
|
|
var nextLength = length + current.Tiles.Count + 1;
|
|
|
|
|
|
- if (current.Connected.Count == 0)
|
|
|
+ if (current.Outgoing.Count == 0)
|
|
|
{
|
|
|
longest = int.Max(longest, nextLength);
|
|
|
}
|
|
|
|
|
|
- foreach (var next in current.Connected)
|
|
|
+ foreach (var next in current.Outgoing)
|
|
|
{
|
|
|
queue.Enqueue((next, nextLength));
|
|
|
}
|
|
|
@@ -102,20 +90,28 @@ public class Map
|
|
|
return longest - 2;
|
|
|
}
|
|
|
|
|
|
- private PathNode BuildPath(Tile start, Vec dir)
|
|
|
+ private PathNode BuildPath(Tile start, Vec dir, IDictionary<Vec, PathNode> map)
|
|
|
{
|
|
|
+ if (map.TryGetValue(start.Position, out PathNode? path))
|
|
|
+ {
|
|
|
+ return path;
|
|
|
+ }
|
|
|
+
|
|
|
var pathNode = new PathNode();
|
|
|
pathNode.Tiles.AddRange(Follow(start, dir));
|
|
|
+ map[start.Position] = pathNode;
|
|
|
|
|
|
- var crossing = At(pathNode.Tiles.Last().Position.Add(pathNode.Tiles.Last().ArrowDirection()))!;
|
|
|
- crossing.Incoming.Add(pathNode);
|
|
|
+ var arrowTile = pathNode.Tiles.Last();
|
|
|
+ var crossing = At(arrowTile.Position.Add(arrowTile.ArrowDirection()))!;
|
|
|
|
|
|
if (crossing != At(_goal))
|
|
|
{
|
|
|
foreach (var outgoing in Neighbors(crossing)
|
|
|
.Where(x => x.Position.Add(x.ArrowDirection()) != crossing.Position))
|
|
|
{
|
|
|
- pathNode.Connected.Add(BuildPath(outgoing, outgoing.ArrowDirection()));
|
|
|
+ var outgoingPath = BuildPath(outgoing, outgoing.ArrowDirection(), map);
|
|
|
+ outgoingPath.Incoming.Add(pathNode);
|
|
|
+ pathNode.Outgoing.Add(outgoingPath);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -173,21 +169,4 @@ public class Map
|
|
|
|
|
|
yield return current;
|
|
|
}
|
|
|
-
|
|
|
- private IEnumerable<PathNode> BreadthFirst()
|
|
|
- {
|
|
|
- Assert(_root != null);
|
|
|
- var queue = new Queue<PathNode>();
|
|
|
- queue.Enqueue(_root!);
|
|
|
- while (queue.Count > 0)
|
|
|
- {
|
|
|
- var current = queue.Dequeue();
|
|
|
- yield return current;
|
|
|
-
|
|
|
- foreach (var next in current.Connected)
|
|
|
- {
|
|
|
- queue.Enqueue(next);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
}
|