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>
261 lines
18 KiB
Markdown
261 lines
18 KiB
Markdown
# 17 — Экстракшен: спуск как ставка
|
||
|
||
## Что изменилось в игре
|
||
|
||
До этой вехи глубина была прогрессом: чем дальше, тем лучше. Теперь она
|
||
**ставка**. Отряд уходит вниз с тем, что нажил, и каждый этаж — заново заданный
|
||
вопрос: ещё ниже или назад, пока есть что выносить.
|
||
|
||
Три правила, из которых следует всё остальное:
|
||
|
||
1. **Унести можно только то, что на выживших.** Павший забирает своё с собой.
|
||
2. **Полный вайп не возвращает ничего.** Снаряжение сбрасывается к стартовому.
|
||
3. **Достигнутая глубина остаётся навсегда.** Она открывает чекпоинты — и это
|
||
единственное, чего смерть не отнимает.
|
||
|
||
Третье правило — ответ на «а если этажей десять тысяч». Проходить их заново
|
||
каждую вылазку не нужно; терять при этом можно только снаряжение.
|
||
|
||
## Два выхода с этажа
|
||
|
||
| | Где | Клавиша | Что делает |
|
||
|---|---|---|---|
|
||
| **спуск** | самая дальняя достижимая точка | `F` | следующий этаж, отряд как есть |
|
||
| **эвакуация** | там, где отряд вошёл на этаж | `E` | забег окончен, добыча в схроне |
|
||
|
||
Эвакуация совпадает с точкой входа не из экономии: это лестница наверх, и в этом
|
||
вся суть напряжения. Спуск лежит на дальнем конце этажа — решив уйти, отряд идёт
|
||
обратно через всё, что успел растревожить, раненый и с полными руками.
|
||
|
||
Кольца на полу разного цвета: зелёное — вниз, голубое — наверх. Оба видны даже
|
||
в полной темноте. Спутать их означает уйти не туда, и цена ошибки здесь — весь
|
||
забег, поэтому подсказки в HUD подкрашены теми же цветами.
|
||
|
||
Ни то ни другое не срабатывает от захода на клетку. Спуск и эвакуация — решения
|
||
игрока: этаж не зачищен, лут не собран, уходить рано — это нормальный выбор, и
|
||
отряд может стоять на выходе сколько угодно.
|
||
|
||
## Профиль
|
||
|
||
[src/sim/profile.h](../src/sim/profile.h) — всё, что переживает забег:
|
||
|
||
```
|
||
maxdepth 13
|
||
runs 6
|
||
extractions 3
|
||
agent 0 cleaver plate charm bandage stimpack - - - -
|
||
stash saber plate vest smg bow charm lantern spurs
|
||
```
|
||
|
||
- **снаряжение пяти бойцов** лежит здесь, а не собирается заново при старте.
|
||
То, в чём отряд ушёл вниз, — это то, в чём он вернулся с прошлой вылазки;
|
||
- **схрон** — общий запас сверх надетого, потолок `STASH_CAP`. Без потолка
|
||
экстракшен превращается в склад, и решение «что взять вниз» исчезает;
|
||
- **максимальная глубина** открывает чекпоинты.
|
||
|
||
Профиль — состояние ИГРОКА, а не мира: он не в `ecs::World` и не сбрасывается ни
|
||
`Reset`, ни `Descend`. Записывается он только в конце забега — авария посреди
|
||
вылазки означает потерю, и это часть контракта, а не недоделка.
|
||
|
||
Формат текстовый по той же причине, что у комнат: файл лежит рядом с игрой, его
|
||
правят руками при отладке, и он обязан читаться глазами.
|
||
|
||
## Чекпоинты
|
||
|
||
Каждые `CHECKPOINT_STEP` (5) этажей. Достигнутая глубина открывает все чекпоинты
|
||
не глубже неё: дошёл до 13-го — доступны D1, D6, D11.
|
||
|
||

|
||
|
||
Рекорд глубины засчитывается **любым исходом**. Дошёл — значит дошёл; требовать
|
||
за чекпоинт ещё и удачную эвакуацию значило бы наказывать дважды за одну смерть.
|
||
|
||
Пять — это «достаточно редко, чтобы дойти до следующего было событием, и
|
||
достаточно часто, чтобы потеря забега не откатывала в самое начало».
|
||
|
||
## Сумка одна на отряд
|
||
|
||
Раньше каждый боец таскал свои шесть ячеек, и это порождало проблему, которую
|
||
нечем было решить: пачка патронов, поднятая бойцом с клинком, доставалась только
|
||
ему и лежала мёртвым грузом до конца забега. Перекладывать между бойцами игра не
|
||
умела.
|
||
|
||
Теперь сумка одна — шестнадцать ячеек на пятерых. Личным остаётся **надетое**:
|
||
руки, броня, карман. Их не разделить, они и есть «кто этот боец».
|
||
|
||
**Вес делится на живых.** Потерять бойца — значит взвалить его долю на
|
||
остальных: обратно наверх отряд пойдёт медленнее, чем шёл сюда. Это не побочный
|
||
эффект, а то, ради чего сумка общая.
|
||
|
||
Правило «унести можно только то, что на выживших» этим не ослаблено, оно стало
|
||
точнее: надетое павшего теряется по-прежнему, а общая ноша на нём не висела —
|
||
её тащил отряд. Вайп по-прежнему не выносит ничего: тогда выживших нет вовсе, и
|
||
сумку некому донести.
|
||
|
||
## Схрон и сборы
|
||
|
||

