Пример #1
0
    public static T CreateMaze <T> (T grid) where T : MazeGrid
    {
        MazeCell currentCell = grid.GetRandomCell();

        while (currentCell != null)
        {
            // Random Walk
            List <MazeCell> unvisitedNeighbours = currentCell.Neighbours.FindAll(c => c.Links().Count == 0); //Unvisited neighbours of current cell

            if (unvisitedNeighbours.Count != 0)                                                              // if has unvisited - link to current cell and set neighbour as new current cell
            {
                MazeCell neighbour = unvisitedNeighbours[Random.Range(0, unvisitedNeighbours.Count)];
                currentCell.Link(neighbour);
                currentCell = neighbour;
            }
            else
            {
                currentCell = null;

                foreach (MazeCell cell in grid.EachCell())
                {
                    /*
                     * List<MazeCell> visitedNeighbours = cell.Neighbours.FindAll(delegate(MazeCell obj) {
                     *  if (obj.Links().Count != 0)
                     *  {
                     *      return true;
                     *  }
                     *  else
                     *  {
                     *      false;
                     *  }
                     * });
                     */
                    List <MazeCell> visitedNeighbours = cell.Neighbours.FindAll(c => c.Links().Count != 0); //was already visited

                    if (cell.Links().Count == 0 && visitedNeighbours.Count != 0)                            //unvisited cell with one visited neighbour
                    {
                        currentCell = cell;
                        MazeCell neighbour = visitedNeighbours[Random.Range(0, visitedNeighbours.Count)];
                        currentCell.Link(neighbour); //connect unvisited cell to one of the availible visited neighbours
                        break;
                    }
                }
            }
        }

        return(grid);
    }
Пример #2
0
    // Recursive backtracker is a depth-first search. But only the difference is that neighbour chooses randomly.
    public static T CreateMaze <T> (T grid, MazeCell startCell = null) where T : MazeGrid
    {
        Stack <MazeCell> stack = new Stack <MazeCell>();

        if (startCell == null)
        {
            startCell = grid.GetRandomCell();
        }
        stack.Push(startCell);   //first cell

        while (stack.Count != 0) //while have unvisited cells
        {
            MazeCell        currentCell = stack.Peek();
            List <MazeCell> neighbours  = currentCell.Neighbours.FindAll(c => c.Links().Count == 0); //check if current cell has unvisited neighbours

            if (neighbours.Count == 0)                                                               //if has no unvisited neighbours
            {
                stack.Pop();                                                                         //pop that cell (remove from stack) - it makes previous cell in the stack the current node
            }
            else //else link neighbour to cur.cell and push in stack
            {
                MazeCell neighbour = neighbours[Random.Range(0, neighbours.Count)]; // we can add bias => it's more possibly to choose especial neighbour (on North, for example)
                currentCell.Link(neighbour);
                stack.Push(neighbour);
            }
        }
        return(grid);
    }
Пример #3
0
    public static T CreateMaze <T>(T grid) where T : MazeGrid
    {
        RowState state                   = new RowState(grid);
        MazeCell cell                    = grid.GetRandomCell();
        float    chanceToLinkInRow       = 0.5f;
        float    chanceToLinkBetweenRows = 0.35f;

        for (int z = 0; z < grid.height; z++)
        {
            for (int x = 1; x < grid.width; x++)
            {
                cell = grid.GetCell(x, grid.height - 1 - z);

                int currentSet      = state.SetFor(z, cell);
                int currentPriorSet = state.SetFor(z, cell.West);

                bool shouldLink = currentSet != currentPriorSet && (cell.South == null || Random.value < chanceToLinkInRow);
                if (shouldLink)
                {
                    cell.Link(cell.West);
                    state.MergeSets(z, cell.West, cell);
                }
            }

            if (cell.South != null)
            {
                var sets = state.SetsInRow(z);
                for (int i = 0; i < sets.Count; i++)
                {
                    var cells = Shuffle(state.CellsInSetInRow(z, sets[i]), (int)(Random.value * int.MaxValue));
                    for (int j = 0; j < cells.Count; j++)
                    {
                        if (j == 0 || Random.value < chanceToLinkBetweenRows)
                        {
                            cell = cells[j];
                            cell.Link(cell.South);
                            state.Record(z + 1, state.SetFor(z, cell), cell.South);
                        }
                    }
                }
            }
        }

        return(grid);
    }
