• Nikitos's avatar
    Порт сценок из audm-neko: $.story и текстовый DSL
    · 14570526
    Nikitos создал
    Первый блок порта (docs/TASKS.md §12.8, §6.1). В audm-neko сценка — текстовый
    файл, который читается и правится в любом редакторе, а исполнитель был
    корутиной на `await`. Переносим то же поведение идиомами `$`.
    
    * story_script.js — разбор DSL (чистые функции): реплики с эмоцией и
      рассказчик, bubble, варианты и выборы с флагами, метки, set (=, +=, -=),
      if со сравнениями, goto/end, wait, camera, move (к маркеру или на +200 px),
      face, anim, ai, image, fade, sound, objective, @free;
    * условия: flag, !flag, ==, !=, >, <, >=, <=; неизвестный флаг — ноль,
      сравнение числа со строкой даёт false, а не исключение;
    * story.js — исполнитель генератором: `yield` отдаёт кадр, `$.task.each` крутит
      сценку до конца. Реплика ждёт нажатия, move — прихода (до 6 с), wait — времени;
    * катсцена (без @free) отбирает управление: $.story.locked(), полосы сверху и
      снизу (9% высоты), игра спрашивает locked() перед чтением ввода; @free идёт
      поверх игры;
    * актёры объявляются игрой ($.story.actor('Некотян', '#companion')), иначе
      ищется узел с таким id; player/игрок/я → #player или #hero;
    * флаги общие на игру (переживают смену сцены): чтение, set/check/resetFlags;
    * события шины: story:line, story:lock, story:objective, story:end;
    * автопилот и внешний ответ: $.story.auto/advance/choose — тем же путём, что
      нажатия игрока, поэтому сценку можно прогнать без ввода.
    
    Три настоящих бага нашлись при сборке движка:
    1) я звал ctx.update, которого нет — фрейм-хуки ставятся через $.update; из-за
       этого падала установка ВСЕГО API (движок писал «bootstrap.js не выставил
       globalThis.$»), а $.task и $.loading.run вообще не могли запуститься —
       исправлено там же;
    2) в QuickJS генераторная функция не отдаёт .next, поэтому $.task.each с
       `function* () {}` падал — теперь принимаются и функция, и итератор;
    3) локальная переменная `node` перекрывала хелпер создания узлов.
    
    Проверка: tests/js/story_test.mjs (17 проверок разбора) и
    tests/agent/highlevel_story_test.py (19 проверок: реплики, выборы, флаги,
    катсцена, возврат управления), полный набор qjs и агентских тестов зелёный.
    14570526