Документация: границы движка, работа через модель, дизайн игры до лейтгейма
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
|
|
|
|
# 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` у бинта был мёртвым числом: расходники не применялись
|
|
|
|
|
|
нигде, и бинт был просто грузом. С весом (выше) он стал грузом буквально.
|
|
|
|
|
|
|
|
|
|
|
|
Патроны нужны тому, у кого **вообще** есть ствол, а не только тому, кто держит
|
|
|
|
|
|
его сейчас: иначе боец с клинком в руках и запасным карабином в сумке таскал бы
|
|
|
|
|
|
найденную пачку до конца забега. Это нашла проверка, а не глаз.
|
|
|
|
|
|
|
Свет как расходник: заряд тратится за путь, а не за время (M23)
Второй ресурс вылазки после патронов. Фонарь садится, погас — обзор падает
до 35%, а твари замечают отряд в 1.35 раза дальше: отряд не слепнет, он
меняется с тварями местами. Батарея встаёт сама, как бинт.
Главное решение — расход за ПРОЙДЕННЫЙ ПУТЬ, а не за время. Первая версия
считала по секундам, то есть была таймером, которого в игре нет по прямому
требованию к жанру: садящийся сам собой фонарь торопил бы игрока ровно как
секундомер, только без циферблата, и думать над этажом стало бы дорого.
За расстояние получается тот же размен, что и с весом, но с другой стороны:
вес делает дорогим «унести всё», свет — «обшарить всё».
Заряд общий на отряд и едет вниз вместе с ним: обновляйся он на этаже, это
был бы ресурс этажа, а не вылазки, и никуда бы не гнал. Чем глубже, тем
дороже шаг, а этажи внизу длиннее — глубина жмёт на свет дважды.
Проверка в --descend меряет правило целиком, и первая её строка не про
баланс, а про жанр: заряд на стоянке обязан стоять. Сам измеритель тоже
был неправ — делил потраченное на смещение отряда, а не на пройденный
путь, и показывал 1.55 за тайл при 1.10 в каталоге.
свет: стоянка 0.2, ход 1.10 за тайл при 1.10 в каталоге
глубина 8: заряда на 383 тайла, это 4.0 прямых пути до спуска
обзор 1.00 -> 0.35 в темноте, батарея встала сама
Хватает ли заряда на этаж считается в этажах и по средней длине забега:
путь до спуска скачет вдвое от сида, и порог по одному этажу ловил бы
удачу, а не баланс.
--accept PASS без изменений: в песочнице света бесконечно, как и патронов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 02:12:05 +07:00
|
|
|
|
### Свет: второй ресурс, и тратится он за ПУТЬ
|
|
|
|
|
|
|
|
|
|
|
|
Фонарь садится. Полного заряда (`LIGHT_FULL`, 420) хватает примерно на
|
|
|
|
|
|
**четыре прямых пути до спуска** — то есть на этаж с осмотром, но не на два
|
|
|
|
|
|
этажа подряд. Кончился — обзор падает до `DARK_SIGHT_MUL` (35%), а твари
|
|
|
|
|
|
начинают замечать отряд в `DARK_AGGRO_MUL` раз дальше. Отряд не слепнет: он
|
|
|
|
|
|
меняется с тварями местами, и первым теперь видит не он.
|
|
|
|
|
|
|
|
|
|
|
|
**Главное решение — заряд тратится за пройденное расстояние, а не за время.**
|
Редкости и аффиксы: находка стала решением (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 06:35:00 +07:00
|
|
|
|
Точнее: за расстояние, пройденное **под управлением игрока** (состояние
|
|
|
|
|
|
`ADVANCING`). Топтание в строю не считается — замер показал, что центр отряда за
|
|
|
|
|
|
две секунды «стоянки» проходит около 0.8 тайла, и списывай игра это, заряд таял
|
|
|
|
|
|
бы, пока игрок думает над картой. То есть вернулся бы тот самый таймер. Драка
|
|
|
|
|
|
тоже бесплатна: свет тратит РАЗВЕДКА, а не бой.
|
Свет как расходник: заряд тратится за путь, а не за время (M23)
Второй ресурс вылазки после патронов. Фонарь садится, погас — обзор падает
до 35%, а твари замечают отряд в 1.35 раза дальше: отряд не слепнет, он
меняется с тварями местами. Батарея встаёт сама, как бинт.
Главное решение — расход за ПРОЙДЕННЫЙ ПУТЬ, а не за время. Первая версия
считала по секундам, то есть была таймером, которого в игре нет по прямому
требованию к жанру: садящийся сам собой фонарь торопил бы игрока ровно как
секундомер, только без циферблата, и думать над этажом стало бы дорого.
За расстояние получается тот же размен, что и с весом, но с другой стороны:
вес делает дорогим «унести всё», свет — «обшарить всё».
Заряд общий на отряд и едет вниз вместе с ним: обновляйся он на этаже, это
был бы ресурс этажа, а не вылазки, и никуда бы не гнал. Чем глубже, тем
дороже шаг, а этажи внизу длиннее — глубина жмёт на свет дважды.
Проверка в --descend меряет правило целиком, и первая её строка не про
баланс, а про жанр: заряд на стоянке обязан стоять. Сам измеритель тоже
был неправ — делил потраченное на смещение отряда, а не на пройденный
путь, и показывал 1.55 за тайл при 1.10 в каталоге.
свет: стоянка 0.2, ход 1.10 за тайл при 1.10 в каталоге
глубина 8: заряда на 383 тайла, это 4.0 прямых пути до спуска
обзор 1.00 -> 0.35 в темноте, батарея встала сама
Хватает ли заряда на этаж считается в этажах и по средней длине забега:
путь до спуска скачет вдвое от сида, и порог по одному этажу ловил бы
удачу, а не баланс.
--accept PASS без изменений: в песочнице света бесконечно, как и патронов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 02:12:05 +07:00
|
|
|
|
|
|
|
|
|
|
Расход по секундам был бы таймером, только без циферблата: садящийся сам собой
|
|
|
|
|
|
фонарь торопил бы игрока ровно так же, а думать над этажом стало бы дорого.
|
|
|
|
|
|
Здесь думать бесплатно. Стоять и разглядывать — бесплатно. Платить приходится
|
|
|
|
|
|
за то, что **обошёл этаж целиком**, а не за то, что задержался.
|
|
|
|
|
|
|
|
|
|
|
|
Получается тот же размен, что и с весом, только с другой стороны:
|
|
|
|
|
|
|
|
|
|
|
|
| ресурс | что он делает дорогим |
|
|
|
|
|
|
|---|---|
|
|
|
|
|
|
| вес | унести всё |
|
|
|
|
|
|
| свет | обшарить всё |
|
|
|
|
|
|
|
|
|
|
|
|
Прямая дорога к спуску дёшева обоими. Полная зачистка — дорога обоими сразу.
|
|
|
|
|
|
|
|
|
|
|
|
Чем глубже, тем дороже шаг (`LightDrain`): на сотом этаже заряда хватает вдвое
|
|
|
|
|
|
меньше, чем на первом, а сами этажи там длиннее. Заряд едет вниз вместе с
|
|
|
|
|
|
отрядом и **не обновляется на новом этаже** — иначе он был бы ресурсом этажа, а
|
|
|
|
|
|
не вылазки, и никуда бы не гнал.
|
|
|
|
|
|
|
|
|
|
|
|
Батарея (0.3 веса) — расходник по тем же правилам, что бинт и пачка: встаёт в
|
|
|
|
|
|
фонарь сама, в тот же шаг, когда свет погас. Держать её в сумке при погасшем
|
|
|
|
|
|
фонаре отряду незачем, а темнота ради темноты — не решение игрока.
|
|
|
|
|
|
|
|
|
|
|
|
Погасший фонарь не даёт **ничего**: его 35% обзора снимаются вместе с зарядом.
|
|
|
|
|
|
Иначе «сел» означало бы «стал слабее», а не «кончился».
|
|
|
|
|
|
|
Отряд растёт с одного оперативника до пяти (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
|
|
|
|
## Отряд из одного
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
Игра начинается **одним оперативником-исследователем**: тактический нож, слабый
|
|
|
|
|
|
фонарь, куртка. Не отрядом — человеком. Остальные четверо нанимаются за опыт,
|
|
|
|
|
|
и это самая дорогая покупка в игре: 600 / 2400 / 9600 / 38400, всего 51000
|
|
|
|
|
|
против дохода в 726 за этаж на десятом (`--tool economy`).
|
|
|
|
|
|
|
|
|
|
|
|
Дорого намеренно. Одиночка с ножом — это первое впечатление от игры, и продать
|
|
|
|
|
|
второго бойца за одну вылазку значило бы выбросить весь хоррор начала: вдвоём
|
|
|
|
|
|
уже не страшно. По кривой второй приходит через две-три ранние вылазки, третий
|
|
|
|
|
|
— когда отряд уверенно берёт десятый этаж, пятый — ближе к двадцать пятому.
|
|
|
|
|
|
|
|
|
|
|
|
Замерено в `--descend`: одинокий оперативник с ножом на первом этаже **выживает
|
|
|
|
|
|
и убивает двух тварей, теряя 59 из 100 здоровья**. Это ровно та цена, ради
|
|
|
|
|
|
которой всё и затевалось: он справляется, но после второй схватки решение
|
|
|
|
|
|
«ещё этаж или наверх» принимается всерьёз.
|
|
|
|
|
|
|
|
|
|
|
|
Внутри кода размер отряда — это ДВА разных понятия, и путать их нельзя:
|
|
|
|
|
|
|
|
|
|
|
|
| | что значит | кто читает |
|
|
|
|
|
|
|---|---|---|
|
|
|
|
|
|
| `NUM_AGENTS` | сколько слотов БЫВАЕТ (5, время сборки) | все циклы, массивы, метрики |
|
|
|
|
|
|
| `Squad::roster` | сколько слотов ЗАНЯТО сейчас | сборка этажа |
|
|
|
|
|
|
| `Agent::present` | этот слот занят человеком | рендер, HUD, экраны, профиль |
|
|
|
|
|
|
| `Agent::alive` | этот человек ещё жив | правила боя, движение, твари |
|
|
|
|
|
|
|
|
|
|
|
|
Правила боя читают только `alive`: для них пустой слот и павший неразличимы, и
|
|
|
|
|
|
это верно. Разница нужна там, где показывают ЧЕЛОВЕКА — у павшего есть тело на
|
|
|
|
|
|
полу и перечёркнутая карточка, у пустого слота нет ни того, ни другого. Иначе
|
|
|
|
|
|
игрок с одним оперативником видел бы вокруг него четыре чужих трупа.
|
|
|
|
|
|
|
|
|
|
|
|
Делать `NUM_AGENTS` динамическим не стали: это сто с лишним мест ради числа,
|
|
|
|
|
|
которое всё равно упирается в пять.
|
|
|
|
|
|
|
Документация: границы движка, работа через модель, дизайн игры до лейтгейма
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
|
|
|
|
## Во что вкладывается опыт
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
Опыт копился с вехи 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)
|
Свет как расходник: заряд тратится за путь, а не за время (M23)
Второй ресурс вылазки после патронов. Фонарь садится, погас — обзор падает
до 35%, а твари замечают отряд в 1.35 раза дальше: отряд не слепнет, он
меняется с тварями местами. Батарея встаёт сама, как бинт.
Главное решение — расход за ПРОЙДЕННЫЙ ПУТЬ, а не за время. Первая версия
считала по секундам, то есть была таймером, которого в игре нет по прямому
требованию к жанру: садящийся сам собой фонарь торопил бы игрока ровно как
секундомер, только без циферблата, и думать над этажом стало бы дорого.
За расстояние получается тот же размен, что и с весом, но с другой стороны:
вес делает дорогим «унести всё», свет — «обшарить всё».
Заряд общий на отряд и едет вниз вместе с ним: обновляйся он на этаже, это
был бы ресурс этажа, а не вылазки, и никуда бы не гнал. Чем глубже, тем
дороже шаг, а этажи внизу длиннее — глубина жмёт на свет дважды.
Проверка в --descend меряет правило целиком, и первая её строка не про
баланс, а про жанр: заряд на стоянке обязан стоять. Сам измеритель тоже
был неправ — делил потраченное на смещение отряда, а не на пройденный
путь, и показывал 1.55 за тайл при 1.10 в каталоге.
свет: стоянка 0.2, ход 1.10 за тайл при 1.10 в каталоге
глубина 8: заряда на 383 тайла, это 4.0 прямых пути до спуска
обзор 1.00 -> 0.35 в темноте, батарея встала сама
Хватает ли заряда на этаж считается в этажах и по средней длине забега:
путь до спуска скачет вдвое от сида, и порог по одному этажу ловил бы
удачу, а не баланс.
--accept PASS без изменений: в песочнице света бесконечно, как и патронов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 02:12:05 +07:00
|
|
|
|
свет: стоянка 0.2, ход 1.10 за тайл при 1.10 в каталоге (прошли 12.7, продвинулись 1.6)
|
|
|
|
|
|
глубина 8: заряда на 383 тайлов, это 4.0 прямых пути до спуска (средний 95, здешний 155)
|
|
|
|
|
|
обзор 1.00 -> 0.35 в темноте, батарея встала сама
|
Документация: границы движка, работа через модель, дизайн игры до лейтгейма
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
|
|
|
|
переноска: налегке 6.9 (скорость 100%), с грузом 12.9 (скорость 63%), плит влезло 1
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Расход патронов проверяется тут же и отдельно: спуск ни с кем не воюет, столбец
|
|
|
|
|
|
«патронов» в таблице стоит на месте — и без прямой проверки бесконечный
|
|
|
|
|
|
боезапас выглядел бы ровно так же.
|
|
|
|
|
|
|
Свет как расходник: заряд тратится за путь, а не за время (M23)
Второй ресурс вылазки после патронов. Фонарь садится, погас — обзор падает
до 35%, а твари замечают отряд в 1.35 раза дальше: отряд не слепнет, он
меняется с тварями местами. Батарея встаёт сама, как бинт.
Главное решение — расход за ПРОЙДЕННЫЙ ПУТЬ, а не за время. Первая версия
считала по секундам, то есть была таймером, которого в игре нет по прямому
требованию к жанру: садящийся сам собой фонарь торопил бы игрока ровно как
секундомер, только без циферблата, и думать над этажом стало бы дорого.
За расстояние получается тот же размен, что и с весом, но с другой стороны:
вес делает дорогим «унести всё», свет — «обшарить всё».
Заряд общий на отряд и едет вниз вместе с ним: обновляйся он на этаже, это
был бы ресурс этажа, а не вылазки, и никуда бы не гнал. Чем глубже, тем
дороже шаг, а этажи внизу длиннее — глубина жмёт на свет дважды.
Проверка в --descend меряет правило целиком, и первая её строка не про
баланс, а про жанр: заряд на стоянке обязан стоять. Сам измеритель тоже
был неправ — делил потраченное на смещение отряда, а не на пройденный
путь, и показывал 1.55 за тайл при 1.10 в каталоге.
свет: стоянка 0.2, ход 1.10 за тайл при 1.10 в каталоге
глубина 8: заряда на 383 тайла, это 4.0 прямых пути до спуска
обзор 1.00 -> 0.35 в темноте, батарея встала сама
Хватает ли заряда на этаж считается в этажах и по средней длине забега:
путь до спуска скачет вдвое от сида, и порог по одному этажу ловил бы
удачу, а не баланс.
--accept PASS без изменений: в песочнице света бесконечно, как и патронов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 02:12:05 +07:00
|
|
|
|
У света первая строка проверки — **не про баланс, а про жанр**: заряд на
|
Редкости и аффиксы: находка стала решением (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 06:35:00 +07:00
|
|
|
|
стоянке обязан стоять, и порог у неё **в тайлах, а не в заряде**. Один и тот же
|
|
|
|
|
|
шаг стоит тем дороже, чем глубже (`LightDrain`), и порог в единицах заряда
|
|
|
|
|
|
объявлял таймером обычное топтание на шестидесятом этаже, пропуская его на
|
|
|
|
|
|
восьмом. Написать таймер случайно очень легко (одна строка со
|
Свет как расходник: заряд тратится за путь, а не за время (M23)
Второй ресурс вылазки после патронов. Фонарь садится, погас — обзор падает
до 35%, а твари замечают отряд в 1.35 раза дальше: отряд не слепнет, он
меняется с тварями местами. Батарея встаёт сама, как бинт.
Главное решение — расход за ПРОЙДЕННЫЙ ПУТЬ, а не за время. Первая версия
считала по секундам, то есть была таймером, которого в игре нет по прямому
требованию к жанру: садящийся сам собой фонарь торопил бы игрока ровно как
секундомер, только без циферблата, и думать над этажом стало бы дорого.
За расстояние получается тот же размен, что и с весом, но с другой стороны:
вес делает дорогим «унести всё», свет — «обшарить всё».
Заряд общий на отряд и едет вниз вместе с ним: обновляйся он на этаже, это
был бы ресурс этажа, а не вылазки, и никуда бы не гнал. Чем глубже, тем
дороже шаг, а этажи внизу длиннее — глубина жмёт на свет дважды.
Проверка в --descend меряет правило целиком, и первая её строка не про
баланс, а про жанр: заряд на стоянке обязан стоять. Сам измеритель тоже
был неправ — делил потраченное на смещение отряда, а не на пройденный
путь, и показывал 1.55 за тайл при 1.10 в каталоге.
свет: стоянка 0.2, ход 1.10 за тайл при 1.10 в каталоге
глубина 8: заряда на 383 тайла, это 4.0 прямых пути до спуска
обзор 1.00 -> 0.35 в темноте, батарея встала сама
Хватает ли заряда на этаж считается в этажах и по средней длине забега:
путь до спуска скачет вдвое от сида, и порог по одному этажу ловил бы
удачу, а не баланс.
--accept PASS без изменений: в песочнице света бесконечно, как и патронов.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-16 02:12:05 +07:00
|
|
|
|
`dt` вместо пути), а заметить на глаз невозможно — цифра в HUD тает одинаково.
|
|
|
|
|
|
|
|
|
|
|
|
Расход сравнивается с числом из каталога, и первая версия проверки показала
|
|
|
|
|
|
1.55 за тайл при 1.10 в правилах. Расходился не свет, а измеритель: он делил
|
|
|
|
|
|
потраченное на **смещение** отряда, а отряд шёл не по прямой. Считать надо путь
|
|
|
|
|
|
пошагово — тогда сходится до сотой.
|
|
|
|
|
|
|
|
|
|
|
|
Хватает ли заряда на этаж — считается в **этажах**, а не в тайлах, и по средней
|
|
|
|
|
|
длине этажей забега: путь до спуска скачет вдвое от сида, и порог, выставленный
|
|
|
|
|
|
по одному этажу, ловил бы удачу, а не баланс.
|
|
|
|
|
|
|
Документация: границы движка, работа через модель, дизайн игры до лейтгейма
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
|
|
|
|
```
|
|
|
|
|
|
7 RUST 13 19 3 149 живых 5, в сумках 30
|
|
|
|
|
|
эвакуация: вынесено 40, потеряно 0, выживших 5, чекпоинт D6
|
|
|
|
|
|
профиль: запись и чтение сходятся
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Круговой прогон здесь не для полноты: запись профиля — единственный путь,
|
|
|
|
|
|
которым игра может стереть всё нажитое, и ошибка в нём выглядит как «схрон
|
|
|
|
|
|
куда-то делся», а не как падение.
|
|
|
|
|
|
|
Отряд растёт с одного оперативника до пяти (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
|
|
|
|
### Как круговой прогон три вехи подтверждал то, чего не было
|
|
|
|
|
|
|
|
|
|
|
|
Он сверял три поля из десяти — глубину, схрон и снаряжение — и всё это время
|
|
|
|
|
|
`Profile::Save` **не писала ни версию формата, ни улучшения**. То есть купленный
|
|
|
|
|
|
запас патронов действовал до конца запуска и молча пропадал при следующем
|
|
|
|
|
|
чтении, а профиль без строки `version` читался как формат 1 и на каждом выходе
|
|
|
|
|
|
прогонялся через все миграции. Пока миграции были пустыми, это ничего не портило
|
|
|
|
|
|
и потому не всплывало; с приходом размера отряда такая запись начала бы
|
|
|
|
|
|
возвращать игроку пятерых бойцов после каждой вылазки.
|
|
|
|
|
|
|
|
|
|
|
|
Отсюда правило: **круговой прогон сверяет поля списком, и список растёт вместе с
|
|
|
|
|
|
форматом**. Выборочная сверка проверяет не формат, а память того, кто её писал.
|
|
|
|
|
|
|
|
|
|
|
|
И второе: прогон делается на НАБИТОМ профиле. Пустое поле сходится с пустым при
|
|
|
|
|
|
любой поломке записи — «0 == 0» подтверждало работу того, чего в файле не было.
|
|
|
|
|
|
|
Документация: границы движка, работа через модель, дизайн игры до лейтгейма
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
|
|
|
|
## Чего ещё нет
|
|
|
|
|
|
|
|
|
|
|
|
- **Схватки за добычу.** В настоящем экстракшене выход можно не отдать —
|
|
|
|
|
|
здесь на этаже нет никого, кто охотится именно за вынесенным.
|
|
|
|
|
|
- **Страховки и торговли.** Схрон только копится; девать его некуда.
|
|
|
|
|
|
- **Траты опыта** — она по-прежнему ждёт своей вехи
|
|
|
|
|
|
([16-descent.md](16-descent.md)).
|