# CLAUDE.md — как работать с этим проектом Инструкции для ИИ-агентов **и** разработчика. Прочитай целиком перед правками. Цель проекта — держать **рабочую, расширяемую базу** рогалика. Не ломать то, что работает; добавлять — по правилам ниже. ## Что это Top-down рогалик (в духе Binding of Isaac). Логика — чистый TypeScript (`src/core/`), рендер — three.js в псевдо-3D (наклонная `PerspectiveCamera`, `src/render/`), сборка/тесты — Bun. Обзор — [`README.md`](./README.md), детали — [`docs/ARCHITECTURE.md`](./docs/ARCHITECTURE.md), рецепты доработки — [`docs/HOWTO.md`](./docs/HOWTO.md). ## 🔑 Золотые правила (нарушать = ломать архитектуру) 1. **Ядро без рендера и DOM.** В `src/core/**` НЕЛЬЗЯ импортировать `three`, обращаться к `window`/`document`/`canvas`. Логика общается с миром только через `InputState` (вход) и публичные поля `Game` (для чтения рендером). 2. **Рендер ничего не меняет в игре.** `src/render/**` только ЧИТАЕТ `Game` и рисует. Любая мутация состояния из рендера — баг. 3. **Случайность только через `Rng`.** Никаких `Math.random()` в `core/`. Это сохраняет детерминизм (тесты, отладка по seed). 4. **Время — в «шагах» (1/60 c), а не в кадрах.** Скорости — «пиксели/шаг», перезарядки — «шаги». Не двигай ничего в коде рендера или прямо в rAF. 5. **Числа — не в коде.** Константы движка (размеры, геометрия дверей, базовый баланс) — в `src/config.ts`; параметры конкретного забега (размер карты, сила врагов, HP игрока, seed) — в правилах уровня `src/core/rules.ts`. Не раскидывай «магические числа» по логике. 6. **Освобождай ресурсы three.js.** Создаёшь геометрию/материал на сущность — обеспечь `dispose()` при её удалении (см. `sync*`/`sweep` в `ThreeRenderer`). 7. **Комментарии и текст для игрока — по-русски**, как в существующем коде. ## Команды ```bash bun run dev # дев-сервер + watch → http://localhost:3000 bun run build # прод-сборка в dist/ bun run typecheck # tsc --noEmit (строгий) — НЕ ловится при bun build! bun test # юнит-тесты ядра bun run check # typecheck + test ``` > ⚠️ `bun build` **не проверяет типы**. Поэтому `bun run typecheck` обязателен — > именно отсутствие тайп-чека когда-то скрыло рантайм-регрессию. ## Definition of Done (для любой правки) 1. `bun run check` зелёный (типы + тесты). 2. Если менял логику — **добавил/обновил тест** в `tests/`. 3. Если менял геймплей/рендер — **проверил в браузере** (`bun run dev`, открыть страницу, увидеть, что играется, в консоли нет ошибок). Юнит-тесты не видят рендер — визуальную проверку не пропускать. 4. Обновил доки, если поменялось поведение или структура. ## Где что лежит (карта для навигации) | Хочешь поменять… | Иди в… | |---|---| | константы движка (размер тайла/комнаты, геометрия дверей, базовый баланс) | `src/config.ts` | | правила уровня / пресеты в меню (размер карты, сила врагов, HP, seed) | `src/core/rules.ts` | | поведение за один шаг (движение, атака, ИИ, переходы) | `src/core/Game.ts` | | данные сущности | `src/core/entities/*` | | генерацию карты | `src/core/world/RoomMap.ts` | | форму комнаты/тайлы | `src/core/world/tiles.ts`, `Room.ts` | | коллизии | `src/core/systems/collision.ts` | | расстановку врагов | `src/core/systems/spawner.ts` | | как рисуется мир (псевдо-3D) | `src/render/ThreeRenderer.ts` | | спрайты/текстуры (графика) | `src/render/assets.ts` (бриф на художку — `docs/ASSET_BRIEF.md`) | | цвета/тинты/фон | `src/render/theme.ts` | | HUD/миникарту | `src/render/HudOverlay.ts` | | стартовое меню | `src/ui/StartMenu.ts` | | раскладку клавиш | `src/input/KeyboardController.ts` | | тайминг/цикл, поток меню↔игра | `src/engine/GameLoop.ts`, `src/main.ts` | Пошаговые рецепты («добавить врага», «новое оружие», «тип комнаты», «сменить рендер») — в [`docs/HOWTO.md`](./docs/HOWTO.md). ## Грабли, на которые уже наступали (не повторять) - **Пустая карта.** `new RoomMap(rng)` ДОЛЖЕН генерировать карту в конструкторе. Если карта пустая — `curRoom` будет `undefined` и всё упадёт на старте. - **`OPP` направлений.** Противоположное к `up` — это `down`, к `left` — `right`. Любая другая раскладка ломает встречные двери и связность карты. - **Пол «выворачивает» перспективу.** Пол в псевдо-3D надо класть ПЛАШМЯ (`flatMesh`, поворот −90° вокруг X). Без поворота он встаёт вертикально и вид ломается. Спрайты/стены — `DoubleSide` (камера переворачивает Y, иначе грани отсекаются). - **Canvas вылезает за рамки.** Холстам нужен CSS-размер (`width/height:100%`), иначе они показываются в размер HiDPI-буфера. - **Комната без врагов не открывается.** Если в комнате 0 врагов (сокровищница) — она должна стать `cleared` сразу при входе, иначе двери не появятся. ## Стиль кода - TypeScript strict, без `any` (кроме узких мест вроде `window as …` в `main.ts`). - Маленькие чистые функции для логики; классы — для сущностей/состояния. - Имена и комментарии осмысленные, по-русски. Комментарий объясняет «почему», а не «что». - Перед коммитом — `bun run check`. ## Чего НЕ делать без явной просьбы - Не добавлять тяжёлые зависимости (физдвижки, фреймворки). База намеренно лёгкая. - Не переписывать архитектуру «ядро ↔ рендер». - Не коммитить `dist/` и `node_modules/` (см. `.gitignore`). - Не превращать игру в полноценное 3D, пока этого не попросили (рендер для этого готов — он изолирован, — но это отдельная большая задача).