Beispiel #1
0
    public Path CreateCompletePath(GridClustered _GridClustered, Dictionary <Tile, Path> _AllFirstParts, Dictionary <Tile, Path> _AllLastParts)
    {
        // init path with the last part which connect the last bridge with the goal
        Path path = new Path(_AllLastParts[m_Bridge.End]);

        // Save the current bridge to reach
        Bridge bridgeToReach = m_Bridge;

        // move backward in the bridgeStep list
        BridgeStep step = this.m_Previous;

        // Each iteration, merge the right path before the current path

        while (step != null)
        {
            Cluster cluster        = _GridClustered.GetClusterOfTile(bridgeToReach.Start);
            Bridge  previousBridge = step.Bridge;

            Path partPath = bridgeToReach.GetPathToBridgeBeginningWith(previousBridge.End);
            path.MergeBefore(partPath.ReversedPath());

            step          = step.m_Previous;
            bridgeToReach = previousBridge;
        }
        path.MergeBefore(_AllFirstParts[bridgeToReach.Start]);

        return(path);
    }
Beispiel #2
0
    public GridClustered CreateGridClustered(int _SizeClusterRows, int _SizeClusterColumns)
    {
        string        pathFile = $@"{Application.persistentDataPath}/Maps/{m_FileName}";
        GridClustered grid     = new GridClustered(pathFile, m_GridRenderer, _SizeClusterRows, _SizeClusterColumns);

        return(grid);
    }
    private void GenerateClusters(int _RowsSize, int _ColumnsSize)
    {
        if (m_GameGrid == null)
        {
            return;
        }

        m_GridClustered      = new GridClustered(m_GameGrid, _RowsSize, _ColumnsSize);
        m_SizeClusterRows    = _RowsSize;
        m_SizeClusterColumns = _ColumnsSize;
    }
