Уровень 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:
@@ -496,6 +496,19 @@ static void pop_start_level(void)
|
||||
|
||||
enter_room(start_room);
|
||||
kid_init(seq, (int8_t)(pos % 10), (int8_t)(pos / 10), dir);
|
||||
/* Спецсобытие «вход падением» (set_start_pos, seg003:0196): на 7-м
|
||||
* уровне Кид ставится в комнату 17, а экран тут же переводится на
|
||||
* комнату ПОД ней (`goto_other_room(3)`: y −= 189, ряд пересчитать) —
|
||||
* он влетает в неё сверху, продолжая падение с шестого уровня. */
|
||||
if (pop_current_level == FALLING_ENTRY_LEVEL &&
|
||||
start_room == FALLING_ENTRY_ROOM) {
|
||||
uint8_t below = pop_room_link(start_room, LINK_DOWN);
|
||||
if (below) {
|
||||
Kid.y = (uint8_t)(Kid.y - 189);
|
||||
Kid.curr_row = pop_y_to_row((int16_t)Kid.y);
|
||||
enter_room(below);
|
||||
}
|
||||
}
|
||||
Kid.sword = 0; /* set_start_pos: sword_0_sheathed */
|
||||
/* play_level (seg003:106): have_sword = level >= have_sword_from_level
|
||||
* (=2) — начиная со второго уровня меч у Кида уже есть. */
|
||||
@@ -759,7 +772,19 @@ int main(void)
|
||||
if (pop_fell_out) { /* Kid пересёк нижнюю границу комнаты */
|
||||
uint8_t down = pop_room_link(cur_room, LINK_DOWN);
|
||||
pop_fell_out = 0;
|
||||
if (down) { /* L2: переход в комнату снизу — продолжает падать */
|
||||
/* Спецсобытие «выход падением» (leave_room, seg002:0504 —
|
||||
* направление вниз даёт особый результат −2; разбор в главном
|
||||
* цикле, seg000:0893). Уровень 6 не заканчивается дверью: Кид
|
||||
* проваливается вниз из комнаты 1 и этим переходит на 7-й.
|
||||
* Проверка ОБЯЗАНА идти раньше связи вниз: у комнаты 1 сосед
|
||||
* снизу есть (шахта, комната 3), и без спецсобытия Кид улетал
|
||||
* туда, а оттуда — в рестарт уровня. */
|
||||
if (pop_current_level == FALLING_EXIT_LEVEL &&
|
||||
cur_room == FALLING_EXIT_ROOM) {
|
||||
Kid.y = 0xFF; /* seg000:0896 — Kid.y = −1 */
|
||||
pop_next_level = (uint8_t)(pop_current_level + 1);
|
||||
}
|
||||
else if (down) { /* L2: переход в комнату снизу — продолжает падать */
|
||||
enter_room(down); /* координаты Kid уже репроецированы pop_map */
|
||||
gfx_set_draw_page(back); /* вернуть текущую back для отрисовки */
|
||||
} else { /* выпал из уровня (нет комнаты снизу) — рестарт */
|
||||
@@ -886,32 +911,28 @@ int main(void)
|
||||
pop_loose_fell = 0;
|
||||
pop_level_set_tile(cur_room, fpos, TILE_EMPTY);
|
||||
}
|
||||
if (pop_loose_exit) { /* кусок долетел до низа комнаты — посадка ниже */
|
||||
uint8_t fcol = (uint8_t)(pop_loose_exit - 1);
|
||||
uint8_t from = pop_loose_exit_room;
|
||||
uint8_t down = pop_room_link(from, LINK_DOWN);
|
||||
if (pop_loose_exit) { /* кусок приземлился в НЕ отрисованной комнате */
|
||||
/* Комнату и тайл посадки считает сам кусок (pop_room.c): он летит
|
||||
* через комнаты честным mob_down_a_row, а не «одним переходом
|
||||
* вниз», как было раньше. Здесь остаётся то, что положено
|
||||
* loose_land (seg007:11E8): щебень на месте посадки и КНОПКА
|
||||
* под ним. */
|
||||
uint8_t lroom = pop_loose_exit_room;
|
||||
uint8_t lpos = (uint8_t)(pop_loose_exit - 1);
|
||||
uint8_t tt = pop_level_tile(lroom, lpos);
|
||||
pop_loose_exit = 0;
|
||||
if (down) {
|
||||
int8_t lrow = pop_room_col_landing(down, fcol);
|
||||
if (lrow >= 0) {
|
||||
uint8_t lpos = (uint8_t)(lrow * 10 + fcol);
|
||||
uint8_t tt = pop_level_tile(down, lpos);
|
||||
/* Кусок сел в комнате СНИЗУ — кнопка там нажимается так
|
||||
* же, как в своей (loose_land, seg007:11E8): на opener
|
||||
* подставляется button_type = щебень, то есть «открыть
|
||||
* НАСОВСЕМ» (modifier 0xFF). Второе место того же
|
||||
* порта: своя комната — в pop_map.c. */
|
||||
if (tt == TILE_OPENER || tt == TILE_CLOSER)
|
||||
pop_trigger_button(down, lpos,
|
||||
(uint8_t)(tt == TILE_OPENER ? TILE_DEBRIS : tt),
|
||||
pop_trob_modif(down)[lpos]);
|
||||
/* На факеле остаётся отдельный тайл «факел с щебнем»
|
||||
* (seg007:1067), а не обычный щебень. */
|
||||
pop_level_set_tile(down, lpos,
|
||||
(uint8_t)((tt == TILE_TORCH || tt == TILE_TORCH_DEBRIS)
|
||||
? TILE_TORCH_DEBRIS : TILE_DEBRIS));
|
||||
}
|
||||
}
|
||||
/* На opener подставляется button_type = щебень, то есть «открыть
|
||||
* НАСОВСЕМ» (modifier 0xFF). Второе место того же порта: своя
|
||||
* комната — в pop_map.c. */
|
||||
if (tt == TILE_OPENER || tt == TILE_CLOSER)
|
||||
pop_trigger_button(lroom, lpos,
|
||||
(uint8_t)(tt == TILE_OPENER ? TILE_DEBRIS : tt),
|
||||
pop_trob_modif(lroom)[lpos]);
|
||||
/* На факеле остаётся отдельный тайл «факел с щебнем»
|
||||
* (seg007:1067), а не обычный щебень. */
|
||||
pop_level_set_tile(lroom, lpos,
|
||||
(uint8_t)((tt == TILE_TORCH || tt == TILE_TORCH_DEBRIS)
|
||||
? TILE_TORCH_DEBRIS : TILE_DEBRIS));
|
||||
}
|
||||
if (pop_ceil_fell) { /* провалилась плита-ПОТОЛОК (ряд 2 комнаты сверху) */
|
||||
uint8_t ccol = (uint8_t)(pop_ceil_fell - 1);
|
||||
|
||||
Reference in New Issue
Block a user