このブログ内を検索可能

2024年7月11日木曜日

テキサスホールデムの確率(10) 勝率計算

相手の平均的な役の確率分布が分かれば勝率が判明する。

相手の役の確率分布を{0,0,0,0,0,0,0,…,1(ワンペア数字3柄2),2(ワンペア数字3柄3),2(ワンペア数字3柄4),1(ワンペア数字4柄1),0,0,0…}と仮定した場合、

自分のカード7組の最大役がワンペア数字3柄3であった場合、「勝ち」となるのは相手がワンペア数字3柄2まですなわち1通りであり、勝率は全体の1+2+2+1=6に対して1なので1/6。

もし自身の現在のカードが6枚ならば、ここから1枚が提示されてこの7組になる確率は1/46でありその勝率は1/6である。結局1/(46*6)=1/276となる。

そしてその6枚のカードは他にも45通り存在し、それらに対して勝率が計算される。その和をとったものは期待値の定義になり、すなわちペイアウト率が判明する。

ただし重複を避けるために最初に結果の7組から、さかのぼって到達可能なパターンを判別し順次加算するため、各2~6組にたいしての並立作業は行えない。

かかる時間としては、7組は133784560通りあり、その各通りに対して7C2+7C5+7C6+7C7=21+21+7+1=50パターンの勝率判定があるので、67億回くらい大小の判定をしなければならない。よってその判定はとにかく簡略化する必要がある。

判定方法としては自身の役の強さ未満の確率分布の総和/確率分布を出すために行った試行回数で求められる。しかしこれは途方もない時間がかかることが予想されるのでいったん試行回数を650000回程度で止めてみた確率分布を採用してみる。

最初の2枚のカードのものでまず計算すると、100000回で32秒かかる。これを133784560通りやるので32*1337ということで40000秒くらいかかる。これは650分に相当し1日足らずで出来る。これは時間がかからず現実的である。

これが分かれば最初2枚時点での勝率がおおまかにわかるので、まず標準の確率分布をしっかりと計算させる。

7C2通りに対して加算処理を行うのが11時間程度なので、

7C5通りに対しても同じく11時間程度。

7C6通りに対しては7/21倍が期待されるので4時間程度。

7C7通りについてはそのまま勝率を用いることができる。

ただし7枚の組に関しては格納すべきリストの量が1億少々になるのでエクセルなどに保存できなさそうでそこをどうするかが課題。

一応下の結果は【ポーカーの確率表】テキサスホールデムポーカーの役の確率や勝率を解説 (pokerguild.jp)に記されているが、この数値が本当かどうかをチェックする。

例えば柄1のAと柄1の5ならば柄が一致しているのでsuitedであり、この表を見ると60%であるが、我の52C2通りのリストでそれに似た数値を得られているかをチェックする。ただし答え合わせまでは時間がかかる。
これがおおむねあっていると分かれば5,6,7枚の組に対しても勝率があっていることがおそらく保証されるので、いよいよ実用化可能。5~7枚の組に関して全データが載っているサイトはおそらくなく、有料レベルである。
正直ポーカーのプログラムとテキサスホールデムの仕様は知り始めてまだ1週間かそこらなので専門用語はほぼ何も知らない。
とりあえずルールに則って厳密な確率を求めることはできるが時間がかかることと、簡易バージョンの作成ができる程度である。そしてそれは先行データにはかけた時間の関係上勝てないがとりあえずカジプロでどれくらい通用するかが気になる。

途中経過として{2500000,{{1,1},{1,3},{1,6},{1,7},{2,6},{2,9},{4,9}},136,0.682751,136,{0.500769,0.151746,0.104533,0.10521,0.0651906,0.0656041,0.0633125,0.0636142,0.0645725,0.0649154,0.0652869,0.0656869,0.0869254,0.0650688,0.0549903,0.0551082,0.0555999,0.0505558,0.0510104,0.05118,0.051496,0.0526326,0.0529934,0.0533849,0.0538071,0.087283,0.0652069,0.0549194,0.0550502,0.0555457,0.050558,0.051025,0.0511983,0.0515161,0.0526592,0.0530217,0.0534151,0.0538389,0.0883532,0.0656368,0.0550524,0.0551591,0.0556651,0.0506536,0.0511237,0.0513004,0.0516234,0.0527719,0.0531412,0.0535426,0.0539735,0.0544433,0.0547887,0.0551341,0.0525799,0.0529617,0.0533603,0.0536252,0.0545335,0.0548358,0.0551643,0.0555193,0.0753445,0.0571774,0.0460347,0.0464242,0.0468182,0.0436464,0.0440715,0.0445159,0.0447856,0.0458574,0.0461668,0.0465039,0.0468689,0.0758109,0.0573871,0.0460522,0.0464423,0.0468424,0.0436676,0.0440928,0.044538,0.0448089,0.0458817,0.0461926,0.0465314,0.0468979,0.0767469,0.0578123,0.0461243,0.0465163,0.0469245,0.0437526,0.0441804,0.0446292,0.0449048,0.0459827,0.0462998,0.0466459}}という結果を得た。
これは{{1,1},{1,2}}というカードの組はもはやこれ以降は出現しないため第1要素のみ計算が完了していることを意味するが勝率は50.1%となっている。だが実際の確率は57%であり、そこそこ異なる。やはりその2枚を除いたもので計算していなかったため誤差がでたものと考えられる。
いずれにせよ、7%も差ができてしまうとこれだけ時間をかけてもあまり有効とは言えないので、自身の役の強さから勝負に出る確率を遺伝的に計算するプログラムへとシフトする。
具体的にはノーペアに対して全掛けする遺伝子は短命であるが、適切にBETを調整する遺伝子は生き残る。ランダムに役毎にどれくらいBETするかの遺伝子を構成し、それ同士で戦わせる。そして相手のBETに応じてBETを変えたりする遺伝子も導入してみたいと思っているが、まずは簡単バージョンでそれを入れないものでやってみたい。

理想としてはそれによって世代を経て成熟していった遺伝子が、ランダムなものに対して非常に高い勝率を維持し続けることである。
この操作は上記のように時間もかからないので、やってみる価値はある。それが無理ならルーレットなどの「偏り」を利用した作戦に出るかもしれない(プレイしていると放出期と回収機の差が激しいため何らかの法則あるいは傾向があるのではないかと考えた)