Пример #1
0
        public bool GetPathTo(Creature creature, Position destPos,
            List<byte> listDir, Int32 maxSearchDist, bool allowZChange, bool intendingToReachDes)
        {
            if (intendingToReachDes &&
                gameMap.TileContainsType(destPos, Constants.TYPE_BLOCKS_AUTO_WALK)) {
                    listDir.Clear();
                return false;
            }

            listDir.Clear();

            Position startPos = creature.CurrentPosition;
            Position endPos = destPos;
            if (endPos == null) {
                return false;
            }

            if (startPos.z != endPos.z)
                return false;

            AStarNodes nodes = new AStarNodes();
            AStarNode startNode = nodes.CreateOpenNode();

            startNode.x = startPos.x;
            startNode.y = startPos.y;

            startNode.g = 0;
            startNode.h = nodes.GetEstimatedDistance
                (startPos.x, startPos.y, endPos.x, endPos.y);

            startNode.f = startNode.g + startNode.h;
            startNode.parent = null;

            Position pos = new Position();
            pos.z = startPos.z;

            short[,] neighbourOrderList =
            {
            {-1, 0},
            {0, 1},
            {1, 0},
            {0, -1},

               		//diagonal
            {-1, -1},
            {1, -1},
            {1, 1},
            {-1, 1},

            };

            //MapTile tile = null;
            AStarNode found = null;

            while (nodes.CountClosedNodes() < 100) {
                AStarNode n = nodes.GetBestNode();
                if (n == null) {
                    listDir.Clear();
                    return false; //No path found
                }

                if (n.x == endPos.x && n.y == endPos.y) {
                    found = n;
                    break;
                } else {
                    for (int i = 0; i < 8; i++) {
                        if (i > 3 && (allowZChange || intendingToReachDes)) {
                            continue;
                        }
                        //Console.WriteLine("neighbourhood["+i+", 1]" + neighbourOrderList[i, 0]);
                        pos.x = (ushort)(n.x + neighbourOrderList[i, 0]);
                        pos.y = (ushort)(n.y + neighbourOrderList[i, 1]);
                        int endPosX = endPos.x;
                        int endPosY = endPos.y;
                        int posX = pos.x;
                        int posY = pos.y;

                        bool outOfRange = false;
                        if (Math.Abs(endPosX - posX) > maxSearchDist ||
                            Math.Abs(endPosY - posY) > maxSearchDist) {
                            outOfRange = true;
                        }

                        if ((!outOfRange) &&
                       (!gameMap.TileContainsType(pos, Constants.TYPE_BLOCKS_AUTO_WALK))
                       || (destPos.x == pos.x && destPos.y == pos.y)) {
                            if (i > 3 && !destPos.Equals(pos)) {
                                nodes.CloseNode(n);
                                continue;
                            }

                            int cost = 0;
                            int extraCost = 0;
                            int newg = n.g + cost + extraCost;

                            AStarNode neighbourNode = nodes.GetNodeInList(pos.x, pos.y);
                            if (neighbourNode != null) {
                                if (neighbourNode.g <= newg) {
                                    continue;
                                }
                                nodes.OpenNode(neighbourNode);
                            } else {
                                neighbourNode = nodes.CreateOpenNode();
                                if (neighbourNode == null) {
                                    listDir.Clear();
                                    return false;
                                }
                            }

                            neighbourNode.x = pos.x;
                            neighbourNode.y = pos.y;
                            neighbourNode.parent = n;
                            neighbourNode.g = newg;
                            neighbourNode.h = (nodes.GetEstimatedDistance((int)neighbourNode.x,
                                (int)neighbourNode.y, (int)endPos.x, (int)endPos.y));
                            neighbourNode.f = neighbourNode.g + neighbourNode.h;
                        }
                    }
                    nodes.CloseNode(n);
                }
            }

            int prevX = endPos.x;
            int prevY = endPos.y;
            int dx, dy;

            while (found != null) {
                pos.x = (ushort)found.x;
                pos.y = (ushort)found.y;

                found = found.parent;

                dx = pos.x - prevX;
                dy = pos.y - prevY;

                prevX = pos.x;
                prevY = pos.y;

                if (dx == 1)
                    listDir.Insert(0, (byte)Direction.WEST);
                else if (dx == -1)
                    listDir.Insert(0, (byte)Direction.EAST);
                else if (dy == 1)
                    listDir.Insert(0, (byte)Direction.NORTH);
                else if (dy == -1)
                    listDir.Insert(0, (byte)Direction.SOUTH);
            }

            bool empty = true;
            if (listDir.Count == 0)
                empty = false;

            return (!empty);
        }