|
||
|
||
Экран отряда (`I`) стал местом сборов: снаряжение бойца слева, общая сумка
|
||
справа, схрон двумя рядами внизу. Предметы перетаскиваются мышью, `Q`/`E`
|
||
листают схрон, правая кнопка по вещи выбрасывает её под ноги.
|
||
|
||
**Наведи — и увидишь, что это.** Подсказка под курсором показывает вес и все
|
||
эффекты предмета, а на строках характеристик объясняет, откуда берётся число.
|
||
До неё вещь была именем и цветным квадратиком: чем VEST отличается от JACKET,
|
||
знал только каталог в коде. С сумкой на шестнадцать мелких ячеек это перестало
|
||
быть терпимым — в ячейку не влезает даже имя.
|
||
|
||
Схрон полон — обмен не состоится целиком, и вещь останется в слоте. Молча терять
|
||
её нельзя: «некуда положить» обязано быть видно.
|
||
|
||
## Вес: что унести
|
||
|
||
Шесть ячеек в сумке отвечали на вопрос «сколько вещей», но не на вопрос «чего
|
||
они стоят»: шесть бинтов и шесть плит обходились одинаково. Теперь у каждой
|
||
вещи есть вес, а у бойца — два порога.
|
||
|
||
| | |
|
||
|---|---|
|
||
| до `CARRY_LIMIT` (7.5) | отряд идёт как шёл |
|
||
| дальше | тем медленнее, чем больше нагрёб, до 55% на пределе |
|
||
| выше `CARRY_MAX` (14) | не поднимет: вещь остаётся лежать |
|
||
|
||
Порогов ДВА намеренно. Один жёсткий предел означал бы «сумка кончилась» — то
|
||
же самое, что счёт ячеек, только считать труднее. Настоящий выбор возникает
|
||
там, где лишнее взять МОЖНО, но за это платят: а идти с этим — обратно через
|
||
весь этаж, который уже растревожен.
|
||
|
||
**Надетое не считается.** За броню уже заплачено множителем скорости (плита —
|
||
0.82), и считать её вес вторично значило бы наказывать за один выбор дважды.
|
||
Хуже того: плита съедала бы почти весь запас, и боец в тяжёлой броне не мог бы
|
||
поднять вообще ничего — вместо решения вышел бы запрет. А вот плита, НАЙДЕННАЯ
|
||
и лежащая в сумке, весит полной мерой: тащить её наверх — это и есть выбор.
|
||
|
||
Выбросить лишнее можно правой кнопкой по ячейке на экране отряда: вещь ложится
|
||
под ноги и подбирается обратно. Из рук бросать нельзя — безоружный боец не
|
||
бежит быстрее, он просто перестаёт быть бойцом.
|
||
|
||
## То, что кончается
|
||
|
||
Наверх гонит не таймер. Часы заставляли бы торопиться механически, а это
|
||
хоррор: давить должно **исчерпание**, а задача — уйти как можно глубже.
|
||
|
||
**Патроны конечны.** Запас (`startAmmo`, 120 на бойца) выдаётся на вылазку и
|
||
едет вниз вместе с отрядом. Перезарядка тянет из него; кончился — стрелок
|
||
молчит, и перезарядка даже не начинается: боец с пустым стволом не изображает
|
||
работу. Восполнить можно только находкой — пачкой на 40 патронов.
|
||
|
||
**Расходники применяются сами.** Ручных действий в игре нет (спек 5), поэтому
|
||
бинт и пачка — не кнопка, а поведение: боец перевязывается, когда ранен ниже
|
||
`healAtFrac` и рядом никого нет, и набивает подсумок, когда стрелять нечем.
|
||
Лечиться в схватке нельзя — перевязка посреди боя обесценила бы урон, который
|
||
тварь только что нанесла.
|
||
|
||
До этой вехи `heal` у бинта был мёртвым числом: расходники не применялись
|
||
нигде, и бинт был просто грузом. С весом (выше) он стал грузом буквально.
|
||
|
||
Патроны нужны тому, у кого **вообще** есть ствол, а не только тому, кто держит
|
||
его сейчас: иначе боец с клинком в руках и запасным карабином в сумке таскал бы
|
||
найденную пачку до конца забега. Это нашла проверка, а не глаз.
|
||
|
||
## Во что вкладывается опыт
|
||
|
||

