Кида сталкивают с ряда 1 на ряд 2, страж падает за спину — Кид встаёт в
боевую стойку без меча и перестаёт реагировать на клавиши.
Оба симптома — один отказ: control() уходит в control_with_sword только при
sword == 2, а для кадров стойки (158/170/171) среди обычных веток нет ни
одной. Разворот к сопернику за спиной (SEQ_60 при char_opp_dist() < -4)
живёт как раз внутри control_with_sword.
Корень — наш чит, а не механика. hurt_by_sword перехватывался бессмертием
в самом начале и безусловно ставил SEQ_74_HIT_BY_SWORD, а это анимация
«получил удар В БОЕВОЙ СТОЙКЕ», её кадры 150..179 все с мечом. В оригинале
(seg002) туда попадают только из ветки sword == 2; безоружного там убивают:
«Being hurt when not in fighting pose means death», take_hp(100).
Спецветка чита удалена целиком — она избыточна: под бессмертием
pop_take_hp(1) и так возвращает 0, и обычный путь сам даёт seq_74 с
сохранённым мечом. Осталось запретить читу действовать в безоружной ветке.
Глушится вызов, а не pop_take_hp: тот общий с физикой (падения/пики/
чомперы), там бессмертие обязано работать при любом положении меча.
Проверено в MAME: в бою удары урона не приносят, без меча — смерть с одного
удара. Разбор и грабли метода — BUGS_CLOSED.md#bug-cheat-imm-1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Уровень 7, комната 14: спуск с ряда 0 на ряд 2 через зацеп (повис на кромке
кнопки (0,2), отпустил, взялся за (2,2)) не работал ни при какой фазе и
задержке — Кид пролетал мимо и разгонялся до fall_y = 33, после чего окно
зацепа закрыто уже по скорости.
Корень: do_fall не давал curr_row выйти за 2, а check_grab целится в тайл
ряда curr_row-1 — то есть ряд 2 своей комнаты становится целью только при
curr_row == 3. В оригинале (seg005:0030) inc_curr_row безусловный, а
get_tile для ряда 3 уходит по links.down (find_room_of_tile, seg006:005D).
- pop_map.c do_fall: inc_curr_row теперь 2 -> 3; ветка «достиг y_land»
гейтится по curr_row <= 2 (при ряде 3 ни in_wall, ни land звать нельзя —
тайлов своей комнаты там нет, а до y_land[4] дело не доходит: комнату
меняет check_leave_below на y >= 211).
- pop_map.c check_action: восстановлена ветка ACT_MIDAIR (кадры 102..105,
seg006:0619) — первые четыре кадра падения, где fall_y ещё не разогнан,
зацеп не работал вовсе. Отсюда же «иногда цепляется, иногда нет».
- tests-host/t_grab.c: регресс grab_below_room_edge_window_exists — сцена
комнаты 14 + переход в 15 по pop_fell_out. До фикса ни одного зацепа,
после — окно из 8 фаз X при задержках 0..5 кадров; проверяется и
играбельность (зацеп при «отпустил и сразу зажал Shift»).
- roomtest.c + pop_guard.h: чит-навигация ставит Кида на верхний ряд в
комнате 14 уровня 7 (GRAB_DOWN_LEVEL/ROOM) — снизу этот спуск не проверить.
Общее правило (снизу вверх) не тронуто: в верхнем ряду пола чаще нет и Кид
проваливается сразу после телепорта.
Проверено: tests-host 5/5 (55 в [grab]), size-check OK, живьём в MAME —
Кид повис на кромке (2,2): frame=91 y=55 row=0 room=15.
Доски: GRAB-BELOW-ROOM в BUGS_CLOSED, GRAB-KBD-TIMING в BUGS_OPEN (отложен
пользователем до готовности всех уровней), план L7-FEATHER в TASKS_OPEN.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Всё проверено пользователем в MAME.
1. Переход 6 -> 7 падением. leave_room (seg002:0504) для «вниз» на уровне 6
из комнаты 1 даёт особый результат −2, главный цикл (seg000:0893) читает
его как ++next_level; вход на 7-м (set_start_pos, seg003:0196) ставит Кида
в комнату 17 и сразу переводит экран на комнату под ней. Проверка ОБЯЗАНА
идти раньше связи вниз: у комнаты 1 сосед снизу есть (шахта, комната 3).
2. BUG-BALCONY-RIGHT: правая половина портала не рисовалась. id 12 стоял в
FORE_ENV_IDS (в tile_table он fore_id ЗЕЛЬЯ), но зелье рисуется из
chtab_1, а в chtab_6 под этим номером — правая часть арки балкона 32x62,
идущая в backtable. Спрайт уезжал в fore-атлас, env-страница получала
дырку (idx 12: w=0 h=0). Найдено трассой POP_TRACE_BT + чтением каталога
.atl; дифф комнаты с оригиналом 1151 -> 375.
3. BUG-BELOWROW-WALL: жёлтые треугольники в шахте падения. load_rowbelow
(seg008:368) при отсутствующей комнате снизу подставляет tiles_0_empty
колонкам 1..9 и tiles_20_wall только левому краю; у нас стеной забивались
все 11 позиций.
4. BUG-MOB-MULTIROOM: честный mob_down_a_row (seg007:1387) — кусок переходит
в комнату снизу и летит дальше. Плита (1,7) комнаты 6 пролетает шахту
комнаты 7 и жмёт кнопку (2,7) комнаты 11, открывая ворота комнаты 18.
5. BUG-MOB-STALE-PAGE: чистка следа куска стояла под гейтом «в отрисованной
комнате» — улетевший вниз оставлял себя на одной из страниц навсегда.
6. BUG-CHAR-STALE-PAGE: тень застывала на двух страницах в РАЗНЫХ позах.
Прямоугольник и valid пишутся внутри `if (w && h)`, а снимок состояния
брался безусловно — при нулевом спрайте слот залипал «тихим». Остаток
(почему спрайт нулевой) заведён как SPRITE-ZERO-W0 в BUGS_OPEN.
NEXT_SESSION переписан: следующая задача — зацеп за край пола в свободном
падении (вход на уровень 7). tests-host 5/5, size-check чист.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Уровень 5, комната 12, тайл (0,9): чёрная дыра вместо арки. У doortop нет
своей базы (base_id 0), и рядом с lattice_down оригинал рисует пару одним
спрайтом 6, опущенным на 3 px. Ветки у нас не было.
Правка нужна В ДВУХ местах: pop_room.c (сама отрисовка) и
toolchain/render_room.py — pop_pack_bg.py собирает атлас по обходу
render_room, без этого спрайт 6 не попал бы в pop_env*.atl.
Найдено сверкой с оригиналом: prince megahit 5 --screenshot-level даёт карту
уровня, снимок MAME совмещается с клеткой комнаты, разница по яркости
показала расхождение ровно в (0,9) — 1892 пикселя до фикса, 995 после
(остаток = Кид, факел, статус-полоса). Что рисует оригинал в тайле,
показала трасса POP_TRACE_BT в add_backtable: id=6 32x63 рядом с id=85 32x4.
Методика записана в BUGS_CLOSED.md и memory.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Три бага одной отладочной сессии, все проверены в MAME пользователем.
1. SHADOW-FIGHT-L5. Кид доставал меч, а тень вставала в боевую стойку и
рисовалась спрайтами стража. В pop_check_can_guard_see_kid первым
множителем стояло `Guard.charid != 0`, тогда как оригинал (seg003:702)
пишет `Guard.charid != charid_1_shadow || current_level == 12`: тень
боевая только на 12-м уровне. Оба симптома шли из одной ветки
control_standing (seg005:352). Возвращён и пропущенный множитель
`Guard.direction != dir_56_none`.
2. SEAM-BUTTON-STALE. Кнопка в шве не меняла вид ни при нажатии, ни при
отжатии. Сигнатура редроя шва сравнивала room_modif, а у кнопки modif —
это индекс LINKLOC, константа уровня: нажатие живёт в doorlinks2, и в
сигнатуру не приходило никогда. seam_row_sig подмешивает бит нажатости.
Оригинал шов в этом случае не перерисовывает вовсе — расхождение
осознанное, записано как D-2 в docs/impl_diff.md.
3. BUG-POTION-STRIPE. Синяя лента паласа пропадала на месте выпитого зелья
и не возвращалась даже после перезахода в комнату. У оригинала
curr_room_tiles — сама таблица уровня, у нас fg живёт в двух местах, и
страницу правил главный цикл уже после pop_process_trobs. В этот зазор
trob зелья крутил фазу пузырька поверх обнулённого модификатора:
bubble_next_frame(0) = 1, а для пола в паласе modif 1 означает «узор не
рисовать» (seg008:499). do_pickup теперь правит страницу уровня сразу.
Тем же лечится меч: animate_sword делал `--mod[tp]` из нуля.
tests-host 5/5 (добавлена заглушка pop_level_set_tile), size-check чист.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Прогон читом ROOMNAV: телепорт в комнату 4 сразу после нажатия кнопки —
зеркала нет вовсе (тайл ставится в момент, когда дверь ДОРИСОВАЛА открытие,
43 тика анимации, телепорт успевает раньше); обычный вход в комнату —
зеркало на месте и непроходимо, кроме правильного прыжка, то есть коллизия
его видит. Сценария «постановка при игроке в комнате» в реальном
прохождении нет: дверь выхода стоит не в комнате зеркала, а при входе
комната и снимок room_fg берутся из данных уровня разом.
Решение пользователя: телепорт по комнатам — отладочный режим, чинить нечего.
Запись целиком уехала в BUGS_CLOSED.md вместе с протоколом и с указанием, чем
лечить, если симптом всё же всплывёт на моде/уровне, где кнопка и зеркало в
одной комнате.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Доска отставала от кода на три задачи — планировать по ней было нельзя.
Сверка проведена грепом по исходникам, а не по записям:
- L4-MIRROR ЗАКРЫТА: шаги 1-5 сделаны и проверены пользователем в MAME
(зеркало в атласе, постановка тайла, отражение, прыжок сквозь зеркало с
рождением тени, левый клип тени). Протокол с разбором решений — в архиве;
- L3-CHOMP и L3-SKEL закрыты ещё 2026-08-08/07 (коммиты dc0bd47, 4d4323f,
db4106a, 1461ed5), на доске значились как предстоящие;
- тайлсет palace (шаг 2 levels_plan) в коде есть целиком — pop_bg_load(type),
pal_*.atl, дворцовый wall_pattern, решётки 25-29 и в tile_table, и в
коллизии (tile_is_floor совпадает с seg006:0628);
- в GUARD-PHYS остаток пересобран по факту: check_chomped_guard сделан,
скелет в check_guard_fallout сделан, ветки ТЕНИ нет — она уехала в L5-SHADOW.
Приёмки: по решению пользователя уровни 1-4 приняты SMOKE-тестами, полные
обходы всех комнат делаются по готовности ВСЕХ уровней — L3-PASS/L4-PASS как
отдельные задачи отменены, вместо них политика приёмок в архиве.
Новая цель — уровень 5. Инвентарь res2005.bin: НИ ОДНОГО нового тайла, всё
портировано на уровнях 1-4. Единственная новая механика — спецсобытие «тень
крадёт зелье» (комната 24): заведена задача L5-SHADOW с портом по SDLPoP
(check_shadow / do_init_shad / do_auto_moves + shad_drink_move /
autocontrol_shadow_level5 + ветка тени в check_guard_fallout), включая
готовые константы и то, что у нас уже есть под это.
Заведён MIRROR-FG-STALE (низкий): place_mirror пишет тайл в данные уровня, но
не в снимок room_fg, по которому работает коллизия — если зеркало поставлено,
пока игрок В комнате 4, оно невидимо для коллизии (тень не родится). В
обычном прохождении недостижимо: дверь выхода в другой комнате. Записан
точный сценарий воспроизведения читом ROOMNAV и фикс на несколько строк.
Правило «в _OPEN только незакрытое» теперь выполняется буквально:
- bug_list.md → BUGS_OPEN.md, bug_closed.md → BUGS_CLOSED.md (ссылки
обновлены во всех документах и в комментарии pop_trob.c);
- из TASKS_OPEN убраны блоки закрытых задач (L3-CHOMP, L3-SKEL, L3-PASS,
L4-MIRROR, DRAW-CHAR), справка по связности комнат уехала в архив;
- из BUGS_OPEN убраны 8 строк таблицы закрытых багов, закрытый T-2 (уехал в
BUGS_CLOSED) и раздел «уровень 3 — неначатые задачи» (обе записи закрыты);
сводная таблица пересобрана по реально открытым записям.
Все внутренние ссылки проверены скриптом: битых якорей 0. make size-check
OK (65 программ), tests-host 5/5.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>