Шагай Наадан: три игры на одном броске костей в Telegram Mini App
Собственный проект: Telegram Mini App по бурят-монгольской игре в шагай. Три режима на одном броске, правила в чистых функциях и 44 теста. Страница открывается по публичному адресу, серверное сохранение, запуск из Telegram и аудитория не проверены.
Коротко (TL;DR)
- Мой собственный проект, не заказ: Telegram Mini App по бурят-монгольской игре в шагай. Три режима на одной механике броска: ежедневное гадание, «покер на шагай» и конские бега с ботом.
- Правила вынесены в чистые функции без React и DOM, источник случайности передаётся параметром. Бросок идёт через crypto.getRandomValues. 44 теста проходят, но распределение выпадений тестом не проверено.
- Три языка интерфейса, звук без файлов, 2.5D на SVG вместо 3D. Бурятской локали нет, нужен носитель языка.
- Статус: страница отвечает 200 по публичному адресу, я прошёл раунд в браузере. Серверное сохранение, запуск из Telegram и аудиторию я не проверял.
Шагай это игра на костях-астрагалах со своими названиями сторон и порядком их значимости. Я хотел собрать её так, чтобы человек открыл мини-приложение в Telegram, бросил кости за десять секунд и сразу понял, что выпало.
Задача
Нужна была игра, которая живёт внутри мессенджера без установки. Я уже писал про Telegram Mini App и когда их заказывают и хотел проверить формат на своём продукте.
Канон я зафиксировал в документе решений. Четыре устойчивые стороны: морин (конь, самая счастливая), хонин (овца, счастливая), ямаан (коза, несчастливая), тэмээн (верблюд, несчастливая). Пятая, үхэр (корова), считается редчайшей и выпадает только в гадании с шансом 0,5%.
К культурной части у меня три запрета: никаких черепов и «костей смерти», никакого шаманского китча, никакой казино-эстетики. Экран «О традиции» прямо говорит, что это ни гадальный сервис, ни азартная игра.
Что я сделал
Три режима на одних костях
Үглөөнэй шагай, ежедневное гадание. Четыре кости, трактовка по традиции: морин и хонин к благу, ямаан и тэмээн к осторожности, четыре разные стороны это дүрбэн бэрхэ, четыре одинаковые это алта. Сутки на одно гадание, лимит считает сервер.
Дүрбэн бэрхэ. Четыре кости, один переброс любого набора, пять раундов, побеждает сумма. В таблице девять комбинаций, от 200 очков за четыре морина до 5 очков без комбинации.
Мори урилдаан, конские бега. Дорожка из 12 клеток, ход это бросок пяти костей, шагов столько, сколько выпало морин. Два тэмээна и больше дают нулевой ход, но выдают жетон «хий морин». Три жетона превращают один ямаан в морин, и это единственное решение игрока: без него режим был бы лотереей. Соперник бот, он помечен как тренировочный и играет по тем же правилам.
Правила и случайность
Игровая логика лежит только в папке rules: бросок, таблица, бега, трактовка гадания, уровни. Там нет React и DOM, генератор случайности передаётся аргументом.
Обычный бросок идёт через crypto.getRandomValues, запасной вариант Math.random. Индекс стороны это округление вниз от случайного числа, умноженного на четыре. Число приходит из 32-битного целого, 2^32 делится на четыре без остатка, значит перекоса в выборе стороны нет. Это мой разбор кода, на выборке я его не мерил.
Детерминированный mulberry32 нужен в двух местах: раскладка событий на дорожке из сида матча и тесты. Четыре стороны равновероятны по решению, а не по измерению: реальный астрагал ложится неравномерно, канонического распределения у меня нет, а «подкрученные» шансы игрок читает как обман.
Вместо 3D я нарисовал кость SVG-силуэтом, у каждой стороны свой, объём делает свет. Звук синтезируется через Web Audio без внешних файлов. Игровые термины в локалях не переводятся, переводится только пояснение. О национальных кодах в интерфейсе я писал в статье про этно-авангард в веб-дизайне.
Что было сложно
Первое, честность броска. Бросок считает клиент, кроме гадания. Commit-reveal и серверный симулятор требуют бэкенда, а объём первой версии я урезал сам: монорепо, Postgres, 3D, монетизация и кланы в неё не вошли. Экран «Проверка честности» я не делал. Без серверного симулятора это была бы декорация, а такая «честность» хуже её отсутствия.
Второе, режим бегов. По исходному промту два тэмээна и три жетона давали обидный сценарий: жетоны сгорают, а ход всё равно нулевой. Я оставил жетоны на руках, если конь всё равно упрётся. Отступление описано в документе решений и закрыто тестом.
Третье, игрок без аккаунта. Гость играет полностью, но прогресс живёт в памяти вкладки. Локальное сохранение я не добавил намеренно: оно создало бы иллюзию сохранённого прогресса, который потом не переедет в аккаунт. Если сервер молчит, клиент ждёт до 8 секунд и честно пишет «результат не сохранён».
Четвёртое, язык. Бурятской локали интерфейса нет, монгольская вычитана машинно. Обе помечены в коде для носителя.
Что получилось
| Что | Состояние |
|---|---|
| Экраны в роутере | 9 |
| Тесты | 44 (32 на правила, 12 на контракт API), все проходят |
| Языки интерфейса | русский, английский, монгольский, по 179 строк |
| Достижения | 8 |
| Основной JS-файл сборки | около 404 КБ, 127 КБ в gzip |
| Публичный адрес | отвечает 200, приложение открывается |
| Серверное сохранение, гадание, лидеры | не проверено |
| Запуск из бота в Telegram | не проверено |
| Число игроков | данных нет |
Тесты я запустил сам. Они проверяют таблицу комбинаций, ветки хода в бегах, трактовки гадания и разбор ответов сервера. Распределение выпадений они не проверяют: там либо фиксированные значения, либо заданный сид.
Страница отдаёт 200, размеры собранных файлов совпадают с локальной сборкой. В браузере я открыл дүрбэн бэрхэ, нажал «Бросить» и получил четыре кости с выбором переброса. На запросы без токена серверная часть отвечает 401 и 405, то есть она живая. Под аккаунтом я не входил, поэтому прогресс, серверное гадание и таблица лидеров не проверены. В документе решений написано, что лидеров нет, но экран и тест контракта в коде уже есть.
Что дальше
Первым пунктом идёт вычитка бурятских и монгольских строк носителем. Тему я разбирал в статье про ИИ для сохранения бурятского языка, и машинный перевод здесь слабое место.
Вторым идёт вход через общий хаб. По документу решений путь игры нужно добавить в список разрешённых возвратов хаба, иначе игрок после входа останется на его главной. Сделано ли это, я не проверял. После этого прогоню полный сценарий с аккаунтом внутри Telegram.
Монетизация, скины костей и кланы ждут, пока игра не покажет, что её открывают повторно. Игровой цикл в других задачах я разбирал в статьях про игру для бизнеса в Telegram и MAX и про карту лояльности как игру.
Частые вопросы
Игра уже запущена в Telegram?
Страница доступна по публичному адресу и открывается. Код рассчитан на Telegram: нативная кнопка назад, вибрация, безопасные зоны. Как приложение открывается из бота, я не проверял. Цифр по игрокам у меня нет.
Бросок честный?
Клиентский бросок использует криптографический генератор браузера и, по моему чтению кода, не даёт перекоса между четырьмя сторонами. Игрок с доступом к клиенту может подменить результат, поэтому без серверного симулятора я не называю режимы турнирными. Гадание считает сервер, но его код я не читал.
Можно ли сделать такое под бренд или праздник?
Механика с броском и правилами в чистых функциях переносится на другие игры. Если нужна разработка Telegram-бота или Mini App, я начинаю с правил и их тестов, потом рисую экраны.
Коротко о главном
Шагай Наадан это три режима на одном броске и правила в отдельном слое. Публичный адрес отвечает, игра играется в браузере.
Серверное сохранение, лидеры, запуск из Telegram и распределение выпадений на большой выборке не проверены. Бурятской локали нет. Это первая версия, и я так её и называю.
Что я делаю для бизнеса
- Боты в Telegram, MAX, VK
- Автоматизация процессов и CRM
- Аналитика и дашборды
- Сайты и лендинги под ключ
Бесплатно: чек-лист «Готов ли ваш бизнес к 152-ФЗ»
12 пунктов, которые проверяют готовность за час: данные, согласия, уведомление в РКН, локализация, защита. Отметьте, что уже сделано, и увидите дыры, за которые сейчас штрафуют.
Готовы обсудить вашу задачу?
Бесплатная консультация — разберём, как внедрить это в вашем бизнесе под ключ. Без форм, пишите напрямую.
Разборы, кейсы и практика — без воды. Выходит регулярно, читать 3–5 минут.


