private List <INavigableTile> ProcessPath(Dictionary <INavigableTile, INavigableTile> tiles, INavigableTile start, INavigableTile end)
    {
        var path = new List <INavigableTile>();

        INavigableTile current = end;

        while (tiles.ContainsKey(current))
        {
            path.Add(current);
            current = tiles[current];
        }

        path.Reverse();

        return(path);
    }
    private List <INavigableTile> FindPath(List <INavigableTile> allTiles, INavigableTile startTile, INavigableTile endTile)
    {
        if (allTiles.Contains(startTile) == false || allTiles.Contains(endTile) == false)
        {
            Debug.LogWarning("AStarPath: Attempting to find path but the start / end path are not part of the graph");
            return(null);
        }

        //Variable init
        Dictionary <INavigableTile, INavigableTile> path = new Dictionary <INavigableTile, INavigableTile>();

        List <INavigableTile> closedSet = new List <INavigableTile>();

        PriorityQueue <float, INavigableTile> openSet = new PriorityQueue <float, INavigableTile>();

        openSet.Enqueue(0, startTile);

        //G Score Init
        Dictionary <INavigableTile, float> g_score = new Dictionary <INavigableTile, float>();

        foreach (INavigableTile h in allTiles)
        {
            g_score[h] = Mathf.Infinity;
        }

        g_score[startTile] = 0;

        //F score init
        Dictionary <INavigableTile, float> f_score = new Dictionary <INavigableTile, float>();

        foreach (INavigableTile h in allTiles)
        {
            f_score[h] = Mathf.Infinity;
        }

        f_score[startTile] = DefaultEstimate(startTile, endTile);

        //Search loop
        while (!openSet.IsEmpty)
        {
            INavigableTile current = openSet.Dequeue().Value;

            //path is complete
            if (current == endTile)
            {
                return(ProcessPath(path, startTile, endTile));
            }

            closedSet.Add(current);

            foreach (var n in current.Neighbours)
            {
                //If move cost is infinite, or tile is impassable
                if (n == null || (n.IsUnlocked == false) || closedSet.Contains(n))
                {
                    continue;
                }

                float tentative_g_score = g_score[current] + n.MoveIntoCost;

                if (openSet.Contains(n))
                {
                    //a shorter path has been found before
                    if (tentative_g_score >= g_score[n])
                    {
                        continue;
                    }
                }

                path[n] = current;

                g_score[n] = tentative_g_score;
                f_score[n] = g_score[n] + DefaultEstimate(n, endTile);

                if (openSet.Contains(n) == false)
                {
                    openSet.Enqueue(f_score[n], n);
                }
            }
        }

        return(null);
    }
 private float DefaultEstimate(INavigableTile a, INavigableTile b)
 {
     return(Vector3.Distance(a.Position, b.Position));
 }
 public AStarPath(List <INavigableTile> allTiles, INavigableTile startTile, INavigableTile endTile)
 {
     Start     = startTile;
     End       = endTile;
     ValidPath = FindPath(allTiles, startTile, endTile);
 }