| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- using System.Collections.Generic;
- using UnityEngine;
- namespace MazeGen
- {
- /// <summary>
- /// The full set of generated rooms so far, plus O(1)-ish id lookup, spatial queries and
- /// exit-usage bookkeeping. Everything else (agent tracking, visualization, collision/merge
- /// logic) reads from here instead of walking the scene hierarchy.
- /// </summary>
- public class MazeGraph
- {
- public readonly Dictionary<int, Room> Rooms = new Dictionary<int, Room>();
- public readonly List<Room> StartRooms = new List<Room>();
- public readonly List<Room> ExitRooms = new List<Room>();
- private readonly SpatialRoomIndex _spatialIndex;
- private int _nextRoomId;
- private int _nextExitId;
- public int RoomCount => Rooms.Count;
- /// <summary>
- /// Total exits across the whole graph that are not yet used. This must never be
- /// allowed to reach 0 while ExitRooms.Count == 0 - if it did, the maze would have no
- /// remaining way to grow and could never produce a reachable exit.
- /// </summary>
- public int UnusedExitCount { get; private set; }
- public MazeGraph(float spatialCellSize)
- {
- _spatialIndex = new SpatialRoomIndex(spatialCellSize);
- }
- public int AllocateRoomId() => _nextRoomId++;
- public int AllocateExitId() => _nextExitId++;
- public void Register(Room room)
- {
- Rooms[room.Id] = room;
- if (room.Kind == RoomKind.Start) StartRooms.Add(room);
- if (room.Kind == RoomKind.Exit) ExitRooms.Add(room);
- _spatialIndex.Add(room);
- }
- public Room Get(int id) => Rooms.TryGetValue(id, out var room) ? room : null;
- public IEnumerable<Room> QueryRoomsNear(Vector2 position, float radius) =>
- _spatialIndex.QueryNearby(position, radius);
- /// <summary>Adds an exit to a room and keeps the unused-exit counter in sync.</summary>
- public void AddExit(Room room, Exit exit)
- {
- room.Exits.Add(exit);
- if (!exit.IsUsed) UnusedExitCount++;
- }
- /// <summary>Marks an exit as used (idempotent) and keeps the unused-exit counter in sync.</summary>
- public void MarkExitUsed(Exit exit)
- {
- if (exit.IsUsed) return;
- exit.IsUsed = true;
- UnusedExitCount--;
- }
- /// <summary>
- /// Undoes a speculative AddExit for an exit that turned out to be unusable (e.g. a
- /// door added on-the-fly to close a loop, where the path to it was later found to be
- /// blocked). Only valid for still-unused exits.
- /// </summary>
- public void RemoveUnusedExit(Room room, Exit exit)
- {
- if (exit.IsUsed) return;
- if (room.Exits.Remove(exit)) UnusedExitCount--;
- }
- }
- }
|