· 1 мин

Баланс игры с нейросетью: что LLM считает сама, а что проверяет код

Нейросеть может помогать с балансом игры: накидать черновик конфига экономики, написать симуляцию и найти перекосы. Считать в голове и выбирать финальные числа ей нельзя: LLM легко выдаёт правдоподобный конфиг, где доход растёт быстрее цен. Проверяет баланс код симуляции, решение по метрикам принимает геймдизайнер.

Баланс игры с нейросетью: что LLM делает в игровой экономике, где ошибается и как проверить конфиг симуляцией на Python. Код, цифры прогона и пример из DnD-бота.

Баланс игры с нейросетью: что LLM считает сама, а что проверяет код
В статье · 7 разделовразвернуть

Баланс игры - это настройка чисел, от которых зависит, насколько игре интересно и честно играть: цены, награды, урон, скорость прокачки. Может ли нейросеть его делать? Частично. LLM быстро накидывает черновик конфига и пишет симуляцию, но считать в голове ей нельзя: проверяет баланс код, а решение по метрикам остаётся за человеком.

Я в мобильном геймдеве с 2020 года: Plarium, GAMETEQ, MetaPlayLab, Redneck, MadOut Games, от продукт-менеджера до ведущего геймдизайнера и продюсера. Баланс я сводил в таблицах задолго до того, как нейросети научились писать код. Сейчас у меня есть свой проект, DnD-бот с ИИ-мастером, где LLM прямо в проде выбирает противников. Ниже один сквозной пример, мобильная игра с монетами и зданием, которое качается до 20-го уровня, симуляция на Python и то, как я развёл работу между нейросетью и кодом у себя в боте.

Что такое баланс игры и игровая экономика?

Игровая экономика - это система ресурсов игры: откуда они приходят, где копятся и куда уходят. Баланс экономики - это подбор чисел так, чтобы ресурсов было ровно столько, чтобы игроку хотелось играть дальше: не нищета, от которой бросают на второй день, и не горы золота, на которые нечего купить к концу недели.

В сквозном примере у меня условная мобильная игра. Игрок закрывает дейлики, получает монеты, плюс копится пассивный доход с главного здания. Монеты уходят на апгрейд того же здания, у него 20 уровней. Почти любая экономика раскладывается на одни и те же элементы, их ещё в Machinations называли источниками, стоками и конвертерами (Machinations primer):

ЭлементЧто делаетВ сквозном примереЧто ломается, если перекрутить
Источник (faucet)создаёт ресурс из ничегодейлики, 300 монет в день при полном закрытииинфляция, ресурс обесценивается
Пассивный источниккапает со временем, часто растёт с прогрессомдоход здания, 100 монет в день на 1-м уровнедоход обгоняет цены, копилка пухнет
Сток (sink)уничтожает ресурсапгрейд здания, цена растёт с уровнемдефицит, игрок упирается в стену
Пулкопит ресурс у игрокакошелёк с монетамиогромный пул = нечего покупать
Конвертерменяет один ресурс на другойуровень здания превращает монеты в доходпетля "доход растёт от трат" разгоняет всю систему
Потолокограничивает прогресс20-й уровень зданияпосле потолка сток пропадает, монеты копятся вхолостую

Главная метрика в такой системе - доля потраченного. Если игрок за месяц тратит 85-90% заработанного, стоки работают. Если 15% - экономика уже сломалась, просто игрок этого пока не заметил.

Может ли нейросеть балансить экономику игры?

Нейросеть может делать черновую работу по балансу: предложить стартовые цифры конфига, написать скрипт симуляции, разобрать таблицу на перекосы, объяснить, почему кривая уезжает. Чего она не может - надёжно считать в голове и отвечать за решение. Финальные числа выбирает человек по метрикам, а проверяет их код.

Индустрия при этом уже вовсю пробует. По опросу GDC State of the Game Industry 2025 (больше 3000 респондентов), 52% разработчиков работают в компаниях, где внедрили генеративный ИИ, лично пользуются им 36%. Одновременно 30% считают, что он вредит индустрии, на 12 пунктов больше, чем годом раньше (Game Developer).

Где LLM реально полезна в балансе, а где нет, я свёл в таблицу:

