private void CreateDenseMaze(CellDungeon dungeon)
        {
            var currentLocation   = dungeon.PickRandomCellAndSetItAsVisited();
            var previousDirection = Direction.North;

            while (!dungeon.AllCellsAreVisited)
            {
                var directionPicker = new DirectionPicker(previousDirection, ChangeDirectionModifier);
                var direction       = directionPicker.PickRandomDirection();

                while (!dungeon.HasAdjacentCell(currentLocation, direction) ||
                       dungeon.AdjacentCellIsVisited(currentLocation, direction))
                {
                    if (directionPicker.HasDirectionToPick)
                    {
                        direction = directionPicker.PickRandomDirection();
                    }
                    else
                    {
                        currentLocation = dungeon.GetRandomVisitedCell(currentLocation);                   // Get a new previously visited location
                        directionPicker = new DirectionPicker(previousDirection, ChangeDirectionModifier); // Reset the direction picker
                        direction       = directionPicker.PickRandomDirection();                           // Get a new direction
                    }
                }

                currentLocation = dungeon.CreateCorridor(currentLocation, direction);
                dungeon.SetCellAsVisited(currentLocation);
                previousDirection = direction;
            }
        }
        private void RemoveDeadEnds(CellDungeon dungeon)
        {
            foreach (var deadEndLocation in dungeon.DeadEndCellLocations)
            {
                if (ShouldRemoveDeadend())
                {
                    var currentLocation = deadEndLocation;

                    do
                    {
                        // Initialize the direction picker not to select the dead-end corridor direction
                        var directionPicker =
                            new DirectionPicker(dungeon[currentLocation].CalculateDeadEndCorridorDirection(), 100);
                        var direction = directionPicker.PickRandomDirection();

                        while (!dungeon.HasAdjacentCell(currentLocation, direction))
                        {
                            if (directionPicker.HasDirectionToPick)
                            {
                                direction = directionPicker.PickRandomDirection();
                            }
                            else
                            {
                                throw new InvalidOperationException("This should not happen");
                            }
                        }
                        // Create a corridor in the selected direction
                        currentLocation = dungeon.CreateCorridor(currentLocation, direction);
                    } while (dungeon[currentLocation].IsDeadEnd); // Stop when you intersect an existing corridor.
                }
            }
        }
        protected virtual IEnumerable <PathFindingNode> GetNodeNeighbours(TerrainMap terrain, IList <IActor> actors,
                                                                          IMovementProfile movementProfile,
                                                                          PathFindingNode node, Point locationTo)
        {
            var picker = new DirectionPicker(Direction.Northwest, 100, movementProfile.AvailableDirections);

            while (picker.HasDirectionToPick)
            {
                Direction direction = picker.PickRandomDirection();
                if (terrain.HasAdjacentLocation(node.Location, direction))
                {
                    Point targetLocation = terrain.GetTargetLocation(node.Location, direction).Value;

                    if (LocationIsTraversable(terrain, actors, movementProfile, targetLocation, locationTo))
                    {
                        yield return
                            new PathFindingNode
                            {
                                Location     = direction.ApplyTransform(node.Location),
                                Direction    = direction,
                                MovementCost = CalculateLocationMovementCost(terrain, actors, movementProfile, targetLocation, locationTo)
                            }
                    }
                    ;
                }
            }
        }