L1: фиксы прогона уровня 1 — уровень мутабелен, стражи, loose-плиты, порядок
Одиннадцать наблюдений первого прогона свелись к шести корням, четыре
наблюдения второго — ещё к четырём. Разбор каждого — bug_closed.md.
Первая волна:
- BUG-LVLSTATE-1: уровень стал мутабельным (эталонная копия foretable для
рестарта, pop_level_set_tile вместо таблицы оверрайдов);
- BUG-RESPAWN-1: рестарт = load_level, тайлы возвращаются из эталона;
- BUG-DEATH-1: смерть от меча доигрывается (порт control_kid, seg006:0CD1);
- BUG-GATE-ANIM-1: ворота в отрисованной комнате перерисовываются
(POP_RD_GATE, порт draw_trob seg007:01E6);
- BUG-COLL-1: полный порт check_collisions/bumped (seg004) вместо поиска
стены только в колонке переднего края;
- BUG-STANDUP-1: убран лишний guard в bumped_floor — вставание у стены
роняло Кида сквозь пол.
Вторая волна:
- BUG-RESPAWN-2: рестарт возвращает и СТРАЖЕЙ (в оригинале play_level на
каждой итерации делает load_level + pos_guards);
- BUG-LOOSE-2: падающий кусок привязан к своей комнате и долетает после
ухода Кида (do_mobs крутит mobs[] независимо от drawn_room);
- BUG-DRAWORDER-1: порядок «Кид / страж» задаётся обходом тайлов
(redraw_needed_tiles: ряды 2,1,0, колонки 0..9), а не ролью персонажа.
По BUG-DRAWORDER-1 понадобилось три захода, и два первых были неполны:
1) сам порядок — но общее окно fore-клипа осталось стражьим, и Кид
нарисовался поверх передних столбов (kid_fore_clip_restore);
2) enter_guard брал curr_col из тайла, а leave_guard пишет туда
get_tilepos(0,row) — у запомненного ТРУПА колонка была 0 при
настоящей X. Теперь колонка выводится из X, как в оригинале;
3) ветка actions_1_run_jump в set_objtile_at_char оказалась не
«упрощаемой»: в беге тайл берётся из нижнего ряда и ЛЕВОЙ колонки
габарита, поэтому бегущий Кид уходит за объекты справа. Считается
для обоих персонажей — enter_guard ставит action=1 и стражу.
Проверено в MAME: зелья/меч/плиты переживают выход из комнаты и
восстанавливаются после смерти; кнопка room5 поднимает решётку; падение с
кнопки больше не роняет в комнату 6; убитый страж жив после respawn;
Кид проходит за телом стража. make size-check — роста нет.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,30 +1,169 @@
|
||||
# roomtest — ОТКРЫТЫЕ баги и незакрытые оптимизации
|
||||
|
||||
Только то, что **не закрыто**. Всё закрытое (и, что важнее, разбор корней —
|
||||
odd-pixel арифметика `char_x`, подстановка тайла нажатой кнопки, баг
|
||||
кодогенератора SDCC) переехало в [`bug_closed.md`](bug_closed.md): прежде чем
|
||||
заводить новый баг, грепни там по симптому.
|
||||
Только то, что **не закрыто**. Всё закрытое (и, что важнее, разбор корней)
|
||||
переехало в [`bug_closed.md`](bug_closed.md): прежде чем заводить новый баг,
|
||||
грепни там по симптому.
|
||||
|
||||
Приоритеты работ — в [`TASKS.md`](TASKS.md), а не здесь. Правило проекта:
|
||||
механику сверять с `../SDLPoP/src/` ДО кодинга.
|
||||
|
||||
Ревизия списка: **2026-08-01** (задача L1-TRIAGE). Закрыты и перенесены в
|
||||
архив семь записей: BUG-1, BUG-2, BUG-3 (стояли как Critical с 2026-07-21,
|
||||
прогнаны в MAME) и вся косметика окклюзии BUG-CEIL-1/2/3, BUG-OCCL-1 (была
|
||||
починена кодом ещё в июле, список просто отстал — чем именно закрыта каждая,
|
||||
расписано в [`bug_closed.md`](bug_closed.md)).
|
||||
Ревизия списка: **2026-08-03** (прогон всех комнат уровня 1). Одиннадцать
|
||||
наблюдений с прогона свелись к шести корням; **все шесть закрыты и проверены
|
||||
в MAME** — разбор в [`bug_closed.md`](bug_closed.md): BUG-LVLSTATE-1 (уровень
|
||||
стал мутабельным), BUG-RESPAWN-1 (респавн перезагружает уровень),
|
||||
BUG-DEATH-1 (смерть от меча), BUG-GATE-ANIM-1 (анимация ворот), BUG-COLL-1
|
||||
(полный порт `check_collisions`), BUG-STANDUP-1 (лишний guard в
|
||||
`bumped_floor`). Клавиатурный BUG-KBD-3 доведён до конца во второй волне
|
||||
(см. ниже); из первой волны открытым остался косметический BUG-SEAM-DRAW-1.
|
||||
|
||||
**Открытых багов нет.** Осталось только незакрытое по оптимизации и
|
||||
незаконченная ревизия комнат:
|
||||
Ревизия **2026-08-03, вечер** (вторая волна с прогона): четыре наблюдения →
|
||||
BUG-KBD-4 (фантомный отжим Shift) и BUG-RESPAWN-2 (стражи не оживают) —
|
||||
**закрыты и проверены в MAME**; BUG-DRAWORDER-1 (Кид поверх тела стража) и
|
||||
BUG-LOOSE-2 (осколки только от одной из двух плит) — **исправлены по SDLPoP,
|
||||
но их сценарии автоматикой не воспроизведены** (см. таблицу ниже).
|
||||
|
||||
| ID | что | тип |
|
||||
|----|-----|-----|
|
||||
| [T-1](#t-1) | пики перерисовываются безусловно | оптимизация |
|
||||
| [T-2](#t-2) | Кид перерисовывается в покое | оптимизация |
|
||||
| [обход 24 комнат](#обход-всех-24-комнат-уровня-1) | таблица заполнена на 5 строк из 24 | ревизия |
|
||||
| ID | что | тип | статус |
|
||||
|----|-----|-----|--------|
|
||||
| [BUG-DRAWORDER-1](#bug-draworder-1) | Кид рисуется поверх тела стража (в оригинале — за телом) | Minor | фикс есть, **сценарий не проверен** |
|
||||
| [BUG-LOOSE-2](#bug-loose-2) | осколки только от одной из двух падающих плит (комната 12) | Minor | фикс есть, **гонка не воспроизведена** |
|
||||
| [BUG-SEAM-DRAW-1](#bug-seam-draw-1) | у решётки на шве экран переключается, а Кид в шве НЕ рисуется | Minor | открыт |
|
||||
| [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт |
|
||||
| [T-2](#t-2) | Кид перерисовывается в покое | оптимизация | открыт |
|
||||
| [обход 24 комнат](#обход-всех-24-комнат-уровня-1) | таблица заполнена на 5 строк из 24 | ревизия | открыт |
|
||||
|
||||
---
|
||||
|
||||
<a id="ручная-перепроверка-2026-08-03"></a>
|
||||
# Ручная перепроверка фиксов (2026-08-03)
|
||||
|
||||
Шесть корней закрыты автоматической проверкой в MAME (мост `mame-z80`:
|
||||
чтение `_Kid`, потиковые трассы, скриншоты) — этого достаточно, чтобы
|
||||
показать, что конкретный сценарий больше не воспроизводится, но НЕ
|
||||
достаточно, чтобы поймать регрессии в соседней механике. Ниже — сценарии
|
||||
ровно в тех формулировках, в которых баги были заведены.
|
||||
|
||||
Собрано и лежит в образе (`make` + `make hdd` уже прогнаны; libc пересобран,
|
||||
`make size-check` без роста).
|
||||
|
||||
| # | что проверить | ожидаемо |
|
||||
|---|---------------|----------|
|
||||
| 1 | комната 22: выпить зелье (0,6), выйти в 16/23 и вернуться | кувшина нет, пузырька над пустым местом нет |
|
||||
| 2 | то же для комнат 14 (0,5) и 17 (2,3) | так же |
|
||||
| 3 | комната 15: подобрать меч (2,2), выйти и вернуться | меча нет; кладка на дальней стене НЕ мигает |
|
||||
| 4 | комната 12: разбить плиты (0,1)/(0,2) и потолок в 16, выйти-вернуться | остаются разбитыми, проём не закрывается |
|
||||
| 5 | комната 17 из 23: разбить (1,5)/(1,6), выпить зелье (2,3), вернуться | всё остаётся |
|
||||
| 6 | **после смерти** зайти в те же комнаты | ВСЁ восстановлено (в оригинале смерть = `load_level`) |
|
||||
| 7 | комната 12: разбег в закрытую решётку (0,9) с полушага | не проходит насквозь; экран может перелистнуться — это [BUG-SEAM-DRAW-1](#bug-seam-draw-1) |
|
||||
| 8 | комната 6: бег справа налево от (0,9), длинный прыжок (0,6)→(0,7) | не влетает внутрь стены |
|
||||
| 9 | комната 5: с кнопки (0,6) падение на (2,7), присед, вставание | остаётся в комнате 5 (проверено трассой: `fr=111 x=177` → `seq_47` → `fr=15 x=173`) |
|
||||
| 10 | комната 5: нажать кнопку (0,4) | поднимаются ОБЕ решётки — (0,5) видно на экране, (0,9) проверять из комнаты 1 |
|
||||
| 11 | страж (комнаты 3, 21) убивает Кида | смерть доигрывается, респавн в стартовой позиции уровня; цикла «убил-воскрес» нет |
|
||||
| 12 | клавиатура: долгая игра с Shift+стрелка | ↑ и Shift не залипают; осторожный шаг не превращается в бег (доработано во второй волне — п.17) |
|
||||
|
||||
## Вторая волна (2026-08-03, вечер)
|
||||
|
||||
| # | что проверить | ожидаемо |
|
||||
|---|---------------|----------|
|
||||
| 13 | **[BUG-DRAWORDER-1]** убить стража там, где через тело можно пройти С ЛЕВОЙ стороны (не у самой кромки), и провести Кида сквозь тело | Кид проходит ЗА телом, когда его тайл в обходе РАНЬШЕ (левее по колонке или ниже по ряду), и поверх — когда позже |
|
||||
| 14 | **[BUG-LOOSE-2]** комната 12: разбежаться по плитам (0,1)/(0,2) и уйти в 15 ДО того, как долетит вторая; вернуться | осколки на ОБОИХ — (1,1) и (1,2) |
|
||||
| 15 | то же в комнате 7 (плиты 0,5/0,6 → 2,5/2,6) | не сломалось: по-прежнему двое осколков |
|
||||
| 16 | плита, улетевшая из комнаты вниз, при возврате | лишнего щебня не появилось |
|
||||
| 17 | **[BUG-KBD-4]** долго играть Shift+стрелка, много тапов подряд | Shift не «отваливается»; если однажды залипнет — снимается первым же нажатием стрелки |
|
||||
| 18 | **[BUG-RESPAWN-2]** убить стража (комнаты 3/21), умереть, вернуться в ту же комнату | страж снова жив, стоит на исходном тайле, HP полные |
|
||||
|
||||
Отдельно стоит посмотреть **на регрессии от порта `check_collisions`** — он
|
||||
трогает всю горизонтальную коллизию: бамп в стену на бегу и в прыжке,
|
||||
осторожный шаг у стены, проход через ОТКРЫТЫЕ ворота, разворот в проёме
|
||||
решётки, переходы через швы (старый BUG-SEAM-PINGPONG).
|
||||
|
||||
---
|
||||
|
||||
# Открытые баги уровня 1
|
||||
|
||||
<a id="bug-draworder-1"></a>
|
||||
## BUG-DRAWORDER-1. Кид рисуется поверх тела стража
|
||||
|
||||
**Симптом.** В оригинале Кид проходит ЗА телом убитого стража; у нас — перед
|
||||
ним.
|
||||
|
||||
**Корень.** Мы рисовали безусловно `pop_guard_draw()` → `kid_draw()`, то есть
|
||||
Кид всегда сверху. В оригинале «кто поверх» никем не назначается: и Кид, и
|
||||
страж кладутся в midtable при обработке СВОЕГО тайла
|
||||
(`set_objtile_at_char`, seg006:13F3), а тайлы обходятся строго —
|
||||
`redraw_needed_tiles` (seg008:1B06) идёт рядами 2,1,0 и внутри ряда
|
||||
колонками 0..9. Нарисованный позже оказывается сверху. Если тайлы совпали,
|
||||
решает `sort_curr_objs` (seg008:203C): у обычных объектов (не тень, не плита)
|
||||
ниже по `obj_y` — значит позже.
|
||||
|
||||
**Фикс** (`roomtest.c`): `guard_over_kid()` считает ключ обхода
|
||||
`(2 - row) * 10 + col` для обоих персонажей (с поправкой
|
||||
`set_objtile_at_char` на лазание/полёт/вис — колонка левее), сравнивает, при
|
||||
равенстве сравнивает `obj_y`, и порядок вызова `pop_guard_draw`/`kid_draw`
|
||||
выбирается по результату.
|
||||
|
||||
**Известное упрощение.** Ветку `actions_1_run_jump` (там оригинал берёт
|
||||
нижний ряд и левую колонку ГАБАРИТА, а не `curr_row`/`curr_col`) не
|
||||
воспроизводим: она требует полного футпринта, а влияет только когда
|
||||
прыгающий Кид делит тайл со стражем — там порядок всё равно разводит `obj_y`.
|
||||
|
||||
**Не проверено.** Сценарий не воспроизведён: в комнате 21 страж падает у
|
||||
самой левой кромки (col 0), слева от тела встать нельзя, а «Кид поверх» при
|
||||
Кид.col=1 > страж.col=0 — это как раз ПРАВИЛЬНЫЙ порядок и бага не
|
||||
показывает. Нужен ручной прогон, п.13 таблицы выше.
|
||||
|
||||
<a id="bug-loose-2"></a>
|
||||
## BUG-LOOSE-2. Осколки только от одной из двух падающих плит
|
||||
|
||||
**Симптом.** Комната 12, соседние падающие плиты (0,1) и (0,2): после
|
||||
пробежки осколки появляются только на (1,2), на (1,1) — нет. В комнате 7
|
||||
(плиты 0,5/0,6 → 2,5/2,6) обе дают осколки.
|
||||
|
||||
**Корень** (гипотеза автора отчёта подтвердилась чтением кода). Наш
|
||||
падающий кусок был привязан к ТЕКУЩЕЙ комнате: `pop_loose_reset()` на смене
|
||||
комнаты звал `pop_loose_mob_reset()` и гасил всё, что ещё летит, а тайл под
|
||||
куском читался из карты отрисованной комнаты. Кид убегает в комнату 15
|
||||
раньше, чем долетает плита (0,1) — кусок уничтожается, `loose_land` не
|
||||
случается, щебень не кладётся. В комнате 7 обе плиты успевают сесть до
|
||||
ухода, поэтому там всё выглядело правильно.
|
||||
|
||||
В оригинале `mobs[]` чистится ТОЛЬКО в `start_level` (seg003:88), `do_mobs`
|
||||
(seg007:1063) прокручивает все куски независимо от `drawn_room`, `move_loose`
|
||||
работает по `curmob.room`, а `redraw_at_cur_mob` (seg007:132C) сверяется с
|
||||
`drawn_room` лишь для ОТРИСОВКИ.
|
||||
|
||||
**Фикс.** У куска появилось поле `room` (`curmob.room`); на смене комнаты
|
||||
зовётся `pop_loose_mob_room_changed()` — сбрасывает только heal-историю;
|
||||
тайл читается через `mob_tile_at()` (своя комната — `tile_code`, чужая —
|
||||
`pop_level_tile`); приземление в покинутой комнате пишет щебень прямо в
|
||||
данные уровня; отрисовка и `check_loose_fall_on_kid` (там оригинал начинает с
|
||||
`Char.room == curmob.room`) — только для своей комнаты. Настоящий
|
||||
`mobs_count = 0` переехал в `pop_start_level`.
|
||||
|
||||
**Не проверено.** Гонка «уйти из комнаты раньше, чем долетит плита»
|
||||
автоматикой не воспроизведена. Ручной прогон — пп. 14–16 таблицы выше.
|
||||
|
||||
<a id="bug-seam-draw-1"></a>
|
||||
## BUG-SEAM-DRAW-1. Кид, упершийся в решётку на шве, не рисуется
|
||||
|
||||
**Симптом.** Комната 5: Кид добегает до закрытой решётки (0,9), решётка его
|
||||
ДЕРЖИТ (проверено: x встаёт на 60 и дальше не растёт), но экран
|
||||
переключается на комнату 1, и в ней Кид не виден — он стоит на `x = 57..60`,
|
||||
левее кромки комнаты (col 0 начинается с 58).
|
||||
|
||||
**Разбор.** Переключение экрана само по себе штатное: `leave_room`
|
||||
(seg002:423) уводит вправо при `char_x_right >= 201`, а левая грань решётки
|
||||
как раз 201 — то есть в оригинале экран тоже перелистнётся, если персонаж
|
||||
встанет ровно на грань. Не штатно то, что персонажа в шве **не рисуют**:
|
||||
`update_kid_render_dx` даёт смещение только когда `kid_room != cur_room`, а
|
||||
`enter_room` сразу выравнивает `kid_room = cur_room`. Это остаток
|
||||
непортированной модели straddle (S3 в `pop_kid_plan`).
|
||||
|
||||
**Что делать.** Довести S3: держать `Kid.room` отдельно от `drawn_room` и
|
||||
рисовать персонажа со смещением ±140, как `xpos_in_drawn_room` (seg004:0405).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Оптимизация отрисовки (записано 2026-07-29)
|
||||
|
||||
@@ -139,3 +278,26 @@ Kid ставится на первый пол, `pop_trob_reset()` возвращ
|
||||
- **ROOMNAV (`=`/`-`) — тоже наш чит**, которого в оригинале не было, как и
|
||||
`S`. Все они со временем съедутся в общий блок читов, разрешаемый в
|
||||
настройках; пока просто включены (`pop_cheats = 1` в `roomtest.c`).
|
||||
|
||||
|
||||
---
|
||||
|
||||
<a id="сырые-наблюдения-прогон-2026-08-03"></a>
|
||||
## Сырые наблюдения (прогон 2026-08-03) → корень
|
||||
|
||||
Формулировки с прогона, как записаны. Закрытые корни — в
|
||||
[`bug_closed.md`](bug_closed.md).
|
||||
|
||||
| # | наблюдение (кратко) | корень | статус |
|
||||
|---|---------------------|--------|--------|
|
||||
| 1 | кувшин выпит, а пузырёк рисуется / кувшин возвращается (14, 22, 17) | BUG-LVLSTATE-1 | закрыт |
|
||||
| 2 | меч возвращается в 15 / мигает контур кладки | BUG-LVLSTATE-1 | закрыт |
|
||||
| 3 | комната 12: пробегает сквозь закрытую решётку (0,9) | BUG-COLL-1 | закрыт |
|
||||
| 4 | после respawn плиты остаются разбитыми, зелья выпитыми | BUG-RESPAWN-1 | закрыт |
|
||||
| 5 | плита/зелье возвращаются и БЕЗ respawn (12→16, 17, 22) | BUG-LVLSTATE-1 | закрыт |
|
||||
| 6 | комната 6: длинный прыжок (0,6)→(0,7) — влёт в стену, респавн | BUG-COLL-1 | закрыт |
|
||||
| 7 | залипает ↑ | BUG-KBD-3 | закрыт (см. `bug_closed.md`) |
|
||||
| 8 | залипает Shift | BUG-KBD-3 / BUG-KBD-4 | закрыт (см. `bug_closed.md`) |
|
||||
| 9 | комната 5: кнопка (0,4) не открывает решётку (0,5) | BUG-GATE-ANIM-1 | закрыт |
|
||||
| 10 | комната 5: с кнопки (0,6) на (2,7), присед — провал в комнату 6 | BUG-STANDUP-1 | закрыт |
|
||||
| 11 | страж убил Кида → Кид воскресает на месте и его убивают снова | BUG-DEATH-1 | закрыт |
|
||||
|
||||
Reference in New Issue
Block a user