ЗадачаСправляется?Что проверять
Накидать стартовый конфиг цен и наградда, быстросоотношение скоростей роста дохода и цен
Написать симуляцию Монте-Карло по описаниюда, это обычный кодчто формулы в коде совпадают с твоим описанием
Посчитать "сколько дней до 20-го уровня" в головенет, ошибается в экспонентахвсегда гонять скриптом
Найти перекос в готовой таблице балансачастичнопересчитать найденное руками
Сыграть в прототип вместо первого тестерачастично, сложность чувствуетинтересно ли играть, она не скажет
Решить, какая кривая правильнаянетэто продуктовое решение по метрикам

Есть и исследования посерьёзнее моих таблиц. В работе NetEase Fuxi AI Lab на KDD 2025 LLM-агенты, собранные по логам 16 294 реальных игроков MMO, торговали на аукционе, и цены коррелировали с разрывом спроса и предложения на 0,67. Но авторы сами пишут про галлюцинации: агенты делали недопустимые в игре действия (arXiv:2506.04699). А в исследовании Чан Сяо и Бренды Янг (октябрь 2024) LLM играла хуже людей в Slay the Spire, но где тяжело было ей, там было тяжело и людям (arXiv:2410.02829). Подробнее про это исследование и рогалики я писал в разборе мета-прогрессии и симуляции прокачки.

Читайте такжеМета-прогрессия в рогалике: как сбалансировать прокачку между забегамиМета-прогрессия в рогалике: что это, как сбалансировать прокачку между забегами и проверить кривую симуляцией на Python до плейтеста. Код и цифры.

Как проверить экономику игры симуляцией?

Проверить экономику симуляцией - значит прогнать тысячу виртуальных игроков через месяц игры и посмотреть на итог: когда они упираются в потолок, сколько монет лежит мёртвым грузом и какую долю заработанного они тратят. Скрипт пишет нейросеть за пару минут, прогон занимает доли секунды.

Беру сквозной пример и два конфига. В конфиге A пассивный доход растёт на 25% с каждым уровнем здания, а цена апгрейда только на 15%. Так выглядит типичный "щедрый" черновик: кажется, что игрок прогрессирует бодро. В конфиге B доход растёт на 8%, цена на 32%. Всё остальное одинаковое: дейлики 300 монет, игрок закрывает от 40% до 100% заданий, первый апгрейд стоит 200 монет.

Скрипт целиком, Python 3.10, без зависимостей:

import random, statistics
 
DAYS = 30            # горизонт: первый месяц игрока
PLAYERS = 1000       # виртуальных игроков
MAX_LVL = 20         # потолок уровня здания
 
def simulate(cfg, seed=1):
    rng = random.Random(seed)
    stock7, stock30, maxed_day, spent_share, levels = [], [], [], [], []
    for _ in range(PLAYERS):
        coins, lvl, earned, spent, maxed = 0, 1, 0, 0, None
        activity = rng.uniform(0.4, 1.0)   # какую долю дейликов игрок закрывает
        for day in range(1, DAYS + 1):
            income = cfg["quests"] * activity + cfg["idle"] * cfg["idle_growth"] ** (lvl - 1)
            coins += income
            earned += income
            while lvl < MAX_LVL:
                price = cfg["base"] * cfg["growth"] ** (lvl - 1)
                if coins < price:
                    break
                coins -= price
                spent += price
                lvl += 1
            if lvl == MAX_LVL and maxed is None:
                maxed = day
            if day == 7:
                stock7.append(coins)
        stock30.append(coins)
        levels.append(lvl)
        spent_share.append(spent / earned)
        maxed_day.append(maxed or DAYS + 1)
    return {
        "медиана дня макс. уровня": statistics.median(maxed_day),
        "уровень на 30-й день": statistics.median(levels),
        "копилка на 7-й день": round(statistics.median(stock7)),
        "копилка на 30-й день": round(statistics.median(stock30)),
        "доля потраченного, %": round(100 * statistics.mean(spent_share), 1),
    }
 
configs = {
    "A: доход x1.25, цена x1.15": dict(quests=300, idle=100, idle_growth=1.25, base=200, growth=1.15),
    "B: доход x1.08, цена x1.32": dict(quests=300, idle=100, idle_growth=1.08, base=200, growth=1.32),
}
for name, cfg in configs.items():
    print(name, simulate(cfg))

