シンプルでおくぶかい頭脳ゲーム・Ostleを、PBシミュレータに載せました。
Rev.1 2023/8/4 評価値計算、入力制御を改善しました。(赤字)
対応機種
プログラム・サイズは1,566ステップです。PB-100実機+拡張メモリでも動作しますが、時間が掛かる為推奨しません。Pokecom GO(no wait)モードだとサクサク動作します。
Ostleゲームについて
・初期盤面は図の通り。自分の駒は□、相手の駒は■、穴は●です。
・自分の駒は一度に1マス押せます。押すときは相手/自分関係なく何個でも同時に押せます。
・盤の外に相手の駒を押し出すと駒を取れます。
・相手の駒を2個取ると勝利です。
・穴も1マスずつ押せます。
・穴に相手の駒を押し出しても取ることができます。
・ただし、穴が動けるのは空いているマスにだけです。
・一つ前の盤面に戻すのは禁止です。
遊び方
PB-100画面には一度に盤面の1行分しか表示できません。そこで、市販されているOstleボードゲームの実物を手元に準備し、画面表示を移しかえてプレイすることをお勧めします。DAISO版なら¥110で入手できます。
プログラムを入力し、shift+[0]またはP0にてRUN[EXE]すると、スタートです。中断後の再開は、P0にてRUN 6[EXE]です。
Player(あなた)が□、CPUが◆です。先攻はあなた(Playerターン)です。
[2][4][6][8]キーでカーソルを操作し、[5]キーを押して動かしたいPlayer駒□又は穴●を選択します。 次に、動かしたい方向に応じて[2][4][6][8]キーを押すと、駒が移動し、CPUターンに移ります。無効なキー入力の場合は、盤面が再表示され、キー入力がやり直しとなります。CPU思考中はカーソルが消えます。
どちらかの駒が盤外に押し出されたか穴に落ちた場合は、これまでに喪失した駒数が表示されます。
どちらかの駒の喪失が2になると、勝者を表示してゲームオーバーです。
注意
・Ostleの公式ルールにありますが、自分の一手前の盤面に戻すことは禁止されています。これは、双方行き詰った時に、押したり引いたりを永遠に繰り返すと、ゲームが進まなくなるためと思われます。このルールをCPU側は遵守しますが、Player側のチェックはしません。従って、Player自身で気を付けて下さい。(変数があと3つあれば実装できるのですが…)
・CPU思考は時間がかかります。これは、CPUの手全てについて局面評価をするためで、なおかつ盤データを圧縮しているためです。各プラットフォームでの所要時間実測値を参考に示します。
Ostle PB一手の所要時間比較
つぶやき
一手先の局面を評価するところまでは押し込みましたが、「身を切らせて骨を断つ」ような戦略的な思考には及びません。とにかくPB-BASICの変数の少なさに苦労しました。その為に盤面データの圧縮が必要になり、処理時間が長くなる原因となっています。どなたか、目から鱗の上手いアルゴリズムで高速化できませんか? もちろん、PB-BASICフォーマットで!
ゲームカード。ただし、実機では一手打ったら風呂に入りますw
PB-SIM形式
[P0]
2 VAC:PRINT "Ostle PB"
4 L=682:M=48:N=341
5 D=12:GOTO 76
6 $="_\SQ\DI\BX":PRINT
8 FOR E=0 TO 4
10 V=E+5*INT(D/5:GOSUB #4:PRINT MID(W+1,1);:NEXT E
12 IF C=0 THEN 52
14 PRINT CSR1.1+5*FRAC(D/5);"<";CSR6;INT(D/5);
16 IF KEY<>"" THEN 16
18 $=KEY:IF $="" THEN 18
20 E=D/5:IF $="4";IF 0<5*FRAC E;D=D-1
22 IF $="6";IF 4>5*FRAC E;D=D+1
24 IF $="8";IF 0<INT E;D=D-5
26 IF $="2";IF 4>INT E;D=D+5
28 IF $<>"5" THEN 6
30 IF KEY<>"" THEN 30
32 V=D:GOSUB #4:IF W<>1;IF W<>3 THEN 6
34 PRINT CSR6;"\LA^\DA\RA?";:H=0
36 $=KEY:IF $="4";H=-1
38 IF $="6";H=1
40 IF $="8";H=-5
42 IF $="2";H=5
44 IF $="" THEN 36
45 IF H=0 THEN 6
46 IF W=1;GOSUB #3:GOTO 50
48 GOSUB #2:IF W<>0 THEN 6
50 D=D+H:C=1-C:GOTO 6
52 G=-3^7:Z=3
54 FOR D=0 TO 24:GOSUB 78:V=D:GOSUB #4:IF W<2 THEN 70
56 IF W=2 THEN 64
58 FOR H=-5 TO 5 STEP 2:IF ABS H=3 THEN 62
60 GOSUB 78:GOSUB #2:IF W=0;GOSUB #1
62 NEXT H:GOTO 70
64 FOR H=-5 TO 5 STEP 2:IF ABS H=3 THEN 68
66 GOSUB 78:GOSUB #3:GOSUB #1
68 NEXT H
70 NEXT D
72 Z=0:D=R:H=S:V=R:GOSUB #4:IF W=3;GOSUB #2:GOTO 76
74 GOSUB #3
76 I=L:J=M:K=N:D=D+H:C=1-C:GOTO 6
78 O=L:P=M:Q=N:F=0:RETURN
[P1]
2 FOR T=0 TO 4:U=5:V=T:GOSUB #6:U=-5:V=T+20:GOSUB #6
4 U=1:V=T*5:GOSUB #6:U=-1:V=T*5+4:GOSUB #6:NEXT T
8 FOR T=0 TO 24:V=T:GOSUB #4:IF W<>3 THEN 22
10 FOR U=-5 TO 5 STEP 2:IF ABS U=3 THEN 20
12 V=T+U:IF V<0 THEN 20
14 IF V>24 THEN 20
16 IF ABS U=1;IF INT(V/5)-INT(T/5)<>0 THEN 20
18 GOSUB #6
20 NEXT U:GOTO 24
22 NEXT T:STOP
24 IF O=I;IF P=J;IF Q=K;F=-4^5
26 F=F+RAN#:IF F>G;G=F:R=D:S=H
28 RETURN
[P2]
1 V=D+H:W=3:IF V<0 THEN 6
2 IF V>24 THEN 6
3 IF ABS H=1;IF INT(V/5)-INT(D/5)<>0 THEN 6
4 GOSUB #4:IF W<>0 THEN 6
5 W=3:GOSUB #5:V=D:W=0:GOSUB #5
6 RETURN
[P3]
1 E=0:V=D
2 GOSUB #4:IF W=3 THEN 8
3 B=W:W=E:GOSUB #5:E=B:V=V+H:IF V<0 THEN 8
4 IF V>24 THEN 8
5 IF ABS H=1;IF INT(V/5)-INT((V-H)/5)<>0 THEN 8
6 IF E=0;RETURN
7 GOTO 2
8 IF E=0;RETURN
9 IF Z=3;F=100*(3-2*E+10*(2-E)*FRAC A+(1-E)*INT A):RETURN
10 A=A+10^(E-2):PRINT:PRINT "Lost";10*FRAC A;"\SQ";INT A;"\DI"
11 IF INT A>=2;PRINT "\SQ Win!":END
12 IF 10*FRAC A>=2;PRINT "\DI Win.":END
13 RETURN
[P4]
1 X=10*FRAC(V/10:Y=INT(V/10
2 W=4*FRAC(INT(L(Y+Z)/4^X)/4:RETURN
[P5]
1 Y=INT(V/10:X=4^(10*FRAC(V/10))
2 X=X*(INT(L(Y+Z)/X/4)*4+W+FRAC(L(Y+Z)/X))
3 L(Y+Z)=RND(X,-1):RETURN
[P6]
1 GOSUB #4:IF W<>1;IF W<>2;RETURN
2 E=4-3*W
3 V=V+U:IF V<0 THEN 9
4 IF V>24 THEN 9
5 IF ABS U=1;IF INT(V/5)-INT((V-U)/5)<>0 THEN 9
6 GOSUB #4:IF W<>1;IF W<>2 THEN 9
7 IF ABS(W*E)=2;E=E*10^(1+(2-W)*INT A):GOTO 9
8 GOTO 3
9 F=F+E:RETURN
実機形式