Меня просили сделать версию моей настольной игры «Битва Големов» в онлайн варианте почти с момента ее придумывания в 2014 году. Полноценно переносить игру я в иМеня просили сделать версию моей настольной игры «Битва Големов» в онлайн варианте почти с момента ее придумывания в 2014 году. Полноценно переносить игру я в и

«Умный» бот для онлайн-версии «Битвы Големов»: от эвристики к иллюзии разума

2026/02/08 22:59
9м. чтение

Меня просили сделать версию моей настольной игры «Битва Големов» в онлайн варианте почти с момента ее придумывания в 2014 году. Полноценно переносить игру я в итоге не стал (да и она бесплатно доступна в Tabletop Simulator), а вот сделать мини-версию для игры с 1 или 2 ботами желание появилось.

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

1111c1482af472933bc6bacfd1389d6b.png

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

А давайте сделаем ИИ

Так как я уже прикручивал ИИ к сайту для помощи по правилам игр, то первым делом решил, а почему бы не сделать это и с ботом. Ресурсы для этого есть, модельки хоть и небольшие (до 20B), я мог использовать.

И здесь возникли три проблемы: ИИ не видит игровое поле, ИИ обладает в достаточной мере «географическим кретинизмом» и на моих ресурсах ИИ долго думал.

Да, можно было скармливать ИИ визуальный скрин с текущей игровой ситуации, но эта попытка провалилась первой. Использовать большую vision модель я не могу из-за ограничений моих ресурсов (у меня доступна на сервере только NVIDIA A5000 на 24 Гб), а маленькие модели часто путали описание и расположение элементов на поле, особенно направление робота, что было наиболее важным. Поэтому пришлось отказаться от этого варианта и передавать ИИ каждый раз полное описание игрового поля (благо оно всего 4x4) и расположение на нем объектов.

Второй момент как раз связан с расположением робота в пространстве. Система координат при движении робота привязана к его «взгляду». То есть в момент своего хода он смотрит относительно координат поля или совпадая с его осями, или в противоположные стороны. А клетки поля для точной ориентации нужно нумеровать или по осям вида X1, X2, X3, X4 и Y1, Y2, Y3, Y4 или по системе «морского боя», расположив на осях координат буквы А,Б,В,Г и цифры 1,2,3,4. То есть в зависимости от того, как мы раположили оси координат и ноль, робот будет видеть перед собой разные клетки. И нейросетевая модель регулярно путала направление робота и какая клетка находится перед ним.

Если она путала расположение робота, то добавление других перемещаемых элементов типа бочек, приводили часто вообще к зацикливанию, особенно в режиме рассуждений.

Выходом, как не странно, стала привязка координатной сети к сторонам света. То есть условный компас привязывался к осям координат (нумерация шла, например, цифрами на Юг, а буквами на восток), а робот находясь на буквенно-цифровой клетке смотрел в определенную сторону света.

90f03ad6252172029df93b82d519f344.jpeg

И здесь вступало в силу третье препятствие. Если использовать не предобученную, а универсальную LLM, то нужно в системном промте было передавать все правила игры. А это поведение робота, доступные команды, алгоритмика повреждений с уменьшением характеристик и т.п. А при каждом запросе (то есть при каждом шаге исполнения программы) передавать текущее состояние игрового поля с расположением элементов, хода игрока и т.п. И передача информации и получение ответа занимало для неразмышляющих моделей секунд 10, а для размышляющих до 30 секунд. Что очень затягивало игровой процесс.
Проблемой было еще то, что Бот, как и игрок, придумывал программу из 3-4 команд до их исполнения, поэтому отрисовку передвижения и взаимодействия с объектами на игровом поле (края поля, камни, сами роботы), пришлось вынести в движок игры.

3e1f7ea8b6ed104b458565e27bfb1896.png

Поигравшись с ИИ, я решил, что не стоит для такой относительно несложной задачи так мучаться и решил пойти другим путем.