|
||
|
||
Опыт копился с вехи M12 и до сих пор был честной заглушкой: число, которое
|
||
ни на что не влияет. Теперь он тратится — на четыре улучшения отряда.
|
||
|
||
| | что даёт | почему это |
|
||
|---|---|---|
|
||
| AMMO RESERVE | +20 патронов на вылазку | |
|
||
| CARRY LIMIT | +1.5 до перегруза | |
|
||
| SIGHT RANGE | +6% обзора | |
|
||
| VIGOR | +12 здоровья | |
|
||
|
||
Все четыре — **ресурсные**, и ни одного силового. Игра про исчерпание, и
|
||
вкладываться в ней надо в то, что кончается: отряд, который бьёт вдвое сильнее,
|
||
перестаёт бояться, а страх тут единственная механика, которую нельзя
|
||
восстановить балансом.
|
||
|
||
Улучшения ОТРЯДНЫЕ, а не на бойца. Не из экономии: личным в этой игре остаётся
|
||
снаряжение, и второе личное измерение превратило бы сборы в бухгалтерию на
|
||
пятерых.
|
||
|
||
Опыт зачисляется только за **успешную эвакуацию** (`FinishRun`): вайп не
|
||
приносит ничего. Это та же ставка, что и с добычей.
|
||
|
||
Приёмки это не касается вообще: улучшения живут в профиле, а `--accept` его не
|
||
подключает — там нет ни снаряжения, ни улучшений, и критерии меряются на том
|
||
же, на чём мерялись всегда.
|
||
|
||
## Итог забега
|
||
|
||

|
||
|
||
Две цифры, ради которых экран и существует: **сколько вынес** и **сколько
|
||
осталось внизу**. Плюс глубина, выжившие и открытый чекпоинт.
|
||
|
||
Забег закрывается ДО показа экрана — в момент вайпа или нажатия `E`. Симуляция
|
||
при этом ничего не решает: она только отмечает `atExit`/`atExtract`, а конец
|
||
забега объявляет UI. Смена мира посреди шага, между движением и стрельбой,
|
||
оставила бы половину систем со ссылками на снесённые сущности.
|
||
|
||
## Как играть
|
||
|
||
```bash
|
||
squad_proto.exe --rooms
|
||
```
|
||
|
||
`NEW RAID` → выбрать чекпоинт → вылазка. `I` перед выходом — разобрать схрон.
|
||
|
||
| Ключ | Что делает |
|
||
|---|---|
|
||
| `--profile <файл>` | другой профиль (полезно для проверок) |
|
||
| `--no-profile` | не читать и не писать профиль вообще |
|
||
|
||
Без `--rooms` игра работает как раньше: одна карта, никакого забега. Приёмка и
|
||
`--headless` профиль не подключают — критерии меряются на прежнем снаряжении.
|
||
|
||
## Проверки
|
||
|
||
```bash
|
||
squad_proto.exe --descend 7 --no-profile
|
||
```
|
||
|
||
Прогон проверяет всю цепочку: спуск по этажам, перенос сумок, эвакуацию,
|
||
**круговой прогон профиля через запись** — и правило переноски.
|
||
|
||
Переноска проверяется на ВЫДУМАННОМ инвентаре, а не по грузу в прогоне: в сумки
|
||
кладутся бинты, чтобы проверить перенос между этажами, и по ним вес выглядит
|
||
втрое меньше настоящего. Первые две попытки выставить пороги делались как раз
|
||
по этой цифре — и обе дали числа, которые не ограничивали ничего.
|
||
|
||
```
|
||
расходники: патроны набиты, лечение сработало (33 -> 58), из сумки ушли обе
|
||
перезарядка: запас 40 -> 16 (магазин 24)
|
||
переноска: налегке 6.9 (скорость 100%), с грузом 12.9 (скорость 63%), плит влезло 1
|
||
```
|
||
|
||
Расход патронов проверяется тут же и отдельно: спуск ни с кем не воюет, столбец
|
||
«патронов» в таблице стоит на месте — и без прямой проверки бесконечный
|
||
боезапас выглядел бы ровно так же.
|
||
|
||
```
|
||
7 RUST 13 19 3 149 живых 5, в сумках 30
|
||
эвакуация: вынесено 40, потеряно 0, выживших 5, чекпоинт D6
|
||
профиль: запись и чтение сходятся
|
||
```
|
||
|
||
Круговой прогон здесь не для полноты: запись профиля — единственный путь,
|
||
которым игра может стереть всё нажитое, и ошибка в нём выглядит как «схрон
|
||
куда-то делся», а не как падение.
|
||
|
||
## Чего ещё нет
|
||
|
||
- **Схватки за добычу.** В настоящем экстракшене выход можно не отдать —
|
||
здесь на этаже нет никого, кто охотится именно за вынесенным.
|
||
- **Страховки и торговли.** Схрон только копится; девать его некуда.
|
||
- **Траты опыта** — она по-прежнему ждёт своей вехи
|
||
([16-descent.md](16-descent.md)).
|