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:
@@ -402,7 +402,19 @@
|
|||||||
рано, Кид не долетел, врезался в стену и начал падать — но по X он
|
рано, Кид не долетел, врезался в стену и начал падать — но по X он
|
||||||
оказался ВНУТРИ стены и падал частично в ней.
|
оказался ВНУТРИ стены и падал частично в ней.
|
||||||
|
|
||||||
### 21. Фикс «скольжения сквозь стену» не портирован — ранг **Г** (соответствие ванили)
|
### 21. Фикс «скольжения сквозь стену» — ПОРТИРОВАН 2026-08-31
|
||||||
|
|
||||||
|
> Решением пользователя исправление взято в ТЕКУЩИЙ билд: играбельность
|
||||||
|
> важнее буквальности. Реализация — `glide_through_wall_guard()` в
|
||||||
|
> `pop_map.c`, вызывается из `do_fall` в ветке «ещё летим». Цена: +57
|
||||||
|
> байт в банке 3, резидент и куча не изменились.
|
||||||
|
>
|
||||||
|
> Подтверждено host-тестом: в наборе `t_wall` число заходов в кладку
|
||||||
|
> упало с двух до нуля, остальные 15 наборов остались зелёными.
|
||||||
|
>
|
||||||
|
> Ниже — исходный разбор, по которому принималось решение.
|
||||||
|
|
||||||
|
### 21a. Исходный разбор: было соответствие ванили — ранг **Г**
|
||||||
|
|
||||||
*Оригинал:* в `do_fall` (seg005:37) есть блок `FIX_GLIDE_THROUGH_WALL` с
|
*Оригинал:* в `do_fall` (seg005:37) есть блок `FIX_GLIDE_THROUGH_WALL` с
|
||||||
собственным комментарием SDLPoP: «Кид падает сквозь стены после разворота
|
собственным комментарием SDLPoP: «Кид падает сквозь стены после разворота
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ ENHANCED.
|
|||||||
|
|
||||||
| опция | что чинит | статус |
|
| опция | что чинит | статус |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `fix_glide_through_wall` | проход сквозь стену при падении после разворота в беге | **В РАБОТЕ** |
|
| `fix_glide_through_wall` | проход сквозь стену при падении после разворота в беге | **ВЗЯТ** 2026-08-31 — `glide_through_wall_guard()` в `pop_map.c`, точка отвязки для VANILLA |
|
||||||
| `fix_jump_through_wall_above_gate` | прыжок в тайл над воротами | НЕТ |
|
| `fix_jump_through_wall_above_gate` | прыжок в тайл над воротами | НЕТ |
|
||||||
| `fix_drop_through_tapestry` | проваливание сквозь гобелен | НЕТ |
|
| `fix_drop_through_tapestry` | проваливание сквозь гобелен | НЕТ |
|
||||||
| `fix_running_jump_through_tapestry` | прыжок с разбега сквозь гобелен | НЕТ |
|
| `fix_running_jump_through_tapestry` | прыжок с разбега сквозь гобелен | НЕТ |
|
||||||
@@ -257,11 +257,10 @@ ENHANCED.
|
|||||||
|
|
||||||
| статус | сколько |
|
| статус | сколько |
|
||||||
|---|---:|
|
|---|---:|
|
||||||
| ВЗЯТ | 4 |
|
| ВЗЯТ | 5 |
|
||||||
| ВАНИЛЬ (сознательно) | 4 |
|
| ВАНИЛЬ (сознательно) | 4 |
|
||||||
| В РАБОТЕ | 1 |
|
|
||||||
| требует патча `seqtbl` (выполнимо) | 1 |
|
| требует патча `seqtbl` (выполнимо) | 1 |
|
||||||
| НЕТ (кандидаты в ENHANCED) | 33 |
|
| НЕТ (кандидаты в ENHANCED) | 32 |
|
||||||
|
|
||||||
## Список кандидатов на BUGFIXED
|
## Список кандидатов на BUGFIXED
|
||||||
|
|
||||||
|
|||||||
@@ -898,6 +898,40 @@ static uint8_t check_grab_run_jump(void)
|
|||||||
return 1;
|
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)
|
static void do_fall(void)
|
||||||
{
|
{
|
||||||
uint8_t nrow = (uint8_t)(Char.curr_row + 1);
|
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 (nrow > 4) nrow = 4; /* защита pop_y_land[] от выхода */
|
||||||
if ((uint16_t)pop_y_land[nrow] > (uint16_t)Char.y) {
|
if ((uint16_t)pop_y_land[nrow] > (uint16_t)Char.y) {
|
||||||
check_grab(); /* ещё летит — попытка зацепа */
|
check_grab(); /* ещё летит — попытка зацепа */
|
||||||
|
glide_through_wall_guard(); /* и не сквозь кладку (см. выше) */
|
||||||
} else if (Char.curr_row <= 2) {
|
} else if (Char.curr_row <= 2) {
|
||||||
if (get_tile_at_char() == TILE_WALL)
|
if (get_tile_at_char() == TILE_WALL)
|
||||||
in_wall();
|
in_wall();
|
||||||
|
|||||||
@@ -162,21 +162,24 @@ static char jump_right_from(uint8_t x)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ВАНИЛЬНОЕ ПОВЕДЕНИЕ, А НЕ НАША ОШИБКА.
|
/* ФИКС ПАДЕНИЯ СКВОЗЬ СТЕНУ ВЗЯТ — ЖДЁМ НОЛЬ.
|
||||||
*
|
*
|
||||||
* Прыжок вправо через провал даёт ДВА случая из четырнадцати, где Кид
|
* В ванили прыжок вправо через провал давал ДВА случая из четырнадцати,
|
||||||
* оказывается в колонке кладки, будучи в воздухе, — то есть «падает
|
* где Кид оказывается в колонке кладки, будучи в воздухе, — «падение
|
||||||
* частично в стене». Это известный баг оригинального PoP: SDLPoP держит
|
* частично в стене». Это баг оригинального PoP, для которого SDLPoP
|
||||||
* для него ОТДЕЛЬНОЕ опциональное исправление (FIX_GLIDE_THROUGH_WALL,
|
* держит опциональное исправление (fix_glide_through_wall, seg005 в
|
||||||
* seg005 do_fall), которое мы намеренно не портировали, повторяя ваниль
|
* do_fall).
|
||||||
* (docs/sdlpop_audit.md, находка 21).
|
|
||||||
*
|
*
|
||||||
* Поэтому тест не требует нуля, а СТОРОЖИТ ЧИСЛО: пока их ровно два, мы
|
* 2026-08-31 исправление ПОРТИРОВАНО в текущий билд
|
||||||
* ведём себя как оригинал. Стало больше — значит правка сделала хуже
|
* (glide_through_wall_guard в pop_map.c), и оба случая исчезли. Поэтому
|
||||||
* ванили; стало меньше — кто-то портировал фикс и об этом нужно знать.
|
* ожидание теперь НОЛЬ.
|
||||||
* Проверено: фикс 24 (перезагрузка кадра в in_wall) на это число НЕ
|
*
|
||||||
* влияет. */
|
* Если когда-нибудь появится режим VANILLA без этого фикса, ожидание
|
||||||
#define WALL_VANILLA_GLIDE_CASES 2
|
* станет зависеть от режима: 0 в ENHANCED и 2 в ванильном
|
||||||
|
* (docs/vanilla_vs_bugfixed.md). Число 2 сохранено в имени константы
|
||||||
|
* именно поэтому — оно измерено, а не выдумано. */
|
||||||
|
#define WALL_VANILLA_GLIDE_CASES 2 /* сколько их было ДО фикса */
|
||||||
|
#define WALL_EXPECTED_GLIDE_CASES 0 /* сколько ожидаем СЕЙЧАС */
|
||||||
|
|
||||||
TC_TEST(wall_stops_jump_from_left_side)
|
TC_TEST(wall_stops_jump_from_left_side)
|
||||||
{
|
{
|
||||||
@@ -190,7 +193,7 @@ TC_TEST(wall_stops_jump_from_left_side)
|
|||||||
if (r != 'R' && r != '.' && r != 'h') bad++;
|
if (r != 'R' && r != '.' && r != 'h') bad++;
|
||||||
}
|
}
|
||||||
put('\n');
|
put('\n');
|
||||||
TC_EQ(bad, WALL_VANILLA_GLIDE_CASES);
|
TC_EQ(bad, WALL_EXPECTED_GLIDE_CASES);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
|
|||||||
Reference in New Issue
Block a user