Вывод прогона (seed=1, 20.10.2026), свёл в таблицу:

КонфигМедиана дня 20-го уровняУровень на 30-й деньКопилка на 7-й деньКопилка на 30-й деньДоля потраченного
A: доход x1,25, цена x1,1514-й день20335 монет115 286 монет13,5%
B: доход x1,08, цена x1,32не дошли за 30 дней11342 монеты1 462 монеты87,2%

Самое коварное тут - 7-й день. По нему конфиги не отличить: 335 и 342 монеты в копилке. Если смотреть на экономику глазами только первую неделю, A выглядит нормально. Ломается он на второй: к 14-му дню половина игроков уже на потолке, сток пропал, и к концу месяца у медианного игрока лежит 115 тысяч монет, на которые нечего купить. Тратит он 13,5% заработанного. В B к 30-му дню медианный игрок на 11-м уровне из 20, тратит 87,2% и ещё есть куда расти.

Причина видна даже без скрипта, если знать, куда смотреть: в A доход растёт быстрее цены. Любая экономика, где конвертер "уровень → доход" обгоняет сток "уровень → цена", рано или поздно разгоняется. Нейросеть такой конфиг выдаёт легко, потому что он "правдоподобный", а правдоподобие и баланс - разные вещи.

Мой критерий-граница: если доля потраченного за первый месяц ниже 70% или копилка на 30-й день больше цены трёх следующих апгрейдов, в экономике нет стока, и её надо чинить до релиза, а не live-ops ивентами потом.

Как это работает у меня в DnD-боте: LLM предлагает, код режет

В моём DnD-боте с ИИ-мастером нейросеть каждый раз выбирает, с кем драться игроку. Это тот же баланс, только боевой: противник должен быть опасным, но не убивать персонажа за ход. Схема, на которой я в итоге остановился: LLM выбирает врагов из заранее подобранного пула, а функция balance_encounter пересчитывает их по таблицам опыта и выкидывает лишних.

Конфиг сложности лежит в отдельном JSON, encounter_target_weights.json. Это веса того, какой бой выпадет при каждой настройке сложности:

{
  "easy":   { "easy": 0.50, "medium": 0.35, "hard": 0.15, "deadly": 0.00 },
  "normal": { "easy": 0.20, "medium": 0.40, "hard": 0.30, "deadly": 0.10 },
  "hard":   { "easy": 0.05, "medium": 0.25, "hard": 0.50, "deadly": 0.20 }
}

До этого выбор был взвешенным рандомом 20/50/25/5 без учёта настроек игрока. А балансер ошибался в самой формуле: персонаж 5-го уровня против четырёх лютоволков CR 1 получал скорректированные 1600 XP вместо 2000, потому что для одиночного героя множитель должен быть 2,5, а не 2,0. 2000 XP - это 1,82 от порога "смертельно" для соло на 5-м уровне. Почти гарантированный вайп, который балансер считал просто тяжёлым боем.

Веселее всего было с самой нейросетью. Нарратор-LLM нашёл обход: через поле combat_state_update в своём ответе он сам дописывал врагов с HP 11 и AC 12, и балансер их вообще не видел. На QA-прогоне из трёх боёв через балансер прошёл только один. Промптом это не лечилось, лечилось архитектурой: канал удалили, и все бои пошли через init_combat → balance_encounter. Теперь LLM может предложить что угодно, но если противник по CR больше рекомендованного в 1,5 раза, код его выбросит.

Вывод, который я переношу на любую экономику: нейросеть не должна иметь права записывать числа в игру в обход проверки. Она предлагает, валидатор режет. Про то, как принимать работу у нейронки, если сам не эксперт в теме, у меня есть отдельный разбор ревью AI-кода.

Как сбалансировать игру с нейросетью: пошагово

