# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project A Unity project (Editor version `6000.3.7f1`, Universal Render Pipeline, 2D/top-down via `Physics2D`) that procedurally generates a maze of connected rooms and populates it with autonomous agents that explore it. All project-specific code lives under `Assets/Scripts/Maze/`, namespace `MazeGen`. There is no code outside that folder worth touching except `Assets/Scenes/SampleScene.unity`, which wires up the single `MazeSceneBuilder` entry point component. ## Commands This is a pure Unity Editor project — there is no CLI build, lint, or test setup in the repo (no `package.json`, `Makefile`, `.asmdef`, or test assemblies). The only way to run/verify changes is: 1. Open the project in Unity Editor `6000.3.7f1` (or compatible 6000.3.x). 2. Open `Assets/Scenes/SampleScene.unity`. 3. Press Play. The `MazeSceneBuilder` component on the scene's root object generates the maze and spawns agents automatically. Compile errors surface in the Unity Console; there's no separate `dotnet build`/`csc` step to invoke. If you need to sanity-check C# syntax without the Editor, treat the generated `Assembly-CSharp.csproj` as a rough reference for compiled files, but it's Editor-generated and shouldn't be hand-edited. ## Architecture The maze is **not** a pre-built grid — it's a lazily-grown graph of `Room` nodes connected by `Exit` doors, generated on demand as agents actually walk through unresolved exits. Nothing beyond an unused exit exists until something tries to go through it. This is what makes "many agents, huge maze" cheap. ### Core data model (`Core/`) - `Room` — a node with `Position` (free `Vector2`, not grid-snapped), `Radius`, `Kind` (Start/Normal/Hallway/Exit), and a list of `Exit`s. `CorridorWaypoints` is set only on elbow-hallway rooms (see below) for stretched rendering. - `Exit` — one doorway. **Grid-locked to the 4 cardinal directions** (0/90/180/270°, `DirectionDegrees`), so a room has at most one exit per side and "the door facing room X" always has a single, exact answer. Exits are matched in connected pairs (`ConnectedRoomId`/`ConnectedExitId`) once resolved; `IsUsed` marks that. - `MazeGraph` — the registry of all rooms, id allocation, `UnusedExitCount` bookkeeping (must never hit 0 before an Exit room exists, or the maze could never be solvable), and spatial lookup via `SpatialRoomIndex` (a uniform grid bucket index, cell size = `roomSpacing`, used for overlap/collision queries — not a maze grid). ### Generation (`Generation/`) - `MazeGenerationSettings` — a `ScriptableObject` with all tunables (room sizes, exit counts, hallway chance, start room count/spread, collision-avoidance search parameters, exit-room eligibility odds). - `MazeGenerator` — the core algorithm, called lazily from `MazeAgentController.TryUseExit` / `AutonomousAgentBrain` whenever an agent uses an unresolved exit (`GenerateConnectedRoom`). On each call it: 1. Computes where a new room *would* go (`fromRoom.Position + exit.Direction * roomSpacing`). 2. **`TryConnectViaExistingDoor`**: if that spot overlaps an existing room, looks for (or adds on-the-fly) a door on that room facing back toward `fromRoom`, and links into it instead of creating an overlapping room — this is what turns the tree into a maze with loops. The link is either direct (`ConnectStraight`, doors face each other head-on) or via a single 90°-bend elbow hallway room (`ConnectWithElbow`, perpendicular doors). All paths run `IsPathClear` (point-to-segment distance vs. every other room) so a corridor can never cut through unrelated geometry. 3. If no door connection works but the spot still overlaps something, `TryRouteAroundObstruction` tries extending further out, then a single 90° bend, before falling back to `FindClearPosition` (a ring/spiral search) as a last resort. 4. Otherwise builds the room normally via `BuildRoom`, rolling cardinal-direction exits (`PickCardinalAngles`). - Known limitation: an elbow hallway's collision footprint is only a small circle at its bend corner, not its full rendered length — something can in rare cases still slip past a corridor without being caught. ### Visualization (`Visualization/`) - `MazeSceneBuilder` — the scene entry point (`[RequireComponent(MazeGenerator)]`). Generates the configured start rooms, spawns `agentCount` agents on staggered coroutine delays, wires each agent's `AutonomousAgentBrain`, tracks win conditions (target finished-agent count and/or a time limit — at least one must be set, else it warns and defaults to requiring all agents), and draws a simple IMGUI HUD (elapsed time/finished count, a clickable agent list that makes the camera follow one, a "zoom to fit maze" button). - `RoomView` — placeholder square sprite per room; renders elbow hallways as stretched/rotated rectangles along `CorridorWaypoints` instead of a single small square. - `ExitMarker` — placeholder door sprite. Purely informational (not clickable — movement is autonomous now): green/blue/gray coloring is relative to whichever agent the camera is currently following. - `PathVisualizer` — one `LineRenderer` per hop; only the followed agent's trail is shown, with the most recent hop bright and earlier hops dimmed. ### Agents (`Agent/`) - `MazeAgent` — plain C# (no `MonoBehaviour`) state: current room, path history, visited-room/used-exit sets, `IsFinished`. Cheap enough to run many of. - `MazeAgentController` — scene-facing wrapper: positions a GameObject, tints it a per-agent color, and drives `TryUseExit` (which calls `MazeGenerator.GenerateConnectedRoom` lazily if the exit isn't resolved yet). - `AutonomousAgentBrain` — per-agent decision loop. Waits a randomized initial delay (so agents don't all decide in lockstep), then ticks a steady `decisionInterval`. `ChooseExit` is explore-biased: prefers an unused exit (fresh territory) > a used exit into a room this agent hasn't personally visited (following another agent's discovery) > backtracking into an already-visited room, with `exploreChance` adding randomness. This is the intended extension point for smarter decisions later (e.g. "peek" a room and weigh danger before choosing). ### Camera & input (`Camera/`, `Input/`) - `MazeCameraController` — manual WASD pan / middle-mouse drag, plus `FocusOn` (smooth glide, used only while following an agent) and `FrameBounds` (instant zoom-to-fit, used by the HUD button). The camera does nothing on its own unless something calls one of those. - `MazeInput` — input-backend-agnostic helpers (`ENABLE_INPUT_SYSTEM` vs legacy `Input`), since this project has the Input System package installed and legacy APIs like `OnMouseDown`/`Input.GetKey` silently break if Active Input Handling is set to "Input System Package (New)" only. ## Conventions worth preserving - Rooms/exits are **cardinal-only** by design (not free-angle) — this is what makes "which side faces which room" and 90°-bend hallway routing well-defined. Don't reintroduce arbitrary exit angles without reworking the routing/merge logic that depends on exact cardinal matching. - All visuals (`RoomView`, `ExitMarker`, agent sprites) are intentionally flat placeholder sprites sharing `RoomView.SharedSquareSprite` — swappable for real art later without touching generation logic. - Generation must stay lazy: don't pre-generate rooms beyond an unused exit "just in case."