BUG-GUARD-DEAF-1 закрыт: страж оборачивается на вернувшегося Кида

Проверено в игре: комната 11 уровня 2, страж выталкивает Кида в 22, Кид
возвращается бегом — страж оборачивается и достаёт меч.  Разбор корня
(is_guard_notice не взводился ни в одном из пяти мест оригинала) переехал
в bug_closed.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Александр Петров
2026-08-05 22:41:20 +03:00
parent 4424ea20a8
commit 3078886306
2 changed files with 83 additions and 78 deletions
+83
View File
@@ -11,6 +11,89 @@
---
## BUG-GUARD-DEAF-1. Страж не оборачивался на вернувшегося Кида — **ЗАКРЫТ 2026-08-05**
**Наблюдение (пользователь, 2026-08-05).** Уровень 2, комната 11, идёт бой
со стражем. Страж **выталкивает Кида в правую комнату 22**. Кид заходит
обратно в комнату 11 — страж стоит на (1,1), **повёрнут налево и Кида не
видит**. Предположение пользователя: это часть большой задачи «полностью
переделать поведение стража по образцу Кида».
**Диагноз: большая переделка тут ни при чём, корень маленький и точный.**
Само возвращение стража в исходную позу — ПРАВИЛЬНОЕ поведение, порт верен;
не хватает ровно одного сигнала.
Разбор по SDLPoP:
1. **Выход Кида из комнаты «усыпляет» стража — так и в оригинале.**
`leave_guard` (seg002:02F5) складывает стража обратно в данные уровня
(тайл, `x`, **направление**, skill, HP), а `enter_guard` (seg002:0112)
при возврате поднимает живого стража **с УБРАННЫМ мечом**
(`sword_0_sheathed` + `seq_77_guard_stand_inactive`) и обнуляет
`is_guard_notice`/`guard_refrac`. То есть страж после возврата ВСЕГДА
неактивен и смотрит в запомненную сторону — у нас так же
(`pop_guard_enter`, `pop_guard.c:127`).
2. **Дальше решает `autocontrol_guard_inactive` (seg002:0876), и он Кида за
спиной ИГНОРИРУЕТ.** Кид вернулся справа, страж смотрит влево →
`char_opp_dist()` отрицательна → ветка `else if (distance < 0) return;`.
Единственный выход из неё — флаг **`is_guard_notice`**: «Кид нашумел».
При нём страж оборачивается (`move_4_down`). Направление в
`check_can_guard_see_kid` НЕ участвует вовсе, так что «не видит» — это
не про луч видимости, а именно про этот флаг.
3. **У нас `is_guard_notice` не взводится НИГДЕ.** `grep` по всем исходникам
roomtest: объявление (`pop_guard.c:20`), сброс (`pop_guard.c:47`) и одно
чтение (`guards.c:171`). Присваивания `= 1` нет ни одного — флаг мёртв,
поэтому неактивный страж не обернётся НИКОГДА, что бы Кид ни делал.
**Где его взводит оригинал** (это и есть объём фикса):
| место | событие |
|-------|---------|
| `seg006:633..641``play_seq`, опкод SOUND | звук `SND_SILENT`(0), `SND_FOOTSTEP`(1), `SND_BUMP`(2). `SND_DRINK`(3)/`SND_LEVEL`(4) — НЕ шум. Главный источник: шаги бега/приземления |
| `seg004:05F1` `bumped_sound` | удар в стену |
| `seg005:185,195` | мягкое и среднее приземление (**только `charid_0_kid`**) |
| `seg006:1294`, `seg006:1734` | Кид обрушил loose-плиту (зацепом и наступив) |
| `seg007:766` | нажата кнопка |
У нас опкод SOUND в `play_seq` (`pop_kid.c:426`) просто съедает байт
аргумента — звука нет, и флаг вместе с ним потерялся. Именно эта строка —
90 % фикса: `SND_SILENT` называется «silent» потому, что звука не издаёт,
**но стражи его всё равно замечают**, и в `seqtbl` он стоит, например, в
`ready` (доставание меча).
**Ожидаемое поведение после фикса.** Кид возвращается в комнату 11 бегом →
первый же `SND_FOOTSTEP` взводит флаг → страж оборачивается и достаёт меч.
Стоя на месте, Кид может подкрасться к стражу со спины — это НЕ баг, а
механика оригинала.
**Оговорка (не проверено вживую).** Разбор построен на том, что страж после
возврата неактивен (меч убран, кадр 166). Это следует из кода
`pop_guard_enter`, но в MAME не снималось; если окажется, что меч у него
ОБНАЖЁН, то работает другая ветка (`autocontrol_guard_active`, где
`can_guard_see_kid == 2` направления не спрашивает) — и тогда корень другой.
Снять при фиксе: `Guard.sword`, `Guard.frame`, `can_guard_see_kid` сразу
после входа в комнату.
**Фикс (2026-08-05): все пять мест портированы.** Опкод SOUND в `play_seq`
(`pop_kid.c`) взводит флаг для звуков 0..2; `bumped_fall`/`bumped_floor`,
мягкое и среднее приземление, обрушенная плита (все три пути `check_press`)
— в `pop_map.c`; щелчок кнопки — в `pop_trob.c`. Заглушка `is_guard_notice`
добавлена в `tests-host/stubs.c` (автопилота стража в наборах нет).
**Проверено в игре (пользователь, 2026-08-05):** тот же сценарий — страж
выталкивает Кида в комнату 22, Кид возвращается бегом — **страж
оборачивается**.
**Что осталось «как в оригинале» и багом не является:** подкрасться к
стражу СТОЯ по-прежнему можно (шумит движение, а не присутствие), и после
возврата в комнату страж всегда поднимается с УБРАННЫМ мечом в неактивной
стойке, повёрнутый туда же, куда смотрел при выходе Кида — это `enter_guard`
(seg002:0112), а не потеря состояния.
---
---
## BUG-JUMPWALL-1. Недолетевший прыжок проходил СКВОЗЬ стену — **ЗАКРЫТ 2026-08-05**
**Симптом (пользователь, приёмка уровня 3).** Комната 14: Кид на (0,8)