Beispiel #4
0
    /// <summary>
    /// Search a path with HPA algorithm
    /// </summary>
    /// <param name="_Start">Tile to start from</param>
    /// <param name="_End">Tile to reach</param>
    /// <param name="_ChronoInfos">Struct with times value to evaluate performance</param>
    /// <param name="_MaxSeconds">Max time allowed to search a solution. If value is negative, no time limit applied</param>
    /// <returns>the shortest path from start tile to end tile if it exists, null otherwise</returns>
    public static Path SearchHPAFromTo(GridClustered _GridClustered, Tile _Start, Tile _End, out ChronoInfos _ChronoInfos, float _MaxSeconds)
    {
        StartChrono();

        if (_Start == null || !_Start.IsAccessible || _End == null || !_End.IsAccessible || _GridClustered == null)
        {
            _ChronoInfos = ChronoInfos.InfosNone;
            return(null);
        }

        Cluster startCluster    = _GridClustered.GetClusterOfTile(_Start);
        Cluster endCluster      = _GridClustered.GetClusterOfTile(_End);
        Path    instantSolution = null;

        if (startCluster == endCluster && (instantSolution = startCluster.ComputeInternalPathFromTo(_Start, _End)) != null)
        {
            _ChronoInfos = StopChrono(_Start, _End, true);
            return(instantSolution);
        }

        List <BridgeStep>           openList = new List <BridgeStep>();
        CustomComparer <BridgeStep> comparer = new CustomComparer <BridgeStep>(false);

        HashSet <Bridge> closeSet = new HashSet <Bridge>();

        // store all the possible bridges connected to the start tile with their path
        // populate the open list with these bridges as all possible first steps
        Dictionary <Tile, Path> allFirstParts = new Dictionary <Tile, Path>();

        for (int i = 0; i < startCluster.Bridges.Count; i++)
        {
            Path path = startCluster.ComputeInternalPathFromTo(_Start, startCluster.Bridges[i].Start);
            if (path != null)
            {
                allFirstParts.Add(startCluster.Bridges[i].Start, path);

                BridgeStep stepToAdd      = new BridgeStep(startCluster.Bridges[i], path.Weight);
                int        indexInsertion = openList.BinarySearch(stepToAdd, comparer);
                if (indexInsertion < 0)
                {
                    indexInsertion = ~indexInsertion;
                }
                openList.Insert(indexInsertion, stepToAdd);
            }
        }

        // store all the possible bridges connected to the end tile with their path
        Dictionary <Tile, Path> allLastParts = new Dictionary <Tile, Path>();

        for (int i = 0; i < endCluster.Bridges.Count; i++)
        {
            Path path = endCluster.ComputeInternalPathFromTo(endCluster.Bridges[i].Start, _End);
            if (path != null)
            {
                allLastParts.Add(endCluster.Bridges[i].Start, path);
            }
        }

        while (openList.Count > 0)
        {
            if (_MaxSeconds > 0 && chrono.Elapsed.TotalSeconds > _MaxSeconds)
            {
                _ChronoInfos = StopChrono(_Start, _End, false);
                return(null);
            }

            BridgeStep stepToExtend = openList.Last();

            removeFromOpenChrono -= chrono.ElapsedMilliseconds;
            openList.RemoveAt(openList.Count - 1);
            removeFromOpenChrono += chrono.ElapsedMilliseconds;

            // if the step is already marked as solution, then it's the shortest solution
            if (stepToExtend.ReachedGoal)
            {
                // recreate whole path
                createSolutionChrono -= chrono.ElapsedMilliseconds;
                Path solution = stepToExtend.CreateCompletePath(_GridClustered, allFirstParts, allLastParts);
                createSolutionChrono += chrono.ElapsedMilliseconds;

                _ChronoInfos = StopChrono(_Start, _End, true);
                return(solution);
            }

            Bridge bridgeToExtend = stepToExtend.Bridge;
            if (closeSet.Contains(bridgeToExtend))
            {
                continue;
            }

            closeSet.Add(bridgeToExtend);

            // when reach a bridge with an end connected to the goal (check in the dictionary allLastParts) for the first time, mark it as one possible solution
            // with the mark, add also the weight of the last part which connect the end bridge and the goal
            // then, re-insert it in the open list at the right index.
            // if we try to extend a bridge already marked, then it's the shortest solution

            // if the bridge to extend is a bridge with the end connected to the goal cluster (in dictionary allLastParts)
            if (endCluster.Bridges.Exists(bridge => bridge.Start == bridgeToExtend.End) && allLastParts.ContainsKey(bridgeToExtend.End))
            {
                // mark step as possible solution and add the weight of the right last part
                stepToExtend.MarkAsSolution(allLastParts[stepToExtend.Bridge.End].Weight);

                // find the right index to re-insert in open list
                // if we try to extend it again, it means that it's the shortest path to the goal
                int indexInsertion = openList.BinarySearch(stepToExtend, comparer);
                if (indexInsertion < 0)
                {
                    indexInsertion = ~indexInsertion;
                }
                openList.Insert(indexInsertion, stepToExtend);
            }
            else
            {
                // Get the cluster from the bridgeToExtend End
                Cluster cluster = _GridClustered.GetClusterOfTile(bridgeToExtend.End);

                // Get the right reversed bridge
                Bridge reverseBridge = cluster.Bridges.Find(b => b.Start == bridgeToExtend.End);

                // loop through all the reversed bridge neighbors
                foreachNeighborsChrono -= chrono.ElapsedMilliseconds;
                foreach (Bridge neighbor in reverseBridge.Neighbors.Keys)
                {
                    // if the bridge is already in close set, skip to next neighbor
                    searchInCloseListChrono -= chrono.ElapsedMilliseconds;
                    bool existInCloseList = closeSet.Contains(neighbor);
                    searchInCloseListChrono += chrono.ElapsedMilliseconds;
                    if (existInCloseList)
                    {
                        continue;
                    }

                    // create extension with neighbor
                    extendPathChrono -= chrono.ElapsedMilliseconds;
                    BridgeStep extension = stepToExtend.MakeExtensionWith(neighbor, reverseBridge.Neighbors[neighbor].Weight);
                    extendPathChrono += chrono.ElapsedMilliseconds;

                    searchInsertionChrono -= chrono.ElapsedMilliseconds;
                    int indexInsertion = openList.BinarySearch(extension, comparer);
                    if (indexInsertion < 0)
                    {
                        indexInsertion = ~indexInsertion;
                    }
                    searchInsertionChrono += chrono.ElapsedMilliseconds;

                    insertToOpenListChrono -= chrono.ElapsedMilliseconds;
                    openList.Insert(indexInsertion, extension);
                    insertToOpenListChrono += chrono.ElapsedMilliseconds;
                }
                foreachNeighborsChrono += chrono.ElapsedMilliseconds;
            }
        }

        // No path found in limited time
        _ChronoInfos = StopChrono(_Start, _End, false);
        return(null);
    }
Beispiel #5
0
 public Cluster(int _AnchorRow, int _AnchorColumn, int _Rows, int _Columns, GridClustered _OwnerGrid) : this(_AnchorRow, _AnchorColumn, _Rows, _Columns)
 {
     m_OwnerGrid = _OwnerGrid;
 }