2021-12-04に更新

CSAサーバ プロトコル ver1.2.1 を読もうぜ(^~^)?

へぐちゃ~(^~^) 公開下書き

ramen-tabero-futsu2.png
「 読もうぜ?」

📖 CSAサーバ プロトコル ver.1.2.1 - 通信形式
📖 CSA標準棋譜ファイル形式 - 棋譜の保存形式

kifuwarabe-futsu.png
「 👆 読めだぜ」

  • ポート番号: 4081

ohkina-hiyoko-futsu2.png
「 👆 メモって行きましょう!」

  • 行単位
  • 行末は常にLF (\n, ASCIIコード 0x0a)
  • 空白は' '1つ (ASCIIコード0x20)。 複数の空白をひとつの空白として使ってはならない
  • 使える文字 はASCIIコード0x21~0x7fをもつ7ビットASCII文字
  • 大文字と小文字を明確に区別する
  • タブは使えない

(クライアントから)ログイン

20211204shogi15b1.png

LOGIN <username> <password>

usernameはクライアントを識別するための文字列。
usernameに使える文字:

  • 数字('0'-'9')
  • 英大文字('A'-'Z')
  • 英小文字('a'-'z')
  • アンダースコア('_')
  • ハイフン('-')

文字数: 32バイト以内

は に固有のパスワード文字列。
使える文字:

  • 空白を含まない文字

文字数: 32バイト以内

(サーバーから)ログインOK

20211204shogi15o2.png

LOGIN:<username> OK

このあとクライアントは 対局待ち 状態になる。

(サーバーから)ログイン認証失敗

20211204shogi15o3.png

LOGIN:incorrect

(クライアントから)ログアウト

20211204shogi15b4.png

対局待ち状態 で:

LOGOUT

(サーバーから)ログアウト受理

20211204shogi15o5.png

LOGOUT:completed

また、サーバーから一方的にコネクションを切断することがある。

(サーバーから)対局条件の通知

20211204shogi15o6.png

サーバーから1行ずつではなく複数行テキストを送信:

BEGIN Game_Summary
Protocol_Version:1.2
Protocol_Mode:Server
Format:Shogi 1.0
Declaration:Jishogi 1.1
Game_ID:20150505-CSA25-3-5-7
Name+:TANUKI
Name-:KITSUNE
Your_Turn:+
Rematch_On_Draw:NO
To_Move:+
Max_Moves:256
BEGIN Time
Time_Unit:1sec
Total_Time:600
Byoyomi:10
Least_Time_Per_Move:1
END Time
BEGIN Position
P1-KY-KE-GI-KI-OU-KI-GI-KE-KY
P2 * -HI *  *  *  *  * -KA * 
P3-FU-FU-FU-FU-FU-FU-FU-FU-FU
P4 *  *  *  *  *  *  *  *  * 
P5 *  *  *  *  *  *  *  *  * 
P6 *  *  *  *  *  *  *  *  * 
P7+FU+FU+FU+FU+FU+FU+FU+FU+FU
P8 * +KA *  *  *  *  * +HI * 
P9+KY+KE+GI+KI+OU+KI+GI+KE+KY
P+
P-
+
+2726FU,T12
-3334FU,T6
END Position
END Game_Summary

基本的に <key>:<value> 構造だが↓

BEGIN <name>
END <name>

↑でネスト構造をしている。

ramen-tabero-futsu2.png
「 試しにインデントを付けてみようぜ?」

kifuwarabe-futsu.png
「 可読性を得たいなら ケチケチせず 最初からインデントすりゃいいのに……」

