Пример #1
0
 public static void Clear()
 {
     Depts       = null;
     TreeList    = null;
     SelectItems = null;
     LevelPath.Clear();
 }
Пример #2
0
    /// <summary>
    /// Returns whether or not the given path could continue in the given direction.
    /// </summary>
    /// <param name="path">The path to check.</param>
    /// <param name="dir">The direction to check.</param>
    /// <returns>True if the path could continue in that direction; false otherwise.</returns>
    private bool IsDirectionPossibleForPathContinuation(LevelPath path, Direction dir)
    {
        // Verify that the path has a tail node
        LevelNode tailNode = path.TailNode;

        if (tailNode == null)
        {
            throw new ArgumentException("Cannot operate on given path; path has no nodes.");
        }

        // Get the new coordinates
        Tuple <int, int> newCoordinates = GetNewCoordinatesInDirection(tailNode.WorldRow, tailNode.WorldColumn, dir);
        int newRow = newCoordinates.First;
        int newCol = newCoordinates.Second;

        // If the coordinates are outside the world, we can't continue here
        if (!AreCoordinatesInsideWorld(path.ParentWorld, newRow, newCol))
        {
            return(false);
        }

        // If there is a non tail node at these coordinates, we can't continue here
        LevelNode nodeAtCoordinates = path.ParentWorld.ChildNodes[newRow, newCol];

        if (nodeAtCoordinates != null && !nodeAtCoordinates.IsTailNodeOfPath())
        {
            return(false);
        }

        return(true);
    }
Пример #3
0
    /// <summary>
    /// Continues the given path from the given node in the given direction.
    /// </summary>
    /// <param name="path">The path to continue.</param>
    /// <param name="previousNode">The previous node that connects to the new node or join. Typically, this will be the given path's tail node.</param>
    /// <param name="directionToContinue">The direction to continue the path in from the previous node.</param>
    /// <exception cref="InvalidOperationException">Thrown if the new node's coordinates would be outside the world.</exception>
    /// <returns>True if the path can continue after this step; false otherwise.</returns>
    private bool ProcessPathContinuation(LevelPath path, LevelNode previousNode, Direction directionToContinue)
    {
        Tuple <int, int> newNodeCoords = GetNewCoordinatesInDirection(previousNode, directionToContinue);
        bool             pathContinuesNextIteration = false;

        // Verify that the new coordinates are inside the world
        if (!AreCoordinatesInsideWorld(previousNode.ParentWorld, newNodeCoords.First, newNodeCoords.Second))
        {
            throw new InvalidOperationException(string.Format(
                                                    "Cannot add new node at the given direction from the given node. New node would have coordinates ({0}, {1}), which are outside the world.", newNodeCoords.First, newNodeCoords.Second));
        }

        // If there's no node at these coordinates, create a new node
        LevelNode nodeAtCoordinates = path.ParentWorld.ChildNodes[newNodeCoords.First, newNodeCoords.Second];

        if (nodeAtCoordinates == null)
        {
            nodeAtCoordinates = new LevelNode(path, newNodeCoords.First, newNodeCoords.Second);

            // Since we added a new node (and didn't join paths), this path continues
            pathContinuesNextIteration = true;
        }

        // Join the nodes
        previousNode.UpdateOpenSideStatus(directionToContinue, true);
        nodeAtCoordinates.UpdateOpenSideStatus(GetOppositeDirection(directionToContinue), true);

        return(pathContinuesNextIteration);
    }
Пример #4
0
 /// <summary>
 /// Removes the given path from this world's list of paths.
 /// </summary>
 /// <param name="path">The path to remove from the list.</param>
 public void RemovePath(LevelPath path)
 {
     if (ChildPaths.Contains(path))
     {
         ChildPaths.Remove(path);
     }
 }
Пример #5
0
    //----------------//
    // Updating Paths //
    //----------------//

    /// <summary>
    /// Adds a new path to this world's list of paths.
    /// </summary>
    /// <param name="path">The path to add to the list.</param>
    public void AddPath(LevelPath path)
    {
        if (!ChildPaths.Contains(path))
        {
            ChildPaths.Add(path);
        }
    }
