BUG-GATE-PASS-1: воспроизведён и разобран; SDLPoP собран с трассой
Сценарий: ур.1 комн.8, ряд 0, x=170, лицом вправо, решётка шва закрыта — разбежаться вправо и не отпускать. Кид проходит сквозь решётку. Корень (две трассы, наша и оригинала, стартовая позиция совпала до пикселя): смена комнаты в этой точке ШТАТНАЯ и у нас, и в оригинале — leave_room вправо блокируют только doortop. Оригинал держит Кида бампом СРАЗУ ПОСЛЕ перехода, потому что check_collisions хранит флаги по паре (колонка в СВОЕЙ комнате, номер комнаты) и сравнивает prev/curr только при совпадении номеров: решётка комнаты 8 и до, и после перехода лежит в слоте 9 с room=8, история не рвётся. У нас индекс — колонка относительно отрисованной комнаты, при переходе все индексы уезжают на 10, поэтому enter_room зовёт pop_coll_invalidate, тот подавляет бамп на кадре входа, а дальше перехода флага 0->1 уже не будет. Что делать — порт индексации оригинала (10 слотов по колонке своей комнаты + массив её номера); тогда pop_coll_invalidate не нужен вовсе. Осторожно: это сердце коллизии из BUG-SEAM-PINGPONG. SDLPoP инструментирован для сверки: POP_TRACE=1 включает покадровую печать Char + обе пары краёв, плюс маркеры BUMPED и LEAVE. В bug_list записана и команда сборки на macOS (штатный Makefile требует pkg-config, которого нет).
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
| ID | что | тип | статус |
|
| ID | что | тип | статус |
|
||||||
|----|-----|-----|--------|
|
|----|-----|-----|--------|
|
||||||
| [BUG-CHEAT-FIGHT-1](#bug-cheat-fight-1) | `+`/`−` в бою с вынутым мечом → Кид теряет управление | Major (чит) | открыт |
|
| [BUG-CHEAT-FIGHT-1](#bug-cheat-fight-1) | `+`/`−` в бою с вынутым мечом → Кид теряет управление | Major (чит) | открыт |
|
||||||
| [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрывшуюся решётку (0,9) комнаты 5 | Major | **ждёт сценария**: прогоном 2026-08-07 не воспроизведён |
|
| [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрытую решётку шва (комн. 8 -> 6) | Major | **воспроизведён, корень найден 2026-08-08**: история флагов коллизии не привязана к комнате |
|
||||||
| [BUG-SPIKE-1](#bug-spike-1) | пики залипают выдвинутыми рядом с Кидом | **низкий** | маловоспроизводимый: ни сценарием, ни попиксельной подгонкой X не поднимается |
|
| [BUG-SPIKE-1](#bug-spike-1) | пики залипают выдвинутыми рядом с Кидом | **низкий** | маловоспроизводимый: ни сценарием, ни попиксельной подгонкой X не поднимается |
|
||||||
| [BUG-CHOMP-JUMP-1](#bug-chomp-jump-1) | прыжок с места вплотную к чомперу: кадр с отступом назад | **низкий** | маловоспроизводимый: на повторе не поднялся; на пререлиз |
|
| [BUG-CHOMP-JUMP-1](#bug-chomp-jump-1) | прыжок с места вплотную к чомперу: кадр с отступом назад | **низкий** | маловоспроизводимый: на повторе не поднялся; на пререлиз |
|
||||||
| [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт |
|
| [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт |
|
||||||
@@ -193,7 +193,89 @@ Smoke-прогон уровня 3 (пользователь, 2026-08-05) дал
|
|||||||
# Открытые баги уровня 1
|
# Открытые баги уровня 1
|
||||||
|
|
||||||
<a id="bug-gate-pass-1"></a>
|
<a id="bug-gate-pass-1"></a>
|
||||||
## BUG-GATE-PASS-1. Проход сквозь закрывшуюся решётку — ЖДЁТ СЦЕНАРИЯ
|
## BUG-GATE-PASS-1. Проход сквозь закрывшуюся решётку — **КОРЕНЬ НАЙДЕН 2026-08-08**
|
||||||
|
|
||||||
|
> **ВОСПРОИЗВЕДЁН И РАЗОБРАН.** Сценарий: уровень 1, комната 8, ряд 0,
|
||||||
|
> `Kid.x = 170`, лицом ВПРАВО, решётка шва (комната 8, колонка 9) ЗАКРЫТА.
|
||||||
|
> Разбежаться вправо и НЕ ОТПУСКАТЬ клавишу. Кид проходит сквозь решётку и
|
||||||
|
> убегает вглубь комнаты 6.
|
||||||
|
>
|
||||||
|
> Ниже — новый разбор; всё, что было раньше (гипотеза про x > 205), не
|
||||||
|
> подтвердилось и оставлено в конце для истории.
|
||||||
|
|
||||||
|
### Корень: история флагов коллизии индексируется НЕ ТАК, как в оригинале
|
||||||
|
|
||||||
|
Сняты две трассы — наша (брейкпоинт на резидентном `kid_tick`) и оригинала
|
||||||
|
(SDLPoP, собран с `POP_TRACE=1`, печать в `play_kid_frame` + маркеры в
|
||||||
|
`bumped` и `exit_room`). Стартовая позиция совпала до пикселя, поэтому
|
||||||
|
сравнение построчное.
|
||||||
|
|
||||||
|
**Оригинал:**
|
||||||
|
|
||||||
|
```
|
||||||
|
LEAVE dir=1 x=61 cxl=184 cxr=201 room=6 смена комнаты — ШТАТНАЯ
|
||||||
|
BUMPED dx=-2 push=-1 x=63 tile=4 col=9 и СРАЗУ бамп о решётку, откат
|
||||||
|
KID f=15 x=60 act=0 col=-1 room=6 drawn=6 сел за решёткой, стоит
|
||||||
|
```
|
||||||
|
|
||||||
|
**Мы:**
|
||||||
|
|
||||||
|
```
|
||||||
|
x 170 -> 196 бегом, col 7 -> 8 -> 9, НИ ОДНОГО бампа
|
||||||
|
x=198 -> room 8 -> 6
|
||||||
|
при удержании ВПРАВО доезжает до col 1 комнаты 6 и бежит дальше
|
||||||
|
```
|
||||||
|
|
||||||
|
Смена комнаты в этой точке правильна и у нас, и у оригинала: `leave_room`
|
||||||
|
(seg002:423) вправо блокируют ТОЛЬКО `doortop`-тайлы, решётки в списке нет, а
|
||||||
|
порог `char_x_right >= 201` совпадает с плоскостью ворот
|
||||||
|
(`x_bump[9+FIRST_ONSCREEN_COLUMN] + TILE_MIDX + wall_dist_from_left[1]`
|
||||||
|
= 191 + 10). Оригинал полагается не на запрет ухода, а на бамп СРАЗУ ПОСЛЕ
|
||||||
|
перехода.
|
||||||
|
|
||||||
|
**Почему бамп есть у них и нет у нас.** `check_collisions` (seg004:0004)
|
||||||
|
хранит флаги так:
|
||||||
|
|
||||||
|
```c
|
||||||
|
row_coll_flags_ptr[tile_col] = curr_flags; // индекс — колонка В РАЗРЕШЁННОЙ комнате
|
||||||
|
row_coll_room_ptr [tile_col] = curr_room; // и рядом — НОМЕР ЭТОЙ КОМНАТЫ
|
||||||
|
...
|
||||||
|
if (curr_row_coll_room[column] >= 0 &&
|
||||||
|
prev_coll_room[column] == curr_row_coll_room[column]) { /* только тогда сравниваем */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
То есть история привязана к паре **(колонка внутри своей комнаты, комната)**.
|
||||||
|
Решётка комнаты 8 и до перехода, и после лежит в слоте 9 с `room = 8` —
|
||||||
|
переход 8->6 историю НЕ рвёт, переход флага 0->1 виден, бамп срабатывает.
|
||||||
|
|
||||||
|
У нас массив `coll_prev/coll_curr` индексируется колонкой ОТНОСИТЕЛЬНО
|
||||||
|
отрисованной комнаты (−2…11). При смене комнаты все индексы уезжают на 10,
|
||||||
|
сопоставить прошлый кадр с текущим нечем, и `enter_room` вынужден звать
|
||||||
|
`pop_coll_invalidate()`; тот ставит «прошлые флаги = уже перекрывал» (3), то
|
||||||
|
есть ПОДАВЛЯЕТ бамп на кадре входа. А к следующему кадру Кид уже за
|
||||||
|
плоскостью ворот — перехода 0->1 не будет никогда.
|
||||||
|
|
||||||
|
### Что делать
|
||||||
|
|
||||||
|
Порт индексации оригинала: хранить флаги в 10 слотах ПО КОЛОНКЕ РАЗРЕШЁННОЙ
|
||||||
|
комнаты плюс параллельный массив её номера, и сравнивать prev/curr только при
|
||||||
|
совпадении номеров. Тогда `pop_coll_invalidate()` не нужен вовсе — история
|
||||||
|
сама «не совпадает» там, где колонка сменила комнату.
|
||||||
|
|
||||||
|
**Осторожно:** это сердце коллизии, вокруг которого разбирался
|
||||||
|
BUG-SEAM-PINGPONG (см. `bug_closed.md`). После правки обязателен прогон
|
||||||
|
швов: комнаты 6/8 первого уровня в обе стороны, осторожный шаг и разбег, плюс
|
||||||
|
проверка, что пинг-понг не вернулся.
|
||||||
|
|
||||||
|
**Инструмент для сверки готов:** SDLPoP собран с трассой, включается
|
||||||
|
`POP_TRACE=1` (правки в `seg000.c` play_kid_frame, `seg004.c` bumped,
|
||||||
|
`seg002.c` exit_room, чтение переменной — `main.c`). Сборка на macOS:
|
||||||
|
`make CFLAGS="-std=gnu99 -O2 -I/opt/homebrew/include -Wno-implicit-function-declaration" LIBS="-L/opt/homebrew/lib -lSDL2 -lSDL2_image"`
|
||||||
|
(в системе нет pkg-config, штатный Makefile без этого не собирается).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### История: прежний разбор (гипотеза НЕ подтвердилась)
|
||||||
|
|
||||||
**Статус: наблюдался один раз (2026-08-03), воспроизвести не удалось ни
|
**Статус: наблюдался один раз (2026-08-03), воспроизвести не удалось ни
|
||||||
тогда, ни прогоном всех комнат уровня 1 (2026-08-07).** Заведён, чтобы
|
тогда, ни прогоном всех комнат уровня 1 (2026-08-07).** Заведён, чтобы
|
||||||
|
|||||||
Reference in New Issue
Block a user