851: Пакет/Покерный Движок
- Используется в:
- Отображается в:
Это «мозг» для игры в покер (Техасский Холдем и другие), построенный по очень строгим правилам. Он не зависит от конкретной игры, но здесь используется именно для покера. Он служит ядром логики для всей системы и работает по чётким протоколам (Состояние, Игра, Команда). Это позволяет отделить сложные правила покера от того, где и как игра запускается.
Покерный движок (@idealic/poker-engine) — это набор инструментов для управления игрой в покер. Представь себе невидимого помощника, у которого есть всё необходимое, чтобы начинать, вести и заканчивать игры. Хотя он создан для покера, его устройство можно применить для любой другой пошаговой игры, например, для шахмат.
Надёжность
Движок разработан по очень строгим правилам, где каждое действие заранее прописано. Его надёжность подтверждают почти 3000 тестов, которые проверяют самые разные ситуации — от обычной игры до очень сложных и редких случаев, вроде деления банка между несколькими игроками. Это гарантирует, что движок будет работать стабильно и без ошибок.
Кроме того:
- Тестирование в хаосе: Весь игровой процесс постоянно проверяется специальными тестами, которые создают непредсказуемые, хаотичные условия, как в реальной жизни.
- Проверен временем: Логика движка основана на системе, которая понимает формат раздач PokerStars. Эту систему проверили на более чем 10 миллионах настоящих игр, которые уже были сыграны.
Принципы устройства
Движок построен на шести главных правилах:
- Ничего не меняется: Каждое изменение в игре не исправляет старые данные, а создаёт их новую копию. Так мы всегда можем посмотреть, что происходило на каждом шагу.
- Всё можно повторить: Благодаря специальному «ключу» случайности, любую игру можно воспроизвести точь-в-точь, как она была.
- Сначала проверка: Перед тем как что-то сделать, движок всегда проверяет, можно ли это делать. Это защищает игру от ошибок.
- Всё по полочкам: Данные (
Состояние), сама игра (Игра) и её логика (Процессоры) чётко разделены и не мешают друг другу. - Всё через команды: Любые изменения в игре происходят через стандартные текстовые команды. Это как история приказов, по которой можно восстановить всю игру.
- Общий язык: Есть общие правила (протоколы), которые делают общение с движком простым и понятным.
Как всё устроено: система «отделов»
Движок использует систему «протоколов» — это как четыре главных отдела, каждый из которых отвечает за свою задачу.
1. Отдел Состояния (Ядро с данными)
Poker.State (раньше назывался Hand) — это универсальный язык для записи того, что происходит в игре.
- Универсальная запись: Может описать состояние любой пошаговой игры (покер, шахматы и т.д.) как последовательность действий.
- Источник правды: Хранит всю историю, чтобы можно было восстановить игру с любого момента.
- Чистые данные: Это просто данные, которые меняются только с помощью специальных «чистых» функций, не создавая беспорядка.
- Личный взгляд: Может «маскировать» данные для каждого игрока, чтобы он не видел чужие карты.
2. Отдел Игры (Исполнитель)
Poker.Game — это «ожившая» игра, которая работает в реальном времени.
- Живое состояние: Превращает статичную запись из
Stateв живой объект, который можно изменять и о котором можно спрашивать информацию. - Следит за правилами: Отвечает за все правила игры, проверяет, можно ли сделать ход (
canApplyAction), и двигает игру дальше. - Швейцарский нож: Содержит много полезных инструментов для управления временем, игроками и анализа ситуации.
- Движение вперёд: Метод
applyAction(game, action)— это главный рычаг, который двигает игру вперёд, изменяя её состояние на основе полученной команды.
3. Отдел Команд (Переводчик)
Poker.Command — это протокол, который создаёт команды.
- Слой-переводчик: Превращает намерения пользователя (например, клик по кнопке) в стандартные текстовые команды, понятные движку.
- Знает ситуацию: Смотрит на текущее состояние
Game, чтобы создать правильные команды (например, рассчитать точную сумму для ставкиallIn). - Разделение: Отделяет то, что видит игрок на экране, от того, как работает движок внутри.
4. Отдел Форматов (Упаковщик)
Poker.Format предоставляет специальные утилиты для работы с данными.
- Упаковка/Распаковка: Эффективно упаковывает и распаковывает состояние игры и команды, чтобы их можно было передать по сети или сохранить.
- Чтение истории: Умеет читать текстовую историю раздач (например, от PokerStars) и превращать её в понятные движку объекты
State.
Статистика и Аналитика
В движке есть специальный отдел Poker.Stats для глубокого анализа игры.
- Философия: Он различает Статистику (простые счётчики, которые обновляются в реальном времени, например, «попытки 3-бета») и Метрики (сложные расчёты на основе статистики, например, «частота 3-бета»).
- Отслеживание по позиции: Запоминает действия игрока с учётом его позиции за столом (в позиции или без), например, «попытка контбета в позиции».
- Сбор данных: Может собирать данные по игроку, раунду торгов (улице) или месту для создания отчётов.
Архитектура системы
Кто за что отвечает
Покерный движок работает и на компьютере игрока (клиенте), и на главном компьютере (сервере).
- На стороне клиента: Помогает быстро отображать изменения на экране и позволяет игроку делать ходы на основе локальной копии игры.
- На стороне сервера: Выступает главным судьёй. Он окончательно проверяет все ходы, следит за честностью игры и отвечает за случайность.
С чем работает
- На сервере: @idealic/game-service — управляет игровыми сессиями, сохранением данных и связью по сети.
- На клиенте: @idealic/poker-ui — отображает состояние
Gameна экране.
Жизненный цикл игры
Покерный движок работает по принципу «запрос-ответ».
- Подключение: Игроки подключаются. Система находит или создаёт стол и ждёт, пока соберётся хотя бы двое.
- Начало игры: Создаётся главное, авторитетное
Состояниеигры с секретным ключом случайности. Карты раздаются, состояние сохраняется и отправляется всем игрокам. - Ходы игроков: Клиент отправляет команду -> Движок её обрабатывает -> Новое состояние сохраняется, «очищается» от секретной информации (чужих карт) и рассылается всем.
- Завершение раздачи: Раздача заканчивается, движок передвигает фишку дилера, ставит блайнды и готовит следующую раздачу.
- Управление игроками: Просьбы выйти, поставить на паузу или вернуться обрабатываются перед началом следующей игры.
- Ожидание: Игра ставится на паузу, если активных игроков становится меньше двух.
- Тайм-ауты: Система периодически проверяет, не затянул ли кто-то с ходом, и автоматически сбрасывает карты, чтобы игра не останавливалась.
Основные возможности
- Управление состоянием: Честная раздача карт, отслеживание сложных ситуаций со ставками и побочными банками.
- Соблюдение правил: Строгая проверка правил ставок, перехода между раундами торгов и определения победителя.
- Управление игроками: Отслеживает позиции (Баттон, СБ, ББ), размеры стеков и историю действий.
- Ход игры:
- Крупье: Координирует взаимодействие между дилером и игроками.
- Дилер: Автоматический помощник, который сам двигает игру вперёд (раздаёт карты, открывает борд).
- Вскрытие карт: Очень быстро определяет победителя с помощью готовых таблиц силы рук (
utils/hand-strength.ts).
Формат команд
Движок использует простой и понятный текстовый формат для всех событий:
- Игрок:
'p1 f'(Игрок 1 сбросил карты),'p2 cc 20'(Игрок 2 уравнял 20),'p3 cbr 100'(Игрок 3 поднял ставку до 100). - Дилер:
'd dh p1 AsKs'(Дилер раздал игроку 1 Туза и Короля пик),'d db AhKhQh'(Дилер выложил на стол Туза, Короля и Даму червей). - Сообщения:
'p4 m Привет!'(Игрок 4 отправил сообщение «Привет!»).
Этот понятный человеку формат используется и для обмена командами между системами, и для записи полной истории игры.