Уровень 6: переход на 7-й, портал, многокомнатное падение плиты
Всё проверено пользователем в MAME. 1. Переход 6 -> 7 падением. leave_room (seg002:0504) для «вниз» на уровне 6 из комнаты 1 даёт особый результат −2, главный цикл (seg000:0893) читает его как ++next_level; вход на 7-м (set_start_pos, seg003:0196) ставит Кида в комнату 17 и сразу переводит экран на комнату под ней. Проверка ОБЯЗАНА идти раньше связи вниз: у комнаты 1 сосед снизу есть (шахта, комната 3). 2. BUG-BALCONY-RIGHT: правая половина портала не рисовалась. id 12 стоял в FORE_ENV_IDS (в tile_table он fore_id ЗЕЛЬЯ), но зелье рисуется из chtab_1, а в chtab_6 под этим номером — правая часть арки балкона 32x62, идущая в backtable. Спрайт уезжал в fore-атлас, env-страница получала дырку (idx 12: w=0 h=0). Найдено трассой POP_TRACE_BT + чтением каталога .atl; дифф комнаты с оригиналом 1151 -> 375. 3. BUG-BELOWROW-WALL: жёлтые треугольники в шахте падения. load_rowbelow (seg008:368) при отсутствующей комнате снизу подставляет tiles_0_empty колонкам 1..9 и tiles_20_wall только левому краю; у нас стеной забивались все 11 позиций. 4. BUG-MOB-MULTIROOM: честный mob_down_a_row (seg007:1387) — кусок переходит в комнату снизу и летит дальше. Плита (1,7) комнаты 6 пролетает шахту комнаты 7 и жмёт кнопку (2,7) комнаты 11, открывая ворота комнаты 18. 5. BUG-MOB-STALE-PAGE: чистка следа куска стояла под гейтом «в отрисованной комнате» — улетевший вниз оставлял себя на одной из страниц навсегда. 6. BUG-CHAR-STALE-PAGE: тень застывала на двух страницах в РАЗНЫХ позах. Прямоугольник и valid пишутся внутри `if (w && h)`, а снимок состояния брался безусловно — при нулевом спрайте слот залипал «тихим». Остаток (почему спрайт нулевой) заведён как SPRITE-ZERO-W0 в BUGS_OPEN. NEXT_SESSION переписан: следующая задача — зацеп за край пола в свободном падении (вход на уровень 7). tests-host 5/5, size-check чист. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -879,7 +879,13 @@ static void mob_tick_one(mob_t *m, uint8_t pg)
|
||||
* страницы своя копия фона). Раньше коридор был фиксирован под ряд 2;
|
||||
* плита-потолок падает через весь ряд 0, поэтому чистим по фактической
|
||||
* прошлой позиции. */
|
||||
if (here && m->prev_y[pg] != MOB_Y_NONE) {
|
||||
/* Гейта по `here` здесь БЫТЬ НЕ ДОЛЖНО: prev_y[pg] — это след, который
|
||||
* кусок оставил ИМЕННО НА ЭТОЙ странице, и стереть его надо независимо
|
||||
* от того, где кусок сейчас. Пока чистка была под `here`, кусок,
|
||||
* улетевший в комнату снизу (mob_down_a_row), навсегда оставлял себя
|
||||
* на одной из двух страниц дабл-буфера — «застрявшая плита», видимая
|
||||
* через кадр (BUG-MOB-STALE-PAGE). */
|
||||
if (m->prev_y[pg] != MOB_Y_NONE) {
|
||||
pop_heal_off(MOB_X0(m->x), m->prev_y[pg] - 27, MOB_W, 32);
|
||||
m->prev_y[pg] = MOB_Y_NONE;
|
||||
}
|
||||
@@ -894,14 +900,34 @@ static void mob_tick_one(mob_t *m, uint8_t pg)
|
||||
if (m->row < 3 && m->y < 226 && MOB_Y_BOUND[m->row + 1] <= m->y) {
|
||||
uint8_t t = mob_tile_at(m);
|
||||
if (t == 0 || t == 11) {
|
||||
m->row++; /* mob_down_a_row */
|
||||
/* mob_down_a_row (seg007:1387): ряд ниже, а из НИЖНЕГО ряда —
|
||||
* в комнату СНИЗУ (y -= 192, ряд 0). Именно так кусок пролетает
|
||||
* несколько комнат подряд: уровень 6, плита (1,7) комнаты 6
|
||||
* проваливается сквозь пустую шахту комнаты 7 и приземляется на
|
||||
* кнопку (2,7) комнаты 11. Раньше мы кусок на границе комнаты
|
||||
* ГАСИЛИ и подменяли одним «переходом вниз» из главного цикла —
|
||||
* дальше первой комнаты он не летел (BUG-MOB-MULTIROOM). */
|
||||
m->row++;
|
||||
if (m->row >= 3) {
|
||||
m->y = (int16_t)(m->y - 192);
|
||||
m->row = 0;
|
||||
m->room = pop_room_link(m->room, 3 /* вниз */);
|
||||
if (!m->room) { /* улетел из уровня — просто гаснет */
|
||||
m->active = 0; m->clean = 2; /* дочистить ОБЕ страницы */
|
||||
return;
|
||||
}
|
||||
here = (uint8_t)(m->room == pop_t_room);
|
||||
}
|
||||
} else if (!here) {
|
||||
/* Приземление в ПОКИНУТОЙ комнате: рисовать нечего, сигнальная
|
||||
* пара pop_loose_landed/pop_debris_at обслуживает только текущую
|
||||
* комнату — щебень кладём прямо в данные уровня (loose_land пишет
|
||||
* в curr_room_tiles комнаты curmob.room, а не отрисованной). */
|
||||
pop_level_set_tile(m->room, (uint8_t)(m->row * 10 + m->col), 0x0E);
|
||||
m->active = 0; m->clean = 0;
|
||||
/* Приземление в ПОКИНУТОЙ комнате: рисовать нечего, но щебень и
|
||||
* КНОПКА под куском обязаны сработать — сигналим главному циклу
|
||||
* комнатой и тайлом (loose_land, seg007:11E8, работает с
|
||||
* curmob.room, а не с отрисованной). */
|
||||
pop_loose_exit_room = m->room;
|
||||
pop_loose_exit = (uint8_t)(m->row * 10 + m->col + 1);
|
||||
/* clean = 2 даже для чужой комнаты: пока кусок летел, он мог
|
||||
* рисоваться в ЭТОЙ, и след остался на обеих страницах. */
|
||||
m->active = 0; m->clean = 2;
|
||||
return;
|
||||
} else if (pop_loose_landed) {
|
||||
/* сигнал прошлого приземления ещё не разобран (один за кадр) —
|
||||
@@ -914,15 +940,11 @@ static void mob_tick_one(mob_t *m, uint8_t pg)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (m->y - 27 >= POP_PLAYFIELD_H) { /* весь ниже поля (улетел из комнаты) */
|
||||
/* Приземление в комнате СНИЗУ разбирает главный цикл — но ИМЕННО
|
||||
* сейчас, когда кусок долетел, а не в момент отрыва плиты: иначе
|
||||
* кнопка внизу срабатывала, пока плита ещё в воздухе. */
|
||||
if (!pop_loose_exit) {
|
||||
pop_loose_exit = (uint8_t)(m->col + 1);
|
||||
pop_loose_exit_room = m->room;
|
||||
}
|
||||
m->active = 0; m->clean = (uint8_t)(here ? 2 : 0);
|
||||
/* Страховка: кусок ушёл ниже поля, не поймав границу ряда (в норме этого
|
||||
* не бывает — mob_down_a_row уводит его в комнату снизу). Просто гаснет,
|
||||
* как у оригинала кусок в комнате 0 (move_loose: `speed = -2`). */
|
||||
if (m->y - 27 >= POP_PLAYFIELD_H) {
|
||||
m->active = 0; m->clean = 2;
|
||||
return;
|
||||
}
|
||||
if (!here) return; /* чужая комната — считаем, но не рисуем */
|
||||
|
||||
Reference in New Issue
Block a user