squad-proto/docs/07-milestones.md
z.kirill 7880f275bd Прототип боевого ядра: отряд, хоррор-слой, ближний бой
Тактический отряд с автоматическим огнём в изометрии, собственный
софтверный растеризатор (raylib только окно, ввод и финальный блит).

Ядро (спек, раздел 6):
- LaneClear: проверка линии огня по своим, стенам и дальности;
- решатель огневых позиций с гистерезисом и коммитом;
- резервирование линий огня и расступание из чужих секторов;
- пули-снаряды, дружественный урон физически возможен.

Хоррор-слой (render-only): свет и туман войны с памятью карты,
светящиеся трассеры, кровь, виньетка, зерно, напряжение.

Ближний бой: сектор удара, три фазы, связка из трёх ударов,
своя дисциплина «не бить сквозь своего».

Проверка: squad_proto.exe --accept прогоняет критерии приёмки
раздела 11 плюс блок M7 по ближнему бою — все PASS,
FRIENDLY_HITS = 0 за 3 минуты боя.

Сборка: cmake -S . -B build && cmake --build build --config Release
raylib 6.0 подтягивается через FetchContent.

Документация — CLAUDE.md как оглавление, содержание в docs/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 13:00:49 +03:00

55 lines
6.4 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.

# 07 — Журнал вех
Порядок из раздела 10 спека: после каждой вехи сборка и запуск, потом следующая.
| Веха | Что сделано | Чем проверено |
|---|---|---|
| **M0** | CMake + raylib через FetchContent, фреймбуфер 480×270, ×3 апскейл, fixed timestep, изометрическая сетка | сборка MSVC x64, окно открывается, текстура 480×270 RGBA8 создаётся |
| **M1** | тайлмап 48×48, генерация уровня, процедурные спрайты пола и стен, камера за якорем, сортировка по глубине | скриншот: ромбы пола шахматкой, кубы стен перекрывают друг друга правильно |
| **M2** | 5 агентов, движение якоря в экранных осях, три строя, separation, коллизии со стенами | скриншот: пятеро в клину, цвета различимы, стены не проходятся |
| **M3** | мишени с респавном, DDA-рейкаст, `LaneClear`, авто-огонь, пули-снаряды, дружественный урон, `FRIENDLY_HITS` | `--headless 60 --no-solver --no-laneavoid`: 1 попадание по своим, uptime 13.6 % — то есть проблема, которую должно решать ядро, воспроизводится |
| **M4** | решатель огневых позиций, гистерезис и коммит, реестр линий и расступание | то же 60 с с включённым ядром: 0 попаданий, uptime 88 % на стоянке у мишеней |
| **M5** | ручное прицеливание, конус ±20°, назначенная цель, `Tab` | сценарий `11.7` в `--accept`: 0 попаданий по своим при активной назначенной цели |
| **M6** | оверлей F1F4, метрики, журнал попаданий по своим, runtime-тюнинг `[ ] - =`, `--set` | скриншот боевого кадра: зелёные линии у всех пятерых, FRIENDLY_HITS 0, uptime 99 % |
| **M7** | ближний бой: классы оружия, сектор удара, три фазы, свой больший круг, дуга; отзывчивый диск на поводке | `--accept`: M7.1M7.3 PASS, 81 взмах / 81 попадание / 23 убийства за 30 с, FRIENDLY_HITS 0; все критерии спека 11 по-прежнему PASS |
## Что находилось по ходу и чинилось
Прогоны без окна оказались полезнее, чем разглядывание кадра: три дефекта,
которые на глаз не видны, нашлись именно так.
1. **Отставшие агенты.** `--probe` показал агента на `y=12`, когда отряд стоял на
`y=26`. Причина — залипание в «тени» стены (локальный минимум seek против
отталкивания) плюс отсутствие правила «идти к отряду, когда стрелять не по чему».
Починено касательным обходом стен и возвратом в слот строя (A5, A6).
2. **Резерв линии, который исчезает, когда нужен.** Линии регистрировались только у
реально стреляющих. Стоит кому-то влезть в линию — стрелок теряет линию, отрезок
пропадает из реестра, и перекрывшего ничто не выталкивает (A3).
3. **Пуля, летящая за цель.** Последнее упорное попадание по своим
(`t=94.49`, воспроизводилось при любых настройках) — снаряд проходил место
умершей мишени и находил своего за ней (A1).
4. **Выход за границы в блиттере спрайтов.** `Framebuffer::Blit` вычислял адрес
строки спрайта до внутреннего цикла. Если спрайт срезан левым краем экрана
больше, чем на свою ширину (`sx0 >= s.w`), индекс уезжал за конец `px`:
цикл пустой, разыменования нет, но индекс уже невалиден. Release это молча
глотал, Debug валился с `vector subscript out of range`. Починено ранним
выходом при пустом диапазоне обрезки.
Вывод на будущее: **проверять в Debug-сборке**. В Release такие ошибки
не проявляются — там нет проверок итераторов MSVC.
5. **Критерий 11.6 мерил не то, что означал.** Тест требовал, чтобы в коридоре
огонь вёл передний, и считал ВСЕ выстрелы. Диагностика показала, что
«нарушения» — это хвостовой агент, стреляющий **назад**, в оставленную позади
комнату: к правилу «не стрелять сквозь своего» это отношения не имеет, впереди
по такой линии никого нет по построению. Теперь считаются только выстрелы по
ходу движения, и результат стал строже: 5/0 вместо 12/4.
6. **Двое с клинками на одной мишени.** Взмахи обрывались друг об друга, урона
почти не было. Починено ценой цели: 37 взмахов / 31 попадание → 74 / 75.
Подробности и замеры по каждому — [08-decisions.md](08-decisions.md).
## Текущий статус
Все измеримые критерии раздела 11 проходят: `squad_proto.exe --accept`
«все проверяемые критерии PASS». Цифры — [09-acceptance.md](09-acceptance.md).