79ea473910
Первый самостоятельный кусок ИИ стража (план, пункт 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>
59 lines
3.4 KiB
C
59 lines
3.4 KiB
C
/*
|
|
* pop_ctrl.h — управление Kid (Фаза K2b): порт диспетчера control()
|
|
* (SDLPoP seg005.c) + модель ввода read_user_control/user_control
|
|
* (seg006.c) поверх held-state клавиатуры <kbd_raw.h>.
|
|
*
|
|
* Kid-only подмножество: без меча и стражи. Map-запросы (стена/край/
|
|
* захват) ЗАСТАБЛЕНЫ «открытый пол» — реальная коллизия (стоп у стены,
|
|
* падение в ямы, повисание) приходит в K3/K4. Даёт отклик на клавиши:
|
|
* бег влево/вправо, разворот, стоп, присед, прыжок с места, прыжок в
|
|
* беге, присед-прыжок.
|
|
*
|
|
* Раскладка (kbd_raw, PS/2 Set 2): ←/→ = движение, ↓ = присед, ↑ =
|
|
* прыжок вверх (с →), Shift = осторожный шаг (K3). ESC — выход (проверяет
|
|
* приложение сам, канал raw забирает весь ввод у DSS).
|
|
*/
|
|
#ifndef POP_CTRL_H
|
|
#define POP_CTRL_H
|
|
|
|
#include <stdint.h>
|
|
|
|
/* Открыть raw-канал клавиатуры и обнулить память авто-повтора.
|
|
* 0 — OK, -1 — ошибка (EBUSY и пр., см. kbd_raw_open). */
|
|
int pop_ctrl_init(void);
|
|
void pop_ctrl_close(void);
|
|
|
|
/* Один кадр ввода: прочитать клавиши -> обновить control_* -> прогнать
|
|
* диспетчер control() (может сменить Kid.curr_seq). Звать ПЕРЕД
|
|
* kid_tick() (play_seq продолжит с новой последовательности). */
|
|
void pop_ctrl_tick(void);
|
|
|
|
/* control_shift зажат ПРЯМО СЕЙЧАС? — для check_grab в физике (pop_map):
|
|
* зацеп за уступ в падении по Shift. Валидно после pop_ctrl_tick. */
|
|
int8_t pop_ctrl_shift_held(void);
|
|
|
|
/* ---- Шина синтетического ввода (порт глобалов control_* из seg005) ----
|
|
* В оригинале ИИ соперника (autocontrol_*, seg002) не имеет своего
|
|
* диспетчера: он ВЫСТАВЛЯЕТ эти переменные, а дальше исполняется тот же
|
|
* control(), что и для игрока. Значения — CONTROL_RELEASED/IGNORE/HELD. */
|
|
#define POP_CONTROL_RELEASED 0
|
|
#define POP_CONTROL_IGNORE 1
|
|
#define POP_CONTROL_HELD (-1)
|
|
/* Оси ЭТОГО кадра (абсолютные): X = -1 влево / +1 вправо, Y = -1 вверх /
|
|
* +1 вниз. Для ИИ «вперёд/назад» уже в системе персонажа, поэтому оси он
|
|
* заполняет как есть, без flip_control_x. */
|
|
extern int8_t control_x, control_y, control_shift;
|
|
#define POP_CONTROL_HELD_FORWARD (-1)
|
|
#define POP_CONTROL_HELD_BACKWARD 1
|
|
#define POP_CONTROL_HELD_UP (-1)
|
|
#define POP_CONTROL_HELD_DOWN 1
|
|
extern int8_t control_forward, control_backward, control_up, control_down,
|
|
control_shift2;
|
|
|
|
/* Диспетчер (seg005:252) для АКТИВНОГО персонажа Char. Игрок идёт через
|
|
* pop_ctrl_tick (тот делает user_control с зеркалом «вперёд»), страж — из
|
|
* своего тика напрямую. */
|
|
void pop_control(void);
|
|
|
|
#endif
|