public Origin(PathPoint from, Tool tool, int distance) { From = from; Tool = tool; Distance = distance; }
private static Dictionary <Point, PathPoint> FindShortestPaths(RegionType[,] riskLevelMap, Point start) { // Dictionary with found paths Dictionary <Point, PathPoint> routes = riskLevelMap.ToQueryable((x, y, item) => new PathPoint() { Location = new Point(x, y), RegionType = riskLevelMap[y, x], ToolToOrigin = RegionToTools[riskLevelMap[y, x]].ToDictionary(z => z, z => new Origin(null, z, int.MaxValue - 10)) }).ToDictionary(x => x.Location); // Set starting point routes[start].ToolToOrigin[Tool.Torch] = new Origin(null, Tool.Torch, 0); // Create process query Queue <PathPoint> toProcess = new Queue <PathPoint>(); toProcess.Enqueue(routes[start]); // Faster search in toProcess HashSet <PathPoint> toProcessHash = new HashSet <PathPoint>() { toProcess.Single() }; // Fast search for neighbours Dictionary <PathPoint, PathPoint[]> neigbours = routes.ToDictionary(x => x.Value, x => x.Value.Neighbours(routes).ToArray()); // Main search loop while (toProcess.Any()) { PathPoint currentPoint = toProcess.Dequeue(); toProcessHash.Remove(currentPoint); // Examine all neighbours foreach (PathPoint neighbour in neigbours[currentPoint]) { // What if we didn't change the tool foreach (Tool tool in currentPoint.ToolToOrigin.Keys.Intersect(RegionToTools[neighbour.RegionType])) { int newDistance = currentPoint.ToolToOrigin[tool].Distance + 1; if (neighbour.ToolToOrigin[tool].Distance > newDistance) { neighbour.ToolToOrigin[tool] = new Origin(currentPoint, tool, newDistance); if (!toProcessHash.Contains(neighbour)) { toProcess.Enqueue(neighbour); toProcessHash.Add(neighbour); } } } // Or we have to change the tool foreach (Tool oldTool in currentPoint.ToolToOrigin.Keys.Except(RegionToTools[neighbour.RegionType])) { foreach (Tool newTool in RegionToTools[neighbour.RegionType]) { int newDistance = currentPoint.ToolToOrigin[oldTool].Distance + 1 + 7; if (neighbour.ToolToOrigin[newTool].Distance > newDistance) { neighbour.ToolToOrigin[newTool] = new Origin(currentPoint, newTool, newDistance); if (!toProcessHash.Contains(neighbour)) { toProcess.Enqueue(neighbour); toProcessHash.Add(neighbour); } } } } } } return(routes); }