Продуманная простота

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

  1. Случайный выбор тактики (банальный бросок кубика);

  2. Дискретная симуляция будущего;

  3. Эвристическая оценка позиции (Манхеттенское расстояние);

  4. Иерархия приоритетов + fallback-логика.

Давайте разберём каждый пункт и посмотрим, как вместе они создают эффект «умного» поведения.

1. Первый ход — не расчёт, а характер: случайный выбор режима

Бот не действует одинаково в каждом раунде. Перед генерацией программы он «бросает кубик» и случайно выбирает один из трёх режимов:

  • Агрессивный: атака в приоритете, минимум защиты, движение к врагу любой ценой.

  • Нормальный: баланс — 60% шанс атаковать вплотную, иначе — защищаться.

  • Осторожный: отступ, поворот от игрока, защита как основной ответ на угрозу.

Это простое решение закрывает нам сразу две задачи:

  • Непредсказуемость — игрок не может выучить «паттерн» бота.

  • Персонификация — каждая партия кажется уникальной, а бот имеющим «характер»: то яростный, то хитрый.

Психологически это работает как антропоморфизация: человек склонен приписывать сознательные мотивы даже простым системам.

2. Дискретная симуляция: бот «представляет», как будет двигаться

Бот не просто выбирает команду «здесь и сейчас». Он симулирует от 3 до 4 шагов вперёд, в зависимости от числа доступных ему команд, обновляя своё виртуальное положение после каждой команды:

let simBot = { ...STATE.bot }; // копия состояния for (let step = 0; step < 4; step++) { // …выбираем команду… // …применяем её к simBot (не к реальному боту!)… }

Симуляция — это упрощённый поиск в глубину (depth-limited DFS), без рекурсии, но с прямым циклом. Длина программы зависит от состояния системы: 4 шага, если система ЦП (мозг робота) в норме, и 3 шага, если система ЦП повреждена. Этого достаточно для маленького поля 4×4, но не слишком дорого вычислительно.

3. Манхеттенское расстояние — простая, но мощная эвристика

Для оценки «насколько близко враг» бот использует Манхеттенское расстояние:

const manhattanDist = (a: Position, b: Position) => Math.abs(a.x - b.x) + Math.abs(a.y - b.y);

Как это работает:

  1. Math.abs(a.x - b.x): Вычисляется абсолютное значение разницы между координатой X точки a и координатой X точки b. Это количество горизонтальных шагов.

  2. Math.abs(a.y - b.y): Вычисляется абсолютное значение разницы между координатой Y точки a и координатой Y точки b. Это количество вертикальных шагов.

  3. Результаты складываются, давая общую минимальную сумму шагов, необходимых для перехода от a к b по сетке.

f94d12b0200af86bc9d269cc9ffdba0b.png

Почему именно Манхэттенское расстояние?

  • Оно быстро считается, так как использует только сложения и модули, без корней.

  • Адекватно отражает реальную «стоимость движения» на сетке с ортогональными шагами (вперёд/назад/влево/вправо).

  • Позволяет сравнивать направления: «если я повернусь вправо и пойду, расстояние станет 2; если влево — 4 , значит я выбираю вправо».

На основе этой метрики бот уже решает стоит ли ему поворачивать к игроку (getTurnToPlayer) или от него (getTurnToEscape) и достиг ли он «ближней зоны» (расстояние = 1), где включается режим ближнего боя.

Это по факту жадная эвристика (greedy heuristic): на каждом шаге бот стремится локально уменьшить расстояние и в 80% случаев это ведёт к глобальному сближению.

4. Иерархия приоритетов + fallback: поведение, устойчивое к «непредвиденному»

