VanguardReMaster/.opencode/skills/vanguard-remaster/game-rules.md

242 lines
17 KiB
Markdown
Raw Permalink 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.

# Правила Vanguard ReMaster (Classic)
Статусы: **[D]** подтверждено пользователем, **[C]** подтверждено кодом,
**[O]** неизвестно/расхождение. Полный конспект официальных правил и сверка —
`docs/game-rules.md`; здесь рабочая база проекта.
## 1. Формат и матч
- **[D]** Формат проекта — **Classic**: BT01 + TD01/TD02. Не Standard,
Premium или G Standard.
- **[D]** Матч BO1; сайд-дека нет.
- **[D]** В Classic нет Ride Deck, Persona Ride, Stride, Legion, Gift,
G-зоны, Bind, Front/Over-триггеров и Grade Support.
- **[C]** В матче два игрока; первый определяется seeded RNG, но может быть
зафиксирован тестом/сервером.
- **[C][D]** Первый ход: нет Battle и атак. `GameEngine` умеет отключать это
правило флагом для тестов, но серверный матч использует запрет.
- **[D]** Таймер: 90 секунд на ход + банк 5 минут; отсутствие 5 минут —
поражение. Реконнект: 0/2/10/30 секунд, затем полный snapshot.
- **[C]** Победа/поражение: 6 карт урона, пустая колода, сдача/выход/разрыв,
истечение времени или отсутствие. Дополнительное условие «авангард исчез»
есть в конспекте, но отдельной проверки в `GameEngine` нет — **[O]**.
## 2. Колода
**[D][C]** Основная колода:
- ровно **50 карт**;
- ровно **16 триггер-карт**;
- не более **4 копий одной карты по `nameId`**, а не по принту/арту;
- не более **4 Heal-триггеров**;
- не более **4 Sentinel**;
- стартовый авангард — карта grade 0 без триггера; движок выбирает первого
подходящего кандидата из колоды;
- **смешивать кланы разрешено** [D, 2026-10-24]. Это осознанное отклонение от
официального ограничения: эффекты, требующие клан/условие, могут не
сработать. `DeckValidator` единство клана не проверяет.
- Колода должна быть собрана из карт, которыми владеет игрок (проверка
`DeckService`); в коллекции лимита копий нет — 4 копии ограничивают только
колоду.
- **[O]** Легальность по формату/banlist и обязательное наличие ровно одного
стартового авангарда в `DeckValidator` отдельно не выделены.
## 3. Начало партии
1. Перемешать колоды.
2. Положить стартового авангарда grade 0 без триггера в VC закрытым.
3. Взять по 5 карт.
4. Mulligan: каждый игрок один раз может вернуть любое количество карт
**в низ колоды**, добрать столько же сверху, затем перемешать. Оба игрока
проходят этап. Возвращённые карты не должны попасть в тот же добор.
5. Открыть стартовых авангардов; первый игрок начинает.
**[C]** В коде `MulliganCommand` сразу выполняет возврат → добор → shuffle, а
`FinishMulliganCommand` передаёт очередь второму игроку; отдельной команды
«выбрать карты и подтвердить» нет.
## 4. Зоны
| Зона | Смысл |
|---|---|
| Deck | закрытая колода, добор сверху |
| Hand | рука; у противника видно только количество |
| Vanguard Circle (VC) | текущий авангард; под ним — Soul |
| Rear-guard Circles (RC) | 5 кругов: 0/1/2 задний ряд, 3/4 передний |
| Guardian Circle (GC) | временная зона защитников/перехватчиков |
| Damage | урон; 6+ — поражение |
| Drop | сброс/уничтоженные карты |
| Trigger | временная зона проверки триггера |
| Soul | карты под VC, не отдельная стопка на поле |
- **[C]** Карты на VC/RC/GC открыты. Закрытыми могут быть рука/колода и урон
после Counter Blast.
- **[C]** Урон входит **лицом вверх**; Counter Blast переворачивает выбранные
карты лицом вниз; Counter Charge — обратно.
- **[D]** Рука противника отображается только рубашкой; колода — только
количеством; урон лицом вниз — только количеством.
- **[C]** Soul не показывается на столе; доступна через ПКМ/список у VC.
- **[D]** Drop по умолчанию пуст; сверху показывается последняя карта, по
клику — весь список.
## 5. Фазы хода
**[C]** Порядок в движке: `Stand → Draw → Ride → Main → Battle → End`.
Mulligan — отдельная фаза до первого хода.
### Stand
Все юниты активного игрока в Rest поднимаются, если нет `CannotStand`.
Ограничения `UntilOwnerNextStand` снимаются после подъёма.
### Draw
Взять 1 карту сверху. Пустая колода — поражение.
### Ride
- Карта из руки на VC; ранг **равен текущему или на 1 выше**.
- Старый авангард уходит в Soul.
- Ride — один раз за ход; можно пропустить.
- Новый авангард входит стоя и открытым.
- **[C]** После Ride сначала срабатывает `OnPlace` новой карты, затем
`OnRideOver` старой; если `OnPlace` открыл pending-способность, текущая
реализация не запускает `OnRideOver` до её завершения. Это техническая
деталь, а не новое правило; при работе с такими картами проверяй сценарий.
### Main
- **Call**: из руки в RC; grade ≤ grade своего VC. Занятый RC разрешён:
прежний юнит уходит в Drop. Призыв из soul/deck и выбор круга работают так
же. Число призывов не ограничено. Юнит входит стоя.
- **Move**: RC ↔ RC только в своей колонке: 0↔3, 2↔4; занятые меняются
местами. VC в Move не участвует.
- **Activate**: ACT-способности; AUTO срабатывают по событиям.
- **End Main**: переход в Battle.
- **[C]** В Main также доступны `EndTurn` и (если разрешено) `EnterBattle`.
### Battle
1. Атака: стоящий юнит **переднего ряда** (VC или RC 3/4), он уходит в Rest.
Цель — VC или передний RC противника.
2. Boost: стоящий юнит 0/1 ранга из заднего ряда той же колонки уходит в Rest;
его сила добавляется атакующему до конца боя. Карта может получить Boost
эффектом.
3. Guard: защищающийся добавляет карты из руки в GC. Grade ≤ grade своего
авангарда. Щит добавляется сразу.
4. Intercept: подходящий RC (обычно grade 2, передний ряд) выходит в GC;
атака переносится на него. Нельзя перехватывать атаку по самому себе.
5. Drive Check: только из VC; 0–2 ранг — 1 проверка, 3+ — 2; эффект может
изменить/обнулить. Арьергард по умолчанию проверок не делает.
6. Сравнение: сила атакующего **>=** силы защищающегося + щит — попадание.
Иначе промах. При попадании по RC цель уходит в Drop; при попадании по VC
наносится урон, равный критическому удару.
7. Damage Check: по одной карте за урон; триггеры срабатывают, затем карта
идёт в Damage.
8. После боя Guardian/Intercept уходят в Drop. Атакующий может атаковать
снова, если есть стоящие передние юниты.
**[C]** Boost/Interceptor/Guard карты и их модификаторы очищаются в
`ClearBattle`; `UntilEndOfBattle` не переживает бой.
### End
Сначала возвращаются карты с `ReturnToDeckTiming.EndOfTurn`, затем снимаются
`UntilEndOfTurn` модификаторы/выданные способности/ограничения. Ход переходит
противнику, начинается Stand.
## 6. Атака, защита, крит и урон
- **[C]** Обычная цель — только VC или передний RC. Задний ряд можно атаковать
только `CanSnipeBackRow` (Tejas) и только в своей колонке. Tejas бьёт задний
ряд и с VC (центральная колонка), и с RC.
- **[C]** Атака/Boost/часть ACT переводят карту в Rest.
- **[C]** Guard: `def.Grade > VanguardGrade` отклоняется. Sentinel сам по себе
даёт 0 щита. Perfect Guard: сброс карты **того же клана** отменяет атаку;
без оплаты — 0 щита и отмены нет. Сброс — опциональная стоимость.
- **[C]** Guard/Intercept карты после боя уходят в Drop; `OnLeaveGuardian`
срабатывает после закрытия боя.
- **[C]** Урон — лицом вверх; 6-я карта вызывает поражение после разрешения
эффектов. Damage Check-триггер сначала кладёт карту в Trigger, применяет
эффект, затем в Damage.
- **[C]** Heal доступен, если урон игрока **>=** урона соперника и в своей
зоне есть карты; лечится карта только из своей зоны урона.
## 7. Триггеры
**[D][C]** В Classic только Critical, Draw, Stand, Heal. Front/Over — нет.
- Триггеры срабатывают при Drive Check и Damage Check.
- Базовый бонус силы — **+5000**; действует до конца хода.
- Power target и второй эффект могут быть разными юнитами, если текст не
запрещает.
- **Critical**: +5000 и +1 крит выбранному юниту.
- **Stand**: +5000 и поднять выбранного отдыхающего арьергарда; если
арьергардов нет, второй эффект не применяется.
- **Draw**: +5000 и немедленно взять карту; отдельной цели для draw нет.
- **Heal**: +5000 и, при условии, лечение 1 урона из своей зоны; если нет
карт/условия — лечение не активируется.
- **[C]** На Damage Check `GrantsPower = true`: усиление тоже применяется.
- После Drive Check карта уходит в руку; после Damage Check — в Damage.
- Бонусы триггеров снимаются в конце хода, в том числе у противника.
## 8. Стоимости
| Стоимость | Реализация |
|---|---|
| Counter Blast X | перевернуть X **открытых** карт урона лицом вниз; при выборе — конкретные |
| Counter Charge X | перевернуть X закрытых карт лицом вверх; если меньше — сколько есть |
| Soul Blast X | X карт из Soul в Drop |
| Soul Charge X | X верхних карт колоды в Soul |
| Discard | выбранная карта из руки в Drop |
| Rest self | повернуть источник |
| Retire self | убрать источник в Drop |
- **[D]** Multi-target Counter Blast: клиент выбирает карты урона; сервер
принимает `DamageIndexes` и переворачивает именно их. Старый одиночный
`DamageIndex` сохранён для совместимости.
- **[O]** Multi-target Soul Blast и другие стоимости ещё не имеют такого же
выбора/протокола.
- **[D]** Стоимость выбирается по объектам, подтверждение — отдельной кнопкой
панели/оверлея; отдельный `CostPaymentOverlay` требуется, но пока не
реализован (текущий CB использует счётчик в панели «Действия»).
## 9. Эффекты и порядок разрешения
- **[C]** Источник истины — `GameEngine`; он меняет `GameState` и пишет
`GameEvent`.
- **[D]** Эффект, сработавший при прохождении атаки, разрешается **после**
получения урона и помещения карты в Damage.
- **[D]** Нельзя начинать новый эффект посреди текущего: цепочка идёт строго
друг за другом. `_resolvingDepth` складывает новые триггеры в
`PendingQueue`; после завершения текущего они предлагаются/разрешаются.
- **[D]** Рекурсию не поддерживаем; при найденном кейсе — отдельное решение.
- Несколько одновременных AUTO: игрок выбирает порядок; активный игрок первым
получает доступ к своим срабатываниям (`PendingOrder`/`SelectTriggerCommand`).
- Optional AUTO: движок спрашивает «активировать/пропустить»; без `Pay`
эффект не выполняется. `CanPay` проверяется до предложения.
- CONT пересчитывается из состояния; вычисленную силу не хранить как истину.
- Модификаторы/способности/ограничения имеют источник, `EffectId` и
`ModifierDuration`: `UntilEndOfBattle`, `UntilEndOfTurn`,
`UntilOwnerNextStand`, `Permanent`.
- `OnPlace` не должен срабатывать от VC, если текст требует RC; проверяй
`IsVanguardOf`/`IsRearGuardOf`/`IsInHand`.
## 10. Особые случаи
- **[D]** Move: если у RC доступен только один круг в колонке, клиент
выполняет перемещение сразу, без выбора цели.
- **[D]** Draw после выбора цели силы сразу тянет карту; второй цели нет.
- **[D]** Heal просит цель только в своей зоне урона и только при выполнении
серверных условий.
- **[D]** Tejas атакует задний ряд своей колонки с VC/RC.
- **[D]** Подсветка урона ограничена зоной урона локального игрока и режимом
оплаты; вне оплаты урон не подсвечивается.
- **[D]** Call в занятый RC заменяет юнита; старый уходит в Drop.
- **[D]** В первый ход атака и переход в Battle недоступны.
- **[C]** `OnRideOver` текущей реализации срабатывает после `OnPlace`, но
может быть отложен/пропущен при pending-способности `OnPlace`; это
техническая граница, проверяй карты с обоими окнами.
- **[O]** Отдельная проверка «авангард исчез» в `GameEngine` не реализована;
не описывай её как гарантированное поражение без решения.