예제 #1
0
        /// <summary>
        ///     Performs path search using A* algorithm for a given start and list of goals.
        ///     <para>Returns list of nodes from best ending node to starting node.</para>
        ///     <para>Returns null if there is no path to any of the goals.</para>
        /// </summary>
        /// <param name="start">Starting node</param>
        /// <param name="goals">List of ending nodes</param>
        /// <param name="limiter">Maximum length of path to search for</param>
        public static List <MainNode> MultiAStar(MainNode start, List <T> goals, int limiter = int.MaxValue)
        {
            if (goals.All(g => g == null) || start == null)
            {
                return(null);
            }
            Stopwatch s    = Stopwatch.StartNew();
            var       open = new Heap <MainNode> {
                MinHeap = true
            };
            var closed   = new HashSet <MainNode>();
            var gs       = new Dictionary <MainNode, float>();
            var fs       = new Dictionary <MainNode, float>();
            var cameFrom = new Dictionary <MainNode, MainNode>();

            open.Add(start, 0.0f);
            while (open.Count > 0)
            {
                MainNode current = open.PopFirst().Object;
                if (goals.Exists(t => current.NodeEqual(t)))
                {
                    open.Clear();
                    closed.Clear();
                    var t = ToList(current, cameFrom);
                    s.Stop();
                    Add(ref _at, s.Elapsed.TotalMilliseconds);
                    return(t);
                }
                closed.Add(current);
                if (gs.GetValueOrDefault(current, 0f) > limiter)
                {
                    continue;
                }
                foreach (MainNode neighbor in current.GetNeighbors())
                {
                    var num = gs.GetValueOrDefault(current, 0f) + current.Distance(neighbor);
                    if ((closed.Contains(neighbor) ||
                         open.Contains(neighbor)) && num >= gs.GetValueOrDefault(neighbor, 0f))
                    {
                        continue;
                    }
                    cameFrom[neighbor] = current;
                    gs[neighbor]       = num;
                    fs[neighbor]       = gs[neighbor] + goals.Min(t => neighbor.Heuristic(t));
                    if (!open.Contains(neighbor))
                    {
                        open.Add(neighbor, fs[neighbor]);
                    }
                }
            }
            open.Clear();
            closed.Clear();
            s.Stop();
            Add(ref _at, s.Elapsed.TotalMilliseconds);
            return(null);
        }
예제 #2
0
        /// <summary>
        ///     Performs path search using Dijkstra's algorithm for a given predicate.
        ///     <para>Returns list of nodes from ending to starting node.</para>
        ///     <para>Returns null if there is no path to goal.</para>
        /// </summary>
        /// <param name="start">Starting node</param>
        /// <param name="targeting">Predicate distinguishing end nodes from the rest</param>
        /// <param name="limiter">Maximum length of path to search for</param>
        public static List <MainNode> Dijkstra(MainNode start, Predicate <MainNode> targeting, int limiter = int.MaxValue)
        {
            if (start == null)
            {
                return(null);
            }
            Stopwatch s    = Stopwatch.StartNew();
            var       open = new Heap <MainNode> {
                MinHeap = true
            };
            var closed   = new HashSet <MainNode>();
            var gs       = new Dictionary <MainNode, float>();
            var cameFrom = new Dictionary <MainNode, MainNode>();

            open.Add(start, 0.0f);
            while (open.Count > 0)
            {
                MainNode current = open.PopFirst().Object;
                if (targeting.Invoke(current))
                {
                    open.Clear();
                    closed.Clear();
                    var t = ToList(current, cameFrom);
                    s.Stop();
                    Add(ref _dt, s.Elapsed.TotalMilliseconds);
                    return(t);
                }
                closed.Add(current);
                if (gs.GetValueOrDefault(current, 0f) > limiter)
                {
                    continue;
                }
                foreach (MainNode neighbor in current.GetNeighbors())
                {
                    var num = gs.GetValueOrDefault(current, 0f) + current.Distance(neighbor);
                    if ((closed.Contains(neighbor) ||
                         open.Contains(neighbor)) && num >= gs.GetValueOrDefault(neighbor, 0f))
                    {
                        continue;
                    }
                    cameFrom[neighbor] = current;
                    gs[neighbor]       = num;
                    if (!open.Contains(neighbor))
                    {
                        open.Add(neighbor, gs.GetValueOrDefault(neighbor, 0f));
                    }
                }
            }
            open.Clear();
            closed.Clear();
            s.Stop();
            Add(ref _dt, s.Elapsed.TotalMilliseconds);
            return(null);
        }
예제 #3
0
        private static List <MainNode> ToList(MainNode current, IDictionary <MainNode, MainNode> cameFrom)
        {
            var objList = new List <MainNode>();

            while (current != null)
            {
                objList.Add(current);
                current = cameFrom.GetValueOrDefault(current, null);
            }
            return(objList);
        }
예제 #4
0
 /// <summary>
 ///     Approximates distance between two nodes using given metric.
 /// </summary>
 /// <param name="goal">Second node to measure distance to</param>
 public abstract float Heuristic(MainNode goal);
예제 #5
0
 /// <summary>
 ///     Returns distance between two nodes using given metric.
 /// </summary>
 /// <param name="b">Second node to measure distance to</param>
 public abstract float Distance(MainNode b);
예제 #6
0
 /// <summary>
 ///     Checks if two nodes are equal.
 /// </summary>
 /// <param name="b">Second node to check</param>
 public abstract bool NodeEqual(MainNode b);
예제 #7
0
 /// <summary>
 ///     Checks if two nodes are equal.
 /// </summary>
 /// <param name="b">Second node to check</param>
 public override bool NodeEqual(MainNode b)
 {
     return(((HashNode)b).Id == Id);
 }
예제 #8
0
        public override float Heuristic(MainNode goal)
        {
            Manhattan2DNode manhattan2Dnode = (Manhattan2DNode)goal;

            return(Math.Abs(manhattan2Dnode.X - X) + Math.Abs(manhattan2Dnode.Y - Y));
        }
예제 #9
0
 public override float Distance(MainNode b)
 {
     return((10 + ((Manhattan2DNode)b).Wall) * 0.1f);
 }
예제 #10
0
        public override bool NodeEqual(MainNode b)
        {
            Manhattan2DNode manhattan2Dnode = (Manhattan2DNode)b;

            return(manhattan2Dnode.X == X && manhattan2Dnode.Y == Y);
        }