Почему мы построили новый бэкгаммон-движок в 2026

Состояние бэкгаммон-AI в 2026 году выглядит странно. Два движка, которые сообщество считает каноническими, оба были спроектированы в совсем другую эпоху — gnubg (архитектура 2003 года, последний полноценный релиз в 2023) и eXtreme Gammon (проприетарный, только для Windows, без API). Оба работают. Оба любимы. Ни один не подходит под то, как разработчики выпускают современные приложения в 2026.

Нам нужен был движок, который отдаёт оценки по HTTP, поддерживает и короткие нарды, и длинные нарды, работает на современном GPU и поддерживается людьми, которые отвечают на письма. Такого не было. Поэтому мы построили свой.

Это история того, как появился Nardex — что мы взяли из академических наработок, что выкинули, что нас удивило и что дальше.

Бэкгаммон-AI в 2026 — короткая карта

Сегодня важны три системы:

  • gnubg (1999 — наши дни): open-source, GPL, золотой стандарт-эталон для академических сравнений. Архитектура сети — прямой потомок TD-Gammon. Работает под Linux/macOS/Windows, но сборка под современный macOS болезненная. Без API; вы вызываете бинарник, передаёте XGID через pipe, парсите текст.
  • eXtreme Gammon (XG): закрытое десктоп-приложение под Windows. Таблицы матч-equity — state-of-the-art; GUI — стандарт для серьёзного анализа куба удвоения. Никакого API — автоматизация требует GUI-скриптинга, что непригодно для production-сервисов.
  • wildbg: более новый open-source проект (Rust, 2022+). Перспективная архитектура, но фокус проекта — сам движок, а не хостовый продукт. Нет HTTP-эндпоинта, нет управляемого inference.

Заметьте пробел: каждый вариант требует встраивать runtime для inference в ваше приложение или на ваш сервер. Если вы хотите выкатить фичу анализа бэкгаммона в веб-приложении или мобильном клиенте — придётся таскать с собой пару сотен мегабайт бинарников плюс веса модели, заниматься установкой CUDA если хотите GPU и разруливать рассинхрон версий между клиентом и сервером.

Это нормально для десктопных инструментов и академических работ. Это ненормально для контент-инструмента, тренерской платформы или social-продукта в духе chess.com, где бэкгаммон — одна из множества фич.

Почему нам понадобился новый движок

Триггер был конкретным: мы хотели запустить сайт по коротким и длинным нардам (вы на нём) с мобильными приложениями, real-time PvP и пост-партийным анализом для каждого игрока. Мы не могли клеить subprocess-вызовы gnubg в request path многотенантного веб-сервиса. Математика очевидна: команда тратила бы больше времени на поддержание gnubg в живых, чем на разработку фич продукта.

Три конкретные потребности, которые существующие варианты не закрывали:

  1. Чистый HTTP-эндпоинт analyze-position — отправляешь позицию + кости + сыгранные ходы, получаешь ранжированные альтернативы с equity и векторами вероятностей. Без subprocess, без парсинга, без version-pinning.
  2. Поддержка длинных нард, нативно — у длинных нард другая стартовая позиция, другое направление движения, нет сноса (hits), своя система начисления марс/кокс. Ни gnubg, ни XG их не моделируют; для этого варианта пришлось бы писать собственный движок. Мы и написали — и сделали это тем же продуктом.
  3. Современное аппаратное ускорение — gnubg и XG оба гонят inference на CPU. Для многотенантного API субсекундная задержка при умеренной concurrency требует GPU. Нам нужны были CUDA, TensorRT, OpenVINO — подключаемые через execution providers ort.

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

Архитектура: Rust + ONNX + CUDA

