PB で将棋!?ゲームになるの?意外になるんです…
RUN DEG K←P D d p k
ルール
RUN DEG K←P 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
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;"←";: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 RETURNPocket 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 盤内又は盤外面及びカーソルの表示ルーチン
| 分類 | 解説 |
|---|---|
| Entry | K(*)=盤面データ |
| A=カーソル位置 | |
| B=盤面フラグ | |
| C=移動元コマ位置(カーソル形状判断用) | |
| Output | |
| Break | J |
| 行番号 | 解説 |
|---|---|
| 1 | |
| 2 | 盤内表示 |
| 4 | 盤外表示 |
| 5 | カーソル表示が画面外になるなら表示しない(エラー回避) |
| 6 | 盤外からコマ打ち込みの場合:カーソル < を表示 |
| 7 | 盤内コマ移動の場合:カーソル ← を表示(ディフォルト) |
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 |
P2 最も有利な敵の手(敵コマ位置及び移動先オフセット)の決定
| 分類 | 解説 |
|---|---|
| Entry | K(*)=現在の盤面 |
| H, I=仮の敵の手(移動する敵コマ位置、移動先オフセット) | |
| F=最高評価値(更新前) | |
| C, D=最も有利な敵の手(更新前) | |
| Output | F=最高評価値(更新後) |
| C, D=最も有利な敵の手(更新後) | |
| Break | E, 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 | 評価値に傾斜配分と乱数を加味し最高値なら、C を H で、D を I で、F を E で更新する 傾斜配分と乱数加味は評価値横並びによる千日手の予防のため |
| 110 |
P3 敵思考ルーチン
| 分類 | 解説 |
|---|---|
| Entry | K(*)=現在の盤面データ |
| Output | C=最適な移動元敵コマの位置 |
| D=最適な移動元敵コマの移動先オフセット | |
| Break | H, I, F,(E, G, J) |
| 行番号 | 解説 |
|---|---|
| 1 | F=最高評価値の保持用.必ず更新されるよう-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 | 敵スロットにコマがあれば、敵陣それぞれに置いた場合を評価し、最高値なら更新. 盤内自陣以外のマスへの移動オフセットは、 |
| 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行が追加されています.ご確認ください. |