CASIO pocket computer
PB-100の宇宙

1行将棋
by NUAO

公開日 2022/10/14

PB で将棋!?ゲームになるの?意外になるんです…

RUN DEG
KP D  d p k

ルール

RUN DEG
KP D  d p k
  • 盤面は12マス、左側5マスが自陣、右側5マスが敵陣
  • 大文字は自コマ、小文字は敵コマ(コンピュータ)
  • K kは王将、P pは桂馬、D dは歩兵
  • 動ける範囲
    • [自陣側]←K→ ←P→→ D→[敵陣側]
    • K(王将):前後に1マス動ける
    • P(桂馬):前に2マス、後ろに1マス動ける
    • D(歩兵):前に1マス動ける
  • 取得した敵コマは盤外に保管され、自コマとして敵陣以外に打ち込める
  • それぞれ王将を取得した時点でゲームオーバー
  • 自分が先手

注意点

盤面が1次元で単純なので、コンピュータは千日手(行ったり戻ったりを繰り返す)を取りやすい.千日手は人間が破ってください.

操作方法

開局

実行前に DEFM 4 で変数領域を確保すること.

shift0 にて実行開始すると、最初に盤内(将棋盤)が表示される.

5 盤内と盤外(取得したコマの保管場所)の表示切替.

盤内の自コマを移動する場合

