squad-proto/docs/01-build-and-run.md
z.kirill e3294cffd4 Личинки, парирование и инструмент --wall (M30)
--WALL. Новый прогон отвечает на вопрос, появившийся вместе с чекпоинтами
через пятьдесят этажей: растёт ли достижимая глубина от вылазки к вылазке.
Отряд из одного, трёх и пяти, одетый по глубине, ставится в скопление
тварей и живёт полторы минуты без управления. Первая стена: одиночка D7,
трое D30, пятеро D30 - петля работает.

И он же нашёл настоящую ошибку: PlaceSquad воскрешал ВСЕ пять слотов, в
том числе незанятые. Строка писалась, когда отряд всегда был впятером;
после появления ростера одиночка выходил на этаж с четырьмя невидимыми
телохранителями. Из-за них прежний замер "одиночка выжил на первом этаже,
100 -> 41" был боем впятером.

ЛИЧИНКИ. С исправленным замером выяснилось, что одиночка с ножом
проигрывает двум бредущим: 210 здоровья против ножа это девять секунд
работы под ответным уроном. Первые этажи населены личинками (55 здоровья,
7 урона, медленные), бредущий уехал на третий этаж, бегун на четвёртый.
Новый ВИД, а не ослабленный бредущий с множителем: глубина в этой игре
меняет, кто выходит, а не числа у одного и того же.

ПАРИРОВАНИЕ. Отдельная характеристика клинка, и чем оружие легче, тем она
выше: нож 34%, сабля 20%, тесак 8%. Не выведена из веса намеренно - её
двигает аффикс PARRY, и лёгкий тесак обязан быть возможен как находка.

Отбить можно, только если удары СОПРИКОСНУЛИСЬ: боец сам должен быть в
замахе или в ударе. Иначе клинок стал бы щитом, работающим, пока стоишь.

Удавшийся отбив снимает урон, бьёт тварь ударом бойца целиком и запускает
повторную атаку с начала фазы, НЕ сбрасывая откат. Последнее и есть суть
размена: сбрасывай отбив откат, выгоднее было бы подставляться под удары.

Плевок отбивается тоже: летит назад и несёт урон бойца, а не твари. Это
его удар, просто по летящей цели.

Проверка меряет размен целиком, включая обратную половину правила:
"стоя столбом не отбивает". Без неё условие про соприкосновение
существовало бы только в комментарии.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 05:04:35 +03:00

208 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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](12-assets.md)).
## Сборка
```bash
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](15-engine-and-editor.md)) |
| `tile2d_walk.exe` | пример на движке: открыть проект, собрать этаж, походить ([18-engine.md](18-engine.md)) |
Третья цель, `tile2d`, — сам движок ([18-engine.md](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 выбирают разные версии по умолчанию. Лечится сносом
каталога — он целиком производный, в нём нет ничего своего:
```bash
rmdir /s /q build # cmd
rm -rf build # bash
cmake -S . -B build
```
Чтобы зафиксировать версию явно, передай генератор при первой конфигурации:
```bash
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](11-melee.md)).
Диск намеренно быстрее бойцов и держится к ним на поводке: команда читается
мгновенно, а средняя скорость похода всё равно определяется ногами отряда.
## Dev-режимы командной строки
Симуляция детерминирована и не зависит от рендера, поэтому её можно гонять без окна.
| Аргумент | Что делает |
|---|---|
| `--accept` | прогоняет сценарии критериев приёмки (спек 11) и печатает PASS/FAIL |
| `--ui-check` | пункты меню без окна: каждый ведёт куда-то, выходит только QUIT |
| `--wall N` | до какой глубины доходит отряд из 1/3/5 бойцов (нужен `--rooms`) |
| `--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` / `upgrade` / `workshop` |
| `--rooms [проект]` | играть в проект (по умолчанию свой, `descent`) вместо захардкоженной карты |
| `--project <имя>` | то же явно: имя каталога в `projects/` или путь к нему |
| `--view <iso\|topdown>` | перебить вид отображения из манифеста проекта (отладочное) |
| `--seed N` | сид сборки уровня (по умолчанию 1) |
| `--depth N` | начать не с первого этажа (для проверок) |
| `--descend N` | прогон забега на N этажей без окна: спуск, сумки, вес, свет, эвакуация, профиль |
| `--tool <команда>` | балансовые инструменты без окна: `weapons`, `enemies`, `ttk`, `reactions`, `economy`, `drops`, `affix`, `craft` |
| `--profile <файл>` | где лежит профиль: схрон, снаряжение, чекпоинты |
| `--no-profile` | не читать и не писать профиль |
`--rooms` на приёмку не влияет: `--accept` и `--headless` проект не подключают
вообще и меряют на прежней карте ([15-engine-and-editor.md](15-engine-and-editor.md)).
Примеры:
```bash
squad_proto.exe --accept
squad_proto.exe --ui-check
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` — СОДЕРЖИМОЕ
(комнаты, каталог, этажи). Разделение не по вкусу: редактор линкуется только с
движком и правил боя не видит вовсе.
```bash
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 # бюджет предмета и потолок аффиксов
squad_proto.exe --tool craft 80 # материалы: доход за вылазку против цены доводки
```
Редактор комнат — отдельное приложение с собственными ключами:
```bash
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 не попадают. Палитра
у библиотеки общая, поэтому манифесты собираются ВМЕСТЕ — иначе цвета тварей
легли бы на палитру, посчитанную по одному полу:
```bash
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](12-assets.md).
Код прогонов — [src/debug/harness.cpp](../src/debug/harness.cpp), маршрут и сценарии описаны там же.
Что означают цифры в выводе — [06-debug-and-tuning.md](06-debug-and-tuning.md).