CASIO pocket computer
PB-100の宇宙

5×5の盤にトランプを配置するポーカー
SQUARE
by PBロッキー

公開日 03/04/18

プログラムリスト

VAC :FOR B=1 TO 5:PRINT B:FOR H=-27 TO 4:I(ABS H)=1:NEXT H:FOR C=1 TO 25
D=.1*INT (62+RAN#*4)+INT (RAN#*(8+B:FOR E=0 TO 24:IF D=L(E) THEN 2
NEXT E:$=" ♠♥♦♣A23456789XJQK*123Hs4fRS":GOTO 7
PRINT "[";MID(FRAC G*9+1,1);MID(G,1);"]";
F=F(H*J+I):G=F(H*K+I):RETURN
H=1:FOR I=5 TO 25 STEP 5:GOTO 10
G=D:GOSUB 4:PRINT I;K;:GOSUB 4:INPUT F:IF ABS (F-3<3;I=K:K=F
IF F+G≠1 THEN 7
F(5*K+I)=D:NEXT C:FOR I=1 TO 5
10 C=1:D=9:E=2:FOR J=1 TO 5:FOR K=1 TO 5:GOSUB 5:IF INT F≠INT G;D=D-.5
11 IF F>INT G*2.5;E=SGN E:GOTO 13
12 IF INT F-G>4;E=0
13 NEXT K:IF FRAC F≠FRAC G;C=0
14 NEXT J:C(C)=6+E:PRINT :IF 0>D*E;D=4
15 A=A+INT (D*9*FRAC (SQR 27*D↑4:PRINT MID(D+20,1);A;:NEXT I:GOTO I
30 STOP :IF A≧B*90;NEXT B:PRINT "CLEAR!!"

15行に続くのが30行なのに注意しましょう.それについての解説は技術情報で.

変数の増設

DEFM 10 EXE

実行の前に変数を10個増設します.(8ステップx 10個 = 80ステップ)

プログラム自体は464ステップで、変数増設分の80ステップとあわせてちょうど544ステップになります.

技術情報

変数表

変数カード配置時の内容約判定時の内容
A得点
Bステージ
CFOR~NEXTフラッシュ判定
D新カード
EFOR~NEXTストレート判定
F座標入力判定カード 1
Gカード表示判定カード 2
H=55→1
IX 座標FOR~NEXT
J=1FOR~NEXT
KY 座標FOR~NEXT
L(0)~L(24)カード

行番号マップ

処理
1初期設定他
2新しいカード、チェック
3キャラクタセット他
4トランプ表示
5カード読み出し
6判定ループ後半
7配置画面表示、キー入力、座標変更
8カード配置用判定
9新しいカード置く、判定ループ前半他
10役判定初期設定、ペア系判定他
11ロイヤルフラッシュの判定
12ストレート判定
13フラッシュ判定
14フラッシュ、ロイヤルフラッシュの決定
ストレートの決定他
15得点計算、役・合計点表示
30クリア判定、エンディング表示他

初期化

FOR H=-27 TO 4:I(ABS H)=1:NEXT H

1行目ではカードの初期化(L(0)~L(24)=1)と同時にカード配置用変数の初期化(H=5, I~K=1)も行っています.

小数部に格納したマーク情報の取り出し

2行目の頭で乱数から新しいカードがつくられます.RAN# が2つありますが、これは1つの変数で整数部にはトランプの数字を、小数部にはマークを格納しているのです.

この式の中の62とは何でしょう?

Dの値の最小は6.2となり、これは A を表します.

ここで併せて4行目のカードの表示を見て下さい.マークを表示するため小数を抜き出すときに FRAC G*10 としてしまいがちですが、 小数部の最小値を0.2にしてあるため FRAC G*9 とすることができます.

さらに整数部の最小値を6にしカード未配置の値を1にしたことで、数字の表示は MID(G,1) とダイレクトに行っています.

ポーカーの役判定アルゴリズム ペア系

10行以降、いよいよ役の判定アルゴリズムを見ていきましょう.

ポーカープログラムを組んだことがあるという方ならご存知のように、ペア系の判定には有効な方法が知られています.私はアスキーの本で知りました. 詳しい本には五角形の図付きで解説されていると思います.

まず、五角形の 5つの頂点に判定する5枚のトランプを置いていきます.そして10本の対角線について、トランプの数字が同じ対角線の数を数えます. 1本ならワンペア、2本ならツーペア、3本ならスリーペア、4本ならフルハウス、フォーカードは6本です.

ポーカーの役判定アルゴリズム ストレート系

このようにペア系が簡潔に判定できるのに対し、ストレートの判定の多くは数字の大きさ順に並び替えたのち、調べるという方法がほとんどでした.

SQUARE では 5つの数字の差が4以内であるかを調べます(12行).その上でペアが無い(0本)ならストレート成立という判定をしています.(14行 IF O>D*E;D=4)

また14行の頭では、5つの数字の差が4以内で、その上フラッシュの場合、 ペア系のチェックを待たずにストレートフラッシュかロイヤルストレートフラッシュの成立となります(C(C)=E+6).

ポーカーの倍率を求める

こうして役の判定結果が D に格納されましたが困ったことに、役の強さと D の数値が必ずしも一致しないのです.

ブタは D=-1、ワンペアは D=0、ツーペアは D=1、 スリーカードは D=2、ストレートは D=4、フラッシュは D=6、 フルハウスは D=3、フォーカードは D=5、ストレートフラッシュは D=8、 ロイヤルストレートフラッシュは D=7 という具合です.

既にお気づきのように3行の $ の内容も役のランク順通りではありません.役の表示はこうして解決できるとして、問題は得点の計算です.

ここで他機種ならデータテーブルを用意して~となりますが、PB-100 の限られたメモリではそうもいきません.

そこで15行頭ではトロネコでおなじみ、データを数式からつくっているのです.

D*9*FRAC(SQR 27*D^4 とするとポーカーの適当な倍率が得られるというのは、コンピュータのメモリが高価だった70年代には割と知られていたテクニック、、、じゃぁありません!! SQUARE を完成に漕ぎつけるために PB-100 を数時間走らせて求めた式なのであります!!

あぁ、あと10ステップも余裕があればもう少しまともな方法もあったのに...(オイオイ!)

変則的なジャンプ命令

15行の最後では NEXT I:GOTO I と見なれないことをしてます.

1回目にここを通過するときは I=6 で6行に飛びます.2回目には I=30 で30行へ.

この変則的な方法で、縦の5組のチェックから横の5組のチェックへの切り替えを行います.

コラム
行番号に絡むリストの圧縮

GOTO 0

一般に BASIC において行番号は、のちのちの追加がしやすいように10おきに、などと入門書には書かれています. しかし Pocket BASIC では、そんな悠長なことをしてられないことがしばしば、私の作品にいたってはそれは必然であります.

PB-100 では GOTO, GOSUB の後にくる行番号はその字数分だけステップを使うため、また一行に62文字までの制限のために、 おいそれと巨大な行番(version 1 BASIC では100行~ 999行)を使うわけには行きません.

とくに1行~9行は、そこにジャンプするのに( :GOTO 1 など)3ステップで可能な点も有効利用したいところです. (こうなると個人的には0行もありにして欲しかったです.)

行番号が一定の数列でなくてもよい

それに加えてSQUAREでは、必ずしも行番号が一定の数列(階差数列)でなくてもよいことを利用してリストを最適化しています.

ご覧のように15行の後に30行が続くのがそれで、変数の変化を把握して :GOTO I のみで分岐させるように工夫した結果、行番号が離れることになりました.

PB-100 では GOTO N*5+9 などと飛び先を変数を含む式で指定して分岐させる方法が多用されますので、以上を頭の隅に置いておけば式部分を圧縮できる場合もでてくるでしょう.

余談ですが version 2以降の BASIC では ON GOTO, ON GOSUB 文を備えていますが、version 1機との互換性の確保のためにも使用は極力控えたいところです.