キー自コマを選ぶ自コマの選定後、移動方向を決める
1, 3カーソルの移動.(カーソル形状は 自コマの移動方向.
2カーソル位置の自コマを選定
それ以外のキー又は進めない方向を押すとキャンセルとなる.

取得したコマを盤内に打ち込む場合

RUN DEG
P  d   

盤外では、左4マス(大文字表示)に取得したコマが表示される.右4マス(小文字表示)は敵が取得したコマが表示される.

キー5 を押して盤外表示に切り替え、打ち込む自コマを選ぶ.盤内表示に切り替わるので、打ち込む位置を決める
1, 3カーソルの移動.カーソルの移動.(カーソル形状は <
2カーソル位置の自コマを選定カーソル位置に打ち込む
それ以外のキー又は進めない方向を押すとキャンセルとなる

プログラムリスト

P0
VAC
K=3:M=2:O=1:R=-1:T=-2:V=-3:B=1
C=0:GOSUB #1
G$=KEY:IF G$="" THEN 8
10 IF G$="1" THEN 20
12 IF G$="3" THEN 24
14 IF G$="2" THEN 38
15 IF G$="5";B=-B:A=0
16 GOTO 5
20 IF A<1 THEN 8
22 A=A-1:GOTO 5
24 IF A>1-B+(B+1)*5 THEN 8
28 A=A+1:GOTO 5
38 C=A+(1-B)*6
40 IF K(C)<1 THEN 5
42 IF B=-1 THEN 74
44 PRINT :PRINT "1<>3?";
45 IF KEY≠"" THEN 45
46 G$=KEY:IF G$="" THEN 46
48 IF G$="1" THEN 54
50 IF G$="3" THEN 58
52 GOTO 5
54 D=-1:IF K(C)=1 THEN 5
56 GOTO 60
58 D=1:IF K(C)=2;D=2
60 IF C+D>-1;IF C+D<12 THEN 64
62 GOTO 5
64 IF K(C+D)>0 THEN 5
66 IF K(C+D)=-3;PRINT :PRINT "Win!":END
68 IF K(C+D)=0 THEN 72
69 FOR J=12 TO 15:IF K(J)=0;K(J)=-K(C+D):GOTO 72
70 NEXT J
72 K(C+D)=K(C):K(C)=0:GOTO 88
74 A=0:B=1
75 GOSUB #1
76 G$=KEY:IF G$="" THEN 76
77 IF G$="1" THEN 81
78 IF G$="3" THEN 83
79 IF G$="2" THEN 85
80 GOTO 5
81 IF A>0;A=A-1:GOTO 75
82 GOTO 76
83 IF A<6;A=A+1:GOTO 75
84 GOTO 76
85 IF K(A)=0;K(A)=K(C):K(C)=0:GOTO 88
86 GOTO 75
88 A=12:GOSUB #1:GOSUB #3
90 IF F<-50 THEN 5
92 IF K(C+D)=3;PRINT :PRINT "Lose":END
94 IF K(C+D)=0 THEN 99
96 FOR J=16 TO 19:IF K(J)=0;K(J)=-K(C+D):GOTO 99
97 NEXT J
99 K(C+D)=K(C):K(C)=0
100 A=C+D:GOTO 5

P1
PRINT :GOTO 3-B
FOR J=0 TO 11:GOSUB K(J)+15:NEXT J:GOTO 5
FOR J=0 TO 7:GOSUB K(J+12)+15:NEXT J
IF A>10;RETURN
IF C>11;PRINT CSR A+1;"<";:RETURN
PRINT CSR A+1;"←";:RETURN
12 PRINT CSR J;"k";:RETURN
13 PRINT CSR J;"p";:RETURN
14 PRINT CSR J;"d";:RETURN
15 RETURN
16 PRINT CSR J;"D";:RETURN
17 PRINT CSR J;"P";:RETURN
18 PRINT CSR J;"K";:RETURN

P2
E=0:IF H+I>-1;IF H+I<12 THEN 3
RETURN
IF H<12 THEN 6
IF K(H+I)=0 THEN 15
RETURN
IF K(H+I)<0;RETURN
15 G=K(H+I):K(H+I)=K(H):K(H)=0
20 IF G>0;E=E+G*2
25 FOR J=0 TO 11
30 IF K(J)<1 THEN 99
35 IF K(J)>1 THEN 50
40 IF J+1>11 THEN 99
45 IF K(J+1)<0;E=E+K(J+1)
47 GOTO 99
50 IF K(J)>2 THEN 80
55 IF J+2>11 THEN 65
60 IF K(J+2)<0;E=E+K(J+2)
65 IF J-1<0 THEN 99
70 IF K(J-1)<0;E=E+K(J-1)
75 GOTO 99
80 IF J+1>11 THEN 90
85 IF K(J+1)<0;E=E+K(J+1)
90 IF J-1<0 THEN 99
95 IF K(J-1)<0;E=E+K(J-1)
99 NEXT J
100 K(H)=K(H+I):K(H+I)=G
105 E=E-(H+I)/20+RAN#/10:IF E>F;C=H:D=I:F=E
110 RETURN

P3
F=-99:FOR H=0 TO 11
IF K(H)>-1 THEN 8
GOTO 8+K(H)
I=-1:GOSUB #2:I=1:GOSUB #2:GOTO 8
I=-2:GOSUB #2:I=1:GOSUB #2:GOTO 8
I=-1:GOSUB #2
NEXT H
FOR H=16 TO 19
10 IF K(H)=0 THEN 12
11 FOR I=5-H TO 11-H:GOSUB #2:NEXT I
12 NEXT H
30 RETURN

Pocket BASIC Simulator形式プログラムリスト

[P0]
1 VAC
2 K=3:M=2:O=1:R=-1:T=-2:V=-3:B=1
5 C=0:GOSUB #1
8 G$=KEY: IF G$="" THEN 8
10 IF G$="1" THEN 20
12 IF G$="3" THEN 24
14 IF G$="2" THEN 38
15 IF G$="5";B=-B:A=0
16 GOTO 5
20 IF A<1 THEN 8
22 A=A-1: GOTO 5
24 IF A>1-B+(B+1)*5 THEN 8
28 A=A+1: GOTO 5
38 C=A+(1-B)*6
40 IF K(C)<1 THEN 5
42 IF B=-1 THEN 74
44 PRINT: PRINT "1<>3?";
45 IF KEY<>"" THEN 45
46 G$=KEY: IF G$="" THEN 46
48 IF G$="1" THEN 54
50 IF G$="3" THEN 58
52 GOTO 5
54 D=-1: IF K(C)=1 THEN 5
56 GOTO 60
58 D=1: IF K(C)=2;D=2
60 IF C+D>-1;IF C+D<12 THEN 64
62 GOTO 5
64 IF K(C+D)>0 THEN 5
66 IF K(C+D)=-3; PRINT: PRINT "Win!":END
68 IF K(C+D)=0 THEN 72
69 FOR J=12 TO 15: IF K(J)=0;K(J)=-K(C+D): GOTO 72
70 NEXT J
72 K(C+D)=K(C):K(C)=0: GOTO 88
74 A=0:B=1
75 GOSUB #1
76 G$=KEY: IF G$="" THEN 76
77 IF G$="1" THEN 81
78 IF G$="3" THEN 83
79 IF G$="2" THEN 85
80 GOTO 5
81 IF A>0;A=A-1: GOTO 75
82 GOTO 76
83 IF A<6;A=A+1: GOTO 75
84 GOTO 76
85 IF K(A)=0;K(A)=K(C):K(C)=0: GOTO 88
86 GOTO 75
88 A=12:GOSUB #1: GOSUB #3
90 IF F<-50 THEN 5
92 IF K(C+D)=3; PRINT: PRINT "Lose": END 
94 IF K(C+D)=0 THEN 99
96 FOR J=16 TO 19: IF K(J)=0;K(J)=-K(C+D): GOTO 99
97 NEXT J
99 K(C+D)=K(C):K(C)=0
100 A=C+D: GOTO 5

[P1]
1 PRINT : GOTO 3-B
2 FOR J=0 TO 11: GOSUB K(J)+15: NEXT J: GOTO 5
4 FOR J=0 TO 7: GOSUB K(J+12)+15: NEXT J
5 IF A>10; RETURN 
6 IF C>11; PRINT CSR A+1;"<";: RETURN 
7 PRINT CSR A+1;"\LA";: RETURN 
12 PRINT CSR J;"k";: RETURN 
13 PRINT CSR J;"p";: RETURN 
14 PRINT CSR J;"d";: RETURN 
15 RETURN 
16 PRINT CSR J;"D";: RETURN 
17 PRINT CSR J;"P";: RETURN 
18 PRINT CSR J;"K";: RETURN 

[P2]
1 E=0: IF H+I>-1; IF H+I<12 THEN 3
2 RETURN 
3 IF H<12 THEN 6
4 IF K(H+I)=0 THEN 15
5 RETURN 
6 IF K(H+I)<0; RETURN 
15 G=K(H+I):K(H+I)=K(H):K(H)=0
20 IF G>0;E=E+G*2
25 FOR J=0 TO 11
30 IF K(J)<1 THEN 99
35 IF K(J)>1 THEN 50
40 IF J+1>11 THEN 99
45 IF K(J+1)<0;E=E+K(J+1)
47 GOTO 99
50 IF K(J)>2 THEN 80
55 IF J+2>11 THEN 65
60 IF K(J+2)<0;E=E+K(J+2)
65 IF J-1<0 THEN 99
70 IF K(J-1)<0;E=E+K(J-1)
75 GOTO 99
80 IF J+1>11 THEN 90
85 IF K(J+1)<0;E=E+K(J+1)
90 IF J-1<0 THEN 99
95 IF K(J-1)<0;E=E+K(J-1)
99 NEXT J
100 K(H)=K(H+I):K(H+I)=G
105 E=E-(H+I)/20+RAN#/10:IF E>F;C=H:D=I:F=E
110 RETURN 

[P3]
1 F=-99: FOR H=0 TO 11
2 IF K(H)>-1 THEN 8
3 GOTO 8+K(H)
5 I=-1: GOSUB #2:I=1: GOSUB #2: GOTO 8
6 I=-2: GOSUB #2:I=1: GOSUB #2: GOTO 8
7 I=-1: GOSUB #2
8 NEXT H
9 FOR H=16 TO 19
10 IF K(H)=0 THEN 12
11 FOR I=5-H TO 11-H: GOSUB #2: NEXT I
12 NEXT H
30 RETURN

変数アサイン

変数説明
Aカーソル位置
B盤面フラグ1:盤内 -1:盤外
C移動するコマの位置(自/敵共用)
D移動するコマの移動先オフセット(自/敵共用)
E積算した評価値
F積算した評価値の最高値
Gキー入力用 又は盤面退避用
H仮に移動する敵コマの位置
I仮に移動する敵コマの移動先オフセット
Jカウンタ用
K(0~11)盤面データ
K(12~15)盤外自スロット
K(16~19)盤外敵スロット

行番号マップ

P0 初期設定

行番号解説
1
2

初期盤面の設定, A=カーソル初期値(0~11)

B=画面表示フラグ(1:盤内表示 -1:盤外表示)

先手攻撃(自コマ)
カーソル移動、コマ選択(盤内・盤外共通)
5盤面表示を更新(カーソルの形をディフォルトにするため C をリセット)
8
10
12
14
15盤内/盤外を切り替える.カーソル位置は左端にリセット
16盤面切り替え又は間違ったキー入力なので盤面再表示へ
左が押された場合
20既に左端だったらキー入力からやり直し(盤内・盤外共通)
22カーソル位置を一つ左に移動して盤面再表示へ
右が押された場合
24既に右端(盤内(B=1)で盤面右端、盤外(B=-1)で自スロット右端)ならばキー入力からやり直し
28カーソル位置を一つ右に移動して盤面再表示へ
選択が押された場合
38盤内(B=1)なら現在のカーソル位置 A を、盤外(B=-1)なら a+12(盤外コマを指定)を C に格納する.
40もし指定したセルが敵コマ又は Null の場合は、何もせず盤面再表示からやり直し
盤内の自コマ移動と盤外からのコマ打ち込みで分岐
42
盤内の自コマ移動/動かす方向を選ぶ
46
48
50
52間違ったキー入力なので盤面の再表示からやり直し(コマ指定のキャンセル)
左が押された場合
54とりあえず移動オフセット D=-1 とし、自コマが D なら盤面再表示からやり直し
56
右が押された場合
58とりあえず移動オフセット D=1 とし、自コマが P なら D=2 にする
自コマ移動先を調べる
60移動先が盤内なら次へ進む
62移動先が盤外なので盤面再表示からやり直し
64移動先に自コマがあるので盤面再表示からやり直し
66移動先に敵将 k があったら自勝ち終了.
68移動先が Null の場合は自コマ移動へ
69移動先に敵コマ p 又は d があるので、自空きスロットを探し敵コマを自コマとして格納する
70
72自コマを移動し、敵コマのターンへ
盤外からのコマ打ち込/打ち込む先を選ぶ
74カーソル位置をリセット、盤面フラグは1(盤内)に切り替える
75打ち込み先を選ぶため、盤面表示する
76
77
78
79
80間違ったキー入力なのでキー入力からやり直し(盤外コマ指定のキャンセル)
81左端でなければカーソル位置を一つ左へ移動し再表示へ
82既に左端だったらキー入力からやり直し
83「自陣+2マス」の右端でなければカーソル位置を一つ右へ移動し再表示へ
84既に右端だったらキー入力からやり直し
85打ち込み先が Null なら打ち込み、自スロットは空きにして後手攻撃へ
86打ち込み先にコマがある場合は再表示からやり直し
後手攻撃(敵コマ)
88カーソルを消して盤面表示を更新し、敵思考ルーチンへ out=C, D, F
90敵コマ打ち手無しの場合(F が全く更新されない)はパスにする
敵コマ移動先を調べる
92移動先に自将 K があったら敵勝ち終了.
94移動先が Null ならば、敵コマ移動へ
96移動先に自コマ P 又は D があるので、敵空きスロットを探し自コマを敵コマとして格納する
97
99敵コマを移動し、自コマのターンへ
次のターンへ
100カーソル位置を敵コマ移動先に変更して再表示へ

P1 盤内又は盤外面及びカーソルの表示ルーチン

分類解説
EntryK(*)=盤面データ
A=カーソル位置
B=盤面フラグ
C=移動元コマ位置(カーソル形状判断用)
Output
BreakJ
行番号解説
1
2盤内表示
4盤外表示
5カーソル表示が画面外になるなら表示しない(エラー回避)
6盤外からコマ打ち込みの場合:カーソル < を表示
7盤内コマ移動の場合:カーソル を表示(ディフォルト)
12
13
14
15
16
17
18

P2 最も有利な敵の手(敵コマ位置及び移動先オフセット)の決定

分類解説
EntryK(*)=現在の盤面
H, I=仮の敵の手(移動する敵コマ位置、移動先オフセット)
F=最高評価値(更新前)
C, D=最も有利な敵の手(更新前)
OutputF=最高評価値(更新後)
C, D=最も有利な敵の手(更新後)
BreakE, G, J
行番号解説
無効な敵の仮の手の排除
1敵の仮の手は盤内への移動か?
2敵の仮の手は盤外への移動なので評価しない
3敵の仮の手は盤内からの移動か?
4盤外からの打ち込みの場合は、Null にのみ打てる
5打ち込み先が Null でなかったので評価しない
6盤内の移動の場合は、敵コマ自身には打てない
仮盤面の生成
15現在の盤面(移動先のマス)を保存した上で、仮盤面を生成(敵コマを移動、元の位置は Null)
プラス評価値(今ターンで敵コマを取る)の積算
20敵の仮の手で自コマが取得できる場合はプラス側評価値を積算する.係数は2倍.
マイナス評価値(次ターンで自コマに取られる)の積算
25仮盤面全マス scan (自コマ毎に積算する)
30敵コマまたは Null なら次のマスへ
35自コマ P 又は K の場合は次へ
40自コマ D の場合、自コマの右1マスが盤外なら評価しない
45自コマ D の場合、自コマの右1マスに敵コマがあった場合マイナス側評価値を加算
47
50自コマ K の場合は次へ
55自コマ P の場合、自コマの右2マスが盤外なら評価しない
60自コマ P の場合、自コマの右2マスに敵コマがあった場合マイナス評価値を加算
65自コマ P の場合、自コマの左1マスが盤外なら評価しない
70自コマ P の場合、自コマの左1マスに敵コマがあった場合マイナス評価値を加算
75
80自コマ K の場合、自コマの右1マスが盤外なら評価しない
85自コマ K の場合、自コマの右1マスに敵コマがあった場合マイナス評価値を加算
90自コマ K の場合、自コマの左1マスが盤外なら評価しない
95自コマ K の場合、自コマの左1マスに敵コマがあった場合マイナス評価値を加算
99
「現在の盤面」の復旧
100
最も有利な敵の手の更新
105

評価値に傾斜配分と乱数を加味し最高値なら、CH で、DI で、FE で更新する

傾斜配分と乱数加味は評価値横並びによる千日手の予防のため

110

P3 敵思考ルーチン

分類解説
EntryK(*)=現在の盤面データ
OutputC=最適な移動元敵コマの位置
D=最適な移動元敵コマの移動先オフセット
BreakH, I, F,(E, G, J)
行番号解説
1F=最高評価値の保持用.必ず更新されるよう-99にしておく.盤内の全敵コマについて調べる.
2自コマまたは Null なら次のマスへ
3
5敵コマ k の場合:左へ1コマ、右へ1コマ移動した場合を評価し、最高値なら C, D, F を更新
6敵コマ p の場合:左へ2コマ、右へ1コマ移動した場合を評価し、最高値なら C, D, F を更新
7敵コマ d の場合:左へ1コマ移動した場合を評価し、最高値なら C, D, F を更新
8
9盤外スロットの全敵コマについて調べる
10
11

敵スロットにコマがあれば、敵陣それぞれに置いた場合を評価し、最高値なら更新.

盤内自陣以外のマスへの移動オフセットは、H=16(敵スロット左端)の場合 5-16=-11 から 11-16=-5 の範囲.

12
30

PBロッキーより

『1行将棋』は、『rogue』で鮮烈なデビューを飾った NUAO 氏が寄稿してくださったゲーム作品の第二弾です.HTML 化はPBロッキーが行い、その際に、他の掲載作とスタイルを統一するための変更を行いました.


ありそうで無かった1次元将棋で、なんと CPU の思考まで実現しています.王将、桂馬、歩兵に絞るという思い切った着想から実装まで、難題に挑んだ作品です.

さて、気になる CPU の棋力ですが、手探りで打っていると歩と桂馬を交換する羽目になったのには泣かされました.なかなかの巧者です.千日手も躊躇しない図太い棋風の持ち主で、攻めあぐねるこちらの臆病を見透かしているかのようです.

僕は襟を正して長考したところ勝利を収める事が出来ました.(時間制限があったらメッタ打ちにされるかもしれません.)4bit CPU とはいえ舐めてかかると、あんた、駒が泣くぜ


NUAO 氏の厚意によって本作品も Public Domain で提供されます.また、氏は本作に加えて『ハノイの塔 on PB-100』も同時に寄稿して下さいました.併せてご覧ください!

更新履歴

日付ノート
2022/10/14公開.
2022/10/17

門真なむ氏による、駒を選んだ際に 2 を離すのが遅いと 1<>3? がキャンセルされしまう問題の修正の提案を NUAO 氏が採用しました.

P0 に45行が追加されています.ご確認ください.