Files
Sprinter-SDCC/applications/PoP/docs/room_model_plan.md
T
snark13 5348feb5f4 Доски приведены в соответствие с кодом; bug_list/bug_closed → BUGS_OPEN/BUGS_CLOSED
Доска отставала от кода на три задачи — планировать по ней было нельзя.
Сверка проведена грепом по исходникам, а не по записям:

- 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>
2026-08-11 16:10:10 +03:00

87 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PoP roomtest — модель `kid_room ≠ drawn_room` (баг #4)
> **Статус: ЖИВОЙ ПЛАН, сделан частично (сверено 2026-08-01).**
> - **S1 — сделан:** `kid_room` заведён отдельно от `cur_room`,
> `update_kid_render_dx()` (`roomtest.c`) даёт рендер-смещение ∓140, а
> `pop_kid_set_render_dx` применяет его в отрисовке. Фактически это пока
> каркас: `enter_room` держит `kid_room == cur_room`, так что смещение
> всегда 0.
> - **S2/S3/S4 — не сделаны и не срочны.** Исходный повод (баг #4,
> пинг-понг у шва) закрыт иначе — поправкой odd-pixel в
> `char_x_forward_edge` + `pop_leave_timer` (разбор корня —
> `../roomtest/BUGS_CLOSED.md`, BUG-SEAM-PINGPONG).
>
> **Зачем документ остаётся.** Полная straddle-модель понадобится для:
> (а) читов осмотра соседних комнат `H/J/U/N` (`levels_plan.md` §4),
> (б) сцен, где Кид и страж в разных комнатах кадра, (в) остатков окклюзии у
> шва (S4). Брать из `../roomtest/TASKS_OPEN.md`, когда дойдёт очередь.
Порт straddle-модели SDLPoP: персонаж может находиться в СОСЕДНЕЙ комнате,
пока на экране ещё ТЕКУЩАЯ (drawn_room). Источник истины — SDLPoP.
## Факты из SDLPoP (подтверждено чтением исходника)
- `Char.room` (реальная комната персонажа) ≠ `drawn_room` (отрисованная) —
штатное состояние.
- **Коллизия через ±140:** `xpos_in_drawn_room()` (seg004:0405) сдвигает
xpos на `±TILE_SIZEX*SCREEN_TILECOUNTX = ±140`, когда `curr_room` колонки
(`curr_row_coll_room[col]`) ≠ `drawn_room` (room_L/room_BL → 140,
room_R/room_BR → +140). Т.е. коллизия строится по РЕАЛЬНЫМ тайлам соседей.
- **Смена экрана:** `check_the_end()` (seg000:0FBD): `if (next_room!=0 &&
next_room!=drawn_room) { drawn_room=next_room; load_room_links; redraw }`.
`next_room` ставится в `exit_room()` (= `Char.room` ПОСЛЕ успешного
`leave_room`). Значит drawn_room следует за Char.room, но Char.room меняется
ТОЛЬКО при реальном пересечении шва (leave_room, seg002:0504) на «легальном»
кадре/действии (не turn/climb/standup).
- **Отрисовка левого соседа:** только `load_leftroom()` (col9 левого соседа в
левую кромку); правый сосед НЕ рисуется (изометрия). Окклюзия ворот на шве —
только левая (seg008:696).
- **Ceiling-полоса:** `draw_room` рисует доп. ряд из `room_A` (row2, draw_main_y
=-1). (Уже реализовано, баг #3.)
## Текущее состояние нашего движка (до #4)
`cur_room` (=drawn_room) ВСЕГДА == комната Kid. Шов подделан: Kid остаётся в
drawn_room с `curr_col=-1/10` + снапшоты соседей `g_lcol/g_rcol` (коллизия ±1
кол) / `lcol_bg` (openness ворот). Уход из комнаты — `pop_leave_dir`/`enter_room`
МГНОВЕННО при пересечении порога `char_x`. Отсюда #4: экран переключается
раньше, чем в оригинале (Kid должен «отступить» за кромку, оставив старую
комнату).
## План (инкременты, каждый проверяется в MAME)
### S1. Данные + рендер-смещение Kid
- Ввести `kid_room` (реальная комната Kid) отдельно от `cur_room`(=drawn_room).
- `kid_x_offset()` = разница комнат: kid_room == left(drawn) → лог. x Kid 140
(рисуется за левой кромкой); right → +140; равны → 0. (порт
xpos_in_drawn_room).
- `kid_draw`/heal/fore используют смещение (Kid рисуется частично за кромкой).
- Проверка: Kid у шва рисуется со сдвигом, экран не дёргается.
### S2. Коллизия по kid_room
- Коллизионный контекст (`g_fg`/edges/`g_room`/modif в pop_map) следует за
`kid_room`, а не за drawn_room. Когда kid_room≠drawn_room — грузим
соседа как коллизионную комнату (curr_col 0..9 в кадре kid_room).
- Отрисовка (room_fg и т.п.) остаётся по drawn_room.
- Порт `curr_row_coll_room[]`/`xpos_in_drawn_room` можно упростить: держим
ОДИН коллизионный room (kid_room) + существующие снапшоты кромок для ±1 кол.
### S3. Отложенная смена drawn_room
- Уход (`check_leave`/`check_leave_below`): ставит `kid_room=сосед`,
репроецирует Kid (x∓140, col∓10) — но drawn_room НЕ меняет сразу.
- `check_the_end`-эквивалент в главном цикле: `if (kid_room != drawn_room &&
<условие коммита>) enter_room(kid_room)`. Условие коммита — по SDLPoP:
как только Char.room сменилась легальным leave (не bumped/turn). Для
«bumped назад за кромку» drawn_room остаётся (симптом #4).
- Проверка сценариев #4/#5 в MAME.
### S4. Полировка
- Окклюзия/ceiling у шва при straddle, BUG-OCCL-1 (глубина), правый край.
## Связанные баги — все ЗАКРЫТЫ (`../roomtest/BUGS_CLOSED.md`)
BUG-CEIL-1 (руки при прыжке вверх), BUG-CEIL-2 (loose в потолке),
BUG-CEIL-3 (потолок над анимируемыми воротами), BUG-OCCL-1 (тень дальней
колонны) — починены без полной straddle-модели. То есть S4 «полировка
окклюзии» осталась актуальной только для окклюзии У ШВА при straddle.
Memory: `pop_seam_room_model`.