squad-proto/docs/01-build-and-run.md
z.kirill d3aa044cbe Редкости и аффиксы: находка стала решением (M25)
Предмет перестал быть строкой каталога. 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>
2026-08-16 02:35:00 +03:00

14 KiB
Raw Blame History

01 — Сборка, запуск, управление

Требования

  • CMake 3.16+
  • Компилятор с C++17. Проверено на MSVC 14.44 (Visual Studio 2022, x64).
  • Интернет при первой конфигурации: raylib 6.0 качается через FetchContent. Если в системе уже стоит raylib 6.x, find_package(raylib 6) возьмёт её и ничего не качает.
  • Репозиторий SpriteForge рядом с игрой (../spriteforge): из него берётся один заголовок include/sfa.h. Лежит в другом месте — передать путь при конфигурации: cmake -S . -B build -DSPRITEFORGE_DIR=<путь>. Сам CLI sf нужен только чтобы пересобирать ассеты (12-assets.md).

Сборка

cmake -S . -B build            # разово; тянет и собирает raylib (~1-2 мин)
cmake --build build --config Release --parallel

Бинарников три, все в build/bin при любом генераторе, включая multi-config:

Цель Что это
squad_proto.exe игра Descent — один из проектов движка
tile2d_editor.exe редактор комнат: инструмент ДВИЖКА, открывает любой проект (15-engine-and-editor.md)
tile2d_walk.exe пример на движке: открыть проект, собрать этаж, походить (18-engine.md)

Третья цель, tile2d, — сам движок (18-engine.md), статическая библиотека, на которой стоят обе. Собрать что-то одно: cmake --build build --config Release --target tile2d_editor.

Debug-сборка (--config Debug) кладёт бинарник туда же и идёт в 60 fps, так что проверять правки стоит именно в ней: MSVC включает проверки итераторов и ловит выходы за границы, которых в Release не видно.

В VS Code: F5 — конфигурация Run (Release) из .vscode/launch.json, сборка идёт задачей build release. Есть также задачи accept и headless 180s.

Makefile в корне остался от исходного шаблона raylib-vscode и не используется — он ссылается на C:/raylib/w64devkit. Актуальная сборка только через CMake.

Если CMake ругается на генератор

CMake Error: Error: generator : Visual Studio 17 2022
Does not match the generator used previously: Visual Studio 18 2026

Каталог build/ привязан к конкретному генератору, и на машине с несколькими Visual Studio его легко получить несогласованным: обычный cmd.exe и Developer Command Prompt выбирают разные версии по умолчанию. Лечится сносом каталога — он целиком производный, в нём нет ничего своего:

rmdir /s /q build          # cmd
rm -rf build               # bash
cmake -S . -B build

Чтобы зафиксировать версию явно, передай генератор при первой конфигурации:

cmake -S . -B build -G "Visual Studio 17 2022" -A x64

Дальше cmake -S . -B build без -G будет переиспользовать генератор из кэша. build/ намеренно в .gitignore — в репозитории его быть не должно.

Управление

Клавиша Действие
WASD движение диска (якоря отряда) в экранных осях
Shift (удерж.) рывок (базовый шаг намеренно медленный)
Space переключить режим ручного прицеливания
/ в ручном режиме — поворот вектора прицела
Tab сменить назначенную цель (внутри конуса прицела)
1 / 2 / 3 строй: клин / линия / кольцо
F спуститься глубже (стоя на зелёном кольце)
E эвакуироваться: забег окончен, добыча в схроне (голубое кольцо)
Esc пауза (из меню — выход)
I экран отряда: снаряжение и сумки
F11 окно / безрамочный на весь экран
F1 оверлей вкл/выкл
F2 линии огня
F3 кандидаты решателя и их оценки
F4 метрики
F5 выключить хоррор-слой (свет/туман/пост)
F6 показать диски обзора
[ / ] выбрать параметр тюнинга
- / = изменить выбранный параметр
R пересобрать ТОТ ЖЕ этаж заново

По умолчанию окно разворачивается безрамочно на весь монитор, а кадр 480x270 масштабируется ЦЕЛЫМ множителем и центрируется — остаток уходит в чёрные поля. Дробное растяжение размывало бы пиксель: одни строки удваивались бы, соседние нет.

Стрельба всегда автоматическая, клавиши огня нет ни в одном режиме. Ближний бой тоже: бойцы с клинком сами доходят до цели и бьют, пока она внутри их круга (11-melee.md).

Диск намеренно быстрее бойцов и держится к ним на поводке: команда читается мгновенно, а средняя скорость похода всё равно определяется ногами отряда.

Dev-режимы командной строки

Симуляция детерминирована и не зависит от рендера, поэтому её можно гонять без окна.

