Оглавление
1. Введение
Приветствую!
Весь год мы слушали об использовании ИИ для разработки программного обеспечения. Постоянно попадается реклама обещающая сделать все за тебя. ВЦИОМ рапортует что каждый второй (51%) пользователь интернета в РФ использовал чат-моделями в повседневной жизни.

На всем этом хайпе я немного упустил момент, когда все решили, что теперь код писать не обязательно, а достаточно лишь иногда пинать говорить Claude, что делать по телефону.
До этого я уже пробовал vibe-кодинг с использованием Cursor, GigaCode и Claude Code. Результат каждый раз меня разочаровывал после пары промптов, но я не теряю надежду и все же верю в светлое будущее данной технологии.
Уже в моей практике чат-модель (агент) может решать задачи по исправлению минорных багов, но до полноценного добавления фич в живой проект он не дотягивает.
В один из январских выходных. Я нашел проблему, что пронзила меня с явной мыслью: "Вот она. Маленькая, но не тривиальная проблема."
Так я и начал путь, которым хочу с вами поделится и подвести итог ответив на несколько вопросов:
Удалось ли решить задачу?
Удалось ли решить ее быстрее, чем без использования чат-моделей?
Если ли какие-то условия/ограничения использования чат-моделей?
И подведем итог описав рекомендации для тех, кто захочет пройти сам по моему пути.
2. Путь к прототипу
Для начала немного расскажу о игре, что мы будем разбирать.
Royal Quest — массовая многопользовательская ролевая онлайн-игра, созданная компанией Katauri Interactive. С апреля 2023 года поддержку игры осуществляет компания Lesta Games. Написана на C++.
Так как это дьяблоид, то монстры умирают не просто сотнями, а миллионами. Из это вытекала у меня логичные вопросы, а сколько я убил монстров за час/день/год. Классная метрика. Классно мериться ... эффективностью.
2.1 Первые попытки
При первом изучении оказалось что такой информации игра не предоставляет напрямую. Ни в настройках, ни публично на каком-то ресурсе такую информацию найти не возможно, что вызвало у меня интерес, но при этом понятный ответ: "А зачем это кому-то если счет идет на 1ккк+?".
Игра предоставляет экспорт логов которые пишутся в чат. Первая реализация была основана именно на них.
Луговая Жужа погибает. Получено опыта: 3.
Росинка погибает. Получено опыта: 2.
Получен предмет: Роса
Луговая Жужа погибает. Получено опыта: 3.
Получен предмет: Елочные игрушки (3шт.)
Морозный гролинг погибает.
Получен предмет: Снежок (8шт.)
Росинка погибает. Получено опыта: 2.
Получен предмет: Желе
Получен предмет: Зеркальный осколок
Луговая Жужа погибает. Получено опыта: 3.
Луговая Жужа погибает. Получено опыта: 3.
Вы достигли 3 уровня!
Луговая Жужа погибает. Получено опыта: 3.
Луговая Жужа погибает. Получено опыта: 3.
Получен предмет: Елочные игрушки (3шт.)
Морозный хлезень погибает.
Получен предмет: Снежок (5шт.)Вот бы было все так просто. Оказалось что в реально времени логи не выгружаются и под капотом логирование оптимизировано так, что игра собирает большой batch и пишет его в двух случаях (которые я заметил):
Переполнение batch.
Выход из игры.
Данный результат не вяжется с тем, что хочется получать информацию в рантайме. Не в 2010 все же живем.
Скрытый текст
Дальше пойдет, то за что можно получить бан почти в любой игре.
2.2 Вторая попытка
Когда натыкаешься на проблему для которой нет прямого решения, начинаешь искать, а как же подобраться к ней так, что бы хотя бы задеть решение носиком получить на него намек.
Игра многопользовательская. Значит она должна отправлять информацию на сервер для синхронизации

Может быть попробовать проанализировать пакеты. Что отправляется на сервер и из него достать эту информацию. Поиск по Google предложил попробовать использовать WireShark.
Удалось выяснить:
После несколькоступенчатого хэндшейка устанавливается socket соединение, что постоянно принимает и транслирует информацию.
Информация зашифрована.
После нескольких тщетных попыток расшифровать пакеты было принято решение признать этот путь тупиковым. Идея всего приложения была отложена в ящик.
2.3 Третья попытка
Вот настал новый год. Появилась пара свободных вечеров. Решил сдуть пыль с этой идеи и взяться за нее снова.
Идея была настолько очевидна, что даже грустно, что я раньше до этого не додумался.
Если я вижу сообщения в логе и данные пишутся батчами. Значит игра заранее выделяет память под эти батчи. Значит где-то это должно лежать в памяти. Так как память находится на нашем ПК, значит эти данные должны быть не зашифрованы, а так же структурированы.
Вооружившись CheatEngine принялся анализировать память.
Удалось найти совпадение по строке.