Сбалансировать игру с нейросетью значит поделить работу: LLM пишет черновик конфига и код симуляции, симуляция считает, человек смотрит на метрики и решает. Весь цикл на одной петле экономики занимает вечер. Главное правило - ни одного числа "на глаз" от нейросети в финальный конфиг.

  1. Опиши петлю экономики словами: источники, стоки, конвертеры, потолки. Как в таблице из первого раздела.
  2. Попроси LLM накидать стартовый конфиг. Отдельно спроси, где доход растёт быстрее цен: это первая точка разгона.
  3. Попроси написать симуляцию на 1000 игроков и 30 дней с разной активностью. Зафиксируй seed, иначе сравниваешь шум.
  4. Задай метрики заранее: день выхода на потолок, копилка на 7-й и 30-й день, доля потраченного.
  5. Меняй один параметр за прогон. Два сразу - и уже не понятно, что сработало.
  6. Конфиг в игре держи отдельно от кода и ставь валидатор на границы, как balance_encounter в боте.
  7. После релиза сверяй симуляцию с живыми метриками и правь модель, а не только конфиг.

Промпт, с которого я бы начал:

ПромптСимуляция игровой экономики
Напиши на Python без зависимостей Монте-Карло симуляцию экономики мобильной игры.
Источники: [дейлики N монет в день, игрок закрывает от X до Y процентов],
[пассивный доход M в день, растёт на G процентов с уровнем здания].
Сток: апгрейд здания, первый стоит P, каждый следующий дороже на K процентов,
потолок L уровней.
Прогони 1000 игроков на 30 дней, seed фиксированный, два-три конфига.
Для каждого выведи: медиану дня выхода на потолок, медианный уровень на 30-й день,
медиану копилки на 7-й и 30-й день, среднюю долю потраченного от заработанного.
Отдельно перечисли места, где доход растёт быстрее цен.
подставь петлю своей игры

Сам код такого размера агент пишет за минуты. Что ещё агент успевает собрать по игре за выходные, я разбирал в статье про создание игр с Claude Code.

Когда нейросеть для баланса игры не нужна

Нейросеть для баланса не нужна, когда чисел мало и их проще проверить руками, или когда ответ даёт только живой игрок. Симуляция и LLM отсекают заведомо сломанные конфиги, но не скажут, весело ли играть, и не заменят метрики после релиза.

  • Чисел меньше десятка. Три цены и две награды проще свести в таблице за десять минут, чем объяснять модели.
  • Баланс про ощущения, а не про ресурсы. Скорость персонажа, отзывчивость управления, тайминги атак - это game feel, его проверяют руками на прототипе, а не формулой.
  • Есть живые метрики. Когда у игры уже есть игроки, лучший источник правды - их данные и A/B-тест конфигов. Модель тут вторична.
  • Нет валидатора. Если некому и нечем проверить, что выдала нейросеть, лучше не пускать её числа в игру вообще. Так у меня в боте и появились враги с HP 11, которых никто не считал)

Моя граница: если в экономике больше одного конвертера (ресурс превращается в доход или в другой ресурс) и игрок играет дольше недели, симуляция окупается за вечер. Меньше - садись и считай в таблице сам.

Частые вопросы

Чем источник отличается от стока в игровой экономике?

Источник (faucet) создаёт ресурс: награды за задания, пассивный доход, лут. Сток (sink) его уничтожает: апгрейды, ремонт, покупки у NPC. Если источники растут быстрее стоков, ресурс копится и обесценивается, это и есть игровая инфляция.

Можно ли доверить ChatGPT или Claude расчёт баланса без кода?

Нет. Языковые модели ошибаются в расчётах экспонент и длинных цепочек, а ошибку выдают уверенно. Пусть модель напишет скрипт симуляции, а числа считает интерпретатор Python: так результат можно воспроизвести и проверить.

Чем Machinations отличается от симуляции на Python?

Machinations - браузерный редактор, где экономика собирается схемой из источников, пулов и стоков и прогоняется Монте-Карло без кода. Скрипт на Python гибче и бесплатен, а с LLM пишется за минуты, но схему в Machinations проще показать команде.

Как готовился материал: черновик собран моим AI-конвейером по темам и заметкам из практики, факты сверены с первоисточниками, финальный текст я прочитал, поправил и утвердил перед публикацией. Обложку к статье тоже рисует нейросеть. Про сам конвейер — в разделе обо мне.

Влад Новиков
Пишу про AI-разработку без глянца. Новые разборы — сначала в канале.
Подписаться