ScriptでPioSOLVER効率を劇的に向上させる
はじめに
※この記事はPioSOLVER Pro以上のライセンスを所有されている方向けの記事となっております。
初めまして。ナノニウムと言います。
皆さんはPioSOLVER(以下Pio)をどのように使用していますか?
Solverは必要な情報を入力するだけでGTO解を計算してくれる大変便利なソフトです。一つ残念なことと言えば、「Solverを計算している間の時間がもどかしい!」ということではないでしょうか。
セッションを終えた後はすぐにでもSolverを回して復習をしたいものですが、Solverの計算は容易には終わりません。また計算したいハンドが複数ある場合、一つの計算が終わったらその都度別のハンドを設定して、再度計算を開始させなければなりません。
手動でSolverを動かすのは正直とても時間効率が悪いと言えます。
もし、Solverを自動で動かすことが出来たらこの効率は劇的に改善するでしょう。そしてPioにはなんとScriptという正にその機能があります。
この素晴らしい手法を提供してくださったのがmaspyさんのnoteです。
Pioは独自のプログラミング言語を使用することが可能であり、そのコマンドが記述されたScriptを読み込ませることで、複数のハンドを自動で計算させることが出来ます。一度Pioをスタートしたらあとは寝てるだけで計算が終わっているなんて、素晴らしい事ではありませんか?
既にこのような自動計算プログラムを実装している方もいらっしゃいます。
彼ら先駆者を参考に、僕はVBA(Excelで動かせるプログラミング言語)で毎セッションの復習Scriptを作成し、Pioで使用しています。以下の動画で実際にScriptを作成している様子を御覧ください。
Scriptの作成から計算開始までにかかる時間はほんの数分です。
ようやく本題ですが、この記事ではPioのScript機能を用いた自動計算を行う方法について解説していきます。
次章に僕が使用しているコードも記載しておりますので、解説云々より取り敢えずPioを自動で使ってみたいという方はそちらをダウンロードしてください。プログラミングスキルをお持ちの方には、本記事が独自のScript作成コードを書くための補助となれば幸いです。
1. 実際のコード(VBA) ※10/13更新
以下、上記動画で僕が普段Script作成に使用しているエクセルシートとなります。PokerStars 6max-zoomでのみ動作を確認しています。
(プログラミングについては専門的学習をしていないため、命名規則等突っ込みたいところは多々あるかと思いますが御了承ください。)
※アンティには対応しておりません。
※PT4ではハンドエクスポートの出力形式がHM3と異なるため、エクスポートしたテキストファイルの内容を一度メモ帳へコピペ保存する必要があります。
以下、このコードを元にしたScript作成のフローについて解説していきます。
2. 自動計算のフロー
フローは主に5つの段階に分けられます。
(括弧内に上記動画内での該当箇所の時間を記載してあります。)
①計算するハンド履歴をまとめる (~0:15)
Holdem ManagerやPoker Trackerをお持ちの方は、セッションの気になったハンドをまとめてExportしましょう。まとめる際にTag付けをしておくと、復習の際にハンドを読み出すのが楽になります。
HMなら該当hand上で右クリックからTagを選択すれば適当なTagを付けることが出来ます。
上記ソフトを持っていない場合はご利用のポーカーサイトにHand Historyを申請しましょう。
②ハンド履歴のtxtファイルをプログラムに入力し、tree作成のためのTreeBuilding.txtファイルを作る (0:20~)
専用のプログラムにハンド履歴を読み取らせ、そこからPioでtree(計算ファイル)を作成するために必要な各ハンドのデータを取得し、それらをPio専用に記述したテキストファイルを作ります。
このハンド履歴を読み取るプログラムが本記事の主眼となります。詳しくは次章の「Hand履歴から必要なデータを取得するコツ」を御覧ください。
作成するテキストファイルは次のような形式で記述します。
※2行目以降における2個目の#以降の各値は全て一例です。
#TreeBuilding #V2
#Range0 #AA:1.0,A2s:0.0,A2o:0.0,...(OOPのレンジを記述)
#Range1 #AA:0.0,A2s:0.0,A2o:0.0,...(IPのレンジを記述)
#Board #7c 4c 8s
#Pot #569
#EffectiveStacks #2495
#AllinThreshold #67
#AddAllinOnlyIfLessThanThisTimesThePot #500
#FlopConfig .BetSize#34,48,73,100,138
#FlopConfig .RaiseSize#50
#TurnConfig .BetSize#50,100
#TurnConfig .RaiseSize#50
#TurnConfig .DonkBetSize#50
#RiverConfig .BetSize#73
#RiverConfig .RaiseSize#50
#RiverConfig .DonkBetSize#50
#FlopConfigIP .BetSize#34,48,73,100,138
#FlopConfigIP .RaiseSize#50
#TurnConfigIP .BetSize#50,100
#TurnConfigIP .RaiseSize#50
#RiverConfigIP .BetSize#73
#RiverConfigIP .RaiseSize#50
尚、作成したテキストファイルはPioViewerで参照できるように、PioSOLVERフォルダ内のTreeBuildingフォルダ内に保存しておきましょう。次の手順③で重要となります。
③PioViewerを起動し、手動でTreeBuildingファイルを再保存する (0:27~0:55)
先程作成したテキストファイルには「IP・OOPのレンジ」「ボード」「初期ポットサイズ」「エフェクティブスタック」「各ストリートのベットサイズ」の情報が記述されています。PioViewerで下記画像のフィールドにある該当ファイルをクリックしてみると、各欄にそれらの情報が自動で入力されます。
Preflopのプレイラインが想定から外れているとプログラムがレンジを拾えないためレンジは空欄となりますので、そこは手動でレンジを入れます。
PioViewerに必要な情報が全て入力されているのを確認したら、上部の「save current parameters」をクリックし、同じファイルへ上書き保存します。
自動化と銘打っておきながら何故この手作業を行うかというと、PioViewerを経由した一連の保存作業によってテキストファイルにはadd lineコマンドを含む自動計算に必要なScriptが追加されるからです。
add lineとはeff・pot-size・bet-sizeから算出される全てのベッティングラインを設定するためのコマンドです。add lineコマンドが追加されたテキストファイルを開いてみると分かりますが、非常に大量のadd lineが記述されています。
このadd lineを全記述するアルゴリズムも実装できればベストなのですが、これを作るのは(僕にとって)非常に困難であり、恐らくScriptの自動作成において一番のネックとなる部分です。しかしPioViewerを経由することで必要なScriptが簡単に記述出来ることを知り、妥協してこれを利用しちゃおうということにしました。
但し、この作業で追加されるScriptはbuild_treeまでです。これだけではPioで動かすことは出来ません。
次の3つのコマンドをbuild_tree以降に記述する必要があります。
go
wait_for_solver
dump_tree 保存先パス
これらは次の手順で追加させます。
④作成したTreeBuildingファイルを結合し一つのScriptにする (0:57~0:58)
作成済みのテキストファイルに計算時間や保存先、goコマンドなどを追加した上で結合させます。プログラムを用いれば一瞬です。
⑤Load ScriptからScriptを読み込ませ、寝る(or外出する) (1:02~)
PioViewerのTools→Load ScriptでPioにScriptを読み込ませます。上手く動作していればコンソールにSOLVER: startedの文字が出力されます。後はゆっくり寝るだけです。
自動計算のフローは以上になります。
VBAを使った僕の手法ではテキストファイルを作る→Pioを一旦経由する→再度テキストファイルを作るという全自動とは言えない手間を踏んでますが、add lineコマンドの追加等も実装出来ればこのような手間も省略出来ると思います。有識者の方はトライしてみてください……!
3. Hand履歴から必要なデータを取得するコツ
先程の手順②において、Scriptの自動作成においてはハンド履歴を読み取るプログラムが必要となります。以下ではStarsのハンド履歴からデータを取得する方法を解説していきます。
PokerStars 6max-zoomのHand Historyは次のような書式となっています。(一部省略)
PokerStars Zoom Hand : Hold'em No Limit ($0.10/$0.25)
Table 'Hydra' 6-max Seat #1 is the button
Seat 1: DimaNi86 ($145.21 in chips)
Seat 2: nanonium ($27.67 in chips)
Seat 3: NeverCall.com ($53.43 in chips)
Seat 4: Geconiel ($28.97 in chips)
Seat 5: Kaiser_EVR ($95.16 in chips)
Seat 6: jeromendg ($73.66 in chips)
nanonium: posts small blind $0.10
NeverCall.com: posts big blind $0.25
*** HOLE CARDS ***
Dealt to nanonium [5d Ad]
Geconiel: raises $0.40 to $0.65
Kaiser_EVR: folds
jeromendg: folds
DimaNi86: folds
nanonium: raises $2.07 to $2.72
NeverCall.com: folds
Geconiel: calls $2.07
*** FLOP *** [7c 4c 8s]
(以下略)
tree作成のために必要なデータは次の4つです。ボード以外のデータは直接ハンド履歴には書かれていませんので、プログラムでは少し工夫する必要があります。
・OOP、IPのレンジ(=Preflopアクションのライン)
・初期ポットサイズ(Starting Pot)
・最小スタック(Effective Stacks)
・Flopのボード
・OOP、IPのレンジ(=Preflopアクションのライン)
・初期ポットサイズ(Starting Pot)
"Dealt to ~"以降の行にある各アクションをなぞりながら、「どのポジションがレイズし誰がコールしたか」「ポットの金額推移」の2つを記録します。
レンジの取得には最後にレイズしたラインと最後にコールしたラインの2つが必要です。
例えばUTGvsBB 3bet-potだったら、"UTG_Raise_BB_Raise"というラインと"UTG_Raise_BB_Raise_UTG_Call"というラインを取得しておきます。
このラインを元にして対応するレンジをデータベース等から参照できます。
アクションのラインを追うにあたり、foldしたプレイヤーは無視出来ますが、fold以外にTimeoutやDisconnectもあるので無視する条件付けの際には注意しましょう。
また、レンジはOOP・IPのどちらなのかを区別する必要があります。ラインを2つ取得したら、それぞれにOOP・IPの区別をしてラベル付けしましょう。
ポジションは各座席に数値を割り振っておくことで比較できます。SBを0としてBB、UTG、MP……の順に連番を降ることで、Raiserの数値 > Callerの数値ならRaiserはIPとなります。
ポットサイズは少し面倒です。ただRaiseやCallした金額を取得していくだけでは、プレイヤーがブラインドだったときの差分を考えたりしなければなりません。
僕のコードではプレイヤー/投入チップの二次元配列を作り、各プレイヤーがポットに投じたチップ量を逐次配列に格納することで、最後に全ての金額を合計する手法をとっています。
Raise toの金額はプレイヤーがポットに投じた全金額となりますのでそのまま配列に上書き格納できます。Call額は差額表記なので格納済みの値に加算します。最初にSB/BBのそれぞれについてブラインド分の金額を格納しておくのを忘れないようにしましょう。
・最小スタック(Effective Stacks)
予めSeat 1~Seat 6の行から全員の名前と対応するチップ量を二次元配列に格納しておきます。Potに残っているプレイヤーのチップ量を比較し、少ない方を最小スタックと見なせます。
・Flopのボード
*** FLOP *** の行から[]内部を参照するだけです。
以上4つのデータを取得できれば、Pioに読み込ませるTreeBuilding.txtファイルを作ることが出来ます。このデータを元にしてadd lineを構築することも出来ます。
4. Pio学習をより便利にするポイント
より計算が早く終わるように出来る工夫は色々あります。これもmaspyさんの記事が参考になります。
①複数のベットサイズはturnまで。turn以降は復習時に再計算。
SolverはPCメモリ上限を超えるサイズのtreeは計算できません。
完全なGTO戦略を計算するためにflop・turn・riverの全てで複数のbetサイズを設定すると、treeサイズは途方も無い数値になります。あなたのPCメモリが何十GBも無い限り、複数のbetサイズ設定はturnまでにしておきましょう。
しかし、ベットsizeを省略するとGTO戦略とは乖離が生じてしまいます。この画像の下の設定ではturn以降のEVは理想よりも低くなってしまうでしょう。
そこで、Turn以降はその場で再計算させる手法を取ります。
そのためには上記maspyさんの記事内で解説されているCreate subtree configrationが非常に役に立ちます。
turnのカードを指定したらCreate subtree configrationをクリックし、turn以降のレンジやベットサイズを再度設定して計算させます。turnからはレンジがある程度絞られることでtreeサイズがかなり小さくなるため、多数のbetサイズを設定してもtree sizeにはあまり影響しません。SBvsBBでflop xxで回ったなどでも無い限り、tree sizeは300MB程度となり、その場で計算させても数分で終わります。400MB以上になると10数分といったところでしょうか。
②保存形式はsmall tree(without rivers)
full treeで保存すると読み込みに少し時間を取られます。turn以降はどのみち再計算させるので、riverの結果を廃した形式で保存すると復習時にcfrファイルの読み込み時間が短縮出来ます。
尚、very small treeで保存するとturnのカードを指定する度に再計算によるラグが生じるため、カードを切り替えて戦略比較をする際などに煩わしくなります。
5. PioSOLVER proを購入しましょう!
ホールデムのPioSOLVERライセンスにはbasic, pro, edgeの3種類があり、
この中でScriptを利用できるのはproとedgeです。Scriptを使用できればPioを非常に効率良く使用出来ますので、Pioの購入を迷っている方は是非proを購入することをお奨めします。
basicとproには2倍近い値段差がありますが、proのライセンスは2PC分であるため、2人で折半すれば実質basicよりも安く購入することができます。(僕も折半購入しました。) proの購入を悩んでいる方は、他に購入したい人を探してみるといいでしょう。
以上となります。ここまでお読みいただきありがとうございました。
感想や質問等はTwitterのリプライないしDMにていつでもお待ちしております。
●参考文献
Pioで使用できるコマンドは次のページにあるfull solver documentationから参照できます。