コード例 #1
0
 public void Enqueue(List <MiniMapSector> queue, MiniMapSector sector)
 {
     if (!queue.Find((sec) => sector.Equals(sec)))
     {
         queue.Add(sector);
     }
 }
コード例 #2
0
        public MiniMapSector AcquireSector(int x, int y, int z, bool forceCache)
        {
            x = System.Math.Max(Constants.MapMinX, System.Math.Min(x, Constants.MapMaxX));
            y = System.Math.Max(Constants.MapMinY, System.Math.Min(y, Constants.MapMaxY));
            z = System.Math.Max(Constants.MapMinZ, System.Math.Min(z, Constants.MapMaxZ));

            x = x / Constants.MiniMapSectorSize * Constants.MiniMapSectorSize;
            y = y / Constants.MiniMapSectorSize * Constants.MiniMapSectorSize;

            MiniMapSector sector = _sectorCache.Find((sec) => sec.Equals(x, y, z));

            if (sector)
            {
                return(sector);
            }
            else

            if (!sector)
            {
                sector = new MiniMapSector(x, y, z);
                if (forceCache)
                {
                    // load it right now
                    sector.LoadSharedObject();

                    // if it exists in the load queue, then remove it
                    Dequeue(_loadQueue, sector);
                }
                else
                {
                    // don't load cache, it ain't really needed
                    Enqueue(_loadQueue, sector);
                }
            }

            // pop the oldest sector
            if (_sectorCache.Count >= Constants.MiniMapCacheSize)
            {
                _sectorCache.RemoveAt(0);
            }

            _sectorCache.Add(sector);
            return(sector);
        }
コード例 #3
0
        private PathState CalculateAStartPath(int startX, int startY, int startZ, int targetX, int targetY, int targetZ, int searchLimit, List <int> steps)
        {
            MiniMapSector[] sectors = new MiniMapSector[4];
            sectors[0] = AcquireSector(startX - Constants.PathMatrixCenter, startY - Constants.PathMatrixCenter, startZ, false);
            sectors[1] = AcquireSector(startX - Constants.PathMatrixCenter, startY + Constants.PathMatrixCenter, startZ, false);
            sectors[2] = AcquireSector(startX + Constants.PathMatrixCenter, startY + Constants.PathMatrixCenter, startZ, false);
            sectors[3] = AcquireSector(startX + Constants.PathMatrixCenter, startY - Constants.PathMatrixCenter, startZ, false);

            // initial sector position (start position in minimap storage)
            var sectorMaxX = sectors[0].SectorX + Constants.MiniMapSectorSize;
            var sextorMaxY = sectors[0].SectorY + Constants.MiniMapSectorSize;

            var closedList = new Dictionary <int, PathItem>();
            var openList   = new Utils.PriorityQueue <KeyValuePair <PathItem, int> >(Comparer <KeyValuePair <PathItem, int> > .Create(ComparePathNodes));

            PathItem currentNode = new PathItem(startX, startY);

            closedList.Add(Hash2DPosition(startX, startY), currentNode);

            PathItem foundNode = null;

            PathState ret = PathState.PathErrorInternal;

            while (currentNode != null)
            {
                if (closedList.Count > searchLimit)
                {
                    ret = PathState.PathErrorTooFar;
                    break;
                }

                if (currentNode.X == targetX && currentNode.Y == targetY && (foundNode == null || currentNode.PathCost < foundNode.PathCost))
                {
                    foundNode = currentNode;
                }

                if (foundNode != null && (currentNode.PathHeuristic >= foundNode.PathCost))
                {
                    break;
                }

                for (int i = -1; i <= 1; i++)
                {
                    for (int j = -1; j <= 1; j++)
                    {
                        if (i == 0 && j == 0)
                        {
                            continue;
                        }

                        int currentPosX = currentNode.X + i;
                        int currentPosY = currentNode.Y + j;
                        int sectorIndex;
                        if (currentPosX < sectorMaxX)
                        {
                            sectorIndex = currentPosY < sextorMaxY ? 0 : 1;
                        }
                        else
                        {
                            sectorIndex = currentPosY < sextorMaxY ? 3 : 2;
                        }

                        int cost = sectors[sectorIndex].GetCost(currentPosX, currentPosY, startZ);
                        if (cost >= Constants.PathCostObstacle)
                        {
                            continue;
                        }

                        int modifier = 1;
                        if ((i * j) != 0)
                        {
                            modifier = 3;
                        }

                        int pathCost  = currentNode.PathCost + modifier * cost;
                        var direction = DirectionFromPosToPos(currentNode.X, currentNode.Y, currentPosX, currentPosY);

                        PathItem neighborNode;
                        if (closedList.TryGetValue(Hash2DPosition(currentPosX, currentPosY), out PathItem handledNode))
                        {
                            neighborNode = handledNode;
                            if (neighborNode.PathCost <= pathCost)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            neighborNode = new PathItem(currentPosX, currentPosY);
                            closedList.Add(Hash2DPosition(currentPosX, currentPosY), neighborNode);
                        }

                        neighborNode.Predecessor   = currentNode;
                        neighborNode.Cost          = cost;
                        neighborNode.PathCost      = pathCost;
                        neighborNode.PathHeuristic = neighborNode.PathCost + Distance(currentPosX, currentPosY, targetX, targetY);
                        neighborNode.Direction     = direction;

                        openList.Push(new KeyValuePair <PathItem, int>(neighborNode, neighborNode.PathHeuristic));
                    }
                }

                if (openList.Count > 0)
                {
                    currentNode = openList.Pop().Key;
                }
                else
                {
                    currentNode = null;
                }
            }

            if (foundNode != null)
            {
                currentNode = foundNode;
                while (currentNode != null)
                {
                    steps.Add((int)currentNode.Direction | currentNode.Cost << 16);
                    if (steps.Count + 1 >= Constants.PathMaxSteps)
                    {
                        break;
                    }
                    currentNode = currentNode.Predecessor;
                }

                steps.RemoveAt(steps.Count - 1);
                steps.Reverse();
                ret = PathState.PathExists;
            }

            return(ret);
        }