Базовый стек:

  • Engine: Rust, в crates/engine/. Представление позиции, генерация легальных ходов, интерфейс evaluator-а. Без async, без аллокаций на горячих путях. Короткие нарды и длинные нарды живут в параллельных модулях с одинаковой поверхностью (backgammon::adapter::Adapter, narde::adapter::Adapter), так что верхние слои остаются variant-agnostic.
  • Inference: ONNX-модели загружаются через ort. Одна модель на вариант игры на фазу (про фазы ниже). Execution providers: CUDA для продакшена, CPU как fallback, TensorRT и OpenVINO доступны как build features.
  • Server: Axum (HTTP), Tokio (runtime), SeaORM (Postgres), Redis (сессии, rate-limits). Тот же Rust-workspace, что и движок, поэтому evaluation движка — это прямые вызовы функций, без subprocess, без IPC.
  • Frontend: SvelteKit (Svelte 5 runes) + Tailwind. Рендерит тот же JSON, который возвращает API; дашборд, который вы видите — это просто заточенный клиент того же эндпоинта.

Самое важное архитектурное решение: движок ничего не знает про HTTP, сервер ничего не знает про ONNX. Каждый слой касается только абстракций нижнего слоя. Звучит банально, но искушение срезать угол реальное, и именно срезание угла делает движки нередеплоимыми спустя годы.

Мультифазные сети: особенность длинных нард

Бэкгаммонные движки исторически используют одну сеть на evaluator. Мы используем несколько, разделённых по фазам игры. Причина — длинные нарды.

В длинных нардах позиция проходит через структурно разные фазы:

  • Blocking — у обеих сторон ещё есть шашки в стартовой четверти, контакт возможен, доминирующая тактика — построение прайма.
  • X escaped — белые очистили стартовую четверть, чёрные — нет (или наоборот). Асимметричная гонка-с-блокировкой.
  • O escaped — симметрично, противоположный игрок.
  • Race — контакт невозможен, обе стороны гонятся к выбрасыванию.

Одной сети тяжело хорошо выучить все четыре фазы — гоночные позиции и блокирующие позиции выглядят почти как разные игры. Поэтому мы обучаем по сети на фазу плюс единую сеть для ранних позиций. На inference фаза позиции определяется за O(1) по счёту шашек, вызывается нужная сеть, и вы получаете более резкую оценку, чем выдала бы one-size-fits-all модель.

Для коротких нард та же идея применима, но с меньшим числом фаз (контакт / гонка). Цена — лишние ~2 МБ весов и одна ветвь определения фазы — оба пренебрежимо малы.

Пайплайн обучения: что мы реально выпустили

Пайплайн живёт в crates/coach/:

  1. Генерация позиций — три источника питают narde_positionsbackgammon_positions):
    • Случайные позиции, сэмплированные из распределения, похожего на реальные частоты в партиях
    • Self-play партии текущей силы сети
    • Реальные сыгранные партии, импортированные из публичных источников; точки решений извлекаются через extract-expert-positions
  2. Rollout-оценка — каждая новая позиция оценивается путём розыгрыша множества коротких партий из неё текущей сетью. Усреднённый исход становится обучающим лейблом.
  3. Обучение — supervised regression сети по парам (позиция, лейбл), с маршрутизацией по фазам, встроенной в обучение.
  4. Турнир — кандидат-модель играет серию матчей против текущей продакшен-модели.
  5. Промоут — победитель турнира становится новой продакшен-моделью; проигравшая отвергается. Все метаданные (UUID модели, фаза, equity-loss vs предыдущего чемпиона, gating-пороги) живут в Postgres.
  6. Реклассификация — старые позиции переоцениваются новым чемпионом, уточняя их лейблы для будущих циклов обучения.

Этот цикл работает непрерывно на RTX 5080. Текущее состояние БД:

  • ~20.6 миллионов позиций нард (random + self-play + extracted)
  • ~192 000 экспертных позиций (точки решений из реальных сыгранных партий)
  • Multi-phase networks for narde (Blocking / Race / X-Escaped / O-Escaped)
  • Backgammon phases (Contact / Race) — в разработке

Самое полезное добавление за последние шесть месяцев — экстрактор экспертных позиций. Случайные позиции учат сеть механике; self-play учит её стратегии своего же уровня; реальные экспертные партии учат её, где на самом деле находятся интересные решения. Обучение на курированном наборе из 192k решений, найденных в реальных сыгранных партиях, заметно улучшило equity-error на отложенной части того же набора — больше, чем любая архитектурная подкрутка, что мы пробовали.

Бенчмарки

