ポーカー ボット ソフトウェア アーキテクチャ: 実践ガイド
ポーカーボットは単一のモデル呼び出しではなく、イベント駆動の意思決定システムです。信頼できるボットは、プロトコル処理、テーブル状態、エクイティ、戦略、リスク管理、テレメトリを分離します。この分離により、ライブテーブルを使わずにポーカーロジックをテストし、ネットワーククライアントを書き換えずに戦略を差し替えられます。
重要なポイント
- トランスポート コードをポーカーの決定から切り離してください。
- サーバーの状態を正として扱い、更新を冪等にします。
- 有効なアクションのチェックとタイムアウトを戦略モデルの外に置きます。
- ローカルでテストし、安定した対戦相手に対してベンチマークを行い、許可されたボット アリーナに参加します。
ポーカーボット ソフトウェアとは何ですか
ポーカー ボット ソフトウェアはゲームの状態を読み取り、有効なアクションを選択し、期限前にそのアクションを返します。有用な定義には、接続回復、ハンド トラッキング、評価、戦略、バンクロール ルール、ロギング、展開などのランタイム全体が含まれます。モデルまたはソルバーは 1 つのコンポーネントにすぎません。
この記事は、自律エージェントを明示的に許可する研究環境およびプラットフォームで使用されるボットについて説明します。これは、人間のポーカー クライアントをスクレイピングしたり、ゲーム整合性システムを回避したりするためのガイドではありません。大手消費者向けルームではそのワークフローが禁止されており、ポリシーの問題以前から脆弱なソフトウェアが生成されています。
わかりやすい考え方はパイプラインです。
event -> normalized state -> features -> decision -> guardrails -> action -> telemetry
各矢印はテスト境界です。ボットが不正な金額を調達した場合、その原因が状態ノーマライザー、戦略、またはアクション ガードのいずれであるかを知る必要があります。 6 つのジョブすべてが 1 つの decide() 関数内に存在する場合、すべての失敗は同じように見えます。
ポーカー ボット アーキテクチャの 6 つの層とは何ですか
プロダクション ポーカー ボットには、プロトコル、状態、ポーカー計算、戦略、コントロール、テレメトリの 6 つのレイヤーが必要です。最初の 2 つはハンドを理解しやすくします。中央の 2 人はアクションを選択します。最後の 2 つは、セッションを破壊する 1 つの悪い決定を阻止します。
| レイヤー | 所有 | 所有してはなりません |
|---|---|---|
| プロトコル アダプター | 認証、メッセージ、再接続 | ポーカー戦略 |
| 州の店舗 | ハンド、スタック、ボード、アクション履歴 | ネットワークの再試行 |
| ポーカーの数学 | ハンド ランク、ポット オッズ、エクイティ、レンジ | ベット実行 |
| 戦略 | フォールド、コール、レイズの意図 | 生のソケット書き込み |
| 安全制御 | 有効なアクション、サイズ制限、期限 | 対戦相手の統計 |
| テレメトリー | 決定、待ち時間、結果、エラー | ライブ決定突然変異 |
最も重要な境界は、戦略の意図と実行可能なアクションの間です。戦略では「ハーフポットを上げる」と言うことができます。制御層は、その意図を現在のメッセージで許可される量に変換する必要があります。これにより、ルール、モンテカルロ ロジック、強化学習、LLM 呼び出しなどのあらゆる戦略が保護されます。
ポーカー エンジンはテーブルの状態をどのように管理すべきでしょうか
状態レイヤーは、信頼できるサーバーイベントから現在の意思決定コンテキストを再構築し、重複を安全に無視する必要があります。ハンド ID、ターン トークン、座席、スタック、ストリート、ボード、ポット、行動履歴、有効なアクション、ボットの位置を追跡する必要があります。ストラテジーで未加工の通信メッセージを解析しないでください。
決定ごとに小さな不変のスナップショットを使用します。このスナップショットは、長期間存続する可変オブジェクトよりもテストが容易で、モデル呼び出しの実行中に遅延ネットワーク イベントによってデータが変更されるのを防ぎます。
from dataclasses import dataclass
from typing import Literal
Action = Literal["fold", "check", "call", "raise"]
@dataclass(frozen=True)
class DecisionContext:
hand_id: str
turn_token: str
street: str
hole_cards: tuple[str, str]
board: tuple[str, ...]
pot: float
stack: float
to_call: float
min_raise: float | None
max_raise: float | None
legal_actions: tuple[Action, ...]イベント ログを現在のスナップショットとは別に保存します。ログはデバッグと再生用です。スナップショットは決定用です。この分離により、WebSocket を開かずに新しい戦略を通じて失敗したハンドをリプレイすることもできます。
Open Poker には、ライブ フローに hand_id と turn_token が含まれています。このトークンは、以前の決定による後の結果が後のターンに適用されるのを防ぎます。 WebSocket プロトコル リファレンス ではメッセージのライフサイクルが文書化されており、ボット ライフサイクル ガイド では再接続と低バランス状態について説明しています。
エクイティサービスとレンジサービスはどのように適合しますか
ポーカーの数学は、カードとレンジを受け入れて計算結果を返す副作用のないサービスである必要があります。ブラフをするかどうかを決める必要はありません。サービスは少なくとも、ハンド ランク、ポット オッズ、エクイティ推定値、有効スタック、スタックとポットの比率、およびポジションを提供する必要があります。
まず決定論的な計算から始めます。ポットオッズと有効なベットサイズの算出は安価で正確です。ボードと相手のレンジによって全列挙が高コストになる場合は、モンテカルロ・エクイティを加えます。Pythonで作るモンテカルロ・ポーカー・エクイティ計算機 はシミュレーションのパターンを示し、ボットのポーカー数学 は周辺の式を扱います。
カードおよびステート ツールの場合、PokerKit は評価に便利なライブラリです。完全な展開ランタイムを装うことなく、ポーカー ゲームのシミュレーションとハンド履歴の作業をサポートします。 OpenSpiel および RLCard は、目標が局所強化学習またはゲーム理論の研究である場合に、より強力に適合します。
相手のレンジは明示的に保持します。レンジは不確実性を含む入力であり、評価器が見つける事実ではありません。対戦相手モデルは観察したアクションからレンジを推定し、エクイティサービスがそれに対して計算を行います。この2つを混ぜると、悪いコールが数学の問題なのか、読みの問題なのかを区別しにくくなります。
戦略を通信処理から切り離す
戦略層は DecisionContext を受け入れ、インテントを返す必要があります。 websocket.send() を直接呼び出すことはできません。このルールにより、同じポリシーを単体テスト、ハンド リプレイ、Slumbot ベンチマーク、またはライブ ボット アリーナで実行できます。
@dataclass(frozen=True)
class DecisionIntent:
action: Action
amount: float | None = None
reason: str = ""
def decide(context: DecisionContext) -> DecisionIntent:
if context.to_call == 0 and "check" in context.legal_actions:
return DecisionIntent("check", reason="free action")
if context.to_call > context.stack * 0.25:
return DecisionIntent("fold", reason="price exceeds risk cap")
return DecisionIntent("call", reason="within risk cap")この例は意図的に単純になっています。インターフェイスはポリシーよりも重要です。この関数は、ポジション別レンジ、相手モデリング、CFR ポリシー、または LLM に置き換えることができます。プロトコルとコントロールは変更されません。
私たちの初期のボットは、ソケット状態とポーカー状態が混在していたため、デバッグが困難でした。再接続すると、戦略メモリのように見える変数がリセットされる可能性があります。これらのレイヤーを分割すると、ハンド リプレイが決定論的になり、接続エラーがポーカー ミステリーではなくプロトコル テストに変わりました。
最も重要な信頼性管理は何ですか
制御層は、戦略が失敗することを前提に設計します。モデルAPIがタイムアウトすることも、エクイティ計算が予算を超えることも、テーブルの状態が変わった後に古い応答が届くこともあります。信頼できるポーカーボットは、送信前にこうした障害を処理します。
ターンごとに次のコントロールを使用します。
- 期限の予算: サーバーの期限ではなく、その前に戦略作業を停止します。
- ターントークンチェック: アクティブなターンと一致しない結果を破棄します。
- 有効なアクション フィルタ: サーバーが提示した有効アクションにないアクションを拒否します。
- サイジング クランプ: レイズは指定された最小値と最大値の間に保ってください。
- フォールバック ポリシー: 正当な場合はチェックし、それ以外の場合はプライマリ戦略が失敗した場合にフォールドします。
- 冪等性: 重複したイベントを 2 回処理しないでください。
Open Poker の現在のプロトコルでは、接続ごとに 1 秒あたり 20 個の WebSocket メッセージが許可され、切断されたシートは 120 秒間保持されます。これらの制限はボットにとって十分に寛大ですが、クライアントが制御されていないループを開くのではなく、再試行と再接続を状態遷移として扱う場合に限ります。
WebSocket エラー ガイド では、クローズ コードとメッセージ エラーについて説明します。 タイムアウト ポスト は、モデルの遅延、非同期の間違い、フォールバックに焦点を当てています。外部モデル API をアタッチする前に両方をお読みください。
ポーカー ボット ソフトウェアをどのようにテストすればよいでしょうか
内側から外側までテストしてください。純粋な数学およびアクション ガードは、サーバーなしでミリ秒以内に実行される必要があります。記録されたハンドリプレイは状態の再構築を検証する必要があります。ベンチマークの対戦相手は戦略の安定性をテストする必要があります。許可されたライブ アリーナが最終的な統合環境である必要があります。
4 つのテスト レベルを使用します。
| レベル | テスト | 失敗をキャッチ |
|---|---|---|
| 1 | 数学とサイジングのための単体テスト | 式と境界のエラー |
| 2 | 録画されたイベントのリプレイ | 状態と冪等性のバグ |
| 3 | 長いローカル セッションまたはベンチマーク セッション | 戦略リークとメモリ増加 |
| 4 | ライブボットアリーナセッション | タイミング、再接続、対戦相手の多様性 |
20 ハンドで勝ったからといって戦略を本番へ投入しないでください。ポーカーの結果にはノイズが多く、ヒーターが短いとアーキテクチャの問題が隠れてしまいます。これを推進する理由は、不正なアクションがゼロであること、決定の待ち時間が制限されていること、クリーンな再接続、安定したメモリ、同じスナップショットに対する再現可能な決定などの不変条件が維持されるためです。
安定したヘッズアップターゲットには、Slumbot が役立ちます。マルチプレイヤー統合のために、Open Poker はライブ テーブルと回転ボット フィールドを公開します。 Open Poker vs Slumbot の比較 では、2 つのテスト ステージで異なる質問の答えが異なる理由が説明されています。
何を構築し、何を借りるべきでしょうか
エージェントを他とは違うものにするポリシーを構築します。維持されているライブラリが適合する場合は、標準のカード評価、プロトコル クライアント、ロギング、メトリクス、およびテスト ユーティリティを借用します。ハンド エバリュエーターを書き換えても戦略が改善されることはほとんどありませんが、サイレント正確さのバグが発生する別の場所が作成されます。
| コンポーネント | ビルド | 借用または適応 |
|---|---|---|
| 独自の戦略 | はい | オプションのベースライン |
| 対戦相手モデリング | 通常 | 統計プリミティブ |
| ハンド評価器 | めったに | PokerKit または別のテスト済みライブラリ |
| WebSocket トランスポート | 薄いラッパー | 標準クライアント ライブラリ |
| 再試行とバックオフ | 設定 | 維持されたユーティリティ |
| ロギングとメトリクス | 設定 | 標準可観測性スタック |
| ゲームサーバーとマッチメイキング | ほとんどのチームではいいえ | 明示的なボット プラットフォーム |
研究のために境界は変わります。新しい抽象化またはゲーム表現をテストしている場合は、エンジンをさらに構築することが重要になる可能性があります。ライブ エージェントを改善しようとしている場合は、その時間を意思決定、データ、評価に費やしてください。
実際のビルド順序とは何ですか
最初に最小の垂直スライスを構築します。接続し、1 つのターンを正規化し、正当なフォールバックを選択し、送信し、結果を記録します。その後、一度に 1 層ずつ深めていきます。これにより、大規模な戦略によって変更コストが高くなる前に、不適切な境界を検出します。
- プロトコル アダプターと
checkまたはfoldフォールバックを実装します。 - 不変の決定スナップショットと記録された再生テストを追加します。
- ポット オッズ、ハンド ランク、および基本的なレンジ ポリシーを追加します。
- アクションガード、期限キャンセル、再接続回復を追加します。
- 対戦相手の特徴とより高価なエクイティ計算を追加します。
- LLM または学習済みポリシーは、ランタイムが安定した後にのみ追加してください。
Python でポーカー ボットを構築するガイド では、最初の垂直スライスが提供されます。 ゼロからリーダーボードへのガイド には、ボットがハンドを終了した後に反復する方法が示されています。ポリシーが変更されても、レイヤー間のインターフェイスを安定した状態に保ちます。
よくある質問
ポーカー ボット ソフトウェアとは何ですか
ポーカー ボット ソフトウェアは、ポーカー ゲームの状態を有効なアクションに変換するプログラムです。完全なシステムには、プロトコル処理、状態追跡、ポーカー計算、戦略、安全制御、テレメトリが含まれています。戦略モデルは 1 つのレイヤーであり、製品全体ではありません。
ポーカー エンジンとは何ですか
ポーカー エンジンはゲーム ルールを適用し、有効な状態を維持します。カードを配り、賭けを追跡し、ポットを解決し、有効なアクションを執行します。ボットはその状態を消費し、アクションを選択します。一部のライブラリは両方の役割を組み合わせていますが、概念は分離したままにする必要があります。
ポーカー ボットに最適なプログラミング言語はどれですか
Python はネットワーク、データ、ML エコシステムが広範囲にわたるため、最も早い開始点となります。 Rust、Go、JavaScript、Java も適切に動作します。 Open Poker には WebSocket と JSON のみが必要なため、言語の選択よりもプロトコルのサポートが重要です。
ポーカー ボットは LLM を使用する必要がありますか
LLM は 1 つの戦略レイヤーにすることができますが、その周りに決定的な制御が必要です。有効なアクションを強制し、レイテンシーを制限し、構造化された出力を検証し、安価なフォールバックを維持します。リモート モデルに接続状態やベットの検証を担当させないでください。
ポーカー ボットを安全にテストするにはどうすればよいですか
最初に単体テストとハンド リプレイを使用し、次に安定したベンチマークまたはローカル シミュレーターを使用します。自律エージェントを明示的に許可するプラットフォーム上でのみライブで実行します。人間のポーカー アカウントに隠しオートメーションを接続してテストを行わないでください。
良いアーキテクチャは、戦略の反復を着実な作業にします。再接続ロジックを変えずに、ルールをモンテカルロ・エクイティやLLMに置き換えられます。Open Poker クイックスタート から始め、最初のポリシーは単純に保ち、巧妙さを加える前にすべてのレイヤーを監視できるようにしてください。