Я делаю браузерную текстовую ролевую игру, где ведущим работает языковая модель. Игрок пишет любое действие своими словами, мастер отвечает рассказом, а игра ведёт механику: здоровье, деньги, характеристики, инвентарь, броски d20. Кажется, что всё просто: отправь модели историю и лист персонажа, получи ответ. На практике самые интересные задачи оказались не в промптах вида «напиши смешно», а на стыке вероятностной модели и детерминированной игровой механики. Ниже — четыре таких места и то, как я их решил.
Стек: Node.js 24, Express, встроенный node:sqlite, модели через OpenRouter и общий для сервера и браузера модуль движка.
1. Механику ведёт код, а не модель
Первая версия была наивной: модели дают весь лист персонажа и просят «ответь и обнови состояние». Это быстро ломается. Модель забывает предметы, раздаёт мечи +100, путает, сколько у героя денег, и через десяток ходов лист персонажа живёт своей жизнью.
Поэтому модель отвечает строгим JSON, в котором кроме рассказа есть только изменения:
{
"check": { "stat": "ХАР", "dc": 12, "why": "уговорить дракона", "kind": "other", "ok": true },
"narration": "Дракон открывает один глаз…",
"hp": -3,
"add": [{ "name": "Чужой сапог", "icon": " 