Exemple #1
0
        /// <summary>
        /// Uses A* to find the distance from the startNode to the destinationNode.
        /// </summary>
        /// <param name="start">The starting waypoint.</param>
        /// <param name="destination">The destination waypoint.</param>
        /// <param name="wrongTierPenalty">The penalty for the waypoints not being on the same tier.</param>
        /// <param name="emulatePodCarrying">Indicates whether to calculate a path that is ensured to be safe for carrying a pod on it.</param>
        /// <returns>The distance.</returns>
        private double CalculateShortestPath(Waypoint start, Waypoint destination, double wrongTierPenalty, bool emulatePodCarrying)
        {
            if (start == null || destination == null)
            {
                return(double.PositiveInfinity);
            }
            if (start == destination)
            {
                return(0);
            }
            // Determine shortest time
            double shortestTime = double.PositiveInfinity;

            foreach (var startNode in _timeGraph.TimeWaypointsOfOriginalWaypoints[start])
            {
                Dictionary <TimeWaypoint, TimeWaypointSearchDatapoint> openLocations   = new Dictionary <TimeWaypoint, TimeWaypointSearchDatapoint>();
                Dictionary <TimeWaypoint, TimeWaypointSearchDatapoint> closedLocations = new Dictionary <TimeWaypoint, TimeWaypointSearchDatapoint>();
                openLocations[startNode] = new TimeWaypointSearchDatapoint(0.0, EstimateTravelTime(startNode, destination), startNode, null, 0);

                // Loop until end is found
                while (true)
                {
                    // Find lowest cost waypoint in openLocations
                    KeyValuePair <TimeWaypoint, TimeWaypointSearchDatapoint> currentNodeKVP = openLocations.ArgMin(w => w.Value.TimeTraveled + w.Value.TimeToGoal);
                    // Something wrong happened -can't find the end
                    if (currentNodeKVP.Equals(default(KeyValuePair <TimeWaypoint, TimeWaypointSearchDatapoint>)))
                    {
                        break;
                    }
                    TimeWaypoint currentNode = currentNodeKVP.Key;

                    // Grab the details about the current waypoint
                    TimeWaypointSearchDatapoint currentNodeData = currentNodeKVP.Value;

                    // If the closest is also the destination or out of iterations
                    if (currentNode.OriginalWaypoint == destination)
                    {
                        // Update traveled time
                        shortestTime = Math.Min(shortestTime, currentNodeData.TimeTraveled);
                        break;
                    }

                    // Transfer closest from open to closed list
                    closedLocations[currentNode] = currentNodeKVP.Value;
                    openLocations.Remove(currentNode);

                    // Expand all the moves
                    foreach (var edge in currentNode.Edges)
                    {
                        // Check whether the node is already on closed
                        if (closedLocations.ContainsKey(edge.Item1))
                        {
                            // Don't deal with anything already on the closed list (don't want loops)
                            continue;
                        }

                        // Can't use a pod storage location for the path
                        if (emulatePodCarrying && edge.Item1.OriginalWaypoint.PodStorageLocation && edge.Item1.OriginalWaypoint != destination)
                        {
                            continue;
                        }

                        // Tag on more distance for a node on the wrong level
                        double additionalDistance = 0;
                        if (edge.Item1.OriginalWaypoint.Tier != destination.Tier)
                        {
                            additionalDistance += wrongTierPenalty;
                        }

                        // If it's not in the open list, add it
                        if (!openLocations.ContainsKey(edge.Item1))
                        {
                            openLocations[edge.Item1] =
                                new TimeWaypointSearchDatapoint(
                                    currentNodeData.TimeTraveled + edge.Item2,                        // The distance already traveled
                                    EstimateTravelTime(edge.Item1, destination) + additionalDistance, // The approximate distance to the goal
                                    edge.Item1,                                                       // The node itself
                                    currentNodeData,                                                  // Parent data
                                    currentNodeData.Depth + 1);                                       // The current depth
                        }
                        else
                        {
                            // It's already in the open list, but see if this new path is better
                            TimeWaypointSearchDatapoint oldPath = openLocations[edge.Item1];
                            // Replace it with the new one, if better
                            if (oldPath.TimeTraveled > currentNodeData.TimeTraveled + edge.Item2)
                            {
                                oldPath.TimeTraveled = currentNodeData.TimeTraveled + edge.Item2;                        // The distance already traveled
                                oldPath.TimeToGoal   = EstimateTravelTime(edge.Item1, destination) + additionalDistance; // The approximate distance to the goal
                                oldPath.Waypoint     = edge.Item1;                                                       // The node itself
                                oldPath.ParentMove   = currentNodeData;                                                  // Parent data
                                oldPath.Depth        = currentNodeData.Depth + 1;                                        // The current depth
                            }
                        }
                    }
                }
            }
            // Return time
            return(shortestTime);
        }
Exemple #2
0
 /// <summary>
 /// Creates a new waypoint search data object.
 /// </summary>
 /// <param name="timeTraveled">The time traveled so far.</param>
 /// <param name="timeToGoal">The estimated time towards the destination.</param>
 /// <param name="waypoint">The waypoint this data object belongs to.</param>
 /// <param name="parentMove">The data of the parent.</param>
 /// <param name="depth">The steps we did to come here.</param>
 public TimeWaypointSearchDatapoint(double timeTraveled, double timeToGoal, TimeWaypoint waypoint, TimeWaypointSearchDatapoint parentMove, int depth)
 {
     TimeTraveled = timeTraveled; TimeToGoal = timeToGoal; Waypoint = waypoint; ParentMove = parentMove; Depth = depth;
 }