Логика выбора команды построена как каскад условий с явным fallback’ом и зависит от выбранного режима и расстояния до игрока:

  1. Приоритет атаки/защиты (Дистанция = 1):

    1.1 Агрессивный режим: Атака (А) имеет высший приоритет, если возможна.

    1.2 Нормальный режим: Шанс атаки (А) составляет 60%. Если атака не выбрана, приоритет у Защиты (D).

    1.3 Осторожный режим: Полный приоритет у Защиты (D).

  2. Приоритет позиционирования (Дистанция > 1):

    2.1 Агрессивный и Нормальный режим: Попытка поворота к игроку (Turn/L/R) с целью локально уменьшить Манхеттенское расстояние. Если поворот невозможен/не нужен, попытка движения вперёд (F).

    2.2 Осторожный режим: Попытка поворота от игрока (Turn/L/R) для увеличения дистанции. Если поворот невозможен/не нужен, попытка движения назад (B).

  3. Защита и Ожидание: Если не выбрано атакующее или позиционное действие, приоритет отдается Защите (D), затем Ожиданию (W).

  4. Запасной выход (Fallback): Если ни одна «умная» команда невозможна или нет доступного действия (исчерпан «запас хода» или ход заблокирован), бот не зависает, а выбирает случайную из оставшихся доступных команд, сохраняя активность.

Также в алгоритме были заложены следующие ключевые приёмы:

  • Контекстная активация: В режиме «осторожный» на дистанции 1 бот не атакует, даже если может — приоритет у защиты.

  • Учёт целостности компонентов: Если шасси повреждено, команда B (назад) автоматически исключается из выбора, так как поломка шасси (DAMAGED) блокирует выполнение этого действия.

  • Запасной выход: Если ни одна «умная» команда невозможна, бот не зависает, а берёт случайную из остатков — сохраняя активность.

Это создаёт эффект устойчивости к ошибкам: даже в «нелепой» ситуации (например, зажат у стены) бот не молчит, а реагирует — пусть и не оптимально. А игрок интерпретирует любую активность как «ум».

Здесь дополнительный эффект дают три психологических триггера:

  1. Бот меняет тактику в зависимости от расстояния и режима — игрок чувствует, что противник «оценивает обстановку».

  2. Даже если бот ошибается, его действия выглядят осмысленно: он поворачивается, потом идёт, потом атакует — как человек.

  3. При потере шасси бот перестаёт отступать, также как и начинает убегать при повреждениях — игроку кажется, что бот «чувствует» своё состояние.

То есть мы получили интеллектуальную иллюзию, достигнутая через чёткую иерархию решений, простые, но адекватные эвристики и отказ от «идеального» в пользу «убедительного».

Еще одна замечательная особенность этого алгоритма — он не стремится победить любой ценой. Его задача — обучать играющего. Агрессивный режим учит защищаться. Осторожный — демонстрирует ценность манёвра. Ошибки в выборе поворота — показывают, как работает Манхеттенская метрика. Такой бот — не враг, а умный спарринг-партнёр. И именно поэтому он запоминается.

Делаем красиво

Дальше пошли уже технические моменты. Сразу скажу - программист из меня лично аховый, поэтому вайб-кодинг «наше все». Я использовал Gemini и Qwen для первых версий, а финальная версия создана уже в Google AI Studio на React и после скомпилирована с ручной доработкой в HTML + JS. И стилизовал под 8-битную игру.

Посражаться с ботами можно по данной ссылке: https://bitvagolemov.prostorobot.ru/games/bg_game_8bit.html

58a49c5179a5649413c76afc4911fe94.png

В финальной версии я добавил возможность играть с 1 или 2 ботами (нужно выбрать из менюшки сверху и нажать на Сброс), случайную генерацию поля с водой, бочками и камнями, а также возможности двигать и разрушать бочки и помещать их в воду, чтобы по ним можно было ходить (как в настольной игре). Из игры перекочевали 8 раундов, чуть измененный режим повреждения ЦП (в игре это или 4 команды у целого ЦП и 2 у поврежденного или просто 3/3 в не зависимости от повреждений), а также 1 вид оружия (атака на 1 клетку силой 2 или 1 единицы в зависимости от повреждения) и 1 вид повреждения шасси (нельзя ехать назад).

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

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

Источник

Возможности рынка
Логотип Ucan fix life in1day
Ucan fix life in1day Курс (1)
$0.0004473
$0.0004473$0.0004473
-10.62%
USD
График цены Ucan fix life in1day (1) в реальном времени
Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу service@support.mexc.com для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.

Вам также может быть интересно