Пример #6
0
    //---------------//
    // Build Helpers //
    //---------------//

    /// <summary>
    /// Continues building the world given the current active paths in it.
    /// </summary>
    /// <param name="world">The world to continue building.</param>
    /// <param name="currentActivePaths">The current active paths in the world.</param>
    /// <returns>The world after all active paths have completed.</returns>
    private LevelWorld BuildWorldFromExistingPaths(LevelWorld world, List <LevelPath> currentActivePaths)
    {
        while (currentActivePaths.Count > 0)
        {
            List <LevelPath> nextIterationActivePaths = new List <LevelPath>();
            foreach (var path in currentActivePaths)
            {
                // Verify that the path has at least one node already
                LevelNode tailNode = path.TailNode;
                Debug.Assert(tailNode != null);

                // Get the possible directions to move
                List <Direction> possibleDirections = GetPossibleDirectionsForPathContinuation(path);

                // Check to see if we're out of possible directions
                if (possibleDirections.Count == 0)
                {
                    // Note that we don't add this current path to the next iteration's paths; this path is done
                    continue;
                }

                // Continue the path in a random direction
                Direction dirToContinueIn        = GetRandomDirection(possibleDirections);
                bool      addPathToNextIteration = ProcessPathContinuation(path, tailNode, dirToContinueIn);
                if (addPathToNextIteration)
                {
                    nextIterationActivePaths.Add(path);
                }

                // Check for a split
                float splitCheck = UnityEngine.Random.Range(0.0f, 1.0f);
                if (splitCheck < splitChance)
                {
                    possibleDirections.Remove(dirToContinueIn);

                    // Check if there are any directions to continue in
                    if (possibleDirections.Count != 0)
                    {
                        // Get the direction for the new node
                        Direction dirToSplitIn = GetRandomDirection(possibleDirections);

                        // Create the new path and add a node to it
                        LevelPath splitPath = new LevelPath(world);
                        addPathToNextIteration = ProcessPathContinuation(splitPath, tailNode, dirToSplitIn);
                        if (addPathToNextIteration)
                        {
                            nextIterationActivePaths.Add(splitPath);
                        }
                    }
                }
            }

            // Update the current paths for the next iteration
            currentActivePaths = nextIterationActivePaths;
        }

        return(world);
    }
Пример #7
0
    public void ResetPath(LevelPath newPath)
    {
        levelPath = newPath;

        animator.enabled = false;
        SetInStartingPosition();

        playerState = State.WaitingToStart;
    }
Пример #8
0
 public void InitializePathVariable()
 {
     path                      = new LevelPath();
     path.minlength            = segmentLengthMin;
     path.maxLength            = segmentLengthMax;
     path.primaryPath          = new Line();
     path.secondaryPaths       = new List <Line>();
     path.primaryPath.segments = new List <LineSegment>();
 }
Пример #9
0
    //-------------//
    // Constructor //
    //-------------//

    /// <summary>
    /// Instantiates a new level node with a single parent path.
    /// </summary>
    /// <param name="parentPath">The parent path for the node.</param>
    /// <param name="row">The row of the world to add the node to.</param>
    /// <param name="col">Thr column of the world to add the node to.</param>
    /// <param name="openSides">The sides of this node that are open, or null for no open sides.</param>
    public LevelNode(LevelPath parentPath, int row, int col, List <Direction> openSides = null)
    {
        ParentPath  = parentPath;
        WorldRow    = row;
        WorldColumn = col;

        // Set all sides to closed
        foreach (var side in directions)
        {
            bool sideIsOpen = openSides != null && openSides.Contains(side);
            UpdateOpenSideStatus(side, sideIsOpen);
        }

        // Insert the node into the structure
        ParentPath.AddNode(this, row, col);
    }
Пример #10
0
    //-------------//
    // Constructor //
    //-------------//

    /// <summary>
    /// Instantiates a new level node with a single parent path.
    /// </summary>
    /// <param name="parentPath">The parent path for the node.</param>
    /// <param name="row">The row of the world to add the node to.</param>
    /// <param name="col">Thr column of the world to add the node to.</param>
    /// <param name="openSides">The sides of this node that are open, or null for no open sides.</param>
    public LevelNode(LevelPath parentPath, int row, int col, List<Direction> openSides = null)
    {
        ParentPath = parentPath;
        WorldRow = row;
        WorldColumn = col;

        // Set all sides to closed
        foreach (var side in directions)
        {
            bool sideIsOpen = openSides != null && openSides.Contains(side);
            UpdateOpenSideStatus(side, sideIsOpen);
        }

        // Insert the node into the structure
        ParentPath.AddNode(this, row, col);
    }
Пример #11
0
    // Use this for initialization
    void Start()
    {
        source = GameObject.Find("OnClick Source").GetComponent <AudioSource>();

        if (PlayerPrefs.GetInt("sound") == 1)
        {
            source.mute = false;
            source.Play();
        }
        else
        {
            source.mute = true;
        }

        level_path = new LevelPath();
    }
