Как я воскресил игру 2001 года с помощью ИИ за $20 и 28 юаней
С приходом AI мир меняется значительными темпами. Ещё 1.5 года я скромно писал свои мыслишки по поводу вайбкодинга, а сейчас использование ИИ в работе само собой разумеющееся.
Почему я пишу этот пост? Потому что фактически это первый пет-проект доведённый до своего логического завершения (сори за спойлеры). Не сказать что я прям такой весь из себя вайбкодер, но стараюсь сжигать свои токены в рамках подписки на ChatGPT, чтобы держать руку на пульсе индустрии. И как это часто бывает, забрасываю я пет-проекты с завидной регулярностью.
Началась эта история в субботу. Мне на глаза попался очередной пост, где хвалили REA, и я решил посмотреть что к чему. Если коротко, то REA – набор тулзов для реверс-инженеринга с помощью ИИ.
Я решил попробовать эту штуку, и первая цель, что пришла в голову – мой незакрытый гештальт, а именно игра "Агент: Особое задание".
Это довольно странный гештальт, да и игра довольно нишевая. Выпустила её студия "Сатурн", ныне закрытая. Но по результатам могу сказать, что это довольно хороший выбор в силу простоты геймплея (жанр point-and-click). Да и в самой игре есть какой-то особый вайб.
И да, заголовок не кликбейт. Игра действительно вышла в 2001 году. И да, я справился силами одной подписки на ChatGPT за 20 баксов.
Конечная цель была запустить игру в браузере и полностью пройти.
Часть 1. Разведка и первый уровень
Исследование по REA я начал с помощью треда в ChatGPT. Сейчас это довольно удобно. В итоге я сказал что хочу сделать, и электро-бро поддержал (у него выбора не было).
В итоге мы начали выстраивать стратегию работы. Я выкачал установщик и распаковал его, затем мы начали изучать содержимое.
Да, когда я говорю "мы", я немного лукавлю. Я в основном запускал нужные команды и показывал результаты чату. Он оценивал и говорил что делать дальше.
Почему не агент? В этом заключается основная хитрость всего проекта. За использование агента расходуются лимиты, а в режиме чата – нет. А моя цель – получать максимум результата за минимум стоимости. Плюс у меня есть понимание того, как вообще выглядела игра.
Оказалось что игра сама по себе состоит из двух частей. Первая – движок. Вторая – скрипты+ресурсы. А так как скрипты лежали в виде простых текстовых файлов, это сильно облегчало задачу. Почему? Фактически нам нужно лишь реализовать движок, интерпретирующий эти скрипты. А это в свою очередь существенно сокращает объём реверс-инженеринга, так как нужно восстановить лишь поведение определенного набора функций. В ином случае возможно пришлось бы восстанавливать из бинарников всю игру, что было бы существенно тяжелее.
Из прикольных находок в первый же день – то, как реализовано перемещение по карте. Игра двухмерная и состоит из спрайтов, но там есть эффект глубины. И сделан он очень интересно.
Не замечаете ничего? Когда я открыл маску, то сразу понял что имею дело с первой локации и сразу понял предназначение.
Белый пиксель - ходить нельзя. А оттенок пикселя задаёт размеры главного героя. Соответственно, чем он темнее, тем герой меньше. И если сама маска проходимости – решение довольно стандартное для двухмерных игр (хотя сложно говорить о "стандартах" в 2001 году), то использование её для масштабирования главного героя лично я нахожу довольно креативным.
Помимо этого внутри обнаружились другие фоны, спрайты, звуки и загадочный формат MULT. Я предположил, что это анимации.
После распаковки игры мы решили имплементировать первую версию. И вот тут я хотел бы остановиться поподробнее на том, как вообще был организован рабочий процесс.
Я решил в этот раз отдать вообще всё на откуп ИИ, в том числе оркестрацию. Во-первых это был эксперимент по поводу того, сможет ли агент работать сам по себе, во-вторых мне немного сложно было понять, а как вообще проводить это восстановление.
Возможно, если я из будущего прочитаю этот абзац, мне будет стыдно. Но фактически процесс выглядел так. Я пишу в чат происходящее, он говорит, что нужно сделать дальше, готовит промпт, я этот промпт отдаю в агентов и они работают. Можно ли было сделать аналогичную оркестрацию напрямую в агенте? Да, можно. Но скорее всего это сильно расходовало лимиты. А я напоминаю, что сижу на подписке за 20 долларов.
Через пару итераций нам удалось добиться того, что первый (37) уровень успешно загружаются, на нём располагаются объекты и некоторые из них даже кликабельные.
Не обошлось и без багов. В первых итерациях не учитывалась глубина объектов и агент проваливался за них.
Часть 2. Скриптовый движок
Как я уже сказал, игра использует свой скриптовый движок, и для меня это было огромным плюсом. И как инженер и немного разработчик игр я по достоинству оценил это решение.
Скрипт привязан к отдельному уровню, и содержит в себе описание объектов, обработчиков событий и последовательностей команд. Причём скрипт может приостанавливать своё выполнение и ожидать завершения анимаций и связанных аудиофайлов, при этом движок продолжает отрисовывать кадры и анимации. По факту – аналог await из современных языков программирования. Круто, что это именно привязка к завершению анимации, а не таймер на количество секунд или кадров.
Сама логика квестов обрабатывается по принципу конечного автомата. То есть клик по объекту мог запускать разные действия в зависимости от состояния. Агенты накидали мне дебаг-меню, что упрощало прохождение. И в одном месте я, списав на баг, пропустил одно из действий и подкрутил себе предмет. Из-за этого у меня не работала часть действий, потому что состояние не изменилось.
Сами скрипты – классика российской игровой разработки. Часть объектов названы на русском в транслите, часть на английском.
Фактически, весь реверс-инжениринг свёлся к восстановлению семантики и логики обработки тех или иных команд с последующей имплементацией их в движке.
Из довольно забавного – в скрипте была опечатка StatrW, хотя движок ожидал StartW, но при этом команда успешно выполнялась. Почему? Дело в слабой хэш-функции, при которой даже в случае опечаток вызывалось корректное поведение.
Ещё в скрипте есть Fault. Изначально мы считали, что это действие при ошибке, но на деле это оказалось запасное событие, когда ни одно из состояний не подходит.
Важный момент – не было целью переделать игру, нужно было именно воссоздать оригинал, но в браузере. Поэтому вся логика была бережно перенесена, так что фактически наша игра должна вести себя аналогично оригиналу. Поэтому все скрипты остались на своём месте. Да, можно было бы их переписать и встроить в код игры, но при таком подходе есть неиллюзорный риск потерять какие-то аспекты.
Как вообще происходит реверс-инженеринг и что такое REA?
REA – набор инструментов и скиллов для агента, позволяющий выполнять реверс-инженеринг. Вообще это довольно богатый тулчейн, но мои агенты в основном использовали статический анализ. Для этого использовалась Ghidra, которая декомпилировала и дизасемблировала код.
И да, по факту это можно делать вручную, но агент имеет здесь неоспоримое преимущество. Он гораздо быстрее восстанавливает поведение, так имеет гораздо бОльший контекст, плюс имеет гораздо лучше отслеживает закономерности.
По факту работа выглядела так: мы выдвигали гипотезу, отдавали агенту на проверку, он с помощью REA исследовал её и подтверждал или опровергал.
Хорошую подсказку давали и сами сценарии
Часть 3. Свиноферма
В процессе работы OpenAI сбросили лимиты, а я до этого ныл в чате, что лимитов мало и скинул ему такой мем.
После чего электро-бро начал назвать агентов свинофермой, и меня это довольно сильно улыбнуло, и в нашем диалоге это закрепилось (хотя мем по факту означает немного другое).
Здесь стоит остановиться и описать распределение обязанностей. По факту для экономии лимитов Sol делал только задачи по ресёрчу и написанию спецификаций, а всей разработкой занималась Luna. Для меня оказалось открытием, что Luna тратит очень мало лимитов, по сравнению с тем же Sol, но при этом при работе по готовым спецификациям не сильно проседает качество её работы. Хотя конечно и тут были приколы. Агенты с самого начала начали писать E2E тесты, и под конец, когда этих тестов стало довольно много, Luna начала застревать на флакающих тестах, и по факту работа над задачами занимала процентов 30% времени, а остаток она вела войну с тестами. При этом сессии могли доходить до часа непрерывной работы, а она тратила всего 5% от 5-часовых лимитов.
И в очередной раз когда у меня кончились 5-часовые лимиты, я решил обратиться к DeepSeek. Они как раз перед этим дропнули новую Flash-модель, и я решил попробовать. Для этого был настроен DeepSeek Harness с подключенной REA, и моделями по API-ключу. Не стал заморачиваться с настройкой OpenCode, так как до этого видел что DeepSeek в своём родном окружении из коробки работает лучше.
И что я могу сказать? DeepSeek не подвёл. Там распределение обязанностей было похожее - Pro-модель для спецификаций, Flash – для реализации по ним. Задачи были того же уровня, Flash получил задачу на реализацию подгрузки сцен по спеке от Sol, а Pro занимался восстановлением оригинальной семантики Show/Hide.
За обе задачи я отдал...
2.67 юаней.
А самое главное - результат был нормальным. Да, по спеке мы уточнили пару моментов, потому что DeepSeek Pro выдал два противоречивших друг другу вывода в одном документе, но по факту – результат хорош за свои деньги.
По итогу к DeepSeek я обращался, когда у меня кончались лимиты по подписке, и он довольно неплохо подхватывал эстафету. Суммарно я сжёг 382 миллиона токенов и потратил на это 28 юаней, что по текущему курсу...
Много это или мало? Думаю, что полноценно использовать DeepSeek по API вместо подписки я пока не готов, но в качестве резервной модели, которая может добить какую-то задачу – вполне.
Тут ещё стоит ради справедливости отметить момент, что я использовал модели со скидкой 50%, потому что это был период вне пиковой нагрузки. Но и период пиковой нагрузки с 4 ночи до 13 дня по МСК, поэтому в целом для использования в рабочее время такой вариант всё ещё неплохо подходит.
Тут конечно чатик мне льстит, потому что по факту в какой-то момент я окончательно занял роль meat proxy, перенося текст между чатом и агентом.
Часть 4. Ход работы
В первые два дня была получена играбельная версия. Воспроизводились звуки, можно было ходить по локации и даже какие-то действия выполнять. Но пройти её было нельзя.
Сначала мы столкнулись с забавным блокером. Буквально на второй сцене главный герой спасает девушку и должен с ней заговорить. Но диалога не происходило, при этом другие действия уже работали. Проблема оказалась в том, что наш парсер скриптов некорректно обрабатывал ситуацию { Case 1, считая это продолжением предыдущей инструкции. Так что мы буквально научили главного героя разговаривать с женщинами.
Ещё один блокер был в логике объединения предметов. Её не было, и реверсом пришлось восстанавливать её.
Дальше я столкнулся с тем, что на одной из локаций пропала лестница. Проблема была в том, что поиск объекта учитывал регистр, а объект и анимация были названы в разных регистрах.
В какой-то момент меня абсолютно достала ситуация, что после каждого бага надо заново перепроходить игру и я решил что пора сделать сохранение/загрузку. Здесь мы естественно отступили от идеи переноса механизма из оригинала. Изучив, как работает сохранение на движке, мы реализовали те же правила, но с использованием современного браузерного API.
После реализации сохранений работа пошла бодрее. Однако по мере прохождения игры, я начал замечать что загрузка занимает очень много времени. Оказалось, что реализованный механизм загрузки подгружал чуть ли не все ресурсы игры. За счёт фикса загрузка из сохранения сейчас занимает пару секунд.
В какой-то момент я начал замечать, что клики работают через одно место. В паре локаций мне буквально пришлось по пикселю искать место, куда можно кликнуть.
Ближе к финалу игры это достигло своей кульминации и превратилось в блокер. Мне нужно было выбрать огнетушитель, но клик считался по пожарному щиту. Оказалось что мы в процессе упустили механизм сортировки предметов. Не буду вдаваться в логику, в итоге оказалось что механизм из оригинальной игры работает гораздо прямолинейней. Ещё в процессе реверса обнаружили что для сортировки используется нестабильный алгоритм.
Последними этапами была реализация карты и возможности воспроизведения кат-сцен, фактически, игру можно было пройти и без них, но я решил что для полного погружения надо.
Что дальше и какие выводы
После прохождения я закинул агентам пару промптов на восстановление оригинального курсора и фикса бага с переходом на другую локацию, но саму цель я считаю выполненной. За 5 дней (из них только 2 были посвещены активной работе) мне с помощью ИИ-агентов удалось восстановить игру до состояния, когда её возможно пройти в браузере от начала и до конца.
Я ещё подчищу репозиторий и выложу всё на GitHub, там будет не только код, но и все исследования и спецификации написанные агентами. Ну и подумаю над тем, чтобы опубликовать играбельный прототип (опасаюсь что за публикацию оригинальных файлов игры меня подвесят кверху яйцами).
Ещё отмечу, что в целом схема с оркестрацией через ChatGPT даёт неплохие результаты. Да, в эпоху автономности и продвинутых оркестраторов копипастить руками промпты может быть довольно кринжово, но фактически это даёт возможность выполнять такую работу по цене одной подписки.
Как я уже писал, Luna – неплохая рабочая лошадка, особенно при наличии качественной спецификации, которая к тому же мало расходует лимиты. Кстати, я не упомянул Astra, но причина одна - я её не использовал. Все задачи вполне решались Sol.
И да, этой работой я не претендую вообще не на что. По своему содержанию это чистейший нейрослоп, я даже в код не заглядывал, а спеки читал по диагонали. У меня было три цели – попробовать REA, поэкспериментировать с оркестрацией через ChatGPT и наконец-то пройти игру, с которой у меня связаны воспоминания из детства. Игра, кстати, неплохая.
Плюсом было прикольно делать некоторые археологические раскопки: смотреть на какие-то решения разработчиков, которые они реализовывали четверть века назад.
Уже в процессе написания этого текста я наткнулся на SaturnVM. Это полноценный движок, который может запускать разные игры от Сатурна той эпохи. Работа более масштабная, и может похвастаться большим объёмом запускаемых игр, но "Агент" там пока не запускается. И я с удовольствием поделюсь с разработчиками (или разработчиком) своими наработками.
Я думал в процессе текущей работы над тем, что можно было бы собрать универсальную платформу запуска таких игр для веба, но я уверен что эта задача в более надёжных руках.
Вообще я поймал себя на мысли, что ИИ действительно может дать таким вот нишевым играм новую жизнь. Чтобы сделать это всё вручную, мне потребовалось бы сильно больше времени, чем эти пять дней, и вряд ли я был бы готов потратить больше недели даже с агентами. А так любой энтузиаст может воссоздать свою игру детства, о которой большинство могли и не слышать. Мне кажется, это круто.
Уверен, что люди, которые разрабатывали эту игру 25 лет назад, не подозревали о том, что её будут раскапывать ИИ-агенты. Уже нет студии Сатурн, разработчикам уже точно сильно за 45, а их работу всё ещё можно оценить.
И да, агенты успешно восстановили игру про Агента. У меня крутилась эта шутка всё время, но не знал куда её вставить.
Возможно, вы подумаете, что я шиз, ведь много где говорю "мы", упоминая себя и агентов. Но я сделал это намеренно, потому что по факту я действительно выступил в роли meat proxy, а всю работу делали агенты и чат.
ну и скриншотиков напоследок
На этом всё, спасибо что дочитали до конца! До новых встреч!