Только данные почему-то пустые. Хммм. Попробуем понять что же он нашел. Найдя дешифровщ��к byte в string удалось получить такие данные.
<TR style='color:#4A92D3' valign=top title='1/8 00:45:27'><TD colspan=2>Луговая Жужа погибает. Получено опыта: 6.Вот это неожиданность. Осмысленные данные. Но почему их нет в CheatEngine?
Ответ оказался простым до невозможности. Кодировка. По умолчанию стоит кодировка не поддерживающая кириллицу. Сменив на UTF-8 удалось получить данные в интерфейсе.

И тут для меня возник небольшой тупик. А что мне делать с этой информацией?
Вооружаемся современным инструментом - чат-моделями.
Решив полностью погрузиться в vibe-кодинг я как бедный студент у которого нет денег взвесив все за и против решил взять челленж пользоваться только бесплатными возможностями моделей.
Достаточно быстро мне удалось добиться от моделей ответа, что мне нужно используя Lua скрипт получать данные из CheatEngine.
Первая пытка была провальная абсолютно. Думаю дело в том что я написал слишком абстрактный промт. По итогу этого запроса я искал ХП, Золото, Врагов и др. но только не нужные мне данные.
Уточнение. Провал. Уточнение. Оу. Воу. Успех!

Данные нашлись. Данные не парсятся, кроме первой строки. Уточнения. Успех.
Скрытый текст
Я наивно полагал что вот оно. Золото. Но это хождение по кругу:
Запрос
Правка
Провал
Повторится ни 1, ни 2, ни 3 раза. Это образ жизни.
Тут я уже почувствовал опьяняющий результат прогресса и современных технологий. Данные парсятся. Данные выводятся. Ну что еще нужно для счастья? Ах, да. Ошибки памяти не хватает.

Claude решил что он у себя дома и оперативки бесконечное количество, а я его разочаровал реальностью. Где память нужно контролировать.
После нескольких итераций удалось добиться, что бы хранились только последние 10 записей. Тем самым удалось уменьшить потребляемую память.
На данный момент я понял одну простую вещь: "То есть я как пользователь, должен запустить и скачать CheatEngine. Руками вбить Lua скрипт и в реальном времени читать данные." Нормальный человек на первом шаге уже выбросит мою идею в мусорку.

Откатываемся и начнем с простого вопроса: "А можно ли читать память самому?". Получив от Qwen ответ - "Да" (токены Claude ушли на перезарядку). Я кинул закономерный вопрос об подходящем инструменте. В ходе рассуждений мы пришли к стеку Python + Pymem. Я не часто использую Python в работе, но решив что vibe ведет меня по этому пути, решил согласиться.
3. Круги ада
На этом этапе я бы уже показал первый прототип, но я должен рассказать о полном пути.
3.1 Круг OS
Я специально упустил момент, что игра разработана для Windows платформы. А так исторически сложилось что для работы я приобрел Mac M1 (давно, но все еще силен как никогда).
Из этого вытекает проблема, что будет меня преследовать до конца разработки. Следите за руками. Что бы запустить игру мне нужно:
Запустить Crossover (транслирует Windows инструкции для MacOS через Wine).
Запустить в нем Steam (что бы он подтянул все нужные зависимости для игры). Отдельно спасибо разработчикам, что добавили игру в Steam. Иначе тут я бы и застрял.
Запустить игру.
Скрытый текст
Вы думаете это фулл путь. Ахахахах, вы еще не видели что будет.
Забегая вперед что из этого вытекает основная проблема. Wine + MacOS работают как докер. При запуске Windows приложения изолируется память от внешних команд, что не проходят напрямую через Wine интерпретатор. А MacOS обеспечивает запрет на доступ к такой памяти.
Из этого вытекает интересное заключение. Что бы получить доступ к памяти процесса в Wine мне программу тоже нужно запускать в Wine. Раньше я этого не заметил, потому что решил CheatEngine тоже через Wine запускать. Мне было лень среди кучи процессов в MacOS искать нужный мне, а в Wine их всего 3: Steam, RQ, CheatEngine.
На этом этапе я перегрелся и пошел спать.
3.2 Инструкции
Попросив Claude написать мне скрипт для чтения данных из памяти я получил приложение. Вот только оно постоянно писало ошибку, что процесс не найден. Хотя игра запущена и процесс найден. Тут я понимаю, что процесс не виден в Wine.
Окей, это мы проходили. Идем по инструкции:
Сделать исполняемый файл.
Запустить в Wine.
Успех.
А как сделать исполняемый питон файл? Везде запускают сразу .py файл. Claude подсказал что нужно использовать PyInstaller.
Прошу его написать скрипт и научить меня как им пользоваться. Получаю инструкцию, .py файл для компиляции. Запускаю. Получаю файл без расширения. Ну ок, но Wine был другого мнения.
Оказывается когда вы компилируете файл в MacOS среде. Вы применяете инструкции что будут работать в Linux ядре, которые не совместимы в Windows среде (привет Java).
Не можешь победить, возглавь. Скачиваем эмулятор Windows для MacOS - ParallelDesctop.
Проходим все этапы настройки. Компилируем. Вытаскиваем из "C:" директории. Запускаем в Crossover и процесс найден. Отлично.