BEGIN Game_Summary
    Protocol_Version:1.2
    Protocol_Mode:Server
    Format:Shogi 1.0
    Declaration:Jishogi 1.1
    Game_ID:20150505-CSA25-3-5-7
    Name+:TANUKI
    Name-:KITSUNE
    Your_Turn:+
    Rematch_On_Draw:NO
    To_Move:+
    Max_Moves:256
    BEGIN Time
        Time_Unit:1sec
        Total_Time:600
        Byoyomi:10
        Least_Time_Per_Move:1
    END Time
    BEGIN Position
        P1-KY-KE-GI-KI-OU-KI-GI-KE-KY
        P2 * -HI *  *  *  *  * -KA * 
        P3-FU-FU-FU-FU-FU-FU-FU-FU-FU
        P4 *  *  *  *  *  *  *  *  * 
        P5 *  *  *  *  *  *  *  *  * 
        P6 *  *  *  *  *  *  *  *  * 
        P7+FU+FU+FU+FU+FU+FU+FU+FU+FU
        P8 * +KA *  *  *  *  * +HI * 
        P9+KY+KE+GI+KI+OU+KI+GI+KE+KY
        P+
        P-
        +
        +2726FU,T12
        -3334FU,T6
    END Position
END Game_Summary

kifuwarabe-futsu.png
「 👆 あっ、 Position に 指し手が付いてるぜ!」

ohkina-hiyoko-futsu2.png
「 棋譜が付いてないと 千日手判定ができないから、ポジションに棋譜を付けて送るのは 必要なのよ。
盤面と棋譜は 分離できないのよ」

ramen-tabero-futsu2.png
「 千日手ルールがなければ 棋譜がなくても 盤面だけでゲームを再開できた」

