/// <summary> /// Executes a random walk from given unvisited cell adding visited cells to visited list on finish /// </summary> /// <param name="unvisitedCell"></param> /// <param name="service"></param> /// <param name="visited"></param> private void RandomWalk(MazeCell unvisitedCell, MazeGenerationService service, List <MazeCell> visited) { //setup data structures necessary for the random walk to take place List <KeyValuePair <MazeCell, Vector2Int> > records = new List <KeyValuePair <MazeCell, Vector2Int> >(); List <MazeCell> neighbours = service.GetNeighbours(unvisitedCell); //pick a random neighbour as the walking position and check whether it is not already visited MazeCell walker = neighbours[Random.Range(0, neighbours.Count)]; if (walker.IsVisited) { //mark the unvisited cell as visited unvisitedCell.MarkAsVisited(); visited.Add(unvisitedCell); //link unvisited cell to the walker and return unvisitedCell.CreatePassage(walker); walker.CreatePassage(unvisitedCell); return; } //get the direction relative to the walker so we can store it as a record Vector2Int direction = unvisitedCell.GetDirectionRelative(walker); records.Add(new KeyValuePair <MazeCell, Vector2Int>(unvisitedCell, direction)); //loop until there are not records left while (records.Count != 0) { //refresh the neighbours list with the walkers neighbours neighbours.Clear(); neighbours.AddRange(service.GetNeighbours(walker)); //pick a random neighbour, and record the direction from the walker to it MazeCell randomNeighbour = neighbours[Random.Range(0, neighbours.Count)]; direction = walker.GetDirectionRelative(randomNeighbour); if (!records.TryUpdate(walker, direction)) { records.Add(new KeyValuePair <MazeCell, Vector2Int>(walker, direction)); } if (randomNeighbour.IsVisited) { //if the random neighbour is visited, carve out a path using the records and clear the records list MarkRecordAsVisitedRecursive(records[0], records, service, visited); records.Clear(); } else { //if the random neighbour isn't visited yet, set it as the new walker cell walker = randomNeighbour; } } }
/// <summary> /// Returns an enumerator that creates a maze by linking cells using prim's algorithm /// </summary> /// <param name="service"></param> /// <returns></returns> public override IEnumerator CreateMazeRoutine(MazeGenerationService service) { //create data structures necessary for algorithm to work MazeCell[] cells = service.Cells.Cast <MazeCell>().ToArray(); List <MazeCell> frontier = new List <MazeCell>(); //set starting point MazeCell startCell = service.RootCell; startCell.MarkAsVisited(); //add neighbours of starting cell to frontier frontier.AddRange(service.GetNeighbours(startCell)); while (frontier.Count != 0) { //pick a random frontier cell, mark it as visited and remove it from the frontier MazeCell randomFrontierCell = frontier[Random.Range(0, frontier.Count)]; randomFrontierCell.MarkAsVisited(); frontier.Remove(randomFrontierCell); //pick a random visited neighbour of it and link it with it List <MazeCell> visitedNeighbours = service.GetVisitedNeighbours(randomFrontierCell); if (visitedNeighbours.Count > 0) { MazeCell randomVisitedNeighbour = visitedNeighbours[Random.Range(0, visitedNeighbours.Count)]; randomFrontierCell.CreatePassage(randomVisitedNeighbour); randomVisitedNeighbour.CreatePassage(randomFrontierCell); } //add unvisited neighbours of it to the frontier if they aren't already in it List <MazeCell> unvisitedNeighbours = service.GetUnVisitedNeighbours(randomFrontierCell); foreach (MazeCell cell in unvisitedNeighbours) { if (!frontier.Contains(cell)) { frontier.Add(cell); } } randomFrontierCell.ShowAsStep(true); yield return(null); randomFrontierCell.ShowAsStep(false); } CompletedRoutine(); }
/// <summary> /// Returns an enumerator that creates a maze by linking cells using the adlous broder algorithm /// </summary> /// <param name="service"></param> /// <returns></returns> public override IEnumerator CreateMazeRoutine(MazeGenerationService service) { //create data structures necessary for algorithm to work List <MazeCell> visited = new List <MazeCell>(); //set starting point MazeCell startCell = service.RootCell; startCell.MarkAsVisited(); visited.Add(startCell); //set current cel as starting cell MazeCell currentCell = startCell; //loop until all cells have been visited long totalCells = service.Cells.LongLength; while (visited.Count != totalCells) { //pick a random neighbour of the current cell List <MazeCell> neighbours = service.GetNeighbours(currentCell); MazeCell randomNeighbour = neighbours[Random.Range(0, neighbours.Count)]; if (!randomNeighbour.IsVisited) { //if the random neighbour hasn't been visited yet, mark it as visited randomNeighbour.MarkAsVisited(); visited.Add(randomNeighbour); //create passage between cell and neighbour randomNeighbour.CreatePassage(currentCell); currentCell.CreatePassage(randomNeighbour); } //set current cell to random neighbour to travel from it currentCell = randomNeighbour; //show stepping feedback currentCell.ShowAsStep(true); yield return(null); currentCell.ShowAsStep(false); } CompletedRoutine(); }