Полный отчёт по задержкам и точности планируется к релизу публичного API. Что мы можем сказать сейчас, честно:

  • Время вызова хостового API доминируется сетевым round-trip от вашего региона до EU дата-центра; CUDA inference одной позиции — субмиллисекундный на современных GPU.
  • Equity-error против gnubg-2-ply на отложенном тестовом наборе по бэкгаммону достаточно мала, чтобы по метрике top-move расхождения концентрировались в дебютных позициях, где несколько ходов набирают в пределах 0.005 equity друг от друга.
  • Для длинных нард внешнего эталонного движка не существует. Внутри мы валидируем против вручную отобранных экспертных позиций из правил Минспорта плюс турнирных партий self-play; калибровка оценок сети совпадает с интуицией экспертов на курированном наборе.

Полные числа мы опубликуем, когда будем уверены, что схема сравнения воспроизводима и честна (одни и те же оппоненты, одна и та же глубина, одно и то же количество rollouts). Размытые бенчмарки никому не помогают; лучше подождать.

Длинные нарды — недопредставленный вариант

Длинные нарды — версия, в которую играют в России, на постсоветском пространстве и на Кавказе. Используется та же доска, те же шашки, те же кости, что и в коротких нардах — но стартовая позиция, направление, правила сноса и начисление очков различаются. Более 30 миллионов человек умеют в это играть, и эффективно ноль современного AI-инструментария для этого варианта.

Почему? Две причины. Первая: академическое сообщество по бэкгаммону остановилось на коротких нардах как стандарте около 1970 года, до того, как персональные компьютеры сделали игры доступными повсюду. Вторая: когда в 1990-х появились методы обучения нейросетей вроде TD-Gammon, их применяли к тому варианту, с которым исследователи были знакомы. Длинные нарды никогда не были объектом исследований.

Для нас это очевидный пробел. Правила Минспорта РФ (приказ №734 от 22.07.2024) формализовали правила длинных нард в 2024. Куб удвоения был официально принят (статья 23). Теперь есть стабильная, цитируемая референция правил — именно то, что нужно движку, чтобы претендовать на корректность.

Наша модель длинных нард использует ту же архитектуру, что и модель коротких нард, но с другой кодировкой входов (194 входа против 186 для коротких нард), отдельным определением фаз (Blocking / Race / X-Escaped / O-Escaped против бинарного Contact/Race для коротких нард) и другой выходной головой (win/lose × normal/мars/коkс против win/lose × normal/гаммон/бэкгаммон). Обучающие данные текут через тот же пайплайн.

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

Что дальше

Roadmap на ближайшие два квартала:

  • Public API GA — закрыть закрытую бету, опубликовать тарифы, выкатить self-serve developer-портал. До этого момента доступ — через lead-форму на /developers.
  • Self-host evaluation — оценить, выпускать ли self-hosted вариант для клиентов с регуляторными ограничениями (EU + Россия). Контейнер, CPU fallback, key management.
  • Глубокий поиск — текущий API возвращает только ply-zero. Ply-2 и ply-3 в roadmap; код движка имеет параметр глубины, но бюджеты кэша и rate-limit нужно перенастраивать.
  • Match-equity tables — open-source MET data на основе наших турниров self-play, аналогично тому, что поставляет XG. Дёшево для нас, ценно для турнирных директоров.
  • Браузерный wasm inference — для низкозадержного офлайн-плея. Маленькие фазовые сети должны спокойно поместиться в wasm-бандл, если квантовать.

Если что-то из этого совпадает с тем, что вы строите — напишите нам через страницу developers.

Попробовать API

Самый быстрый способ оценить Nardex — посмотреть сравнение с gnubg и XG и 5-минутный quickstart по API. Обе страницы предполагают, что вы разработчик, и не тратят ваше время на маркетинговые тексты.

Если хотите контекст по самим играм — правила коротких нард и правила длинных нард — точки входа. Они рассчитаны на конечных пользователей; developer-страницы предполагают, что вы уже знаете игры.

Мы небольшая команда. На письма обычно отвечаем быстро. Если хотите узнать, поддержим ли мы конкретный use case до того, как подавать заявку на доступ — спросите.