Аргумент Что делает
--accept прогоняет сценарии критериев приёмки (спек 11) и печатает PASS/FAIL
--headless <сек> прогон по маршруту без окна + метрики каждые 10 с
--probe к --headless: подробности по каждому агенту на стоянках
--no-solver отключить решатель огневых позиций (A/B сравнение)
--no-laneavoid отключить расступание из чужих линий (A/B сравнение)
--melee N сколько слотов строя держат клинок (по умолчанию 2, 0 = все стрелки)
--set имя=значение подкрутить любой параметр из TUNABLES без пересборки
--shot [кадров] [файл] снять скриншот через N кадров и выйти
--clean стартовать без оверлея — чистый кадр для скриншотов
--sf-tiles пол и стены из библиотеки SpriteForge + hot reload по sf watch
--sf-enemies анимированные твари оттуда же (цикл шага вместо статичного спрайта)
--sf и то, и другое разом
--sprites что загрузчик видит в build/sprites, и выход
--windowed окно 1440x810 вместо безрамочного на весь экран
--sandbox прежняя песочница: мишени вместо тварей, отряд без снаряжения
--ui-shot <экран> снять кадр с menu / squad / pause / defeat
--rooms [проект] играть в проект (по умолчанию свой, descent) вместо захардкоженной карты
--project <имя> то же явно: имя каталога в projects/ или путь к нему
--view <iso|topdown> перебить вид отображения из манифеста проекта (отладочное)
--seed N сид сборки уровня (по умолчанию 1)
--depth N начать не с первого этажа (для проверок)
--descend N прогон забега на N этажей без окна: спуск, сумки, вес, свет, эвакуация, профиль
--tool <команда> балансовые инструменты без окна: weapons, enemies, ttk, reactions, economy, drops, affix
--profile <файл> где лежит профиль: схрон, снаряжение, чекпоинты
--no-profile не читать и не писать профиль

--rooms на приёмку не влияет: --accept и --headless проект не подключают вообще и меряют на прежней карте (15-engine-and-editor.md).

Примеры:

squad_proto.exe --accept
squad_proto.exe --headless 300
squad_proto.exe --headless 300 --no-solver --no-laneavoid    # каким прототип был бы без ядра
squad_proto.exe --headless 300 --melee 0                     # чистый отряд стрелков
squad_proto.exe --headless 300 --set safetyMargin=0.25 --set laneReserve=2.0
squad_proto.exe --clean --shot 220 melee.png                 # кадр без отладки
squad_proto.exe --sf-tiles                                   # тайлы из build/sprites
squad_proto.exe --sf                                         # тайлы + анимированные твари
squad_proto.exe --rooms --seed 42                            # уровень из projects/descent/rooms
squad_proto.exe --project hollow                             # второй проект: вид сверху
squad_proto.exe --rooms --view topdown                       # свой проект чужим видом

Инструментов две группы, и делятся они по предмету: squad_proto --tool считает БАЛАНС (урон, сопротивления, экономика), tile2d_editor --tool — СОДЕРЖИМОЕ (комнаты, каталог, этажи). Разделение не по вкусу: редактор линкуется только с движком и правил боя не видит вовсе.

squad_proto.exe --tool ttk        # время убийства и разброс по стихиям
squad_proto.exe --tool enemies    # здоровье и сопротивления тварей
squad_proto.exe --tool reactions  # реакции и три ограничителя
squad_proto.exe --tool economy    # доход опыта против цены дерева
squad_proto.exe --tool drops 1 100 # кривая редкости находок по глубине
squad_proto.exe --tool affix 40   # бюджет предмета и потолок аффиксов

Редактор комнат — отдельное приложение с собственными ключами:

tile2d_editor.exe --project descent          # правка комнат игры
tile2d_editor.exe --project hollow           # другой проект
tile2d_editor.exe --check --project descent  # проверить набор без окна, PASS/FAIL
tile2d_editor.exe --check --project hollow   # то же для второго проекта, ЕГО кривой
tile2d_editor.exe --room arena          # открыть конкретную комнату
tile2d_editor.exe --level 42            # сразу показать сборку уровня по сиду

Без --project редактор берёт единственный найденный проект. Проектов в репозитории уже два, поэтому имя обязательно: молча взятый «первый попавшийся» читался бы как «открылось не то». Игре имя можно не давать — она знает своё (descent), и --rooms открывает именно его.

Ассеты для --sf* собираются отдельной командой и в git не попадают. Палитра у библиотеки общая, поэтому манифесты собираются ВМЕСТЕ — иначе цвета тварей легли бы на палитру, посчитанную по одному полу:

sf build assets/manifests/environment.yaml assets/manifests/enemies.yaml \
  --output build/sprites --cache-dir .sfcache --jobs 8 --rebuild-palette
sf codegen --build-dir build/sprites --output generated/spriteforge_assets.h

Осечка на любом шаге оставляет процедурный набор целиком: полусобранный хуже прежнего. Поэтому --sf — это улучшение картинки, а не условие запуска.

Порядок работы с манифестами — 12-assets.md.

Код прогонов — src/debug/harness.cpp, маршрут и сценарии описаны там же. Что означают цифры в выводе — 06-debug-and-tuning.md.