Пример #12
0
 public static int[] GetSelfAndChildrenIds(int id)
 {
     if (LevelPath.TryGetValue(id, out var result))
     {
         return(result);
     }
     else
     {
         var dept = Get(id);
         if (dept == null)
         {
             return(new int[] { });
         }
         result = CalcSelfAndChildrenIds(id);
         LevelPath.Add(id, result);
         return(result);
     }
 }
Пример #13
0
        private void PathEdit_Shown(object sender, EventArgs e)
        {
            pathCopy             = (LevelPath)Edit.Copy();
            numRequirement.Value = pathCopy.Requirement;
            switch ((PathGate)pathCopy.Gate)
            {
            case PathGate.Level: chkLevels.Checked = true; break;

            case PathGate.Area: chkAreas.Checked = true; break;

            case PathGate.Orb: chkOrbs.Checked = true; break;

            default: chkNope.Checked = true; break;
            }
            switch ((PathStyle)pathCopy.Style)
            {
            case PathStyle.Visible: chkVisible.Checked = true; break;

            default: chkHidden.Checked = true; break;
            }
            UpdateObject();
        }
Пример #14
0
    /// <summary>
    /// Returns a list of the possible directions the given path could continue in.
    /// </summary>
    /// <param name="path">The path whose directions to return.</param>
    /// <returns>The possible directions to continue in.</returns>
    private List <Direction> GetPossibleDirectionsForPathContinuation(LevelPath path)
    {
        List <Direction> directions = new List <Direction>()
        {
            Direction.UP,
            Direction.RIGHT,
            Direction.DOWN,
            Direction.LEFT
        };

        List <Direction> possibleDirectionsForPath = new List <Direction>();

        foreach (var dir in directions)
        {
            if (IsDirectionPossibleForPathContinuation(path, dir))
            {
                possibleDirectionsForPath.Add(dir);
            }
        }

        return(possibleDirectionsForPath);
    }
Пример #15
0
    public void ResetProgress()
    {
        LevelPath[] leveldatas = new LevelPath[15];
        leveldatas[0]  = new LevelPath("Regular/", "5x5/", string.Empty);
        leveldatas[1]  = new LevelPath("Regular/", "6x6/", string.Empty);
        leveldatas[2]  = new LevelPath("Regular/", "7x7/", string.Empty);
        leveldatas[3]  = new LevelPath("Regular/", "8x8/", string.Empty);
        leveldatas[4]  = new LevelPath("Regular/", "9x9/", string.Empty);
        leveldatas[5]  = new LevelPath("Bonus/", "5x5/", string.Empty);
        leveldatas[6]  = new LevelPath("Bonus/", "6x6/", string.Empty);
        leveldatas[7]  = new LevelPath("Bonus/", "7x7/", string.Empty);
        leveldatas[8]  = new LevelPath("Bonus/", "8x8/", string.Empty);
        leveldatas[9]  = new LevelPath("Bonus/", "9x9/", string.Empty);
        leveldatas[10] = new LevelPath("10x10/", string.Empty, string.Empty);
        leveldatas[11] = new LevelPath("11x11/", string.Empty, string.Empty);
        leveldatas[12] = new LevelPath("12x12/", string.Empty, string.Empty);
        leveldatas[13] = new LevelPath("13x13/", string.Empty, string.Empty);
        leveldatas[14] = new LevelPath("14x14/", string.Empty, string.Empty);
        string reset = "000000000000000000000000000000";

        try
        {
            foreach (LevelPath leveldata in leveldatas)
            {
                StreamWriter swr = new StreamWriter(leveldata.CreateLevelDataPath());

                using (swr)
                {
                    swr.Write(reset);
                    swr.Close();
                }
            }
        }
        catch (Exception except)
        {
            Debug.Log(except);
        }
    }
Пример #16
0
    //---------------//
    // Build Helpers //
    //---------------//

    /// <summary>
    /// Returns a list of the possible directions the given path could continue in.
    /// </summary>
    /// <param name="path">The path whose directions to return.</param>
    /// <returns>The possible directions to continue in.</returns>
    private List<Direction> GetPossibleDirectionsForPathContinuation(LevelPath path)
    {
        List<Direction> directions = new List<Direction>()
        {
            Direction.UP,
            Direction.RIGHT,
            Direction.DOWN,
            Direction.LEFT
        };

        List<Direction> possibleDirectionsForPath = new List<Direction>();

        foreach (var dir in directions)
        {
            if (IsDirectionPossibleForPathContinuation(path, dir))
            {
                possibleDirectionsForPath.Add(dir);
            }
        }

        return possibleDirectionsForPath;
    }