Пример #4
0
        public void MergeSets(MazeCell lvalue, MazeCell rvalue)
        {
            lvalue.Link(rvalue);
            int setToMergeUsing = setsForCells[rvalue];
            int setToMergeInto  = setsForCells[lvalue];

            for (int i = 0; i < setsForCells.Count; i++)
            {
                if (setsForCells[setsKeys[i]] == setToMergeUsing)
                {
                    setsForCells[setsKeys[i]] = setToMergeInto;
                }
            }
        }
Пример #5
0
    // Implements Random Walkers
    public static T CreateMaze <T>(T grid) where T : MazeGrid
    {
        // Get random initial cell
        MazeCell currentCell = grid.GetRandomCell();

        int unvisitedCellsCount = grid.size - 1;

        // Random walks until visit all cells. Takes long time 'cause can walk on visited cells => possibility to hang around
        while (unvisitedCellsCount > 0)
        {
            var neighbourCell = currentCell.GetRandomNeighbour();

            if (neighbourCell.Links().Count == 0) //if current cell hasn't yet been linked to any other cell.
            {
                currentCell.Link(neighbourCell);
                unvisitedCellsCount--;
            }

            currentCell = neighbourCell;
        }

        return(grid);
    }
Пример #6
0
    public static T CreateMaze <T>(T grid, MazeSidewinderSettings settings) where T : MazeGrid
    {
        // Random Generator
        Random.State initialState = Random.state;
        if (settings.useFixedSeed)
        {
            Random.InitState(settings.seed.GetHashCode());
        }
        else
        {
            Random.InitState(Time.time.ToString().GetHashCode());
        }

        Direction vertical   = settings.verticalCarveDirectionNorth ? (Direction.North) : (Direction.South);
        Direction horizontal = settings.horizontalCarveDirectionEast ? (Direction.East) : (Direction.West);

        foreach (MazeCell[] cellRow in grid.EachRow(vertical, horizontal))
        {
            List <MazeCell> row = new List <MazeCell>();

            foreach (MazeCell cell in cellRow)
            {
                if (cell == null)
                {
                    continue;
                }

                row.Add(cell);

                //check if is out of width / height to avoid carve walls
                bool atVerticalBoundary   = settings.verticalCarveDirectionNorth ? (cell.North == null) : (cell.South == null);
                bool atHorizontalBoundary = settings.horizontalCarveDirectionEast ? (cell.East == null) : (cell.West == null);
                bool carveMainDirection;

                if (settings.isVerticalDirectionMain)
                {
                    carveMainDirection = atHorizontalBoundary || (!atVerticalBoundary && Random.value < settings.chanceToCarveOutMain);
                }
                else
                {
                    carveMainDirection = atVerticalBoundary || (!atHorizontalBoundary && Random.value < settings.chanceToCarveOutMain);
                }

                if (carveMainDirection)
                {
                    MazeCell member = row[Random.Range(0, row.Count)]; //get random cell in a row

                    if (settings.isVerticalDirectionMain)
                    {
                        if (settings.verticalCarveDirectionNorth)
                        {
                            if (member.North != null) //if has neighbour at North => carve out wall
                            {
                                member.Link(member.North);
                            }
                        }
                        else
                        {
                            if (member.South != null)
                            {
                                member.Link(member.South);
                            }
                        }
                    }
                    else
                    {
                        if (settings.horizontalCarveDirectionEast)
                        {
                            if (member.East != null)
                            {
                                member.Link(member.East);
                            }
                        }
                        else
                        {
                            if (member.West != null)
                            {
                                member.Link(member.West);
                            }
                        }
                    }

                    row.Clear(); // Clear row
                }
                else // if not carve north - break walls in horizontal axis between cells on row
                {
                    if (settings.isVerticalDirectionMain)
                    {
                        if (settings.horizontalCarveDirectionEast)
                        {
                            cell.Link(cell.East);
                        }
                        else
                        {
                            cell.Link(cell.West);
                        }
                    }
                    else
                    {
                        if (settings.verticalCarveDirectionNorth)
                        {
                            cell.Link(cell.North);
                        }
                        else
                        {
                            cell.Link(cell.South);
                        }
                    }
                }
            }
        }

        Random.state = initialState;

        return(grid);
    }