CASIO pocket computer
PB-100の宇宙

top > ゲームライブラリ > SQUARE > プログラムリスト

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

プログラムリスト

    1 VAC :FOR B=1 TO 5:PRINT B:FOR H=-27 TO 4:I(ABS H)=1:NEXT H:FOR C=1 TO 25
    2 D=.1*INT (62+RAN#*4)+INT (RAN#*(8+B:FOR E=0 TO 24:IF D=L(E) THEN 2
    3 NEXT E:$=" ♠♥♦♣A23456789XJQK*123Hs4fRS":GOTO 7
    4 PRINT "[";MID(FRAC G*9+1,1);MID(G,1);"]";
    5 F=F(H*J+I):G=F(H*K+I):RETURN
    6 H=1:FOR I=5 TO 25 STEP 5:GOTO 10
    7 G=D:GOSUB 4:PRINT I;K;:GOSUB 4:INPUT F:IF ABS (F-3<3;I=K:K=F
    8 IF F+G≠1 THEN 7
    9 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 10EXE

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

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

技術情報

変数表

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 step も余裕があればもう少しまともな方法もあったのに...(オイオイ!)

変則的なジャンプ命令

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 の後にくる行番号はその字数分だけ step を使うため、また一行に 62 文字までの制限のために、 おいそれと巨大な行番( version 1 BASIC では 100 行~ 999 行)を使うわけには行きません.

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

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

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

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

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

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