squad-proto/docs/20-gdd.md

272 lines
18 KiB
Markdown
Raw Permalink Normal View History

Документация: границы движка, работа через модель, дизайн игры до лейтгейма 18-engine.md границы Tile2D, проекции 2D, формат проекта, второй проект 19-agent.md инструменты --tool, скиллы, терминал в редакторе 20-gdd.md акты, петли, рост отряда, закон масштаба, бюджет 200 часов 21-damage.md семь стихий, статусы, десять реакций, формулы, триггеры 22-loot.md редкости, аффиксы, артефакты, зачарования, материалы 23-endgame.md Бездна, мутации, лидерборды, 262 ачивки Плюс правки 01/02/07/15/16/17 под переехавшие пути и новые правила забега. Дизайнерская часть держится на одном законе: угроза растёт квадратично, сила отряда — линейно с затуханием, разрыв закрывается ЗНАНИЕМ, а не числами. Из него выведены и экономика опыта (41 млн против 44 млн дохода), и то, почему реакции считаются от глубины, а не от урона оружия, и почему в Бездне множитель HP разрешён, а во всём авторском контенте запрещён. .claude/commands: скиллы /tile2d, /room, /floor — правила этого движка, которые нельзя вывести из кода. Главное записано первым: не отчитываться об успехе без прохода --tool validate. Числа в этих документах — вход для инструментов, а не украшение. Расхождение между таблицей и выводом инструмента означает, что неправ документ. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 01:07:45 +07:00
# 20 — Дизайн игры: от одного исследователя до отряда думслееров
Это мастер-документ. Формулы урона и стихий — [21-damage.md](21-damage.md),
предметы и зачарования — [22-loot.md](22-loot.md), бесконечный лейт, лидерборды
и ачивки — [23-endgame.md](23-endgame.md).
Всё, что здесь написано, обязано ужиться с уже построенным: спуск и бюджет
опасности ([16-descent.md](16-descent.md)), экстракшен ([17-extraction.md](17-extraction.md)),
вес, боезапас и расходники, движок Tile2D ([18-engine.md](18-engine.md)).
Где новое ломает старое — сказано прямо.
## 1. Обещание игры
Первый экран: **один** оперативник-исследователь. Тактический нож, слабый
фонарь, костюм радиозащиты. Полупустая лаборатория, две вялых твари, свет
работает. Не страшно — и это НАМЕРЕННО: игроку показывают дно шкалы, чтобы
через сто этажей он мог оглянуться.
Отряд растёт с одного оперативника до пяти (M24) Игра начинается ОДНИМ человеком: тактический нож, слабый фонарь, куртка. Остальные четверо нанимаются за опыт по кривой 600/2400/9600/38400 — самая дорогая покупка в игре и намеренно. Одиночка с ножом это первое впечатление, и продать второго бойца за одну вылазку значило бы выбросить весь хоррор начала: вдвоём уже не страшно. NUM_AGENTS осталась величиной времени сборки и означает теперь ВМЕСТИМОСТЬ, а не размер отряда: делать её динамической это сотня мест ради числа, которое всё равно упирается в пять. Занятость слота это Agent::present, и он отличается от alive. Правила боя читают только alive — для них пустой слот и павший одно, и это верно. Разница нужна там, где показывают человека: у павшего есть тело на полу и перечёркнутая карточка, у пустого слота нет ни того, ни другого. Проверка в --descend меряет цепочку «в профиле -> на этаже» и потолок, а главное — переживает ли одиночка первую схватку: отряд: в профиле 1 -> на этаже 1, после найма 2, цена 600, сверх потолка отказ одиночка с ножом на первом этаже: выжил, 100 -> 41, подошло 2, убил 2 Первая версия этой проверки не измеряла ничего: боец стоял минуту, к нему не подошёл никто, и «выжил» было пустым словом. Теперь отряд ставится рядом с тварью. Попутно найдено и исправлено: Profile::Save три вехи не писала ни версию формата, ни улучшения. Купленный запас патронов действовал до конца запуска и молча пропадал при чтении, а профиль без версии читался как формат 1. Круговой прогон этого не видел, потому что сверял три поля из десяти и делал это на пустом профиле, где всё сходится само. Теперь он сверяет поля списком и на набитом профиле. Формат профиля 3: добавлена строка squad. Старый профиль играл впятером и получает пятерых при миграции — отобрать их значило бы съесть отряд, которого игрок не терял. --accept PASS без изменений: без профиля отряд по-прежнему впятером. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 02:29:19 +07:00
> Сделано в M24. С поправкой на то, что есть: костюма радиозащиты в игре нет —
> сопротивления пока только у тварей, поэтому одиночка выходит в куртке.
> Замерено: он переживает первую схватку и убивает двух тварей, оставаясь с 41
> здоровьем из 100 ([17-extraction.md](17-extraction.md)).
Документация: границы движка, работа через модель, дизайн игры до лейтгейма 18-engine.md границы Tile2D, проекции 2D, формат проекта, второй проект 19-agent.md инструменты --tool, скиллы, терминал в редакторе 20-gdd.md акты, петли, рост отряда, закон масштаба, бюджет 200 часов 21-damage.md семь стихий, статусы, десять реакций, формулы, триггеры 22-loot.md редкости, аффиксы, артефакты, зачарования, материалы 23-endgame.md Бездна, мутации, лидерборды, 262 ачивки Плюс правки 01/02/07/15/16/17 под переехавшие пути и новые правила забега. Дизайнерская часть держится на одном законе: угроза растёт квадратично, сила отряда — линейно с затуханием, разрыв закрывается ЗНАНИЕМ, а не числами. Из него выведены и экономика опыта (41 млн против 44 млн дохода), и то, почему реакции считаются от глубины, а не от урона оружия, и почему в Бездне множитель HP разрешён, а во всём авторском контенте запрещён. .claude/commands: скиллы /tile2d, /room, /floor — правила этого движка, которые нельзя вывести из кода. Главное записано первым: не отчитываться об успехе без прохода --tool validate. Числа в этих документах — вход для инструментов, а не украшение. Расхождение между таблицей и выводом инструмента означает, что неправ документ. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-14 01:07:45 +07:00
Последний экран, которого нет: пятеро в силовой броне идут сквозь Бездну,
поджигают, замораживают и расщепляют всё в радиусе, и всё равно однажды не
возвращаются.
Между этими двумя точками — 200 часов, и ни одной минуты, где сила решала бы
всё сама.
## 2. Закон масштаба — главное правило всей математики
> **Угроза растёт квадратично. Сила отряда — линейно с затуханием.
> Разрыв закрывается ЗНАНИЕМ, а не числами.**
Угроза этажа — это бюджет опасности, он уже квадратичный:
`T(d) = 3 + 2.2·(d1) + 0.10·(d1)²`.
Сила отряда `P` растёт от улучшений, снаряжения и артефактов, но каждый источник
имеет затухание (§6). Поэтому `T(d) / P` неизбежно растёт, и на каждой глубине
есть **стена** — этаж, где отряд перестаёт справляться.
Сдвинуть стену можно тремя способами, и только третий не имеет потолка:
| Способ | Даёт | Потолок |
|---|---|---|
| улучшения и снаряжение | +58 этажей за полный тир | есть, жёсткий |
| артефакты и зачарования | +36 этажей за сборку | есть, мягкий |
| **знание** — стихии, реакции, порядок целей, маршрут | ×1.53 к эффективной силе | **нет** |
Отсюда следуют все дальнейшие решения. Если бы числа закрывали разрыв, игра
перестала бы быть хоррором на сороковом этаже: страшно не там, где мало урона,
а там, где ты не понимаешь, что тебя убивает.
**Что ломается, если нарушить.** Дайте силе расти быстрее квадрата — и лейтгейм
превратится в покос травы, а лидерборд — в тест на терпение. Дайте угрозе расти
быстрее силы без канала знания — и стена станет непроходимой стеной, а не
задачей.
## 3. Акты и глубины
Шесть актов авторского содержимого, дальше — бесконечность.
| Акт | Глубины | Тема | Что вводится | Отряд |
|---|---|---|---|---|
| I. Лаборатория | 18 | STEEL | базовый бой, вес, патроны | 1 |
| II. Технические уровни | 920 | RUST | стихии INC/CRY, первые аффиксы, 2-й оперативник | 2 |
| III. Био-крыло | 2135 | FLESH | TOX, on-death эффекты, зачарования | 3 |
| IV. Криокамеры | 3652 | FROST | ARC, реакции, специализации | 4 |
| V. Реактор | 5372 | EMBER | RAD, аномалии, артефакты | 5 |
| VI. Провал | 73100 | VOID | VOID, залом, сборки-ключи | 5 |
| VII. Бездна | 101+ | ABYSS | мутации, сезоны, лидерборды | 5 |
Тем становится семь (сейчас четыре: `THEME_COUNT = 4` в `engine/theme.h`).
Полосы задаются проектом (`themes` в `project.txt`), поэтому это правка данных,
а не движка.
Каждый акт — это **новая причина умирать**, а не новый цвет стен. Акт без
собственной механики смерти вырезается.
## 4. Игровой цикл
Три петли, вложенные друг в друга. Каждая обязана давать ответ на вопрос
«зачем ещё раз».
### Петля этажа (38 минут)
Спуститься → разведать → решить, где драка неизбежна → собрать находки →
уйти на спуск или наверх. Решение одно и постоянное: **ещё этаж или назад**.
Его задают ресурсы (патроны, бинты, вес) и здоровье, а не таймер.
### Петля вылазки (2545 минут)
Чекпоинт → 512 этажей → эвакуация или вайп. Ставка: снаряжение на выживших.
Награда: добыча, опыт, материалы, продвижение рекорда.
### Петля мета (десятки часов)
Опыт → узлы улучшений. Материалы → крафт и зачарования. Артефакты → сборки.
Рекорд глубины → новые чекпоинты → доступ к более глубоким находкам.
```
┌──────────── этаж ────────────┐
спуск│ разведка → бой → находки │уход
└───────────┬──────────────────┘
↓ эвакуация
┌──────── вылазка ─────────────┐
│ опыт · материалы · артефакты │
└───────────┬──────────────────┘
↓ база
┌────────── мета ──────────────┐
│ узлы · крафт · сборка отряда │
└───────────┬──────────────────┘
↓ глубже
```
## 5. Двести часов: откуда цифра
Не «на глазок», а из бюджета времени.
| Величина | Значение |
|---|---|
| среднее время этажа | 4.5 мин (акт I — 2.5, акт VI — 7) |
| этажей за вылазку | 5 → 12 (растёт с глубиной чекпоинтов) |
| время вылазки с подготовкой | 28 → 48 мин |
| вылазок на продвижение одного чекпоинта (5 этажей) | 1 → 12 |
Вылазок на акт: I — 6, II — 22, III — 38, IV — 56, V — 74, VI — 96.
**Итого ≈ 292 вылазки × 40 мин ≈ 195 часов.**
Кривая «вылазок на чекпоинт» растёт линейно: `R(c) = 1 + 0.55·c`, где `c`
номер чекпоинта. Линейно, а не экспоненциально: экспонента даёт стену, за
которой игрок уходит, а не гриндит.
**Правило против гринда:** каждая вылазка обязана давать прогресс, даже
провальная. Вайп сохраняет рекорд глубины и половину материалов, найденных на
этажах глубже предыдущего рекорда (см. §7). Ноль прогресса за 40 минут — это
причина закрыть игру, а не мотивация.
## 6. Рост отряда
### 6.1. Оперативники
Начинаем с одного. Каждый следующий — событие, а не покупка.
| № | Класс | Где | Условие |
|---|---|---|---|
| 1 | **Исследователь** | старт | — |
| 2 | **Штурмовик** | D912 | капсула стазиса + 2 500 опыта |
| 3 | **Техник** | D2126 | капсула + 18 000 опыта + 3 био-ядра |
| 4 | **Егерь** | D3642 | капсула + 90 000 опыта + 5 крио-ядер |
| 5 | **Инквизитор** | D5360 | капсула + 400 000 опыта + артефакт |
Капсула — редкая находка в своей полосе глубин (шанс на этаж 6%, пити на 20-м
этаже полосы). Найти её можно только В ЭТОЙ полосе: пропустить акт и прийти за
пятым оперативником на десятом этаже нельзя.
Классы различаются НЕ статами, а поведением в бою — игра без ручных действий
(спек 5), и класс это то, как оперативник ведёт себя сам:
| Класс | Поведение | Слабость |
|---|---|---|
| Исследователь | держит дистанцию, первым замечает аномалии, +обзор | ломается в ближнем бою |
| Штурмовик | идёт первым, держит удар, ломает строй тварей | жрёт патроны и бинты |
| Техник | ставит турель/мину на стоянках, чинит броню между этажами | почти не бьёт сам |
| Егерь | бьёт по одиночным целям с дистанции, добивает раненых | бесполезен в толпе |
| Инквизитор | накладывает стихии по площади, запускает реакции | хрупкий, ест материалы |
Пятеро — потолок жёсткий: `NUM_AGENTS = 5` уже в коде, и это же потолок
читаемости строя. Шестой в клине не виден.
### 6.2. Дерево улучшений
Пять ветвей, в каждой 8 узлов, у каждого 5 уровней = **200 уровней узлов**.
| Ветвь | О чём | Пример узлов |
|---|---|---|
| Снабжение | патроны, вес, расходники | запас, переноска, ёмкость сумки, авто-бинт |
| Живучесть | HP, броня, сопротивления | живучесть, латание, сопротивление RAD |
| Огневая мощь | урон, крит, скорострельность | пробитие, крит, перезарядка |
| Стихии | элементы и реакции | сила стихии, длительность, сила реакций |
| Разведка | обзор, находки, аномалии | обзор, шанс редкого, чтение аномалий |
Существующие четыре улучшения (`Upgrade::AMMO/CARRY/SIGHT/VIGOR` в
`sim/profile.h`) становятся первым кольцом ветвей Снабжения и Живучести.
**Затухание — обязательное.** Уровень `L` узла даёт долю от максимума узла:
```
gain(L) = maxGain · (1 1 / (1 + 0.55·L))
```
L=1 → 35% максимума, L=2 → 52%, L=3 → 62%, L=4 → 69%, L=5 → 73%.
Пятый уровень стоит вчетверо дороже первого и даёт вчетверо меньше — и это
честно написано в подсказке узла.
**Цена уровня:** `cost(node, L) = base(node) · 2.15^L`, где `base` — от 150
(первое кольцо) до 12 000 (внешнее). Полное дерево ≈ **41 миллион опыта**.
### 6.3. Сходится ли экономика опыта
Опыт за этаж: `XP(d) = T(d) · 10 · (1 + 0.15·(d1))` — это уже работающая
формула (`xpPerDanger`, `xpScale`).
| Глубина | XP за этаж |
|---|---|
| 5 | 205 |
| 20 | 3 460 |
| 50 | 29 300 |
| 80 | 116 000 |
| 100 | 190 000 |
За 292 вылазки по 8 этажей средней глубины акта набегает ≈ **44 миллиона**.
Дерево стоит 41 — сходится с запасом 7% на переигрывание. Это не совпадение:
`base` узлов подобраны от этой суммы обратным счётом.
**Опыт зачисляется только за эвакуацию** — правило уже в коде (`FinishRun`).
Вайп теряет весь опыт вылазки, и это главный источник напряжения на выходе.
## 7. Что теряется и что остаётся
Дополняет правила экстракшена ([17-extraction.md](17-extraction.md)).
| | Эвакуация | Вайп |
|---|---|---|
| надетое на выживших | остаётся | — |
| надетое на павших | теряется | теряется |
| общая сумка | в схрон целиком | теряется |
| опыт вылазки | зачисляется | теряется |
| материалы | все | **половина того, что найдено глубже рекорда** |
| рекорд глубины | растёт | **растёт** |
| узлы, артефакты в схроне | остаются | остаются |
Половина материалов при вайпе — единственная поблажка во всей системе, и она
куплена конкретной ценой: без неё «пошёл проверить, что там на пять этажей
глубже» стоит сорок минут и не даёт ничего. Прогресс обязан идти даже из
провала, иначе разведка глубины перестаёт быть занятием.
## 8. Что должно измениться в коде
Не «когда-нибудь», а список того, что эта математика требует прямо сейчас.
| Что | Где | Объём |
|---|---|---|
| отряд переменного размера 1→5 | `sim/squad.*`, HUD, строй | средний |
| стихии и сопротивления | `sim/loadout.h`, `sim/target.*`, каталог | крупный |
| шина триггеров on-hit/on-kill | поверх `sim/events.h` — журнал УЖЕ есть | средний |
| аффиксы предметов | `sim/items.h` → предмет с рулонами | крупный |
| материалы и крафт | `sim/profile.h`, новый экран | средний |
| дерево узлов | `sim/profile.h` + экран | средний |
| темы FLESH.. VOID | данные проекта | мелкий |
| мутации тварей | `engine/catalog.*` + `sim/enemy.*` | средний |
**Порядок работ.** Стихии → триггеры → аффиксы → материалы → дерево → классы →
мутации. Каждый шаг — отдельная веха со своими проверками, как всё в этом
репозитории. Стихии первыми, потому что от них зависят и аффиксы, и мутации, и
половина ачивок.
## 9. Как это проверяется
Дизайн, который нельзя измерить, — это пожелание. Для каждого утверждения выше
есть или должен появиться инструмент ([19-agent.md](19-agent.md)):
| Утверждение | Чем меряется |
|---|---|
| угроза растёт квадратично | `--tool curve 1 120` |
| стена сдвигается на 58 этажей за тир | `--tool wall <сборка>` (новый) |
| TTK держится в коридоре | `--tool ttk <глубина>` (новый) |
| экономика опыта сходится | `--tool economy` (новый): доход против цены дерева |
| 200 часов | `--tool time` (новый): бюджет по актам из таблицы §5 |
| набор комнат тянет глубину | `--tool validate` (есть) |
Числа в этих документах — **вход** для инструментов, а не украшение. Расхождение
между таблицей и выводом инструмента означает, что неправ документ.