対局の一般情報

  • Protocol_Version (必須)
    • このプロトコル全体のテキストが従っているCSAプロトコルバージョン
  • Protocol_Mode (省略時は Server
    • Server の場合は、サーバを経由する対局
    • Direct の場合は、対局者同士が直接指し手を送り合う対局(本書では取り扱わない)
  • Format (必須)
    • このプロトコルが何のゲームかを表す。本書では Shogi 1.0 固定
  • Declaration (省略時は情報なし)
    • 大雑把に言うとローカルルールを表す。本書では Jishogi 1.1 (本書ではこれ固定)
  • Game_ID (省略時は空文字列)
    • この対局に振られたID
  • Name+ (必須)
    • 先手プレイヤー名
  • Name-:(必須)
    • 後手プレイヤー名
  • Your_Turn (必須)
    • この対局条件を受け取ったプレイヤーが先手なら +、後手なら -
  • Rematch_On_Draw (省略時はNO)
    • NO 固定。 引き分けのときに自動的に再試合をするなら YES にする仕様だが使ってない
  • To_Move (必須)
    • 対局の開始直後に指す方が先手なら +、 後手なら -。 再開局面なら後手から指すこともありえる
  • Max_Moves (省略可)
    • 手数の上限。省略したら無制限。数え方は 先手の着手数+後手の着手数。再開局面なら、それまでに指した数も手数に参入すること。手数が手数の上限に一致するときが最後の着手

持ち時間情報

BEGIN Time
    ...略...
END Time

👆 と書いていたら 先手、後手の両者に同じ持ち時間のルールが適用される。

BEGIN Time+
    ...略...
END Time+
BEGIN Time-
    ...略...
END Time-

👆 と書いていたら 先手、後手で異なる持ち時間のルールが適用される。

どちらも書かれていなければ、持ち時間無制限。

  • Time_Unit (省略時は1秒とする)
    • 秒単位なら 'sec'
    • 分単位なら 'min'
    • ミリ秒単位なら 'msec'
  • Least_Time_Per_Move (省略時は0)
    • 1手の着手に必ず記録される消費時間(最少消費時間)を単位時間で表現する。 これが1秒である場合、少なくとも1手あたり1秒が消費される。
      これが0のときのルールを突いたのが 稲庭将棋 で、時間攻めが成立することがある
  • Time_Roundup (省略時はNO)
    • YESの場合、単位時間未満の時間が切り上げて記録される。NOの場合は切り捨てられる

また、以下の4つは、いずれかが含まれる。すべて省略されたら時間無制限とする

  • Total_Time (省略可)
    • 対局中の持時間の初期値
  • Byoyomi (省略可)
    • 長文になるので この記事の最後で説明する
  • Delay (省略可)
    • 長文になるので この記事の最後で説明する
  • Increment (省略可)
    • 長文になるので この記事の最後で説明する

対局の局面情報

BEGIN Position
    ...略...
END Position

👆 上記のように囲まれているところの情報

また行頭は、以下のいずれか

P1
P2
P3
P4
P5
P6
P7
P8
P9
P+
P-

持ち駒の書き方:

先手の持ち駒が金1枚、歩1枚のとき:

P+00KI00FU

駒の書き方は後述

CSA標準棋譜ファイルにある AL は CSAサーバープロトコルでは使用しない

(クライアントから)対局の合意

20211204shogi15b7.png

AGREE[ <GameID>]

(注:[]内は省略可能である事を示す。以下も同様。)

<GameID> は、同意する対局条件中の Game_ID

(クライアントから)対局の拒否

20211204shogi15b8.png

REJECT[ <GameID>]

(サーバーから)対局不成立の合図

20211204shogi15o9.png

REJECT:<GameID> by <rejector>

双方のクライアントは 対局待ち 状態に戻る

(サーバーから)対局開始の合図

20211204shogi15o10.png

START:<GameID>

クライアントは、自分の手番なら指し手を送る。

(クライアントから)指し手の送信

20211204shogi15b11.png

先手7六歩なら:

+7776FU

先手(下手)は +
後手(上手)は - を付ける。

位置:

1二を 12、5一を51、8九を 89 というふうに、2桁の数字で表す。
駒台は 00 とする。

駒名:

FU KY KE GI KI KA HI OU TO NY NK NG UM RY

(クライアントから)投了

20211204shogi15b11.png

%TORYO

(クライアントから)勝利宣言

20211204shogi15b11.png

%KACHI

(クライアントから)中断の申請

20211204shogi15b11.png

%CHUDAN

サーバーはめんどくさかったら このメッセージを送ってきたクライアントの負けにする

(クライアントから)空白の送信

20211204shogi15b12.png

手番に関わらず、

  • 長さ0の文字列
  • \n の1文字

をサーバーに送ることができるが、

  • 30秒を経たずに同一のクライアントが送信したら反則負け

とする

(サーバーから)指し手の送信

20211204shogi15o13.png (中断の通知と兼用)

サーバーは、消費時間を付けて、両クライアントに送信する

+7776FU,T12

およびゲームオーバーの通知

20211204shogi15o14.png

サーバーは、なんらかのことが起こったとき、(指し手に) # で始まる2行を付けて送信する

千日手で引き分けなら:

+6978KI,T2
#SENNICHITE
#DRAW

連続王手の千日手なら:

-8493OU,T2
#OUTE_SENNICHITE
#WIN
-8493OU,T2
#OUTE_SENNICHITE
#LOSE

連続王手の千日手以外の不正な着手なら:

+0031FU,T1
#ILLEGAL_MOVE
#WIN
+0031FU,T1
#ILLEGAL_MOVE
#LOSE

時間切れなら:

#TIME_UP
#WIN
#TIME_UP
#LOSE

投了したら:

%TORYO,T4
#RESIGN
#WIN
%TORYO,T4
#RESIGN
#LOSE

勝利宣言の条件が満たされていれば:

%KACHI,T8
#JISHOGI
#WIN
%KACHI,T8
#JISHOGI
#LOSE

勝利宣言の条件が満たされていなければ:

%KACHI,T8
#ILLEGAL_MOVE
#WIN
%KACHI,T8
#ILLEGAL_MOVE
#LOSE

相手の手番で指し手を送信したら:

#ILLEGAL_ACTION
#LOSE
#ILLEGAL_ACTION
#WIN

Max_Moves の手数に到達し、上記のいずれの結果でもなければ:

#MAX_MOVES
#CENSORED

対局が終了したクライアントは 対局待ち状態 に復帰する

(サーバーから)中断の通知

20211204shogi15o13.png (指し手の送信と兼用)

#CHUDAN

このメッセージを受け取ったクライアントは、対局を再開できるよう備えて 対局を中断する

タイムラインの例

          machine1         server         machine2

1                ←   [対局条件]   →
2  AGREE aGAME   →                ←  AGREE aGAME
3                ←  START:aGAME   →
4                                  ← [指し手(初手)]
5                ←  [確認&時間]   →
6 [指し手(2手目)]→
7                ←  [確認&時間]   →
8                                  ←[指し手(3手目)]
9                ←  [確認&時間]   →
   …
       [投了]     →
                 ←[結果通知&終了] →

持ち時間の説明を解読しろだぜ

ramen-tabero-futsu2.png
「 はあ~ 持ち時間の説明が わかんねーっ」

kifuwarabe-futsu.png
「 分からないことを 分かるようになる手法を身に付けてないなら お父んは 学生の本分をサボっていたんだぜ」

ohkina-hiyoko-futsu2.png
「 ノートにまとめましょう」

勉強ノートまとめ中

存在する組み合わせ

[ 0]            /         /       /          
[ 1]            /         /       / Increment
[ 2]            /         / Delay /          
[ 3]            /         / Delay / Increment
[ 4]            / Byoyomi /       /          
[ 5]            / Byoyomi /       / Increment
[ 6]            / Byoyomi / Delay /          
[ 7]            / Byoyomi / Delay / Increment
[ 8] Total_Time /         /       /          
[ 9] Total_Time /         /       / Increment
[10] Total_Time /         / Delay /          
[11] Total_Time /         / Delay / Increment
[12] Total_Time / Byoyomi /       /          
[13] Total_Time / Byoyomi /       / Increment
[14] Total_Time / Byoyomi / Delay /          
[15] Total_Time / Byoyomi / Delay / Increment

ramen-tabero-futsu2.png
「 👆 とっかかりとして、存在する組み合わせに番号を振るか」

kifuwarabe-futsu.png
「 ライプニッツ先生の教え 2進数は物事を見通すのに便利 わらう」

勉強ノートまとめ中

存在する組み合わせ
                                               Group
[ 0]            /         /       /                A B   D   F
[ 1]            /         /       / Increment            D   F G
[ 2]            /         / Delay /                A B   D E
[ 3]            /         / Delay / Increment            D E   G
[ 4]            / Byoyomi /       /                A B       F   H
[ 5]            / Byoyomi /       / Increment                F G H
[ 6]            / Byoyomi / Delay /                A B     E     H
[ 7]            / Byoyomi / Delay / Increment              E   G H
[ 8] Total_Time /         /       /                  B C D   F
[ 9] Total_Time /         /       / Increment          C D   F G
[10] Total_Time /         / Delay /                  B C D E
[11] Total_Time /         / Delay / Increment          C D E   G
[12] Total_Time / Byoyomi /       /                  B C     F   H
[13] Total_Time / Byoyomi /       / Increment          C     F G H
[14] Total_Time / Byoyomi / Delay /                  B C   E     H
[15] Total_Time / Byoyomi / Delay / Increment          C   E   G H

ramen-tabero-futsu2.png
「 👆 Total_Time と Increment の両方がないのを Group A と分類するとしようぜ」

ramen-tabero-futsu2.png
「 👆 同様に、 Increment だけないのを Group B と分類するとしようぜ。
Total_Time があるのを Group C
Byoyomi がないのを Group D
Delay があるのを Group E
Delay がないのを Group F
Increment があるのを Group G
Byoyomi があるのを Group H としようぜ」

kifuwarabe-futsu.png
「 チャールズ バークラの慎重さを見習わない ずさんな後付けわらう」

ohkina-hiyoko-futsu2.png
「 無いことと、 0 になったことは 分ける必要があるわよ」

ramen-tabero-futsu2.png
「 時間軸でのイベントの発生も 分類したいぜ」

20211201shogi4.png

ramen-tabero-futsu2.png
「 👆 つまり こうなのでは?」

図1: 通算持ち時間の説明

 |                               |
 |-----------------|             | [Total_Time]
 |                 |             |
 |                 |-------------| [加算時間の総和]
 |                 |             |
 |-------------------------------| [通算持ち時間]
 |                 |             |

[Total_Time]とは、その名前に反して、持ち時間の初期値のようなもの。
[通算持ち時間] がいわゆる 持ち時間 にあたる。
[加算時間の総和] とは、1手指す直前にもらえる持ち時間。

備考:
    本来のフィッシャークロックルールは1手指した後にもらえるが、
    CSAプロトコルでは1手指す前にもらえる(通信遅延を考えると、指す前にもらえた方がコンピューターには嬉しい)
図2: 残り時間の説明

 |                               |
 |-------------------------------| [通算持ち時間]
 |                 |             |
 |-----------------|             | [通算消費時間]
 |                 |             |
 |                 |-------------| [残り時間]
 |                 |             |

[残り時間]とは、各地点において[通算持ち時間]から[通算消費時間]を差し引いた時間。現在以降に消費可能な時間を意味する
図3: TimeUp の説明

 |                               |         |
 |-------------------------------|         | [通算持ち時間]
 |                               |         |
 |-----------------------------------------| [通算消費時間]
 |                               |         |
 |                               |         | [残り時間]なし
 |                               |         |
                                  ---------
                                  実際には 0 の幅で十分

[TimeUp] とは、 [通算消費時間] が [通算持ち時間] 以上になった場合
図4: 秒読み時間の説明

時間消費の開始           残り時間が空         着手
[CountDownStart]        [TimeUp]            [Moved]
    |                      |                   |
    |                      |                   |
    |                      |                   |
     ----------------------
    [残り時間]
                            -------------------
                            [秒読み時間]

[残り時間]を使い切ってから [秒読み時間] が開始される
図5:  Byoyomi があるケースでの 2回目のTimeUp の説明

残り時間が空
[TimeUp]
 |                               |         |
 |-------------------------------|         | [秒読み時間]
 |                               |         |
 |-----------------------------------------| [秒読み後からの消費時間]
 |                               |         |
 |                               |         | [残り時間]なし
 |                               |         |
                                  ---------
                                  実際には 0 の幅で十分

[2回目のTimeUp] となる。扱いは [TimeUp] と同じ
図6: Delay の説明

[時間計測開始]    [消費時間記録開始]    [着手]
    |               |                    |
    |               |                    |
    |               |                    |
     ---------------
     [遅延時間]
                     --------------------
                     [消費時間]

[Delay](遅延時間)とは、手番側の時間の計測が開始されてから消費時間として記録される時間の計測が開始されるまでの時間。
[時間計測開始] から [着手] までの時間から、遅延時間を差し引いた時間が [消費時間] とみなされる
勉強ノートまとめ中

[Group A]なら
    時間無制限

[Group B]なら
    [加算時間]なし
    [通算消費時間]が[通算持ち時間]以上になったら [TimeUp]となる

[Group C]なら
    [TimeUp]したなら
        [秒読み時間]が付与される
        [秒読み時間] 内に着手が行われたなら
            着手の消費時間は [Byoyomi]開始前と開始後の消費時間の合計がその着手の消費時間として記録される

[Group D]なら
    1手ごとに課されるような時間制限はない
    [TimeUp] した なら
            その時点で負け。

[Group E]なら
    [遅延時間]内に行われた着手は
        時間の消費を行っていないものとみなされる。
    [消費時間]内に行われた着手は
        'Least_Time_Per_Move' の記述がある場合に限り最少消費時間が消費されたものとみなされる。
        'Least_Time_Per_Move' の記述がない場合には、消費時間は0となる。

[Group F]なら
    消費時間の計測は手番側の時間の計測の開始と同時に開始される。

[Group H] なら
    [TimeUp] したら
            その直後から [秒読み時間] が付与される

Total_Time: (省略可)
    [持ち時間の初期値]。

Byoyomi: (省略可)
    [残り時間] を使い切ってから 指し手1手ごとに付与される時間。

Delay: (省略可)
    図6参照

Increment: (省略可)
    手番側の [時間計測開始]の直前に [Total_Time]の他に加算される時間(加算時間)。
    図1参照

状態遷移から見るクライアント

ramen-tabero-futsu2.png
「 クライアントの状態遷移をはっきりしようぜ?」

kifuwarabe-futsu.png
「 初期状態、対局待ち状態、対局状態 の3つしかないのでは?」

ramen-tabero-futsu2.png
「 飛んでくるコマンドをベースに 考えてくれだぜ」

ノート

[初期状態] ----Login----> ----OK----> [対局待ち状態]
[初期状態] ----Login----> ----Denied----> [初期状態]

対局条件がサーバーから飛んでくる

[対局待ち状態] ----Agree----> [対局条件返信状態]
[対局待ち状態] ----Reject----> [対局条件返信状態]

マッチした

[対局条件返信状態] ---- ----> [対局状態]

自分の手番なら

[対局状態] ---- 指し手 ----> [対局状態]

勝ったとか反則だとかサーバーから返ってきたら

[対局状態] ---- 指し手 ----> [対局待ち状態]

ramen-tabero-futsu2.png
「 👆 [対局条件返信状態] というのがあるな」

ohkina-hiyoko-futsu2.png
「 そこで サーバーにほっとかれたら 永遠に待機してんの?」

kifuwarabe-futsu.png
「 永遠に待機するだろ」

ramen-tabero-futsu2.png
「 接続ぶっちぎって 再ログインしたら どうなるんだぜ?」

kifuwarabe-futsu.png
「 さすがに 接続切れ はサーバーも検知するだろ。初期化だぜ」

ohkina-hiyoko-futsu2.png
「 全パターンを含んだ 状態遷移図を 書いてちょうだい」

20211201shogi5a1.png

ramen-tabero-futsu2.png
「 👆 こうじゃないか?」

📖 state.gif

kifuwarabe-futsu.png
「 👆 公式の状態遷移図と見比べてくれだぜ」

ohkina-hiyoko-futsu2.png
「 それは floodgate の shogi-server なんで、 WCSCのサーバーとは違うのよ」

ramen-tabero-futsu2.png
「 何に合わせれば……」

ohkina-hiyoko-futsu2.png
「 floodgate のいう CSAモードに合わせましょう。
この CSAモードは WCSCのサーバーとは違うのよ」

ramen-tabero-futsu2.png
「 3パターン存在するのか……」

kifuwarabe-futsu.png
「 floodgate は 対局が終わると 切断してくるぜ。
CSAサーバープロトコルは 対局待ち状態 に戻るぜ」

ramen-tabero-futsu2.png
「 ぐぬぬ……」

20211201shogi6.png

ramen-tabero-futsu2.png
「 👆 じゃあ こうだぜ」

20211204shogi14.png

ramen-tabero-futsu2.png
「 👆 まだまだ 考え中」

20211204shogi18.png

ramen-tabero-futsu2.png
「 👆 ここまで まとまってきたぜ」

kifuwarabe-futsu.png
「 そんな図を描いても、どうやって コーディングに落とし込むんだぜ?」

何度でもクリック!→

むずでょ

光速のアカウント凍結されちゃったんで……。ゲームプログラムを独習中なんだぜ☆電王戦IIに出た棋士もコンピューターもみんな好きだぜ☆▲(パソコン将棋)WCSC29一次予選36位、SDT5予選42位▲(パソコン囲碁)AI竜星戦予選16位

Crieitは個人で開発中です。 興味がある方は是非記事の投稿をお願いします! どんな軽い内容でも嬉しいです。
なぜCrieitを作ろうと思ったか

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください!

ボードとは?

むずでょ の最近の記事