Пример #17
0
 public Waypoint(int index, Vector3 point, LevelPath levelPath)
 {
     this.index     = index;
     this.point     = point;
     this.levelPath = levelPath;
 }
Пример #18
0
    /// <summary>
    /// Builds a new world with the class's parameters and returns the start node of the world.
    /// </summary>
    /// <exception cref="InvalidOperationException">Thrown if world dimensions, start coordinates, or split chance is invalid.</exception>
    /// <returns>The start node in the new world.</returns>
    public LevelNode BuildNewWorld()
    {
        // Verify world dimensions
        if (rowsInWorld < 1 || colsInWorld < 1)
        {
            throw new InvalidOperationException(
                string.Format("Invalid world dimensions ({0}, {1}). Dimensions must be >= 1.", rowsInWorld, colsInWorld));
        }

        // Verify split chance
        if (splitChance < 0 || splitChance > 1)
        {
            throw new InvalidOperationException(
                string.Format("Invalid split chance {0}. Split chance must be >= 0 and <= 1.", splitChance));
        }

        // Create the world
        LevelWorld world = new LevelWorld(rowsInWorld, colsInWorld);

        // Verify start coordinates
        if (!AreCoordinatesInsideWorld(world, startRow, startCol))
        {
            throw new InvalidOperationException(
                string.Format("Invalid start coordinates ({0}, {1}) for world with dimensions ({0}, {1}). Coordinates must be located inside world.", startRow, startCol, rowsInWorld, colsInWorld));
        }

        // Add the first path and start node
        LevelPath firstPath = new LevelPath(world);
        LevelNode startNode = new LevelNode(firstPath, startRow, startCol);

        // Get the directions for the next two nodes
        List<Direction> possibleDirections = GetPossibleDirectionsForPathContinuation(firstPath);
        Debug.Assert(possibleDirections.Count >= 2); // Since the world is square and there are no other nodes, there should always be at least 2 possible directions

        Direction dirOfFirstPath = GetRandomDirection(possibleDirections);
        possibleDirections.Remove(dirOfFirstPath);
        Direction dirOfSecondPath = GetRandomDirection(possibleDirections);

        // Add the nodes to the world
        AddNodeToWorld(startNode, firstPath, dirOfFirstPath);
        LevelPath secondPath = new LevelPath(world);
        AddNodeToWorld(startNode, secondPath, dirOfSecondPath);

        // Begin adding paths
        List<LevelPath> currentActivePaths = new List<LevelPath>()
        {
            firstPath,
            secondPath
        };

        while (currentActivePaths.Count > 0)
        {
            List<LevelPath> nextIterationActivePaths = new List<LevelPath>();
            foreach (var path in currentActivePaths)
            {
                // Verify that the path has at least one node already
                Debug.Assert(path.TailNode != null);
                
                // Get the possible directions to move
                possibleDirections = GetPossibleDirectionsForPathContinuation(path);

                // Check to see if we're out of possible directions
                if (possibleDirections.Count == 0)
                {
                    // Note that we don't add this current path to the next iteration's paths; this path is done
                    continue;
                }

                // Get the direction for the new node
                Direction dirToContinueIn = GetRandomDirection(possibleDirections);

                // Check if this is a join or if we're adding a new node
                Tuple<int, int> newCoordinates = GetNewCoordinatesInDirection(path.TailNode, dirToContinueIn);
                LevelNode nodeAtCoordinates = world.ChildNodes[newCoordinates.First, newCoordinates.Second];

                // If there's no node at these coordinates, add the node
                if (nodeAtCoordinates == null)
                {
                    AddNodeToWorld(path.TailNode, path, dirToContinueIn);

                    // This path continues next iteration
                    nextIterationActivePaths.Add(path);
                }

                // Otherwise, process a path join
                else
                {
                    JoinNodes(path.TailNode, nodeAtCoordinates);

                    // Note that we don't add this current path to the next iteration's paths; this path is done
                    continue;
                }

                // Check for a split
                float splitCheck = UnityEngine.Random.Range(0.0f, 1.0f);
                if (splitCheck < splitChance)
                {
                    possibleDirections.Remove(dirToContinueIn);
                    
                    // Check if there are any directions to continue in
                    if (possibleDirections.Count == 0)
                    {
                        // Get the direction for the new node
                        Direction dirToSplitIn = GetRandomDirection(possibleDirections);

                        // TODO: Implement. Perhaps refactor lines 103 to 125
                    }
                }
            }

            // Update the current paths for the next iteration
            currentActivePaths = nextIterationActivePaths;
        }
        

        return startNode;
    }
