using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Hallucinate.GameSetup.Maze { public class PrimsAlgorithm : IMazeAlgorithm { private const int InitialX = 2; private const int InitialZ = 2; private const int MaxIterations = 10000; private const int TargetCorridorNeighbours = 1; public void Generate(MazeGrid grid) { int x = InitialX; int z = InitialZ; grid.SetCell(x, z, MazeCellType.Corridor); List walls = GetNeighbouringWalls(grid, x, z); int iterations = 0; while (walls.Count > 0 && iterations < MaxIterations) { int rIndex = Random.Range(0, walls.Count); MapLocation w = walls[rIndex]; walls.RemoveAt(rIndex); if (grid.CountSquareNeighbours(w.x, w.z, MazeCellType.Corridor) == TargetCorridorNeighbours) { grid.SetCell(w.x, w.z, MazeCellType.Corridor); foreach (var nw in GetNeighbouringWalls(grid, w.x, w.z)) { if (!walls.Contains(nw)) walls.Add(nw); } } iterations++; } } public IEnumerator GenerateStepByStep(MazeGrid grid, float interval) { int x = InitialX; int z = InitialZ; grid.SetCell(x, z, MazeCellType.Corridor); yield return new WaitForSeconds(interval); List walls = GetNeighbouringWalls(grid, x, z); foreach(var w in walls) grid.SetCell(w.x, w.z, MazeCellType.Processing); int iterations = 0; while (walls.Count > 0 && iterations < MaxIterations) { int rIndex = Random.Range(0, walls.Count); MapLocation w = walls[rIndex]; walls.RemoveAt(rIndex); if (grid.CountSquareNeighbours(w.x, w.z, MazeCellType.Corridor) == TargetCorridorNeighbours) { grid.SetCell(w.x, w.z, MazeCellType.Corridor); if (interval > 0) yield return new WaitForSeconds(interval); foreach (var nw in GetNeighbouringWalls(grid, w.x, w.z)) { if (grid.GetCell(nw.x, nw.z) == MazeCellType.Wall) { grid.SetCell(nw.x, nw.z, MazeCellType.Processing); walls.Add(nw); } } } else { // If it's no longer a candidate, turn it back to Wall grid.SetCell(w.x, w.z, MazeCellType.Wall); } iterations++; } } private List GetNeighbouringWalls(MazeGrid grid, int x, int z) { List neighbours = new List(); foreach (var dir in MapLocation.Directions) { int nx = x + dir.x; int nz = z + dir.z; // Correction nx = x + dir.x; nz = z + dir.z; if (grid.IsInBounds(nx, nz)) { MazeCellType type = grid.GetCell(nx, nz); if (type == MazeCellType.Wall || type == MazeCellType.Processing) { neighbours.Add(new MapLocation(nx, nz)); } } } return neighbours; } } }