Add timeout when calculating unreachable path

5s timeout, assuming destination is unreachable otherwise.
This commit is contained in:
ORelio 2015-12-17 17:40:26 +01:00
parent 902b04656c
commit 71277362be

View file

@ -98,54 +98,59 @@ namespace MinecraftClient.Mapping
/// <returns>A list of locations, or null if calculation failed</returns> /// <returns>A list of locations, or null if calculation failed</returns>
public static Queue<Location> CalculatePath(World world, Location start, Location goal, bool allowUnsafe = false) public static Queue<Location> CalculatePath(World world, Location start, Location goal, bool allowUnsafe = false)
{ {
HashSet<Location> ClosedSet = new HashSet<Location>(); // The set of locations already evaluated. Queue<Location> result = null;
HashSet<Location> OpenSet = new HashSet<Location>(new []{ start }); // The set of tentative nodes to be evaluated, initially containing the start node
Dictionary<Location, Location> Came_From = new Dictionary<Location, Location>(); // The map of navigated nodes.
Dictionary<Location, int> g_score = new Dictionary<Location, int>(); //:= map with default value of Infinity AutoTimeout.Perform(() =>
g_score[start] = 0; // Cost from start along best known path.
// Estimated total cost from start to goal through y.
Dictionary<Location, int> f_score = new Dictionary<Location, int>(); //:= map with default value of Infinity
f_score[start] = (int)start.DistanceSquared(goal); //heuristic_cost_estimate(start, goal)
while (OpenSet.Count > 0)
{ {
Location current = //the node in OpenSet having the lowest f_score[] value HashSet<Location> ClosedSet = new HashSet<Location>(); // The set of locations already evaluated.
OpenSet.Select(location => f_score.ContainsKey(location) HashSet<Location> OpenSet = new HashSet<Location>(new[] { start }); // The set of tentative nodes to be evaluated, initially containing the start node
? new KeyValuePair<Location, int>(location, f_score[location]) Dictionary<Location, Location> Came_From = new Dictionary<Location, Location>(); // The map of navigated nodes.
: new KeyValuePair<Location, int>(location, int.MaxValue))
.OrderBy(pair => pair.Value).First().Key; Dictionary<Location, int> g_score = new Dictionary<Location, int>(); //:= map with default value of Infinity
if (current == goal) g_score[start] = 0; // Cost from start along best known path.
{ //reconstruct_path(Came_From, goal) // Estimated total cost from start to goal through y.
List<Location> total_path = new List<Location>(new[] { current }); Dictionary<Location, int> f_score = new Dictionary<Location, int>(); //:= map with default value of Infinity
while (Came_From.ContainsKey(current)) f_score[start] = (int)start.DistanceSquared(goal); //heuristic_cost_estimate(start, goal)
{
current = Came_From[current]; while (OpenSet.Count > 0)
total_path.Add(current);
}
total_path.Reverse();
return new Queue<Location>(total_path);
}
OpenSet.Remove(current);
ClosedSet.Add(current);
foreach (Location neighbor in GetAvailableMoves(world, current, allowUnsafe))
{ {
if (ClosedSet.Contains(neighbor)) Location current = //the node in OpenSet having the lowest f_score[] value
continue; // Ignore the neighbor which is already evaluated. OpenSet.Select(location => f_score.ContainsKey(location)
int tentative_g_score = g_score[current] + (int)current.DistanceSquared(neighbor); //dist_between(current,neighbor) // length of this path. ? new KeyValuePair<Location, int>(location, f_score[location])
if (!OpenSet.Contains(neighbor)) // Discover a new node : new KeyValuePair<Location, int>(location, int.MaxValue))
OpenSet.Add(neighbor); .OrderBy(pair => pair.Value).First().Key;
else if (tentative_g_score >= g_score[neighbor]) if (current == goal)
continue; // This is not a better path. { //reconstruct_path(Came_From, goal)
List<Location> total_path = new List<Location>(new[] { current });
while (Came_From.ContainsKey(current))
{
current = Came_From[current];
total_path.Add(current);
}
total_path.Reverse();
result = new Queue<Location>(total_path);
}
OpenSet.Remove(current);
ClosedSet.Add(current);
foreach (Location neighbor in GetAvailableMoves(world, current, allowUnsafe))
{
if (ClosedSet.Contains(neighbor))
continue; // Ignore the neighbor which is already evaluated.
int tentative_g_score = g_score[current] + (int)current.DistanceSquared(neighbor); //dist_between(current,neighbor) // length of this path.
if (!OpenSet.Contains(neighbor)) // Discover a new node
OpenSet.Add(neighbor);
else if (tentative_g_score >= g_score[neighbor])
continue; // This is not a better path.
// This path is the best until now. Record it! // This path is the best until now. Record it!
Came_From[neighbor] = current; Came_From[neighbor] = current;
g_score[neighbor] = tentative_g_score; g_score[neighbor] = tentative_g_score;
f_score[neighbor] = g_score[neighbor] + (int)neighbor.DistanceSquared(goal); //heuristic_cost_estimate(neighbor, goal) f_score[neighbor] = g_score[neighbor] + (int)neighbor.DistanceSquared(goal); //heuristic_cost_estimate(neighbor, goal)
}
} }
} }, TimeSpan.FromSeconds(5));
return null; return result;
} }
/* ========= LOCATION PROPERTIES ========= */ /* ========= LOCATION PROPERTIES ========= */