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
-78
View File
@@ -28,7 +28,6 @@ BUG-GATE-PASS-1 — однократное наблюдение прохода
| ID | что | тип | статус |
|----|-----|-----|--------|
| [BUG-SPIKE-1](#bug-spike-1) | пики залипают выдвинутыми рядом с Кидом (h=1 → пробег безвреден, острия видны на экране) | Minor | **не воспроизводится по требованию; смертельность подтверждена замером** |
| [BUG-GUARD-DEAF-1](#bug-guard-deaf-1) | страж не оборачивается на вернувшегося Кида: `is_guard_notice` не взводился | Major | **фикс есть, ждёт игровой проверки** |
| [BUG-GRAB-1](#bug-grab-1) | ур. 2 комн. 9: прыжок с места через 3 тайла — нет зацепа за кромку | Major | **причина найдена (клавиатура, BUG-KBD-5), фикс есть, ждёт игровой проверки** |
| [BUG-GATEMOD-1](#bug-gatemod-1) | ворота стартуют закрытыми, хотя в уровне открыты | Major | **фикс есть, ждёт проверки** |
| [Уровень 2](#уровень-2) | остальные баги с приёмки | — | принимаются по ходу |
@@ -187,83 +186,6 @@ check_spiked (seg006:0658): убивает при h>=2 на кадрах б
---
<a id="bug-guard-deaf-1"></a>
## BUG-GUARD-DEAF-1. Страж не оборачивается на вернувшегося Кида — ФИКС ЕСТЬ, ЖДЁТ ИГРОВОЙ ПРОВЕРКИ
**Наблюдение (пользователь, 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` (автопилота стража в наборах нет).
**Как проверить в игре:** комната 11 уровня 2, дать стражу вытолкнуть Кида
вправо в комнату 22 и вернуться бегом — на первом же шаге страж обязан
обернуться и достать меч. Подкрасться к нему СТОЯ (не двигаясь) по-прежнему
можно — это механика оригинала, а не баг.
---
<a id="bug-grab-1"></a>
## BUG-GRAB-1. Прыжок с места через провал в 3 тайла: зацепа нет — **ПРИЧИНА НАЙДЕНА, ФИКС ЕСТЬ, ЖДЁТ ИГРОВОЙ ПРОВЕРКИ**