Esempio n. 1
0
        private static GridPos jumpLoop(JumpPointParam iParam, int iX, int iY, int iPx, int iPy)
        {
            GridPos retVal             = null;
            Stack <JumpSnapshot> stack = new Stack <JumpSnapshot>();

            JumpSnapshot currentSnapshot = new JumpSnapshot();
            JumpSnapshot newSnapshot     = null;

            currentSnapshot.iX    = iX;
            currentSnapshot.iY    = iY;
            currentSnapshot.iPx   = iPx;
            currentSnapshot.iPy   = iPy;
            currentSnapshot.stage = 0;

            stack.Push(currentSnapshot);
            while (stack.Count != 0)
            {
                currentSnapshot = stack.Pop();
                switch (currentSnapshot.stage)
                {
                case 0:
                    if (!iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY))
                    {
                        retVal = null;
                        continue;
                    }
                    else if (iParam.SearchGrid.GetNodeAt(currentSnapshot.iX, currentSnapshot.iY).Equals(iParam.EndNode))
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    currentSnapshot.tDx = currentSnapshot.iX - currentSnapshot.iPx;
                    currentSnapshot.tDy = currentSnapshot.iY - currentSnapshot.iPy;
                    currentSnapshot.jx  = null;
                    currentSnapshot.jy  = null;
                    if (iParam.CrossCorner)
                    {
                        // check for forced neighbors
                        // along the diagonal
                        if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0)
                        {
                            if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY)) ||
                                (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY - currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY - currentSnapshot.tDy)))
                            {
                                retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                continue;
                            }
                        }
                        // horizontally/vertically
                        else
                        {
                            if (currentSnapshot.tDx != 0)
                            {
                                // moving along x
                                if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + 1)) ||
                                    (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY - 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY - 1)))
                                {
                                    retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                    continue;
                                }
                            }
                            else
                            {
                                if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY)) ||
                                    (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY)))
                                {
                                    retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                    continue;
                                }
                            }
                        }
                        // when moving diagonally, must check for vertical/horizontal jump points
                        if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0)
                        {
                            currentSnapshot.stage = 1;
                            stack.Push(currentSnapshot);

                            newSnapshot       = new JumpSnapshot();
                            newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                            newSnapshot.iY    = currentSnapshot.iY;
                            newSnapshot.iPx   = currentSnapshot.iX;
                            newSnapshot.iPy   = currentSnapshot.iY;
                            newSnapshot.stage = 0;
                            stack.Push(newSnapshot);
                            continue;
                        }

                        // moving diagonally, must make sure one of the vertical/horizontal
                        // neighbors is open to allow the path

                        // moving diagonally, must make sure one of the vertical/horizontal
                        // neighbors is open to allow the path
                        if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) || iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                        {
                            newSnapshot       = new JumpSnapshot();
                            newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                            newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                            newSnapshot.iPx   = currentSnapshot.iX;
                            newSnapshot.iPy   = currentSnapshot.iY;
                            newSnapshot.stage = 0;
                            stack.Push(newSnapshot);
                            continue;
                        }
                        else if (iParam.CrossAdjacentPoint)
                        {
                            newSnapshot       = new JumpSnapshot();
                            newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                            newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                            newSnapshot.iPx   = currentSnapshot.iX;
                            newSnapshot.iPy   = currentSnapshot.iY;
                            newSnapshot.stage = 0;
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    else     //if (!iParam.CrossCorner)
                    {
                        // check for forced neighbors
                        // along the diagonal
                        if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0)
                        {
                            if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY)) ||
                                (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY + currentSnapshot.tDy) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy)))
                            {
                                retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                continue;
                            }
                        }
                        // horizontally/vertically
                        else
                        {
                            if (currentSnapshot.tDx != 0)
                            {
                                // moving along x
                                if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY + 1)) ||
                                    (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY - 1) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - currentSnapshot.tDx, currentSnapshot.iY - 1)))
                                {
                                    retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                    continue;
                                }
                            }
                            else
                            {
                                if ((iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + 1, currentSnapshot.iY - currentSnapshot.tDy)) ||
                                    (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY) && !iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX - 1, currentSnapshot.iY - currentSnapshot.tDy)))
                                {
                                    retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                                    continue;
                                }
                            }
                        }


                        // when moving diagonally, must check for vertical/horizontal jump points
                        if (currentSnapshot.tDx != 0 && currentSnapshot.tDy != 0)
                        {
                            currentSnapshot.stage = 3;
                            stack.Push(currentSnapshot);

                            newSnapshot       = new JumpSnapshot();
                            newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                            newSnapshot.iY    = currentSnapshot.iY;
                            newSnapshot.iPx   = currentSnapshot.iX;
                            newSnapshot.iPy   = currentSnapshot.iY;
                            newSnapshot.stage = 0;
                            stack.Push(newSnapshot);
                            continue;
                        }

                        // moving diagonally, must make sure both of the vertical/horizontal
                        // neighbors is open to allow the path
                        if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                        {
                            newSnapshot       = new JumpSnapshot();
                            newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                            newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                            newSnapshot.iPx   = currentSnapshot.iX;
                            newSnapshot.iPy   = currentSnapshot.iY;
                            newSnapshot.stage = 0;
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    retVal = null;
                    break;

                case 1:
                    currentSnapshot.jx = retVal;

                    currentSnapshot.stage = 2;
                    stack.Push(currentSnapshot);

                    newSnapshot       = new JumpSnapshot();
                    newSnapshot.iX    = currentSnapshot.iX;
                    newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                    newSnapshot.iPx   = currentSnapshot.iX;
                    newSnapshot.iPy   = currentSnapshot.iY;
                    newSnapshot.stage = 0;
                    stack.Push(newSnapshot);
                    break;

                case 2:
                    currentSnapshot.jy = retVal;
                    if (currentSnapshot.jx != null || currentSnapshot.jy != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    // moving diagonally, must make sure one of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) || iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                    {
                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }
                    else if (iParam.CrossAdjacentPoint)
                    {
                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;

                case 3:
                    currentSnapshot.jx = retVal;

                    currentSnapshot.stage = 4;
                    stack.Push(currentSnapshot);

                    newSnapshot       = new JumpSnapshot();
                    newSnapshot.iX    = currentSnapshot.iX;
                    newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                    newSnapshot.iPx   = currentSnapshot.iX;
                    newSnapshot.iPy   = currentSnapshot.iY;
                    newSnapshot.stage = 0;
                    stack.Push(newSnapshot);
                    break;

                case 4:
                    currentSnapshot.jy = retVal;
                    if (currentSnapshot.jx != null || currentSnapshot.jy != null)
                    {
                        retVal = new GridPos(currentSnapshot.iX, currentSnapshot.iY);
                        continue;
                    }

                    // moving diagonally, must make sure both of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX + currentSnapshot.tDx, currentSnapshot.iY) && iParam.SearchGrid.IsWalkableAt(currentSnapshot.iX, currentSnapshot.iY + currentSnapshot.tDy))
                    {
                        newSnapshot       = new JumpSnapshot();
                        newSnapshot.iX    = currentSnapshot.iX + currentSnapshot.tDx;
                        newSnapshot.iY    = currentSnapshot.iY + currentSnapshot.tDy;
                        newSnapshot.iPx   = currentSnapshot.iX;
                        newSnapshot.iPy   = currentSnapshot.iY;
                        newSnapshot.stage = 0;
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;
                }
            }

            return(retVal);
        }
        private static GridPos JumpLoop(JumpPointParam jpParam, int x, int y, int px, int py)
        {
            var stack = new Stack <JumpSnapshot>();

            var currentSnapshot = new JumpSnapshot
            {
                X     = x,
                Y     = y,
                Px    = px,
                Py    = py,
                Stage = 0
            };

            stack.Push(currentSnapshot);
            GridPos retVal = null;

            while (stack.Count != 0)
            {
                currentSnapshot = stack.Pop();
                JumpSnapshot newSnapshot;
                switch (currentSnapshot.Stage)
                {
                case 0:
                    if (!jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y))
                    {
                        retVal = null;
                        continue;
                    }
                    else if (jpParam.SearchGrid.GetNodeAt(currentSnapshot.X, currentSnapshot.Y).Equals(jpParam.EndNode))
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }

                    currentSnapshot.Dx = currentSnapshot.X - currentSnapshot.Px;
                    currentSnapshot.Dy = currentSnapshot.Y - currentSnapshot.Py;
                    if (jpParam.DiagonalMovement == DiagonalMovement.Always || jpParam.DiagonalMovement == DiagonalMovement.IfAtLeastOneWalkable)
                    {
                        // check for forced neighbors
                        // along the diagonal
                        if (currentSnapshot.Dx != 0 && currentSnapshot.Dy != 0)
                        {
                            if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y)) ||
                                (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y - currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y - currentSnapshot.Dy)))
                            {
                                retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                continue;
                            }
                        }
                        // horizontally/vertically
                        else
                        {
                            if (currentSnapshot.Dx != 0)
                            {
                                // moving along x
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y + 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + 1)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y - 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y - 1)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                            else
                            {
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                        }
                        // when moving diagonally, must check for vertical/horizontal jump points
                        if (currentSnapshot.Dx != 0 && currentSnapshot.Dy != 0)
                        {
                            currentSnapshot.Stage = 1;
                            stack.Push(currentSnapshot);

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }

                        // moving diagonally, must make sure one of the vertical/horizontal
                        // neighbors is open to allow the path

                        // moving diagonally, must make sure one of the vertical/horizontal
                        // neighbors is open to allow the path
                        if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) || jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                        {
                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y + currentSnapshot.Dy,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                        else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                        {
                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y + currentSnapshot.Dy,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    else if (jpParam.DiagonalMovement == DiagonalMovement.OnlyWhenNoObstacles)
                    {
                        // check for forced neighbors
                        // along the diagonal
                        if (currentSnapshot.Dx != 0 && currentSnapshot.Dy != 0)
                        {
                            if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y + currentSnapshot.Dy) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y)) ||
                                (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y + currentSnapshot.Dy) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy)))
                            {
                                retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                continue;
                            }
                        }
                        // horizontally/vertically
                        else
                        {
                            if (currentSnapshot.Dx != 0)
                            {
                                // moving along x
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y + 1)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y - 1) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - currentSnapshot.Dx, currentSnapshot.Y - 1)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                            else
                            {
                                if ((jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + 1, currentSnapshot.Y - currentSnapshot.Dy)) ||
                                    (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y) && !jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X - 1, currentSnapshot.Y - currentSnapshot.Dy)))
                                {
                                    retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                                    continue;
                                }
                            }
                        }

                        // when moving diagonally, must check for vertical/horizontal jump points
                        if (currentSnapshot.Dx != 0 && currentSnapshot.Dy != 0)
                        {
                            currentSnapshot.Stage = 3;
                            stack.Push(currentSnapshot);

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }

                        // moving diagonally, must make sure both of the vertical/horizontal
                        // neighbors is open to allow the path
                        if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                        {
                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + currentSnapshot.Dx,
                                Y     = currentSnapshot.Y + currentSnapshot.Dy,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    else                             // if(jpParam.DiagonalMovement == DiagonalMovement.Never)
                    {
                        if (currentSnapshot.Dx != 0)
                        {
                            // moving along x
                            if (!jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y))
                            {
                                retVal = new GridPos(x, y);
                                continue;
                            }
                        }
                        else
                        {
                            if (!jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                            {
                                retVal = new GridPos(x, y);
                                continue;
                            }
                        }

                        //  must check for perpendicular jump points
                        if (currentSnapshot.Dx != 0)
                        {
                            currentSnapshot.Stage = 5;
                            stack.Push(currentSnapshot);

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X,
                                Y     = currentSnapshot.Y + 1,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                        else                                 // tDy != 0
                        {
                            currentSnapshot.Stage = 6;
                            stack.Push(currentSnapshot);

                            newSnapshot = new JumpSnapshot
                            {
                                X     = currentSnapshot.X + 1,
                                Y     = currentSnapshot.Y,
                                Px    = currentSnapshot.X,
                                Py    = currentSnapshot.Y,
                                Stage = 0
                            };
                            stack.Push(newSnapshot);
                            continue;
                        }
                    }
                    retVal = null;
                    break;

                case 1:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }

                    currentSnapshot.Stage = 2;
                    stack.Push(currentSnapshot);

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X,
                        Y     = currentSnapshot.Y + currentSnapshot.Dy,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

                case 2:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }

                    // moving diagonally, must make sure one of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) || jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    else if (jpParam.DiagonalMovement == DiagonalMovement.Always)
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;

                case 3:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }

                    currentSnapshot.Stage = 4;
                    stack.Push(currentSnapshot);

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X,
                        Y     = currentSnapshot.Y + currentSnapshot.Dy,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

                case 4:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }

                    // moving diagonally, must make sure both of the vertical/horizontal
                    // neighbors is open to allow the path
                    if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;

                case 5:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }
                    currentSnapshot.Stage = 7;
                    stack.Push(currentSnapshot);

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X,
                        Y     = currentSnapshot.Y - 1,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

                case 6:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }
                    currentSnapshot.Stage = 7;
                    stack.Push(currentSnapshot);

                    newSnapshot = new JumpSnapshot
                    {
                        X     = currentSnapshot.X - 1,
                        Y     = currentSnapshot.Y,
                        Px    = currentSnapshot.X,
                        Py    = currentSnapshot.Y,
                        Stage = 0
                    };
                    stack.Push(newSnapshot);
                    break;

                case 7:
                    if (retVal != null)
                    {
                        retVal = new GridPos(currentSnapshot.X, currentSnapshot.Y);
                        continue;
                    }
                    // keep going
                    if (jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X + currentSnapshot.Dx, currentSnapshot.Y) && jpParam.SearchGrid.IsWalkableAt(currentSnapshot.X, currentSnapshot.Y + currentSnapshot.Dy))
                    {
                        newSnapshot = new JumpSnapshot
                        {
                            X     = currentSnapshot.X + currentSnapshot.Dx,
                            Y     = currentSnapshot.Y + currentSnapshot.Dy,
                            Px    = currentSnapshot.X,
                            Py    = currentSnapshot.Y,
                            Stage = 0
                        };
                        stack.Push(newSnapshot);
                        continue;
                    }
                    retVal = null;
                    break;
                }
            }

            return(retVal);
        }