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); }
// 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); }
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); }
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; } } }
// 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); }
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); }