using System.Collections; using System.Collections.Generic; using UnityEngine; namespace Hallucinate.GameSetup.Maze { /// /// Central controller for the Maze system. /// Manages algorithm selection, debug speed, and regeneration. /// public class MazeManager : MonoBehaviour { public enum AlgorithmType { Recursive, Wilsons, Prims, Crawler } [Header("System Settings")] public MazeGrid[] mazes; public float floorHeight = 3.5f; public int connectionsPerFloor = 2; [SerializeField] private AlgorithmType selectedAlgorithm; [SerializeField] private int width = 30; [SerializeField] private int depth = 30; [Header("Debug Settings")] [SerializeField] private bool debugMode = true; [Range(0.001f, 0.5f)] [SerializeField] private float visualizationInterval = 0.05f; [Header("References")] [SerializeField] private MazeRenderer mazeRenderer; [SerializeField] private Transform mazeContainer; [Header("Corridor Setting")] public GameObject straightManHoleLadder; public GameObject straightManHoleUp; public GameObject deadendManHoleLadder; public GameObject deadendManHoleUp; private MazeGrid _grid; private Coroutine _generationCoroutine; private void Start() { Regenerate(); } private void Update() { if (Input.GetKeyDown(KeyCode.R)) { Regenerate(); } } [ContextMenu("Regenerate")] public void Regenerate() { if (_generationCoroutine != null) { StopCoroutine(_generationCoroutine); } mazeRenderer.Clear(); // Step 1: Initialize all maze floors for (int i = 0; i < mazes.Length; i++) { mazes[i] = new MazeGrid(width, depth); mazes[i].Level = i; // Generate each floor using the selected algorithm IMazeAlgorithm algorithmForFloor = GetAlgorithm(selectedAlgorithm); algorithmForFloor.Generate(mazes[i]); } // Step 2: Create connections between adjacent floors for (int i = 0; i < mazes.Length - 1; i++) { MazeGrid currentFloor = mazes[i]; MazeGrid nextFloor = mazes[i + 1]; List possibleConnections = new List(); for (int z = 0; z < depth; z++) { for (int x = 0; x < width; x++) { // Check if both floors have a corridor at this position bool isCurrentFloorPath = currentFloor.GetCell(x, z) == MazeCellType.Corridor; bool isNextFloorPath = nextFloor.GetCell(x, z) == MazeCellType.Corridor; if (isCurrentFloorPath && isNextFloorPath) { possibleConnections.Add(new Vector2Int(x, z)); } } } ShuffleList(possibleConnections); int connectionsMade = 0; foreach (Vector2Int pos in possibleConnections) { if (connectionsMade >= connectionsPerFloor) break; int x = pos.x; int z = pos.y; // Set stair cells currentFloor.SetCell(x, z, MazeCellType.StairsUp); nextFloor.SetCell(x, z, MazeCellType.StairsDown); connectionsMade++; } } // Step 3: Render all floors if (mazes.Length > 0) { for (int i = 0; i < mazes.Length; i++) { mazeRenderer.Initialize(mazes[i], mazeContainer, i == 0); } _grid = mazes[0]; } else { _grid = new MazeGrid(width, depth); mazeRenderer.Initialize(_grid, mazeContainer); IMazeAlgorithm algorithm = GetAlgorithm(selectedAlgorithm); if (debugMode) { _generationCoroutine = StartCoroutine(algorithm.GenerateStepByStep(_grid, visualizationInterval)); } else { algorithm.Generate(_grid); } } } private void ShuffleList(List list) { for (int i = 0; i < list.Count; i++) { T temp = list[i]; int randomIndex = Random.Range(i, list.Count); list[i] = list[randomIndex]; list[randomIndex] = temp; } } private IMazeAlgorithm GetAlgorithm(AlgorithmType type) { return type switch { AlgorithmType.Recursive => new RecursiveAlgorithm(), AlgorithmType.Wilsons => new WilsonsAlgorithm(), AlgorithmType.Prims => new PrimsAlgorithm(), AlgorithmType.Crawler => new CrawlerAlgorithm(), _ => new RecursiveAlgorithm() }; } } }