PoP roomtest: страж замечает Кида и достаёт меч (ИИ, шаг 1)
Первый самостоятельный кусок ИИ стража (план, пункт 2). В оригинале у соперника нет своего диспетчера: autocontrol_* (seg002) выставляет те же глобалы control_*, что и ввод игрока, а дальше исполняется общий control(). Инфраструктура под это встала прошлым коммитом, здесь — сама логика. Порт: - check_can_guard_see_kid (seg003:688) — луч видимости по ряду: стены и верхи дверей рвут его совсем, loose/чомпер/дыра/неподнятые ворота дают «вижу, но не пойду». В guards.c (банк 1); - Opp + loadshad_and_opp (seg006:841) и char_opp_dist (seg006:2135); - autocontrol_guard_inactive (seg002:710) + move_* (seg002:0706..); - ветки control(): control_guard_inactive (seg006:2123) и draw_sword (seg005:945) — соперник уходит сразу в seq_90 en garde; - pop_guard_tick перестроен по play_guard_frame (seg000:1246): окно Char/Opp вокруг ИИ, диспетчера и play_seq. По дороге: - Kid.alive не выставлялся (= 0 = «мёртв» в семантике оригинала), из-за чего луч видимости не мог сработать в принципе — ставим -1 в kid_init; - Kid.room не выставлялась вовсе; условие Kid.room == Guard.room всегда было ложным. Ставим в enter_room (полная модель Kid.room != drawn_room у шва по-прежнему впереди); - pop_tile_at — тайл текущей комнаты наружу из pop_map (луч видимости); - control_x/y/shift открыты в шину: ИИ заполняет оси как есть, без flip_control_x (его «вперёд» уже в системе персонажа). Проверено в MAME (комната 3, страж на tile 17): страж переходит из стойки 166 в 171 stand_with_sword, sword=2, can_guard_see_kid=2; ввод игрока не пострадал. Клинок отдельным спрайтом пока не рисуется — sword.atl содержит только кадры 229..237 (подъём меча Кидом), остальные строки sword_tbl приедут с боёвкой. Бюджет (225 кадров, комната 3): 384 168 – 384 636 тактов, 0.893–0.895 кадра, запас 45 364. Прошлый замер 382 584 – 383 064 — шаг стоил ~1 570. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -132,6 +132,12 @@ static kframe kid_frame; /* кадр Kid для kid_draw */
|
||||
* копирование платится один раз на переключение персонажа. */
|
||||
pop_char_t Char;
|
||||
|
||||
/* Opp (seg006): СОПЕРНИК активного персонажа — вторая копия, которую ставят
|
||||
* рядом с Char (loadkid_and_opp / loadshad_and_opp, seg006:809). Через неё
|
||||
* ИИ и боёвка меряют дистанцию (char_opp_dist), не зная, кто именно перед
|
||||
* ними: для стража Opp = Kid, для Кида Opp = Guard. */
|
||||
pop_char_t Opp;
|
||||
|
||||
void pop_loadkid(void) { Char = Kid; }
|
||||
void pop_savekid(void) { Kid = Char; kid_frame = cur_frame; }
|
||||
/* Выгрузка БЕЗ кадра: control() кадр не трогает, а cur_frame в этот
|
||||
@@ -139,6 +145,7 @@ void pop_savekid(void) { Kid = Char; kid_frame = cur_frame; }
|
||||
void pop_savekid_state(void) { Kid = Char; }
|
||||
void pop_loadshad(void) { Char = Guard; }
|
||||
void pop_saveshad(void) { Guard = Char; pop_gframe = cur_frame; }
|
||||
void pop_loadshad_and_opp(void) { Char = Guard; Opp = Kid; }
|
||||
|
||||
int pop_kid_data_load(const char *path)
|
||||
{
|
||||
@@ -327,6 +334,7 @@ void kid_init(uint8_t seq_id, int8_t col, int8_t row, int8_t dir)
|
||||
Kid.fall_x = Kid.fall_y = 0;
|
||||
Kid.repeat = 0;
|
||||
Kid.charid = 0; /* charid_0_kid: своя таблица кадров */
|
||||
Kid.alive = -1; /* в оригинале ЖИВОЙ = alive < 0 */
|
||||
Kid.curr_seq = kid_seq_off[seq_id];
|
||||
pop_kid_play(); /* до первого кадра */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user