Webサービスプレイポーカー

画像 こんにちは、Habr。



私はスポーツプログラミングに非常に惹かれており、ポーカーも大好きです。 そこで、ポーカーボットトーナメントを開始して、1石で2羽の鳥を殺すことにしました。



他の同様のイベントとは異なり、参加者のプログラムはWebサービスとして実装できます。Webサービスとしては、ディーラーがHTTP経由で通信します。


プロジェクトの最初のアイデアは私の友人のものです(彼はHabrからではありません)。 初めてこのような音がしたとき:

ポーカールームでプレイするボットには何も問題はないと思います。 おそらく、ロボットが互いにしかプレイしない特別なポーカークラブを組織する方が正直でしょう。 だから私はそのようなボットを書きたいです。 あなたはどうですか?

何を答えたか覚えていません。 そのようなサービスを作ることは、私にとってもっと面白かったです。 チャレンジが受け入れられました;)



エンジン



すぐ上の面白い画像は、システムの主要なコンポーネントとそれらの相互関係を示しています。 別のコメントには、ポーカーエンジンに関連する部分が必要です。 適切な既製のエンジンが見つからなかったので、ポーカークルーピアのロジックとボットとの通信を実装する小さな(〜1000行)pythonパッケージを作成しました。 パッケージには、ポーカーハンドとその直接の行動を生成するためのシンプルなUnixスタイルのインターフェイスが付属しています。



エンジンは、トーナメントロジック、ユーザーデータベースなどについて何も「知りません」。 彼は「クルーパー」としてのみ機能し、この配布の最終状態を含むXMLの形式で作業の結果を返します。



このような実装により、ボットの開発/テスト中にポーカールーム内とユーザーのコンピューターの両方で同じエンジンを使用することが可能になります(SDKと呼びます)。 これにより、ボットはユーザーのテストラボと実際のトーナメントゲーム中に同じ状態になり、コードの重複が減少します。



エンジンのソースコードはGithubで公開されています(MITライセンス)。 WindowsでSDKとして使用するために、Pythonインタープリターを有効にしてexeファイルが構築されます( py2exeを使用)。 LinuxおよびMacの場合、SDKはソースコードで提供され、オペレーティングシステムにインストールされた(デフォルトで)インタープリターを使用します。



現在の実装では、エンジンはポーカーの1つのバージョンのみをサポートしています-固定レートのテキサスホールデム。 ウィキペディアで判断すると、これは世界で最も人気のあるポーカーゲームの1つです。



ユーザーがシステムを完全にローカルで起動できるように、SDKをWebサービスとして作成しませんでした。 したがって、ボットに対して何百もの回帰テストを記述し、各変更後でも非常に迅速に実行できます。 さらに、このようなシナリオを実装するために、ソースにパッチを当てたり、エンジンに独自のインターフェースを作成したりする必要はありません。すべてが「設計どおり」に動作します。



テスト自体は、ステートレスAPIのおかげで書くのが簡単で快適です。



API



選択肢があれば、ほとんど常にステートレスAPIを作成します。 この場合、この選択はそれほど明白ではありませんでした。 各ターンで配布履歴全体をボットに渡す必要があります(これは決定を下すために最低限必要な情報です)。



現在、この情報(配布の「状態」と呼びます)は、HTTP POST要求を使用してXML形式でボットに送信されます。 最悪の場合、このXMLの重量は最大4KBです。 たくさんか少しかを決めるのはあなた次第ですが、これはボットの開発プロセスを簡素化し、新しい参加者のエントリーしきい値を下げるために私が払うつもりの価格です。



開発は非常に簡単です-参加者は、XMLを解析し、その中に記述された状況を分析し、特定の決定(パス、サポート、増加、オールインなど)を行うプログラムを作成するだけです。



XMLドキュメントスキーマは独立して開発する必要がありました。





<?xml version="1.0"?> <game> <table button="2"> <player sit="0" name="vbo" stack="80" in_stack="100"/> <player sit="2" name="lenny" stack="80" in_stack="100"/> <player sit="5" name="psycho" stack="90" in_stack="100"/> </table> <posts> <post amount="10" player="psycho" type="small_blind"/> <post amount="20" player="vbo" type="big_blind"/> </posts> <betting> <round name="preflop"> <action amount="20" player="lenny" type="call"/> <action amount="10" player="psycho" type="fold"/> <action amount="20" player="vbo" type="check"/> </round> <round name="flop"> <action amount="0" player="vbo" type="check"/> <action amount="0" player="lenny" type="check"/> </round> <round name="turn"/> <round name="river"/> </betting> <community> <card rank="Q" suit="H"/> <card rank="A" suit="H"/> <card rank="7" suit="S"/> <card rank="T" suit="S"/> </community> </game>
      
      