コード例 #4
0
 public void Dequeue(List <MiniMapSector> queue, MiniMapSector sector)
 {
     queue.Remove(sector);
 }
コード例 #5
0
ファイル: MiniMapSector.cs プロジェクト: Cjaker/TibiaUnity3D
 public bool Equals(MiniMapSector sector)
 {
     return(Equals(sector.SectorX, sector.SectorY, sector.SectorZ));
 }
コード例 #6
0
        public MiniMapSector AcquireSector(int x, int y, int z, bool cache)
        {
            x = System.Math.Max(Constants.MapMinX, System.Math.Min(x, Constants.MapMaxX));
            y = System.Math.Max(Constants.MapMinY, System.Math.Min(y, Constants.MapMaxY));
            z = System.Math.Max(Constants.MapMinZ, System.Math.Min(z, Constants.MapMaxZ));

            int sectorX = x / Constants.MiniMapSectorSize * Constants.MiniMapSectorSize;
            int sectorY = y / Constants.MiniMapSectorSize * Constants.MiniMapSectorSize;
            int sectorZ = z;

            MiniMapSector sector = null;
            int           it     = _sectorCache.Count - 1;

            while (it > 0)
            {
                var tmpSector = _sectorCache[it];
                if (tmpSector.Equals(sectorX, sectorY, sectorZ))
                {
                    sector = tmpSector;
                    _sectorCache.RemoveAt(it);
                    break;
                }

                it--;
            }

            if (!sector)
            {
                it = _saveQueue.Count - 1;
                while (it >= 0)
                {
                    var tmpSector = _saveQueue[it];
                    if (tmpSector.Equals(sectorX, sectorY, sectorZ))
                    {
                        sector = tmpSector;
                        break;
                    }

                    it--;
                }
            }

            if (!sector)
            {
                sector = new MiniMapSector(sectorX, sectorY, sectorZ);
                if (cache)
                {
                    sector.LoadSharedObject();
                    Dequeue(_loadQueue, sector);
                }
            }

            if (_sectorCache.Count >= Constants.MiniMapSectorSize)
            {
                MiniMapSector tmpSector = null;
                foreach (var sec in _sectorCache)
                {
                    if (!sec.Dirty)
                    {
                        tmpSector = sec;
                        _sectorCache.Remove(sec);
                        break;
                    }
                }

                if (!tmpSector)
                {
                    tmpSector = _sectorCache[0];
                    _sectorCache.RemoveAt(0);
                }

                Dequeue(_loadQueue, tmpSector);
                if (tmpSector.Dirty)
                {
                    Enqueue(_saveQueue, tmpSector);
                }
            }

            _sectorCache.Add(sector);
            return(sector);
        }
