Esempio n. 1
0
        /// <summary>
        /// Adds a Node to teh Heap
        /// </summary>
        /// <param name="d">A node used on the heap</param>
        public void Add(HeapNode d)
        {
            switch (this.direction)
            {
            case HeapDirection.LowPriority:
            {
                int i   = this.length;
                int id2 = i / 2;

                while (i > 1 && this.list[id2].Priority > d.Priority)
                {
                    this.list[i] = this.list[id2];
                    i            = id2;
                    id2          = i / 2;
                }
                this.list[i] = d;
                this.length++;
                break;
            }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Removes a Node from the Heap with the highest prioroty
        /// </summary>
        /// <returns>Returns a HeapNode object</returns>
        public HeapNode Remove()
        {
            switch (this.direction)
            {
            case HeapDirection.LowPriority:
            {
                if (this.length == 1)
                {
                    return(null);
                }
                int j, i = 1;

                HeapNode d    = this.list[1];
                int      hl1  = this.length - 1;
                int      hl12 = hl1 / 2;

                HeapNode tmp = this.list[hl1];
                while (i <= hl12)
                {
                    j = i + i;
                    if ((j < hl1) && this.list[j].Priority > this.list[j + 1].Priority)
                    {
                        j++;
                    }
                    if (this.list[j].Priority >= tmp.Priority)
                    {
                        break;
                    }
                    this.list[i] = this.list[j];
                    i            = j;
                }
                this.list[i] = tmp;
                this.length--;
                return(d);
            }
            }
            return(null);
        }
Esempio n. 3
0
        /// <summary>
        /// Finds a Path to teh given Destination
        /// </summary>
        /// <param name="DestinationX">The destinations X System.Drawing.Point</param>
        /// <param name="DestinationY">The destinations Y System.Drawing.Point</param>
        /// <param name="StartX">The starting X System.Drawing.Point</param>
        /// <param name="StartY">The starting Y System.Drawing.Point</param>
        /// <returns>A Path object containg the Path's Coordinates</returns>
        public Path FindPath(int DestinationX, int DestinationY, int StartX, int StartY)
        {
            System.Drawing.Point dest  = new System.Drawing.Point(DestinationX - this.map.X, DestinationY - this.map.Y);
            System.Drawing.Point start = new System.Drawing.Point(StartX - this.map.X, StartY - this.map.Y);

            double newg = 0;
            int    cx   = 0;
            int    cy   = 0;
            Node   node;
            int    vxvy;
            Node   cnode;

            bool done = false;

            Heap openqueue = new Heap(500000, HeapDirection.LowPriority);

            //Node Array
            Node[,] ng = new Node[this.map.SizeX, this.map.SizeY];

            Node enode = new Node(dest.X, dest.Y, false, false, null, 0, 0);
            Node snode = new Node(start.X, start.Y, false, true, null, 0, Distance.DiagShortcut(dest, start) * this.patherconfig.Factor);

            ng[snode.X, snode.Y] = snode;

            openqueue.Add(new HeapNode(snode, snode.F));

            while (!done)
            {
                //Game.Print("In loop");
                HeapNode tn = openqueue.Remove();
                if (tn == null)
                {
                    break;
                }
                node = (Node)tn.Item;

                if (node.X == enode.X && node.Y == enode.Y)
                {
                    done           = true;
                    this.LastScore = node.F;
                    //if(_reduc == 99)
                    //	return node.f;

                    //BUILD PATH USING REFRENCED PARENTS
                    //var donebuild = false;

                    ArrayList ptd = new ArrayList();
                    ArrayList fp  = new ArrayList();
                    ptd.Add(node);
                    if (((Node)ptd[ptd.Count - 1]).Parent != null)
                    {
                        do
                        {
                            ptd.Add(((Node)ptd[ptd.Count - 1]).Parent);
                            if (((Node)ptd[ptd.Count - 1]).Parent == null)
                            {
                                break;
                            }
                        } while (true);
                    }

                    //Adding padding
                    for (int p = 0; p < ptd.Count; p++)
                    {
                        for (int px = -1; px < 2; px++)
                        {
                            for (int py = -1; py < 2; py++)
                            {
                                if ((px * py) != 0 && (px != 0 && py != 0))
                                {
                                    continue;                                                                      //continue if diagonal or same coordinate
                                }
                                if (!this.map.IsWalkable(((Node)ptd[p]).X + px + this.map.X, ((Node)ptd[p]).Y + py + this.map.Y))
                                {
                                    ((Node)ptd[p]).X += (px * (-1));                                    // changed ((Node)ptd[p]).Y to ((Node)ptd[p]).X
                                    ((Node)ptd[p]).Y += (py * (-1));
                                }
                            }
                        }
                    }

                    //reverse the path now so we can work with it from start and reduce the points
                    double vecanglelast = 0;
                    double vecanglenew  = 0;
                    double vecdistance  = 0;
                    for (int d = ptd.Count - 1; d >= 0; d--)
                    {
                        if (d == ptd.Count - 1 && d > 0)
                        {                                       //add first point always
                            fp.Add(ptd[d]);
                            if (this.patherconfig.ReductionType == Reduction.WalkingReduction)
                            {
                                vecanglelast = Distance.GetAngle(((Node)fp[fp.Count - 1]).X, ((Node)fp[fp.Count - 1]).Y,
                                                                 ((Node)ptd[d - 1]).X, ((Node)ptd[d - 1]).Y);
                            }
                            else
                            {
                                vecanglelast = 0;
                            }
                            continue;
                        }

                        if (d == 0)
                        {                                                       //add last point always
                            fp.Add(ptd[d]);
                            break;
                        }

                        if (this.patherconfig.ReductionType == Reduction.WalkingReduction)
                        {
                            vecanglenew = Distance.GetAngle(((Node)fp[fp.Count - 1]).X, ((Node)fp[fp.Count - 1]).Y, ((Node)ptd[d]).X, ((Node)ptd[d]).Y);
                        }
                        else
                        {
                            vecanglenew = 0;
                        }
                        vecdistance = Distance.Euclidian(((Node)fp[fp.Count - 1]).X, ((Node)fp[fp.Count - 1]).Y, ((Node)ptd[d]).X, ((Node)ptd[d]).Y);

                        if (vecanglenew != vecanglelast || vecdistance > this.patherconfig.PathPointDistance)
                        {
                            fp.Add(ptd[d]);
                            if (this.patherconfig.ReductionType == Reduction.WalkingReduction)
                            {
                                vecanglelast = Distance.GetAngle(((Node)fp[fp.Count - 1]).X, ((Node)fp[fp.Count - 1]).Y, ((Node)ptd[d - 1]).X, ((Node)ptd[d - 1]).Y);
                            }
                            else
                            {
                                vecanglelast = 0;
                            }
                            continue;
                        }
                    }
                    this.path = new Path();
                    //Put the offset back in and move to path
                    for (int d = 0; d < fp.Count; d++)
                    {
                        this.path.CoordinateList.Add(new System.Drawing.Point(((Node)fp[d]).X + this.map.X, ((Node)fp[d]).Y + this.map.Y));
                    }
                    //				print("OUT mlmap FindPath");
                    return(this.path);
                }

                else
                {                               // look for adjacent blocks that we attach to and add them to open
                    for (int vy = -1; vy < 2; vy++)
                    {
                        for (int vx = -1; vx < 2; vx++)
                        {
                            if (vx == 0 && vy == 0)
                            {
                                continue;                                                //continue if we are on the current node
                            }
                            cx = node.X + vx; cy = node.Y + vy;
                            //Game.Print("cx, cy: " + cx.ToString() + ", " + cy.ToString());
                            vxvy = vx * vy;
                            //check for map edge
                            if (cy < 0 || cy > this.map.SizeY - 1 || cx < 0 || cx > this.map.SizeX - 1)
                            {
                                continue;
                            }

                            //check for walkability and small diagonal gaps that cant be passed
                            if ((this.map.CollisionData[cx, cy] & 1) > 0)
                            {
                                continue;
                            }
                            //CHANGED 02-10-2004 as a test (commented out extra checks)

                            if (vxvy != 0 && ((this.map.CollisionData[node.X, cy] & 1) > 0) &&
                                ((this.map.CollisionData[cx, node.Y] & 1) > 0))
                            {
                                continue;
                            }
                            //if ((AreaData[cy][cx+1] & 1) || (AreaData[cy][cx-1] & 1) ||
                            //	(AreaData[cy+1][cx] & 1) || (AreaData[cy-1][cx] & 1)) continue;
                            //if (((AreaData[cy][cx+1] & 1) && (AreaData[cy][cx-1] & 1)) ||
                            //	((AreaData[cy+1][cx] & 1) && (AreaData[cy-1][cx] & 1))) continue;

                            newg = node.G + SCORE[Math.Abs(vxvy)];

                            cnode = ng[cx, cy];

                            if (cnode == null)
                            {
                                cnode      = new Node(cx, cy, false, false, node, newg, Distance.DiagShortcut(dest.X, dest.Y, cx, cy) * this.patherconfig.Factor);
                                ng[cx, cy] = cnode;
                            }
                            else
                            {
                                if (cnode.G > newg)
                                {
                                    cnode.IsClosed = false;
                                    cnode.G        = newg;
                                    cnode.Parent   = node;
                                }
                                else
                                {
                                    continue;
                                }
                            }

                            if (!cnode.IsOpen)
                            {
                                cnode.IsOpen = true;
                                openqueue.Add(new HeapNode(cnode, cnode.F));
                                //AreaData[cnode.y][cnode.x] |= 0x200000;
                            }
                        }
                    }
                    node.IsOpen = false;    node.IsClosed = true;
                    //AreaData[node.y][node.x] |= 0x100000;
                }
            }

            throw new ApplicationException("Could not find a path to destination");
        }