Предмет перестал быть строкой каталога. ItemInstance несёт редкость и до
шести аффиксов, и «карабин» с первого этажа больше не равен «карабину» с
сорокового. Четыре редкости, десять тегов, тир и бюджет от глубины.
Аффиксы не заводят новых каналов влияния: каждый тег ложится в то, что уже
есть — урон оружия, смесь стихий, пробитие, четыре числа бойца, ресурсы
вылазки. У предмета по-прежнему нет ручки к правилу «не бить своих», и
появиться ей неоткуда.
ItemInstance неявно приводится к ItemId, поэтому полторы сотни мест,
которым нужен ВИД вещи, остались как были. Цена решения — присваивание в
ItemId молча теряет рулоны; таких мест три (подбор, схрон, запись
профиля), и все они работают с экземпляром целиком.
Замеры поймали три расхождения дизайн-документа с самим собой:
* формула редкости противоречила таблице рядом с ней: 2.7% находок с
аффиксами на первом этаже против 22%. Выбрана формула, наклон поднят
до схождения с таблицей на дне (12% обычных на сотом);
* бюджет пускал восемь высших аффиксов вместо обещанных шести;
* предельная вещь собиралась к семидесятому этажу вместо сотого.
Числа пересчитаны, документ исправлен: 6·cost(9) = 294 <= B(100) = 295 <
7·cost(9) = 343. Предельная вещь существует ровно на дне и ровно одна.
Проверка в --descend меряет не бросок, а ПРОВОДКУ до бойца — там, где
дважды умирали вес и стихии:
аффиксы: урон 12.0 -> 18.0, здоровье 100 -> 140, броня 0.10 -> 0.25,
пробитие 0.20, KIN 1.00 -> 0.60, CRY 0.40, сумма долей 1.000
Последнее число не украшение: конверсия обязана переводить урон, а не
добавлять седьмую долю сверх единицы.
Попутно, на глубине 30 и только там:
* «зачистка поля» в проверках не держалась — у твари есть откат
воскрешения, и с нулевым таймером она оживала тем же шагом. Лечение
вне схватки и расход света на стоянке молча мерили бой. На восьмом
этаже тварей мало, и проверка проходила по удаче;
* порог «стоянка бесплатна» стоял в единицах заряда, а тот же шаг стоит
дороже с глубиной. Переведён в тайлы — и сразу показал, что отряд в
строю проходит 0.8 тайла за две секунды «стоянки». Свет теперь
списывается только в ADVANCING: топтание и драка бесплатны, тратит
РАЗВЕДКА. Без этого таймер возвращался через чёрный ход.
Формат профиля 4: токен предмета вида rifle@relic+dmg7,0:0.63. Миграции
не требует — у старых токенов нет хвоста после '@'.
--accept PASS без изменений: в песочнице находок нет вовсе.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
14 KiB
CLAUDE.md — оглавление
Этот файл — только навигация. Содержание живёт в docs/, по одному файлу на тему.
Читай нужный раздел, а не весь проект.
Документация
| Файл | О чём | Когда открывать |
|---|---|---|
| docs/00-overview.md | что это за прототип, границы задачи | первое знакомство |
| docs/01-build-and-run.md | сборка, запуск, управление, dev-режимы CLI | собрать и потыкать |
| docs/02-architecture.md | карта модулей, порядок шага симуляции, правила зависимостей | перед любой правкой кода |
| docs/03-rendering.md | софтверный фреймбуфер, изометрия, сортировка, спрайты | рендер, камера, спрайты |
| docs/04-world.md | тайлмап, планировка уровня, DDA-рейкаст, коллизии, мишени | карта, LOS, коллизии |
| docs/05-squad-ai.md | ядро: LaneClear, решатель огневых позиций, резерв линий, стрельба | поведение отряда |
| docs/06-debug-and-tuning.md | оверлей F1–F4, метрики, runtime-тюнинг, --set |
отладка и балансировка |
| docs/07-milestones.md | журнал вех M0–M6: что сделано и чем проверено | история и статус |
| docs/08-decisions.md | отклонения от спека и почему, с замерами | «почему тут не как в ТЗ» |
| docs/09-acceptance.md | критерии приёмки (спек 11) и их текущие цифры | приёмка |
| docs/10-atmosphere.md | хоррор-слой: свет, туман войны, трассеры, напряжение | картинка и атмосфера |
| docs/11-melee.md | ближний бой: сектор удара, три фазы, свой круг, дуга | клинки, классы оружия |
| docs/12-assets.md | ассеты: конвейер SpriteForge, манифесты, загрузчик, hot reload | добавить или пересобрать спрайт |
| docs/13-combat.md | бой: каталог оружия, твари, снаряжение, меню и HUD | оружие, враги, инвентарь, UI |
| docs/14-monsters.md | твари-ассеты: Blender-риг на пять морфологий, листы, проверки | нарисовать или пересобрать тварь |
| docs/15-engine-and-editor.md | движок и редактор: три цели сборки, каталог сущностей, формат комнат, генератор уровней | делать комнаты, менять генерацию, трогать границу движка |
| docs/16-descent.md | спуск: глубина как первичное понятие, бюджет опасности, лут, кривая сложности | менять сложность, добавлять тварей и лут |
| docs/17-extraction.md | экстракшен: эвакуация, профиль и схрон, чекпоинты, что теряется | правила забега, снаряжение между вылазками |
| docs/18-engine.md | Tile2D: границы движка, проекции 2D, формат проекта, второй проект | трогать движок, заводить проект, добавлять вид отображения |
| docs/19-agent.md | движок и ЛЛМ: инструменты --tool, скиллы, терминал в редакторе |
работать над проектом через claude/codex |
| docs/20-gdd.md | дизайн игры: акты, петли, рост отряда, закон масштаба, 200 часов | что и зачем строим дальше |
| docs/21-damage.md | урон: семь стихий, статусы, реакции, формулы, триггеры | боевая математика |
| docs/22-loot.md | добыча: редкости, аффиксы, артефакты, зачарования, материалы | предметы и экономика |
| docs/23-endgame.md | лейтгейм: Бездна, мутации, лидерборды, 262 ачивки | всё после сотого этажа |
Быстрые факты
- Исходный спек: SQUAD_PROTOTYPE_SPEC.md — источник истины по правилам.
- Сборка:
cmake -S . -B build && cmake --build build --config Release. Целей три:tile2d(библиотека),build/bin/squad_proto.exe(игра),build/bin/tile2d_editor.exe(редактор комнат). - Инструментов две группы, и делятся они по предмету:
squad_proto --tool— баланс (урон, сопротивления, экономика),tile2d_editor --tool— содержимое (комнаты, каталог, этажи). Редактор не линкуется сsim/и правил боя не видит, поэтому смешать их нельзя. - Содержимое щупают инструментами, а не глазами:
tile2d_editor --tool help. Правка делается файлами (комнаты и каталог — текст), последствия читаются командой:--tool validate,--tool floor,--tool map(19-agent.md). Код возврата 1 = поломка. - В редакторе снизу терминал (клавиша
`): те же инструменты, git, сборка и запросы кclaude/codexпрямо оттуда. Открытый проект уходит потомкам переменнойTILE2D_PROJECT. - Самопроверка:
squad_proto.exe --acceptпечатает PASS/FAIL по всем измеримым критериям. Содержимое проверяется отдельно:tile2d_editor.exe --check(комнаты и покрытие глубин),squad_proto.exe --descend 8(спуск, эвакуация, круговой прогон профиля). - Унести можно только то, что на ВЫЖИВШИХ. Павший теряет своё, вайп теряет всё, достигнутая глубина не теряется никогда (17-extraction.md).
NUM_AGENTS— это вместимость, а не размер отряда. Сколько слотов занято, говоритSquad::roster, а занят ли конкретный —Agent::present. Правила боя читают толькоalive(пустой слот и павший для них одно), а рендер, HUD и профиль обязаны смотреть наpresent: иначе у одинокого оперативника вокруг появятся четыре чужих трупа (17-extraction.md).- Таймера в игре нет и не заводить. Фонарь тратит заряд за ПРОЙДЕННЫЙ ПУТЬ,
а не за время: стоять и думать бесплатно, дорого — обшарить этаж целиком.
Расход со
dtвместо пути — это таймер, и--descendего ловит (17-extraction.md). - Закон масштаба: угроза растёт квадратично, сила отряда — линейно с затуханием, разрыв закрывается ЗНАНИЕМ (стихии, реакции, порядок целей). Числа не должны спасать — иначе хоррор кончается на сороковом этаже (20-gdd.md).
- Предмет — это ЭКЗЕМПЛЯР, а не вид.
ItemInstanceнеявно приводится кItemId, и это удобно ровно до того места, где вещь копируют: присваивание вItemIdмолча теряет редкость и аффиксы. Подбор, перекладывание и запись профиля обязаны работать с экземпляром целиком (22-loot.md). - Ни одного чистого улучшения. Артефакт без цены становится обязательным, а обязательный предмет — это вырезанный слот (22-loot.md).
- Глубина — первичное понятие. Вся кривая сложности живёт в одной функции
DescribeFloor(engine/progression.h); размазывать её по генератору, каталогу и рендеру нельзя (16-descent.md). - Редактор линкуется только с движком. Обращение из
editor/кsim/,ai/илиui/— ошибка сборки, и так задумано (15-engine-and-editor.md). Редактор принадлежит движку: он открывает любой проект (--project <имя>) и ни одной игры по имени не знает. - Тексты НА ЭКРАНЕ — латиницей: встроенный шрифт raylib кириллицы не знает и рисует её вопросами. Комментарии и вывод в консоль остаются русскими.
- Числа игры — в src/tuning.h, размеры движка — в engine/config.h. Магических констант по коду быть не должно.
src/ai/не знает про рендер, изометрию и ввод. Это правило не нарушать.- Правило «не бить своих» одно на все классы оружия: у ствола это отрезок, у клинка — сектор. Ослаблять его нельзя нигде.
RenderGameпринимаетconst Game&— эффекты физически не могут влиять на симуляцию.- Приёмка меряется в ПЕСОЧНИЦЕ:
Game::combatModeвыключен, в мире мишени, на бойцах нет снаряжения. Ломать это нельзя — иначе--acceptмеряет другое.
Ассеты
Спрайты собирает внешний CLI SpriteForge (C:\Users\uuu\Documents\spriteforge).
Полный порядок работы — в docs/12-assets.md, здесь только запреты:
- игра хранит манифесты
assets/manifests/, исходникиassets/sources/и сгенерированныйgenerated/spriteforge_assets.h; собранное лежит вbuild/sprites/и в git не попадает; - не открывать
build/sprites/*.sfa,.sfcache/, сгенерированные PNG и contact sheet: проверка только текстом —sf list,sf describe,sf ascii,sf validate,sf stats; - строковых ID ассетов в C++ нет — только константы
SF_ASSET_*; - не править репозиторий SpriteForge ради одной игровой сущности.
Agent sprite production
For ANY request to create, change, replace, or add game art, follow .claude/commands/sprite.md
(the /sprite workflow) automatically even when the user did not type the slash command.
Never satisfy an art request with a one-off procedural runtime drawing.
When asked to create an agent, armor, or weapon sprite, use /agent-sprite and
assets/agents/catalog.yaml; do not draw a one-off procedural humanoid. Agent art is
an aligned paper-doll: body, armor and held weapon are separate 70x90, eight-direction
layers sharing one rig and pivot. Run tools/build_agent_assets.ps1 after ingestion.
Start the game with --sf-agents (or --sf) to see the generated layers. Blender is
installed at C:\Program Files\Blender Foundation\Blender 5.2\blender.exe.
Monster sprite production
Enemies do NOT go through the agent paper-doll. They have their own Blender-first
pipeline: assets/monsters/catalog.yaml, tools/blender/monster_rig.py,
tools/monster_assets.py (monster-init, monster-render, monster-render-all,
validate, sync). Five kinds, five distinct morphologies — never one humanoid
recoloured five times. Asset ids are <kind>_<animation>; renaming them breaks
tools/asset_coverage.py. Full rules in docs/14-monsters.md.