このスキームは、人間の理解にとっては非常に単純であり(たとえば//プレーヤー/ @スタックなどのわずかな冗長性を含む)、ロボットによる分析に便利です。 さらに、近い将来、JSONバージョンのスキームを作成する予定です。



ディストリビューションの内部表現のために、エンジンはデッキのある拡張されたバージョンを使用し、各ボットに対してそのトランスポートが示されます(URLなど)、ポケットカードなど。 配布の最終状態には、ショーダウンノードも含まれます。これにより、どのプレイヤーが勝ち、どのカードを持っているか(オープンする必要がある場合)がわかります。 現在の実装では、最終的な配布状態は、ボットの作成者がポーカールームのサイトでゲームの統計を表示したときにのみ表示されます。



他のすべての情報は、POST要求の個別のフィールドで送信されます(HTTPトランスポートの場合)。 これは、XMLをまったく解析せずに単純なボットを作成できるようにするためです。 さらに、このような実装により、テストの作成がより便利になります。テストボットは、XMLをまったく解析せず、たとえば、ランダムに、または最も単純なアルゴリズムに従って(「チェック/呼び出し」または「良いカードをベット/レイズ」の精神で)動作する場合があります。



この目的のために、「クループ」は、この状況で実行できるアクションのリストをボットに提供します。 ボットがこのリストにないアクションを実行すると、その応答はフォールドと見なされ、応答テキスト(通常はスタックトレース例外)がポーカールームの横のログに書き込まれます。 現時点では、ボットが壊れた場合、私自身がこれらのログを読み、参加者のメールに書き込みます。 もちろん、近い将来、このプロセスは自動化されます;)



トーナメント



スポーツプログラミング競技会では、私は常に次のことに非常に怒っています。





そのため、最初からメインのコンテストを「無限」にすることにしました。 人々のための本当のオンラインポーカークラブを想像してください。 いつでもそこに来て、 お金を投げ 、テーブルに座って、楽しい時間を過ごすことができます。 スキルを向上させ、より高いステークスのテーブルに座ったり、自由時間に「キャンディラッパー」を楽しんだりすることができます。



もちろん、私はロボットのようにすぐにそのようなことをしませんでした-たとえば、6か月の開発の後、サービスの入り口のしきい値が高すぎることを実感し、素晴らしい隔離でプレーします。



したがって、初心者のために、サンドボックスのようなもの-ポーカーボットのトーナメントを立ち上げました。これはいつでも参加でき、他の参加者を背景にしたプログラムのレベルを知ることができます。



ポーカールームは、毎日の初めに、前日に勝ち取った(または負けた)お金の量に基づいて、トーナメント参加者の評価を行います。 その後、各ユーザーの残高はゼロに設定され、競争は最初から始まります。 競争の一環として、ポーカールームは、すべてのボットが常にプレイし、可能であればさまざまな対戦相手とプレイするように努めています。 現在の実装では、これには次のルールが使用されます。





これらのルールを実装するアルゴリズム(図では「トーナメントワーカー」)は、並行して、非同期で、完全に独立して動作します。 これにより、マシンの負荷が均一になり、単位時間あたりの分布数が一定になります。 また、このアーキテクチャにより、システムのスケーラビリティが向上します。



サイトのようなワーカーは、PHPで実装され(私はPythonよりもここで経験が豊富です)、PostgreSQLデータベースを操作します。 テーブルキューの並列処理を保証するために、候補を選択するときにpg_try_advisory_lockが使用されます。 この方法が最も正しいことを保証することはできません。 コメントでこの問題について議論できてうれしいです。



計画



ポーカールームのソースコードをオープンアクセスにアップロードする理由はまだありません。コードは複雑すぎず、プロジェクトにあまりにも結びついていません。 代わりに、「エンジン」の改善(無制限のポーカーのサポートの追加など)、「学習」ボットのAPIの実装(つまり、過去のゲームの結果を取得する)、および参加者が参加する新しいタイプのゲームの開発に焦点を当てます別のAPIがテーブル自体の座席を管理し、必要に応じてテーブルを離れることができます。 一般的に、彼らはほとんど人間のように振る舞うことができます。



また、CoffeeScriptのような言語のブラウザーで直接ボットを開発し、特別なWebインターフェースを介してテストするために、初心者(またはWebから少し離れた)プログラマーのエントリーしきい値を下げる予定です。 アルゴリズムのビジュアルエディタを作成することも素晴らしいことです。 もちろん、絶対的な機会を与える必要はありませんが、プログラマでない人でもこのサービスを使用できます。これは非常に便利です。 現時点では、このようなエディターを作成する方法はわかりません。 それらがある場合は、コメントの購読を解除してください。



プロジェクトは「楽しみのために」行われます。 これらすべての「牛」の実施期限を公表することは無意味です。 git logから判断すると、2月上旬に現在の実装を開始しました。 このことから、私の速度について結論を導き出すことができます。



読者がプレイに興味がある場合、ポーカールームのベータ版がここで機能します 。 また、YouTubeでは、PHPで簡単なボットを作成し、テストし、トーナメントに登録する方法に関する短いビデオを見ることができます。



UPD [2013年531日]プロジェクトは、投稿の公開後数か月で凍結されました。 その理由は、コミュニティからの肯定的なフィードバックにもかかわらず、サービスの実際のユーザーは数十人しかいなかったため、ソリューションの更新がすぐに停止したためです。 プロジェクトを再開したい場合は、PMに私に手紙を書いてください。



All Articles