ポーカーの役判定エンジン
ポーカーの役判定 - 永字八法のNScripterによる実装。
もやもやしていたものを吐き出せて、すっきりした。
軽く検証したが、徹底的な検証はまた後日やるかも。
説明
以下のスクリプトで、poker_hand命令を実装する。
- 名前
- poker_hand
- 引数
- 5つの文字列を取る。それぞれが、手札を意味する。
- 返値
- 直接はなし。ただし、フラグ変数を変更する。
- 用途
- 与えられた五つの文字列をカードとして解釈し、それがポーカーの役を満たすかどうかを判定する。
引数について
一つ一つの文字列は、"n,m"のようなものを期待している。前半nはスートの番号である。後半mはカードの番号である。
たとえば、スペードのエースは"1,1"のようになるだろう。(スートと番号の対応は使用者にまかされている。)クラブのキングは、"4,13"だろうか。
ジョーカーは、(使うのであれば)"0,0"を使用するべきである。
また、与える順番は考慮されない。
返値について
直接の返値はないが、いくつかの変数が書き変わるので、それを参照する。
- %poker_strait
- 手札がストレートになるとき、1になる。
- %poker_royal
- ストレートの中で特に、1,10,11,12,13によるものならば、1になる。
- %poker_flash
- 手札が(ジョーカーを除いて)同一のスートで構成されていると、1になる。
- %poker_five_card
- ファイブカードの時、1になる。
- %poker_four_card
- フォーカードの時、1になる。
- %poker_fullhouse
- フルハウスの時、1になる。
- %poker_three_card
- スリーカードの時、1になる。
- %poker_two_pair
- ツーペアの時、1になる。
- %poker_one_pair
- ワンペアの時、1になる。
(なお、役は判定できるが、役の強さがどのような順になるか、あるいは役の点数の設定などは使用者にまかされている。)
特徴
- ジョーカーが何枚あっても対応できる。
- 同一のカードが複数あっても対応できる。
これはつまり、複数のパックをまとめて一つのデッキにして使用する場合を想定している。
使用例
poker_hand "1,1","1,10","1,11","1,12","1,13"
上記を実行すると、%poker_strait, %poker_royal, %poker_flashの三つが1になり、ロイヤルストレートフラッシュであることがわかる。
poker_hand "1,1","2,3","3,5","4,7","5,9"
上記を実行すると、フラグ変数全てが0になり、いわゆる「ブタ」であることがわかる。
スクリプト(define節、game以上)
mov %0,100 ; 適宜変更すること。 numalias poker_hand1,%0:inc %0 numalias poker_hand2,%0:inc %0 numalias poker_hand3,%0:inc %0 numalias poker_hand4,%0:inc %0 numalias poker_hand5,%0:inc %0 numalias poker_loop,%0:inc %0 numalias poker_loop2,%0:inc %0 numalias poker_loop3,%0:inc %0 numalias poker_number_max,13 ; 数字の最大値 numalias poker_suit_max,4 ; スートの種類 numalias poker_number_matrix,%0:inc %0 numalias poker_number_matrix2,%0:inc %0 numalias poker_suit_matrix,%0:inc %0 dim ?poker_number_matrix[poker_number_max] dim ?poker_number_matrix2[5] dim ?poker_suit_matrix[poker_suit_max] numalias poker_numbers_max,%0:inc %0 numalias poker_numbers_min,%0:inc %0 numalias poker_number,%0:inc %0 numalias poker_suit,%0:inc %0 numalias poker_temp,%0:inc %0 numalias poker_count,%0:inc %0 numalias poker_flash,%0:inc %0 numalias poker_royal,%0:inc %0 numalias poker_royal_flag,10 ; 10 で始まるストレートがロイヤル numalias poker_strait,%0:inc %0 numalias poker_five_card,%0:inc %0 numalias poker_four_card,%0:inc %0 numalias poker_fullhouse,%0:inc %0 numalias poker_three_card,%0:inc %0 numalias poker_two_pair,%0:inc %0 numalias poker_one_pair,%0:inc %0 defsub poker_hand
スクリプト(game以下、*start以上)
*poker_hand ; 手札の取得。手札は、/区切りを期待している。 getparam $poker_hand1,$poker_hand2,$poker_hand3,$poker_hand4,$poker_hand5 ; 手札表を初期化する。 for %poker_loop=0 to poker_number_max:mov ?poker_number_matrix[%poker_loop],0:next for %poker_loop=0 to 5:mov ?poker_number_matrix2[%poker_loop],0:next for %poker_loop=0 to poker_suit_max:mov ?poker_suit_matrix[%poker_loop],0:next ; 手札を分解して手札表に格納する。 for %poker_loop=poker_hand1 to poker_hand5 split $%poker_loop,",",%poker_suit,%poker_number mov ?poker_suit_matrix[%poker_suit],?poker_suit_matrix[%poker_suit]+1 if %poker_suit=0 mov %poker_number,0 mov ?poker_number_matrix[%poker_number],?poker_number_matrix[%poker_number]+1 next ; 手札の判定 gosub *poker_hand_flash gosub *poker_hand_strait ; 初期化 for %poker_loop=poker_five_card to poker_one_pair mov %%poker_loop,0 next if %poker_strait>0 return ; ストレート系の手札なら、ペア系の判定はしない。 gosub *poker_hand_pair return ; フラッシュ判定 *poker_hand_flash mov %poker_temp,0 ; 初期化 mov %poker_flash,0 ; 初期化 for %poker_loop=1 to poker_suit_max if ?poker_suit_matrix[%poker_loop]>0 inc %poker_temp; next notif %poker_temp>1 mov %poker_flash,1 ; 使われているスートが1種類ならば、フラッシュだ。 return ; ストレート判定 *poker_hand_strait ; 下準備 mov %poker_numbers_max,0 mov %poker_numbers_min,6 for %poker_loop=1 to poker_number_max if %poker_numbers_max<?poker_number_matrix[%poker_loop] mov %poker_numbers_max,?poker_number_matrix[%poker_loop] notif ?poker_number_matrix[%poker_loop]=0 if %poker_numbers_min>?poker_number_matrix[%poker_loop] mov %poker_numbers_min,?poker_number_matrix[%poker_loop] mov ?poker_number_matrix2[?poker_number_matrix[%poker_loop]],?poker_number_matrix2[?poker_number_matrix[%poker_loop]]+1 next if %poker_numbers_min=6 mov %poker_numbers_min,0 mov %poker_strait,0 ; 初期化 ; ペアが存在するのならば、それはストレートではない。 if %poker_numbers_max>1 return if %poker_numbers_max=0 mov %poker_strait,1:mov %poker_royal,1:return ; 全部ジョーカーなら、ロイヤルストレートに決まってる。 ; 実際の判定 ; 10から始まるストレートか? mov %poker_royal,1 for %poker_loop=poker_royal_flag to poker_royal_flag+poker_number_max mov %poker_temp,?poker_suit_matrix[0] mov %poker_loop2,-1 mov %poker_count,0 ~ inc %poker_loop2 if %poker_loop2=5 if %poker_count=5 mov %poker_strait,1:break mov %poker_loop3,%poker_loop+%poker_loop2 ; Don't Erase if %poker_loop3>poker_number_max sub %poker_loop3,poker_number_max:skip -1 ; 判定 if ?poker_number_matrix[%poker_loop3]>0 inc %poker_count:jumpb if %poker_temp>0 dec %poker_temp:inc %poker_count:jumpb ~ mov %poker_royal,0 next return *poker_hand_pair ; 下準備 if %poker_numbers_max=0 return ; 全部ジョーカーだってよ。その場合はペアにはならんわなあ。 ; ジョーカーの枚数によって分岐。 tablegoto ?poker_suit_matrix[0],*poker_hand_pair0,*poker_hand_pair1,*poker_hand_pair2,*poker_hand_pair3,*poker_hand_pair4 ; ジョーカーが0枚 *poker_hand_pair0 if %poker_numbers_max=4 mov %poker_four_card,1 ; フォーカード if %poker_numbers_max=3 if %poker_numbers_min=2 mov %poker_fullhouse,1 ; フルハウス if %poker_numbers_max=3 if %poker_fullhouse=0 mov %poker_three_card,1 ; スリーカード if %poker_numbers_max=2 if ?poker_number_matrix2[1]=1 mov %poker_two_pair,1 ; ツーペア if %poker_numbers_max=2 if ?poker_number_matrix2[1]=3 mov %poker_one_pair,1 ; ワンペア return ; ジョーカーが1枚 *poker_hand_pair1 if %poker_numbers_max=4 mov %poker_five_card,1 ; フォーカード+ジョーカー=ファイブカード if %poker_numbers_max=3 mov %poker_four_card,1 ; スリーカード+ジョーカー=フォーカード if %poker_numbers_max=2 if %poker_numbers_min=2 mov %poker_fullhouse,1 ; ツーペア+ジョーカー=フルハウス if %poker_numbers_max=2 if %poker_numbers_min=1 mov %poker_three_card,1 ; ワンペア+ジョーカー=スリーカード if %poker_numbers_max=1 mov %poker_one_pair,1 ; かろうじてワンペア return ; ジョーカーが2枚 *poker_hand_pair2 if %poker_numbers_max=3 mov %poker_five_card,1 ; スリーカード+2ジョーカー=ファイブカード if %poker_numbers_max=2 mov %poker_four_card,1 ; ペア+2ジョーカー=フォーカード if %poker_numbers_max=1 mov %poker_three_card,1 ; 1+2ジョーカー=スリーカード return ; ジョーカーが3枚 *poker_hand_pair3 if %poker_numbers_max=2 mov %poker_five_card,1 ; ペア+3ジョーカー=ファイブカード if %poker_numbers_max=1 mov %poker_four_card,1 ; 1+1+3ジョーカー=フォーカード return ; ジョーカーが4枚 *poker_hand_pair4 mov %poker_five_card,1 ; ファイブカードしかないだろ、常考。 return