コード例 #7
0
        public PathState CalculatePath(int startX, int startY, int startZ, int targetX, int targetY, int targetZ, bool forceDiagonal, bool forceExact, List <int> steps)
        {
            int dX = targetX - startX;
            int dY = targetY - startY;

            if (steps == null)
            {
                return(PathState.PathErrorpublic);
            }
            else if (targetZ > startZ)
            {
                return(PathState.PathErrorGoDownstairs);
            }
            else if (targetZ < startZ)
            {
                return(PathState.PathErrorGoUpstairs);
            }
            else if (dX == 0 && dY == 0)
            {
                return(PathState.PathEmpty);
            }
            else if (System.Math.Abs(dX) >= Constants.PathMaxDistance || System.Math.Abs(dY) > Constants.PathMaxDistance)
            {
                return(PathState.PathErrorTooFar);
            }

            // check if this tile is known to be obstacle

            // simple case, adjacent square
            if (System.Math.Abs(dX) + System.Math.Abs(dY) == 1)
            {
                int cost = GetFieldCost(targetX, targetY, targetZ);
                if (forceExact || cost < Constants.PathCostObstacle)
                {
                    if (dX == 1 && dY == 0)
                    {
                        steps.Add((int)PathDirection.East);
                    }
                    else if (dX == 0 && dY == -1)
                    {
                        steps.Add((int)PathDirection.North);
                    }
                    else if (dX == -1 && dY == 0)
                    {
                        steps.Add((int)PathDirection.West);
                    }
                    else if (dX == 0 && dY == 1)
                    {
                        steps.Add((int)PathDirection.South);
                    }

                    steps[0] = steps[0] | cost << 16;
                    return(PathState.PathExists);
                }
                return(PathState.PathEmpty);
            }

            // simple case, adjacent diagonal square (while diagonal is actually allowed)
            if (forceDiagonal && System.Math.Abs(dX) == 1 && System.Math.Abs(dY) == 1)
            {
                int cost = GetFieldCost(targetX, targetY, targetZ);
                if (forceExact || cost < Constants.PathCostObstacle)
                {
                    if (dX == 1 && dY == -1)
                    {
                        steps.Add((int)PathDirection.NorthEast);
                    }
                    else if (dX == -1 && dY == -1)
                    {
                        steps.Add((int)PathDirection.NorthWest);
                    }
                    else if (dX == -1 && dY == 1)
                    {
                        steps.Add((int)PathDirection.SouthWest);
                    }
                    else if (dX == 1 && dY == 1)
                    {
                        steps.Add((int)PathDirection.SouthEast);
                    }
                    steps[0] = steps[0] | cost << 16;
                    return(PathState.PathExists);
                }
                return(PathState.PathEmpty);
            }

            // A* Algorithm

            // acquiring 4 directional sectors
            MiniMapSector[] tmpSectors = new MiniMapSector[4];
            tmpSectors[0] = AcquireSector(startX - Constants.PathMatrixCenter, startY - Constants.PathMatrixCenter, startZ, false);
            tmpSectors[1] = AcquireSector(startX - Constants.PathMatrixCenter, startY + Constants.PathMatrixCenter, startZ, false);
            tmpSectors[2] = AcquireSector(startX + Constants.PathMatrixCenter, startY + Constants.PathMatrixCenter, startZ, false);
            tmpSectors[3] = AcquireSector(startX + Constants.PathMatrixCenter, startY - Constants.PathMatrixCenter, startZ, false);

            // obtain local variables of constants
            int matrixCenter = Constants.PathMatrixCenter;
            int matrixSize   = Constants.PathMatrixSize;

            // heuristic multiplier
            var minCost = int.MaxValue;

            foreach (var sector in tmpSectors)
            {
                minCost = System.Math.Min(minCost, sector.MinCost);
            }

            // initial sector position (start position in minimap storage)
            var sectorMaxX = tmpSectors[0].SectorX + Constants.MiniMapSectorSize;
            var sextorMaxY = tmpSectors[0].SectorY + Constants.MiniMapSectorSize;

            // obtain the center of the grid, and resetting it
            // the center of the grid is matchin our initial position, so we will use MatrixCenter with offset as a workaround
            PathItem pathItem = _pathMatrix[matrixCenter * matrixSize + matrixCenter];

            pathItem.Reset();
            pathItem.Predecessor   = null;
            pathItem.Cost          = int.MaxValue;
            pathItem.PathCost      = int.MaxValue;
            pathItem.PathHeuristic = 0;
            _pathDirty.Add(pathItem); // push the initial position to the closed list

            // obtain the final position at our grid
            PathItem lastPathNode = _pathMatrix[(matrixCenter + dY) * Constants.PathMatrixSize + (matrixCenter + dX)];

            lastPathNode.Predecessor = null;
            lastPathNode.Reset();

            int tmpIndex;

            if (targetX < sectorMaxX)
            {
                tmpIndex = targetY < sextorMaxY ? 0 : 1;
            }
            else
            {
                tmpIndex = targetY < sextorMaxY ? 3 : 2;
            }

            lastPathNode.Cost     = tmpSectors[tmpIndex].GetCost(targetX, targetY, targetZ);
            lastPathNode.PathCost = 0;
            // from the constructor, the distance is the manhattan distance from start_pos to target_pos
            lastPathNode.PathHeuristic = lastPathNode.Cost + (lastPathNode.Distance - 1) * minCost;

            // now add that to our closed list
            _pathDirty.Add(lastPathNode);

            // clear our heap and push the current node to it.
            _pathHeap.Clear(false);
            _pathHeap.AddItem(lastPathNode, lastPathNode.PathHeuristic);

            PathItem currentPathItem = null;
            PathItem tmpPathItem     = null;

            // looping through the very first SQM in the heap
            while ((currentPathItem = _pathHeap.ExtractMinItem() as PathItem) != null)
            {
                // check if the current move won't exceed our current shortest path, otherwise end it up
                // if it exceeds, then we will loop again through our heap, if exists
                // if not, then we are done searching if the current path is undefined that means we can't
                // reach that field

                if (currentPathItem.HeapKey < pathItem.PathCost)
                {
                    for (int i = -1; i <= 1; i++)
                    {
                        for (int j = -1; j <= 1; j++)
                        {
                            if (i != 0 || j != 0)
                            {
                                int gridX = currentPathItem.X + i;
                                int gridY = currentPathItem.Y + j;

                                // check if that grid is in the range or validity
                                if (!(gridX < -matrixCenter || gridX > matrixCenter || gridY < -matrixCenter || gridY > matrixCenter))
                                {
                                    int currentPathCost;
                                    if (i * j == 0) // straight movement (not diagonal)
                                    {
                                        currentPathCost = currentPathItem.PathCost + currentPathItem.Cost;
                                    }
                                    else // diagonal movements worth as 3 as a normal movement;
                                    {
                                        currentPathCost = currentPathItem.PathCost + 3 * currentPathItem.Cost;
                                    }

                                    tmpPathItem = _pathMatrix[(matrixCenter + gridY) * matrixSize + (matrixCenter + gridX)];
                                    if (tmpPathItem.PathCost > currentPathCost)
                                    {
                                        tmpPathItem.Predecessor = currentPathItem;
                                        tmpPathItem.PathCost    = currentPathCost;
                                        if (tmpPathItem.Cost == int.MaxValue)
                                        {
                                            int currentPosX = startX + tmpPathItem.X;
                                            int currentPosY = startY + tmpPathItem.Y;
                                            if (currentPosX < sectorMaxX)
                                            {
                                                tmpIndex = currentPosY < sextorMaxY ? 0 : 1;
                                            }
                                            else
                                            {
                                                tmpIndex = currentPosY < sextorMaxY ? 3 : 2;
                                            }

                                            tmpPathItem.Cost          = tmpSectors[tmpIndex].GetCost(currentPosX, currentPosY, startZ);
                                            tmpPathItem.PathHeuristic = tmpPathItem.Cost + (tmpPathItem.Distance - 1) * minCost;
                                            _pathDirty.Add(tmpPathItem);
                                        }

                                        if (!(tmpPathItem == pathItem || tmpPathItem.Cost >= Constants.PathCostObstacle))
                                        {
                                            if (tmpPathItem.HeapParent != null)
                                            {
                                                _pathHeap.UpdateKey(tmpPathItem, currentPathCost + tmpPathItem.PathHeuristic);
                                            }
                                            else
                                            {
                                                tmpPathItem.Reset();
                                                _pathHeap.AddItem(tmpPathItem, currentPathCost + tmpPathItem.PathHeuristic);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            var ret = PathState.PathErrorpublic;

            if (pathItem.PathCost < int.MaxValue)
            {
                currentPathItem = pathItem;
                tmpPathItem     = null;
                while (currentPathItem != null)
                {
                    if (!forceExact && currentPathItem.X == lastPathNode.X && currentPathItem.Y == lastPathNode.Y && lastPathNode.Cost >= Constants.PathCostObstacle)
                    {
                        currentPathItem = null;
                        break;
                    }

                    if (currentPathItem.Cost == Constants.PathCostUndefined)
                    {
                        break;
                    }

                    if (tmpPathItem != null)
                    {
                        dX = currentPathItem.X - tmpPathItem.X;
                        dY = currentPathItem.Y - tmpPathItem.Y;
                        if (dX == 1 && dY == 0)
                        {
                            steps.Add((int)PathDirection.East);
                        }
                        else if (dX == 1 && dY == -1)
                        {
                            steps.Add((int)PathDirection.NorthEast);
                        }
                        else if (dX == 0 && dY == -1)
                        {
                            steps.Add((int)PathDirection.North);
                        }
                        else if (dX == -1 && dY == -1)
                        {
                            steps.Add((int)PathDirection.NorthWest);
                        }
                        else if (dX == -1 && dY == 0)
                        {
                            steps.Add((int)PathDirection.West);
                        }
                        else if (dX == -1 && dY == 1)
                        {
                            steps.Add((int)PathDirection.SouthWest);
                        }
                        else if (dX == 0 && dY == 1)
                        {
                            steps.Add((int)PathDirection.South);
                        }
                        else if (dX == 1 && dY == 1)
                        {
                            steps.Add((int)PathDirection.SouthEast);
                        }
                        steps[steps.Count - 1] = steps[steps.Count - 1] | currentPathItem.Cost << 16;
                        if (steps.Count + 1 >= Constants.PathMaxSteps)
                        {
                            break;
                        }
                    }

                    tmpPathItem     = currentPathItem;
                    currentPathItem = currentPathItem.Predecessor;
                }

                if (steps.Count == 0)
                {
                    ret = PathState.PathEmpty;
                }
                else
                {
                    ret = PathState.PathExists;
                }
            }
            else
            {
                ret = PathState.PathErrorUnreachable;
            }

            foreach (var tmp in _pathDirty)
            {
                tmp.Cost     = int.MaxValue;
                tmp.PathCost = int.MaxValue;
            }
            _pathDirty.Clear();
            return(ret);
        }
コード例 #8
0
        public PathState CalculatePath(int startX, int startY, int startZ, int targetX, int targetY, int targetZ, bool forceDiagonal, bool forceExact, List <int> steps)
        {
            int dX = targetX - startX;
            int dY = targetY - startY;

            if (steps == null)
            {
                return(PathState.PathErrorInternal);
            }
            else if (targetZ > startZ)
            {
                return(PathState.PathErrorGoUpstairs);
            }
            else if (targetZ < startZ)
            {
                return(PathState.PathErrorGoDownstairs);
            }
            else if (dX == 0 && dY == 0)
            {
                return(PathState.PathEmpty);
            }
            else if (System.Math.Abs(dX) >= Constants.PathMaxDistance || System.Math.Abs(dY) > Constants.PathMaxDistance)
            {
                return(PathState.PathErrorTooFar);
            }

            // check if this tile is known to be obstacle

            // simple case, adjacent square
            if (System.Math.Abs(dX) + System.Math.Abs(dY) == 1)
            {
                int cost = GetFieldCost(targetX, targetY, targetZ);
                if (forceExact || cost < Constants.PathCostObstacle)
                {
                    if (dX == 1 && dY == 0)
                    {
                        steps.Add((int)PathDirection.East);
                    }
                    else if (dX == 0 && dY == -1)
                    {
                        steps.Add((int)PathDirection.North);
                    }
                    else if (dX == -1 && dY == 0)
                    {
                        steps.Add((int)PathDirection.West);
                    }
                    else if (dX == 0 && dY == 1)
                    {
                        steps.Add((int)PathDirection.South);
                    }

                    steps[0] = steps[0] | cost << 16;
                    return(PathState.PathExists);
                }
                return(PathState.PathEmpty);
            }

            // simple case, adjacent diagonal square (while diagonal is actually allowed)
            if (forceDiagonal && System.Math.Abs(dX) == 1 && System.Math.Abs(dY) == 1)
            {
                int cost = GetFieldCost(targetX, targetY, targetZ);
                if (forceExact || cost < Constants.PathCostObstacle)
                {
                    if (dX == 1 && dY == -1)
                    {
                        steps.Add((int)PathDirection.NorthEast);
                    }
                    else if (dX == -1 && dY == -1)
                    {
                        steps.Add((int)PathDirection.NorthWest);
                    }
                    else if (dX == -1 && dY == 1)
                    {
                        steps.Add((int)PathDirection.SouthWest);
                    }
                    else if (dX == 1 && dY == 1)
                    {
                        steps.Add((int)PathDirection.SouthEast);
                    }
                    steps[0] = steps[0] | cost << 16;
                    return(PathState.PathExists);
                }
                return(PathState.PathEmpty);
            }

            // A* Algorithm

            // acquiring 4 directional sectors
            MiniMapSector[] tmpSectors = new MiniMapSector[4];
            tmpSectors[0] = AcquireSector(startX - Constants.PathMatrixCenter, startY - Constants.PathMatrixCenter, startZ, false);
            tmpSectors[1] = AcquireSector(startX - Constants.PathMatrixCenter, startY + Constants.PathMatrixCenter, startZ, false);
            tmpSectors[2] = AcquireSector(startX + Constants.PathMatrixCenter, startY + Constants.PathMatrixCenter, startZ, false);
            tmpSectors[3] = AcquireSector(startX + Constants.PathMatrixCenter, startY - Constants.PathMatrixCenter, startZ, false);

            // obtain local variables of constants
            int matrixCenter = Constants.PathMatrixCenter;
            int matrixSize   = Constants.PathMatrixSize;

            // heuristic multiplier
            var overallMinCost = int.MaxValue;

            foreach (var sector in tmpSectors)
            {
                overallMinCost = System.Math.Min(overallMinCost, sector.MinCost);
            }

            // initial sector position (start position in minimap storage)
            var sectorMaxX = tmpSectors[0].SectorX + Constants.MiniMapSectorSize;
            var sextorMaxY = tmpSectors[0].SectorY + Constants.MiniMapSectorSize;

            // obtain the center of the grid, and resetting it
            // the center of the grid is matchin our initial position, so we will use MatrixCenter with offset as a workaround
            PathQueueNode pathNode = m_PathMatrix[matrixCenter * matrixSize + matrixCenter];

            pathNode.Reset();
            pathNode.Predecessor   = null;
            pathNode.Cost          = pathNode.PathCost = int.MaxValue;
            pathNode.PathHeuristic = 0;

            m_PathDirty.Add(pathNode); // push the initial position to the closed list

            // obtain the final position at our grid
            PathQueueNode lastPathNode = m_PathMatrix[(matrixCenter + dY) * Constants.PathMatrixSize + (matrixCenter + dX)];

            lastPathNode.Predecessor = null;
            lastPathNode.Reset();

            int tmpIndex;

            if (targetX < sectorMaxX)
            {
                if (targetY < sextorMaxY)
                {
                    tmpIndex = (int)Directions.North;
                }
                else
                {
                    tmpIndex = (int)Directions.East;
                }
            }
            else if (targetY < sextorMaxY)
            {
                tmpIndex = (int)Directions.West;
            }
            else
            {
                tmpIndex = (int)Directions.South;
            }

            lastPathNode.Cost     = tmpSectors[tmpIndex].GetCost(targetX, targetY, targetZ);
            lastPathNode.PathCost = 0;
            // from the constructor, the distance is the manhattan distance from start_pos to target_pos
            lastPathNode.PathHeuristic = lastPathNode.Cost + (lastPathNode.Distance - 1) * overallMinCost;

            // now add that to our closed list
            m_PathDirty.Add(lastPathNode);

            // clear our heap and push the current node to it.
            m_PathPriorityQueue = new Priority_Queue.FastPriorityQueue <PathQueueNode>(50000);
            m_PathPriorityQueue.Enqueue(lastPathNode, lastPathNode.PathHeuristic);

            PathQueueNode currentPathNode = null;
            PathQueueNode tmpPathNode     = null;

            uint s = 0, s2 = 0;

            // looping through the very first SQM in the heap
            while (m_PathPriorityQueue.Count > 0)
            {
                s++;
                currentPathNode = m_PathPriorityQueue.Dequeue();
                // check if the current move won't exceed our current shortest path, otherwise end it up
                // if it exceeds, then we will loop again through our heap, if exists
                // if not, then we are done searching if the current path is undefined that means we can't
                // reach that field
                if (currentPathNode.Priority >= pathNode.PathCost)
                {
                    break;
                }

                for (int i = -1; i <= 1; i++)
                {
                    for (int j = -1; j <= 1; j++)
                    {
                        if (i == 0 && j == 0)
                        {
                            continue;
                        }

                        int gridX = currentPathNode.x + i;
                        int gridY = currentPathNode.y + j;

                        // check if that grid is in the range or validity
                        if (gridX < -matrixCenter || gridX > matrixCenter || gridY < -matrixCenter || gridY > matrixCenter)
                        {
                            continue;
                        }

                        int currentPathCost;
                        if (i * j == 0) // straight movement (not diagonal)
                        {
                            currentPathCost = currentPathNode.PathCost + currentPathNode.Cost;
                        }
                        else // diagonal movements worth as 3 as a normal movement;
                        {
                            currentPathCost = currentPathNode.PathCost + 3 * currentPathNode.Cost;
                        }

                        tmpPathNode = m_PathMatrix[(matrixCenter + gridY) * matrixSize + (matrixCenter + gridX)];
                        if (tmpPathNode.PathCost > currentPathCost)
                        {
                            tmpPathNode.Predecessor = currentPathNode;
                            tmpPathNode.PathCost    = currentPathCost;
                            if (tmpPathNode.Cost == int.MaxValue)
                            {
                                int currentPosX = startX + tmpPathNode.x;
                                int currentPosY = startY + tmpPathNode.y;
                                if (currentPosX < sectorMaxX)
                                {
                                    if (currentPosY < sextorMaxY)
                                    {
                                        tmpIndex = (int)Directions.North;
                                    }
                                    else
                                    {
                                        tmpIndex = (int)Directions.East;
                                    }
                                }
                                else if (currentPosY < sextorMaxY)
                                {
                                    tmpIndex = (int)Directions.West;
                                }
                                else
                                {
                                    tmpIndex = (int)Directions.South;
                                }
                                tmpPathNode.Cost          = tmpSectors[tmpIndex].GetCost(currentPosX, currentPosY, startZ);
                                tmpPathNode.PathHeuristic = tmpPathNode.Cost + (tmpPathNode.Distance - 1) * overallMinCost;
                                m_PathDirty.Add(tmpPathNode);
                            }

                            if (tmpPathNode == pathNode || tmpPathNode.Cost >= Constants.PathCostObstacle)
                            {
                                continue;
                            }

                            s2++;
                            if (tmpPathNode.Queue == m_PathPriorityQueue)
                            {
                                m_PathPriorityQueue.UpdatePriority(tmpPathNode, currentPathCost + tmpPathNode.PathHeuristic);
                            }
                            else
                            {
                                tmpPathNode.Reset();
                                m_PathPriorityQueue.Enqueue(tmpPathNode, currentPathCost + tmpPathNode.PathHeuristic);
                            }
                        }
                    }
                }
            }

            //Debug.Log("Recuresive Count: " + s + ", " + s2);

            var ret = PathState.PathErrorInternal;

            if (pathNode.PathCost < int.MaxValue)
            {
                currentPathNode = pathNode;
                tmpPathNode     = null;
                while (currentPathNode != null)
                {
                    if (!forceExact && currentPathNode.x == lastPathNode.x && currentPathNode.y == lastPathNode.y && lastPathNode.Cost >= Constants.PathCostObstacle)
                    {
                        currentPathNode = null;
                        break;
                    }

                    if (currentPathNode.Cost == Constants.PathCostUndefined)
                    {
                        break;
                    }

                    if (tmpPathNode != null)
                    {
                        dX = currentPathNode.x - tmpPathNode.x;
                        dY = currentPathNode.y - tmpPathNode.y;
                        if (dX == 1 && dY == 0)
                        {
                            steps.Add((int)PathDirection.East);
                        }
                        else if (dX == 1 && dY == -1)
                        {
                            steps.Add((int)PathDirection.NorthEast);
                        }
                        else if (dX == 0 && dY == -1)
                        {
                            steps.Add((int)PathDirection.North);
                        }
                        else if (dX == -1 && dY == -1)
                        {
                            steps.Add((int)PathDirection.NorthWest);
                        }
                        else if (dX == -1 && dY == 0)
                        {
                            steps.Add((int)PathDirection.West);
                        }
                        else if (dX == -1 && dY == 1)
                        {
                            steps.Add((int)PathDirection.SouthWest);
                        }
                        else if (dX == 0 && dY == 1)
                        {
                            steps.Add((int)PathDirection.South);
                        }
                        else if (dX == 1 && dY == 1)
                        {
                            steps.Add((int)PathDirection.SouthEast);
                        }
                        steps[steps.Count - 1] = steps[steps.Count - 1] | currentPathNode.Cost << 16;
                        if (steps.Count + 1 >= Constants.PathMaxSteps)
                        {
                            break;
                        }
                    }

                    tmpPathNode     = currentPathNode;
                    currentPathNode = currentPathNode.Predecessor;
                }

                if (steps.Count == 0)
                {
                    ret = PathState.PathEmpty;
                }
                else
                {
                    ret = PathState.PathExists;
                }
            }
            else
            {
                ret = PathState.PathErrorUnreachable;
            }

            foreach (var tmp in m_PathDirty)
            {
                tmp.Cost     = int.MaxValue;
                tmp.PathCost = int.MaxValue;
            }
            m_PathDirty.Clear();
            return(ret);
        }
コード例 #9
0
 internal void Dequeue(List <MiniMapSector> queue, MiniMapSector sector)
 {
     queue.Remove(sector);
 }