3.3 Чтец
Процесс найден. Но данные не считываются. Это мы уже проходили. Кидаем запрос Claude получает ответ. Повторить пока не получится.
Спустя несколько попыток получаем рабочий скрипт. Я до этого не сильно смотрел что пишет Claude в плане пояснений и кода. А тут заметил интересную деталь. Он сканирует какую-то определенную часть памяти.
Он сканирует память в которой вероятнее всего находится Куча (Heap) приложения. Что логично, зачем сканировать все, если мы ищем конкретно данные приложения.
Прикольно что Claude сам догадался до такой оптимизации. Дадим ему +1 балл.
Теперь приложение сканирует память в реальном времени и даже насколько это мне нужно оптимально.
3.4 Небольшой итог
На данном этапе я был рад как школьник, который понял что Фибоначчи можно считать по формуле, а не складывая числа друг за другом.
Ядро приложения готов. Данные находятся. Данные читаются. Осталось 20% работы. Сделать дэшборд. Каммон, это 20% которые растянутся до 80%
3.5 Сохранение
Достаточно рутинная часть. Акцентирую внимание на некоторых деталях. Принял решение, что нужно 2 файла:
Полный дамп считанных данных.
Дамп распаршенный в Json.
И тут мне прям понравилось как работает Claude. Он сделал отдельный класс для дэшборда. Сделал 2 отдельных экспортера. И отдельно парсер. И все сам. Я параллельно играл в RQ.
Вот только путь был запутанный до невозможности:
Промт Claude.
Результат копируем в VSCode в MacOS.
В терминале в Parallel запускаем билдер.
Копируем скомпилированный файл в MacOS.
Запускаем его в CrossOver.
Если результат не устраивает. Вернись к шагу 1.
По итогу было получено 2 файла с нужно мне структурой и данными

3.6 Дэшборд
Начинается всем знакомый этап. Переложи JSON и отобрази данные так, что бы заказчику понравилось. Первые попытки в дизайн были комичны, но я решил что сделать популярный стиль console-like.

Приложение умело считывать данные из Json-файла и начало показывать даже нужную мне статистику.

Заметны некоторые огрехи которые видны не вооруженным взглядом. Я решил повторить свою многоходовочку, но на этот раз меня ждал некоторый сюрприз.
После очередной неудачно итерации, сообщив мне что он и я не прав он взял и переписал весь дэшборд на другой фреймворк. Это должно для меня было стать звоночком.
После полного переписывания дизайн починился и все стало выглядеть хорошо.
След этапом стала краткая статистика, но и тут меня ждал сюрприз. Вот раньше люди не знали как отцентровать div. Теперь модель в той же ловушке. Я итераций 7 потратил на то, что бы он сделал правильную рамочку. Само сложно было заставить его отображать нижнюю границу и это будет меня преследовать не один раз.
Как можно заметить начались проблемы свойственные живым проектам. Что-то добавляешь, что-то ломается - баланс.
Сделал редизайн в серый цвет. И тут произошло то, что выбило меня из колеи. Контекст в Claude кончился.
3.7 Неожиданный поворот
У вас Claude стирал проект? У меня стер.
Claude я уже использовал в агентном стиле. Подключив расширение для работы с файловой системой. Заставив его заново просканировать проект в новом чате вручную (импортировать чат может только с подпиской). Я попросил его в очередной раз поправить одну из границ. Он промахнулся с файлом. Взял старую версию еще до редизайна в серый я не поняв это заранее разрешил редактирование файла и тут я осознал всю бренность бытия какую ошибку я допустил.
После этого я решил что каждое изменение это будет копипаста файла. Git подключать я не хотел, потому что думал: "Ну все. Еще один промт и готово".
3.8 Да где конец?
В один момент Claude начал подозрительно быстро кушать токены, поэтому вторым мои постоянным инструментом стал Qwen-coder. Он меня радовал еще меньше. Любой новый код, что я в нем пытался сгенерировать. Выдавал ошибку.
Но чем он мне понравился это превратить его в паттер Кодер -> Ревьювер -> Кодер. Я решил таким способом сделать рефакторинг. Потому что то как выглядел код, я даже не хочу показывать. Ну ладно, покажу:
def _update_all_monsters(self, stats: Dict):
"""Обновляет экран всех монстров"""
self.canvas.delete('all')
all_monsters = sorted(stats['monsters'].items(), key=lambda x: x[1], reverse=True)
y = 10
x = 10
w = 500
box_h = len(all_monsters) * 18 + 80
ty = self._draw_box(x, y, w, box_h, f"ВСЕ МОНСТРЫ ({stats['total_monsters']})")
...def _update_all_items(self, stats: Dict):
"""Обновляет экран всех предметов"""
self.canvas.delete('all')
all_items = sorted(stats['items'].items(), key=lambda x: x[1], reverse=True)
y = 10
x = 10
w = 500
box_h = len(all_items) * 18 + 80
ty = self._draw_box(x, y, w, box_h, f"ВСЕ ПРЕДМЕТЫ ({stats['total_items']})")
...В репо глянете, кому будет интересно.
Рефакторинг провелся весело и забавно. Один писал замечания другой правил и так по кругу. Вот только бесконечному кругу. Все как в жизнИ.
3.9 Последнее о чем бы я хотел рассказать
Поняв что я в тупике в рамках чтения файла. Курсор двигать по файлу и запоминать символ/линию такое себе. В пару промт-ов решил проблему перенеся все на SQLite. Это было невероятно просто. Теперь данные читались из БД. Структурировались и можно было настроить курсор на основе БД.
Я сломался на простом. Добавил новую кнопку, что бы я мог читать данные с текущего времени. Добавил на mini-дэшборд новую кнопку. Кнопки слились. Совершаем привычный круг почета. И не сработало. Хмм.

