SprPoP: падение сквозь стену больше не проходит

Портировано опциональное исправление SDLPoP (fix_glide_through_wall,
seg005 в do_fall).  В ванили персонаж, падающий после разворота в беге,
может оказаться внутри кладки и лететь «в стене» — баг оригинала,
воспроизведённый пользователем в игре и затем на host-тесте.

Решением 2026-08-31 фикс взят в ТЕКУЩИЙ билд: играбельность важнее
буквальности.  Реализация вынесена отдельной функцией
glide_through_wall_guard() в pop_map.c намеренно — при разделении
VANILLA/ENHANCED это готовая точка отвязки, достаточно не звать её в
ванильном режиме.

ПРОВЕРКА.  Набор t_wall был заранее написан так, чтобы сторожить ЧИСЛО
заходов в кладку: до фикса их было ровно два из четырнадцати стартовых
позиций, после — ноль.  Остальные 15 наборов (в том числе phys с 1733
проверками и grab) остались зелёными.  Живая проверка в MAME
пользователем: корректно.

Ожидание в тесте обновлено ОСОЗНАННО, прежнее число сохранено рядом
отдельной константой с пометкой «сколько было до фикса»: оно измерено, и
понадобится, когда появится режим VANILLA — там ожидание станет зависеть
от режима.

ЦЕНА: +57 байт в банке 3 (свободно 3043), резидент и куча не изменились.
По скорости попадание только на кадры падения: пересчёт колонки — одно
деление, дистанция до кромки считается лишь если персонаж действительно
внутри кладки.

Документы: в аудите находка 21 переведена в «портировано» с сохранением
исходного разбора; в vanilla_vs_bugfixed статус фикса стал ВЗЯТ, сводка
пересчитана (5 взято, 32 кандидата в ENHANCED).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011MsUsEFAQfsjjQpJ7RtKVY
This commit is contained in:
2026-08-31 20:52:44 +03:00
parent c218e8b983
commit 4e12aa50d1
4 changed files with 68 additions and 19 deletions
+35
View File
@@ -898,6 +898,40 @@ static uint8_t check_grab_run_jump(void)
return 1;
}
/* НЕ ДАТЬ ПРОЛЕТЕТЬ СКВОЗЬ СТЕНУ В ПАДЕНИИ.
*
* Порт опционального исправления SDLPoP (fix_glide_through_wall, seg005 в
* do_fall). В ванили personаж, падающий после разворота в беге, может
* оказаться внутри кладки и лететь «в стене» — баг оригинала, известный и
* воспроизводимый; у нас он ловится host-тестом (tests/host/t_wall.c,
* набор wall_stops_jump_from_left_side).
*
* ВЗЯТО В ТЕКУЩИЙ БИЛД по решению 2026-08-31: играбельность важнее
* буквальности. При разделении VANILLA/ENHANCED эта функция — готовая
* точка отвязки: достаточно не звать её в ванильном режиме
* (docs/vanilla_vs_bugfixed.md).
*
* Условие оригинала: персонаж внутри тайла стены, либо внутри верха двери
* (в обоих вариантах) при движении ВЛЕВО. Порог 8 и сдвиг на 15 назад —
* из исправления; они выбраны так, чтобы вытолкнуть на ту же дистанцию,
* что даёт выталкивание из стены при приземлении. Горизонтальную
* скорость гасим: иначе следующий кадр внесёт персонажа обратно. */
static void glide_through_wall_guard(void)
{
uint8_t t;
int d;
determine_col();
t = get_tile_at_char();
if (t != TILE_WALL &&
!((t == TILE_DOORTOP || t == TILE_DOORTOP_FLOOR) && Char.direction < 0))
return;
d = distance_to_edge_weight();
if (d < 8) return;
Char.x = (uint8_t)char_dx_forward((int8_t)(d - 15));
Char.fall_x = 0;
}
static void do_fall(void)
{
uint8_t nrow = (uint8_t)(Char.curr_row + 1);
@@ -908,6 +942,7 @@ static void do_fall(void)
if (nrow > 4) nrow = 4; /* защита pop_y_land[] от выхода */
if ((uint16_t)pop_y_land[nrow] > (uint16_t)Char.y) {
check_grab(); /* ещё летит — попытка зацепа */
glide_through_wall_guard(); /* и не сквозь кладку (см. выше) */
} else if (Char.curr_row <= 2) {
if (get_tile_at_char() == TILE_WALL)
in_wall();