paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

スリーカードポーカーゲームを作りたい 払い戻し機能を作る編

作成中のスリーカードポーカーゲームですがゲームのメインであるベット、払い出しの作成が残っています。

賭け系の処理は

  • 賭ける
  • 勝負
  • 払い戻し

の順となりますが、ゲームを続ける限りチップの増減が発生します。
実装するにはこれらの流れをループさせないと行けません。

自分のレベルだと気が遠くなりそうな処理が残ってますが、遠くなるのはまだ早いです。
出来るところからやりましょう。

という訳で今回は払い戻し機能を作ります。

スリーカードポーカーの払い戻し

スリーカードポーカーは3つの払い戻しがあって

  • 手札で勝つ
    • アンティを賭けないと勝負できない
    • 払い戻しはベット額の2倍
  • アンティボーナス
    • 手札役ボーナス
    • 手札で負けてももらえる
  • アプラスボーナス
    • アンティとは別にベットする
    • 手札役ボーナス
    • 手札で負けてももらえる

があります。

細かい配当

  • アンティボーナス
    • ストレート 1:1
    • スリーカード 5:1
    • ストレートフラッシュ 6:1
  • アプラスボーナス
    • ワンペア 1:1
    • フラッシュ 4:1
    • ストレート 6:1
    • スリーカード 30:1
    • ストレートフラッシュ 40:1

カジノによってレートが違うそうですが、GTAオンラインのレートを採用しています。

作成済みの役判定の戻り値が使えそうなので、今回は試しにペアプラスボーナスを作ってみます。
チップを賭ける部分は作ってないですが、役ごとにn倍でいいですね。

手札判定の戻り値

手札判定後は役名と役ランク値が辞書型で返ってきます。
この役ランク値を流用しましょう。 強い役順に6~1のランクが返ってくるのでこの値を払い戻しの役判定に使います。

  • 役判定の関数
def Judge(hands, dealer=False):

    # Devide hands into suits and numbers
    suit = [ hands[0][0] , hands[1][0] , hands[2][0] ]
    rank = [int(x[1:]) for x in hands]

    # Sort of numbers for role evaluation
    rank.sort()

    # Evaluation of hand
    if len(set(suit)) == 1 and rank[1] == rank[0] + 1 and rank[2] == rank[1] + 1:
        return {'Straight Flash': 6}, max(rank)
    elif len(set(suit)) == 1 and rank[0] == 14 and rank[1] == 2 and rank[2] == 1:
        return {'Straight Flash': 6}, max(rank)
    elif len(set(rank)) == 1:
        return {'Three of a kind!': 5}, max(rank)
    elif rank[1] == rank[0] + 1 and rank[2] == rank[1] + 1:
        return {'Straight!': 4}, max(rank)
    elif rank[0] == 14 and rank[1] == 2 and rank[2] == 1:
        return {'Straight!': 4}, max(rank)
    elif len(set(suit)) == 1:
        return {'Flash!': 3}, max(rank)
    elif len(set(rank)) == 2:
        return {'One Pair!': 2}, max(rank)
    elif max(rank) < 12 and dealer == True:
        return {'Less than Queen-high. Dealer can\'t play': 0}, max(rank)
    elif max(rank):
        return {'High card!': 1}, max(rank)
        

アプラスの払い戻しをコードにするとこんな感じです。
handrankの部分にJudgeで帰ってきた役ランク値を入れます。

def Pair_plus(handrank, chip):
     if 2 in handrank:
         return chip * 1
     elif 3 in handrank:
         return chip * 4
     elif 4 in handrank:
         return chip * 6
     elif 5 in handrank:
         return chip * 30
     elif 6 in handrank:
         return chip * 40
     else:
         return None

動かしてみる

肝心のチップを賭ける処理が作れていないので、試しにこの部分だけターミナルで動かしてみます。
本当はpython使いとしてpdbとか使って動かしてみるのがいいんでしょうけど難しいので手動でやります。

>>> import pokerapp
>>> 
>>> d = pokerapp.Deck()
>>> d.shuffle()
>>> 
>>> 
>>> player = pokerapp.Handout(d)
>>> player
['♢7', '♢13', '♢2']
>>> 
>>> h = pokerapp.Judge(player)
>>> h
({'Flash!': 3}, 13)
>>> 
>>> def Pair_plus(handrank, chip):
...     if 2 in handrank:
...         return chip * 1
...     elif 3 in handrank:
...         return chip * 4
...     elif 4 in handrank:
...         return chip * 6
...     elif 5 in handrank:
...         return chip * 30
...     elif 6 in handrank:
...         return chip * 40
...     else:
...         return None
... 
>>> 
>>> Pair_plus(h[0].values(),100)
400

手札はダイヤのフラッシュです。
チップを100賭けていたとして、ちゃんと4倍の400が返ってきますね。

ここで思ったのですが、アンティボーナスも同じ仕組みなので
払い戻しは同じ機能を持たせる様にクラス化しちゃった方が良さそうですね。
(クラスを作るってのはこういう事か…?)

払い戻しの疑似コード

クラス化はさっき思い付いたばかりなのでとりあえず疑似コードで残しておきます。

class payoff (bet, hand)

    def anti

      if hand == straight 
        bet * 1
      elif hand == three of a kind 
        bet * 4
      elif hand == straignt flash 
        bet * 5
      else 
        none

    def pairplus

      if hand == pair 
        bet * 1
      elif hand == flush 
        bet * 4
      elif hand == straight 
        bet * 6
      elif hand == three of a kind 
        bet * 30
      elif hand == straight flush 
        bet * 40
      else
        none

    def check
      bet + anti + pairplus

これでいけそうな気がします。
あとはゲーム開始~終了までの賭け金処理をどうするかですね。

スリーカードポーカーのややこしいところは勝負に負けても役ボーナスで配当が発生するところなんですよね。
ベット額、アンティ、ペアプラスのタプルとかにしてそれぞれの値を入れ換えていくのがいいのかな?
そして勝負後に各払い戻し分を足して返ってくると。

これが出来てから一連の処理をループさせればゲームになりそうですね。
先がちょっと見えてきました。


本シリーズ