Токены Claude кончились. Qwen через 5 попыток тоже сдался. Держась на последней нервной клетке и руководствуясь мыслью: "Пойду гляну код. Действительно ли там все так нахардкожено что невозможно внести изменения?". Я решил проблему изменив 2 значения.
canvas = Canvas(
container,
width=180,
height=125, # Увеличена высота canvas
bg=self.theme['bg'],
highlightthickness=0
)
canvas.pack()
self.canvas = canvas # Обновляем ссылку
# Рамка: теперь высота 120 (чтобы помещалась в canvas высотой 125)
canvas.create_rectangle(5, 5, 175, 120, outline=self.theme['border'], width=2) canvas = Canvas(
container,
width=180,
height=135, # Увеличена высота canvas
bg=self.theme['bg'],
highlightthickness=0
)
canvas.pack()
self.canvas = canvas # Обновляем ссылку
# Рамка: теперь высота 120 (чтобы помещалась в canvas высотой 125)
canvas.create_rectangle(5, 5, 175, 130, outline=self.theme['border'], width=2)На этом свой MVP закончил.


4. Заключение
По мне удалось используя бесплатные версии чат-моделей разработать свой MVP проект за 3 вечера.
Что было реализовано:
Чтение памяти приложения в реальном времени.
Сохранение этих данных в трех форматах.
Визуализация данных в приятном виде.
Сделал бы я быстрее не используя модели? Однозначно нет.
Поддерживаемый ли это код? Нет. Данный код требует рефакторинга. Чистки проекта. Я не упомянул, что Claude очень любил строить из себя git создавая на новую фичу новый файл.
Хотел бы отметить сильные стороны что я заметил:
Написания ядра. Модели превосходно справлялись с созданием нового: Ядро, фича, рефакторинг.
Документирование. Они документируют даже если их не просишь.
Атомарность изменений. Нужно сделать фичу - сделает конкретно фичу не распыляясь на доп рефакторинг, когда это не нужно.
Слабые стороны:
Полная безответственность при написании кода. Его просто сложно поддерживать.
Не могут стабильно поддерживать свой код. Все стереть и написать заново вместо изменения - стандартная практика.
"Я забыв". Кончился контекст? Восстанови его в новом чате. Ах, у тебя весь код это весь контекст. Извинись!
Рекомендации которые я хотел бы дать:
Делите все что можете на то что можете. Можете сделать три экспортера для трех разных форматов - сделайте это. Кажется что это достаточно очевидная практика, но с моделями это ощущается острее.
Делайте саммари по коду. Контекст однажды кончится. Заведите сразу AI.md файл куда будут писаться все важные моменты: Предназначения файлов, Фичи, Баги и все что может помочь модели восстановить контекст.
Составляйте свои промты и коллекционируйте их. Знаешь паттерн "Абстрактная фабрика"? Теперь нужно выучить/записать промт для составления и добавления новой фичи используя Copilot-агента.
Следующий для меня этап - это армия Claude Code агентов. Посмотрим как это будет работать на добавлении новой фичи в мой MVP. Обязательно этим поделюсь.
Спасибо всем.