Пример #19
0
    //---------------//
    // Updating Node //
    //---------------//

    /// <summary>
    /// Removes this node from its parent path and parent world.
    /// </summary>
    public void DeleteNode()
    {
        ParentPath.RemoveNode(this);
        ParentPath = null;
    }
Пример #20
0
    /// <summary>
    /// Adds a new node to the world given the previous node, the direction to the new node, and parent path.
    /// </summary>
    /// <param name="previousNode">The node that connects to the new node; often the previous node in the path.</param>
    /// <param name="parentPathOfNewNode">The parent path of the new node.</param>
    /// <param name="directionToNewNode">The direction from the previous node to the new node.</param>
    /// <exception cref="InvalidOperationException">Thrown if the new node's coordinates would be outside the world or if there is already a node at these coordinates.</exception>
    /// <returns>The newly created node.</returns>
    private LevelNode AddNodeToWorld(LevelNode previousNode, LevelPath parentPathOfNewNode, Direction directionToNewNode)
    {
        Tuple<int, int> newNodeCoords = GetNewCoordinatesInDirection(previousNode, directionToNewNode);

        // Verify that the new coordinates are inside the world
        if (!AreCoordinatesInsideWorld(previousNode.ParentWorld, newNodeCoords.First, newNodeCoords.Second))
        {
            throw new InvalidOperationException(string.Format(
                "Cannot add new node at the given direction from the given node. New node would have coordinates ({0}, {1}), which are outside the world.", newNodeCoords.First, newNodeCoords.Second));
        }

        // Verify that there is no node at these coordinates already
        if (parentPathOfNewNode.ParentWorld.ChildNodes[newNodeCoords.First, newNodeCoords.Second] != null)
        {
            throw new InvalidOperationException(string.Format(
                "Cannot add new node at location ({0}, {1}); location already has a node.", newNodeCoords.First, newNodeCoords.Second));
        }

        // Create the new node
        LevelNode newNode = new LevelNode(parentPathOfNewNode, newNodeCoords.First, newNodeCoords.Second);

        // Update the open side statuses
        previousNode.UpdateOpenSideStatus(directionToNewNode, true);
        newNode.UpdateOpenSideStatus(GetOppositeDirection(directionToNewNode), true);

        return newNode;
    }
Пример #21
0
 /// <summary>
 /// Removes the given path from this world's list of paths.
 /// </summary>
 /// <param name="path">The path to remove from the list.</param>
 public void RemovePath(LevelPath path)
 {
     if (ChildPaths.Contains(path))
     {
         ChildPaths.Remove(path);
     }
 }
