PoP roomtest: подъём/спуск на ОТКРЫТЫХ воротах (потерянная проверка openness)

Kid не мог залезть на тайл поднятой решётки: срывался обратно.  can_climb_up
(seg005:09DF) выбирает seq_73 («влез под решётку и съехал») только для
ЗАКРЫТЫХ ворот — условие включает curr_room_modif[curr_tilepos] >> 2 < 6, а у
нас его не было, и seq_73 играл при любой решётке над головой при взгляде
влево.

Та же дыра нашлась в спуске: down_pressed (seg005:482) запрещает climb-down с
тайла ворот лицом влево тоже ТОЛЬКО пока они закрыты
(|| curr_room_modif[curr_tilepos] >> 2 >= 6).  Без этого Kid приседал вместо
спуска даже под поднятой решёткой.

Openness обеих проверок берётся общим хелпером gate_modif(col,row) (вынесен из
gate_passable — умеет свою комнату и соседнюю через шов).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 10:59:30 +03:00
parent 5e09bd9d5a
commit b106aba59b
+25 -10
View File
@@ -204,14 +204,21 @@ static uint8_t get_tile(int8_t col, int8_t row)
* g_link_r col0; ВНУТРИ комнаты (0..9) — текущая комната g_room (иначе после * g_link_r col0; ВНУТРИ комнаты (0..9) — текущая комната g_room (иначе после
* перехода Kid встаёт на ту же створку уже как на внутрикомнатную и его отбивает * перехода Kid встаёт на ту же створку уже как на внутрикомнатную и его отбивает
* обратно). Открыто ⇔ (modif>>2)+6 >= char_height (бары выше головы). */ * обратно). Открыто ⇔ (modif>>2)+6 >= char_height (бары выше головы). */
/* Живой модификатор (openness) ворот в (col,row): своя комната или соседняя
* через шов. 0xFF — тайла нет (за краем уровня). */
static uint8_t gate_modif(int8_t col, int8_t row)
{
if (row < 0 || row > 2) return 0xFF;
if (col == -1 && g_link_l) return pop_trob_modif(g_link_l)[row * 10 + 9];
if (col == 10 && g_link_r) return pop_trob_modif(g_link_r)[row * 10 + 0];
if (col >= 0 && col <= 9) return pop_trob_modif(g_room)[row * 10 + col];
return 0xFF;
}
static uint8_t gate_passable(int8_t col, int8_t row) static uint8_t gate_passable(int8_t col, int8_t row)
{ {
uint8_t gm; uint8_t gm = gate_modif(col, row);
if (row < 0 || row > 2) return 0; if (gm == 0xFF) return 0;
if (col == -1 && g_link_l) gm = pop_trob_modif(g_link_l)[row * 10 + 9];
else if (col == 10 && g_link_r) gm = pop_trob_modif(g_link_r)[row * 10 + 0];
else if (col >= 0 && col <= 9) gm = pop_trob_modif(g_room)[row * 10 + col];
else return 0;
return (uint8_t)((gm >> 2) + 6) >= (uint8_t)kid_fp_height(); return (uint8_t)((gm >> 2) + 6) >= (uint8_t)kid_fp_height();
} }
@@ -656,13 +663,18 @@ int pop_wall_ahead(void)
/* grab_timer истёк — можно подтягиваться? */ /* grab_timer истёк — можно подтягиваться? */
uint8_t pop_hang_grab_ready(void) { return grab_timer == 0; } uint8_t pop_hang_grab_ready(void) { return grab_timer == 0; }
/* can_climb_up: тайл над персонажем — обычный подъём (seq_10) либо подъём /* can_climb_up (seg005:09DF): тайл над персонажем — обычный подъём (seq_10)
* к закрытой калитке/зеркалу/чомперу (seq_73). */ * либо подъём к ЗАКРЫТОЙ калитке/зеркалу/чомперу (seq_73 = «влез и съехал
* обратно»). Для ворот условие включает ОТКРЫТОСТЬ:
* curr_tile2 == tiles_4_gate && direction != right && modif >> 2 < 6
* — под поднятой решёткой (modif >> 2 >= 6) подъём обычный. Без проверки
* модификатора Kid срывался и с открытых ворот. */
uint8_t pop_hang_climb_up_seq(void) uint8_t pop_hang_climb_up_seq(void)
{ {
uint8_t t = get_tile_above_char(); uint8_t t = get_tile_above_char();
if (((t == TILE_MIRROR || t == TILE_CHOMPER) && Kid.direction == 0) || if (((t == TILE_MIRROR || t == TILE_CHOMPER) && Kid.direction == 0) ||
(t == TILE_GATE && Kid.direction != 0)) (t == TILE_GATE && Kid.direction != 0 &&
(uint8_t)(gate_modif(Kid.curr_col, (int8_t)(Kid.curr_row - 1)) >> 2) < 6))
return SEQ_73_CLIMB_UP_TO_GATE; return SEQ_73_CLIMB_UP_TO_GATE;
return SEQ_10_CLIMB_UP; return SEQ_10_CLIMB_UP;
} }
@@ -711,8 +723,11 @@ uint8_t pop_down_action(void)
if (!tile_is_floor(get_tile_behind_char()) && distance_to_edge_weight() >= 8) { if (!tile_is_floor(get_tile_behind_char()) && distance_to_edge_weight() >= 8) {
uint8_t through = get_tile_behind_char(); uint8_t through = get_tile_behind_char();
get_tile_at_char(); /* g_curr_tile = под персонажем */ get_tile_at_char(); /* g_curr_tile = под персонажем */
/* seg005:482: спуск с тайла-ворот лицом ВЛЕВО запрещён только пока они
* ЗАКРЫТЫ (modif >> 2 < 6); под поднятой решёткой спуск обычный. */
if (can_grab(through) && if (can_grab(through) &&
(Kid.direction >= 0 || get_tile_at_char() != TILE_GATE)) { (Kid.direction >= 0 || get_tile_at_char() != TILE_GATE ||
(uint8_t)(gate_modif(Kid.curr_col, Kid.curr_row) >> 2) >= 6)) {
Kid.x = (uint8_t)char_dx_forward((int8_t)(distance_to_edge_weight() - 9)); Kid.x = (uint8_t)char_dx_forward((int8_t)(distance_to_edge_weight() - 9));
kid_set_seq(SEQ_68_CLIMB_DOWN); kid_set_seq(SEQ_68_CLIMB_DOWN);
return 1; return 1;