Пример #22
0
    /// <summary>
    /// Builds a new world with the class's parameters and returns the start node of the world.
    /// </summary>
    /// <exception cref="InvalidOperationException">Thrown if world dimensions, start coordinates, or split chance is invalid.</exception>
    /// <returns>The start node in the new world.</returns>
    public LevelNode BuildNewWorld()
    {
        // Verify world dimensions
        if (rowsInWorld < 1 || colsInWorld < 1)
        {
            throw new InvalidOperationException(
                      string.Format("Invalid world dimensions ({0}, {1}). Dimensions must be >= 1.", rowsInWorld, colsInWorld));
        }

        // Verify split chance
        if (splitChance < 0 || splitChance > 1)
        {
            throw new InvalidOperationException(
                      string.Format("Invalid split chance {0}. Split chance must be >= 0 and <= 1.", splitChance));
        }

        // Create the world
        LevelWorld world = new LevelWorld(rowsInWorld, colsInWorld);

        // Verify start coordinates
        if (!AreCoordinatesInsideWorld(world, startRow, startCol))
        {
            throw new InvalidOperationException(
                      string.Format("Invalid start coordinates ({0}, {1}) for world with dimensions ({0}, {1}). Coordinates must be located inside world.", startRow, startCol, rowsInWorld, colsInWorld));
        }

        // Add the first path and start node
        LevelPath firstPath = new LevelPath(world);
        LevelNode startNode = new LevelNode(firstPath, startRow, startCol);

        // Get the directions for the next two nodes
        List <Direction> possibleDirections = GetPossibleDirectionsForPathContinuation(firstPath);

        Debug.Assert(possibleDirections.Count >= 2); // Since the world is square and there are no other nodes, there should always be at least 2 possible directions

        Direction dirOfFirstPath = GetRandomDirection(possibleDirections);

        possibleDirections.Remove(dirOfFirstPath);
        Direction dirOfSecondPath = GetRandomDirection(possibleDirections);

        // Add the nodes to the world
        ProcessPathContinuation(firstPath, startNode, dirOfFirstPath);
        LevelPath secondPath = new LevelPath(world);

        ProcessPathContinuation(secondPath, startNode, dirOfSecondPath);

        // Begin adding paths
        List <LevelPath> currentActivePaths = new List <LevelPath>()
        {
            firstPath,
            secondPath
        };

        // Add preliminary paths
        BuildWorldFromExistingPaths(world, currentActivePaths);

        // Fill in empty nodes
        Tuple <int, int> emptyNodeCoordinates = GetCoordinatesOfEmptyNodeInWorld(world, true);

        while (emptyNodeCoordinates != null)
        {
            // Create the new path and node
            LevelPath newPath = new LevelPath(world);
            LevelNode newNode = new LevelNode(newPath, emptyNodeCoordinates.First, emptyNodeCoordinates.Second);

            // Connect it to an adjacent non-empty node
            LevelNode adjacentNode = GetAdjacentNonEmptyNode(world, newNode);
            if (adjacentNode == null)
            {
                throw new InvalidOperationException(string.Format(
                                                        "Cannot continue this path; node at ({0}, {1}) has no adjacent non-empty nodes.", newNode.WorldRow, newNode.WorldColumn));
            }

            // Get the direction to the adjacent node and connect the two
            Direction dirToAdjacentNode = GetDirectionToCoordinates(newNode.WorldRow, newNode.WorldColumn, adjacentNode.WorldRow, adjacentNode.WorldColumn);
            newNode.UpdateOpenSideStatus(dirToAdjacentNode, true);
            adjacentNode.UpdateOpenSideStatus(GetOppositeDirection(dirToAdjacentNode), true);

            BuildWorldFromExistingPaths(world, new List <LevelPath>()
            {
                newPath
            });
            emptyNodeCoordinates = GetCoordinatesOfEmptyNodeInWorld(world, true);
        }

        return(startNode);
    }
Пример #23
0
    //----------------//
    // Updating Paths //
    //----------------//

    /// <summary>
    /// Adds a new path to this world's list of paths.
    /// </summary>
    /// <param name="path">The path to add to the list.</param>
    public void AddPath(LevelPath path)
    {
        if (!ChildPaths.Contains(path))
        {
            ChildPaths.Add(path);
        }
    }
Пример #24
0
    // Use this for initialization
    void Start()
    {
        levelPath = FindObjectOfType <LevelPath>();

        StartCoroutine(SpawnWaveAfterSeconds(3));
    }
Пример #25
0
    //---------------//
    // Updating Node //
    //---------------//

    /// <summary>
    /// Removes this node from its parent path and parent world.
    /// </summary>
    public void DeleteNode()
    {
        ParentPath.RemoveNode(this);
        ParentPath = null;
    }
Пример #26
0
    /// <summary>
    /// Returns whether or not the given path could continue in the given direction.
    /// </summary>
    /// <param name="path">The path to check.</param>
    /// <param name="dir">The direction to check.</param>
    /// <returns>True if the path could continue in that direction; false otherwise.</returns>
    private bool IsDirectionPossibleForPathContinuation(LevelPath path, Direction dir)
    {
        // Verify that the path has a tail node
        LevelNode tailNode = path.TailNode;
        if (tailNode == null)
        {
            throw new ArgumentException("Cannot operate on given path; path has no nodes.");
        }

        // Get the new coordinates
        Tuple<int, int> newCoordinates = GetNewCoordinatesInDirection(tailNode.WorldRow, tailNode.WorldColumn, dir);
        int newRow = newCoordinates.First;
        int newCol = newCoordinates.Second;

        // If the coordinates are outside the world, we can't continue here
        if (!AreCoordinatesInsideWorld(path.ParentWorld, newRow, newCol))
        {
            return false;
        }

        // If there is a non tail node at these coordinates, we can't continue here
        LevelNode nodeAtCoordinates = path.ParentWorld.ChildNodes[newRow, newCol];
        if (nodeAtCoordinates != null && !nodeAtCoordinates.IsTailNodeOfPath())
        {
            return false;
        }

        return true;
    }