はじめに
PC 将棋アプリ ShogiGUI の定跡ファイル (拡張子 .sbk、以下「SBK」 1 ) は、一部の将棋関係者やコンピュータ将棋関係者の間で非常によく使われています。
この記事では SBK のデータ構造を解説します。
ShogiGUI と SBK
ShogiGUI は各種将棋 AI と連携できる Windows の GUI アプリケーションです。ShogiGUI には様々な機能があり、将棋の研究に必要な機能が揃っているためプロ棋士の間でもよく使われています。ShogiGUI が持つ強力な機能の一つが定跡機能であり、そこで用いられるのが SBK です。
SBK は ShogiGUI のために作られた定跡ファイル形式です。SBK には局面をキーとした定跡手の一覧や、各定跡手の評価、出現頻度、コメントなどが格納されます。
ShogiGUI 以外の SBK 実装
BookConv
BookConv は ShogiGUI の開発者によって作られた定跡ファイル変換ツールで、ソースコードが公開されています。ShogiGUI のソースコードやデータ定義が非公開であるため、BookConv のソースコードは SBK の仕様に関する唯一の公式な情報源であると言えます。
ShogiHome
ShogiHome は筆者が開発しているソフトウェアで、ShogiGUI と同様に GUI 上で棋譜の閲覧や解析、対局などが可能です。比較的新しいバージョンでは複数種類の定跡ファイル形式の閲覧と編集が可能であり、v1.28.0 のアルファ版からは SBK も扱えるようになっています。
SBK のデータ定義
SBK は Protocol Buffers (以下 Protobuf) を用いて定義されており、その定義ファイル book.proto は BookConv の GitHub リポジトリで閲覧可能です。このファイルに限り CC0 2 が適用されており、誰でも自由に使うことができます。
Protobuf の定義ファイルは protoc コマンド や Buf CLI を通すことで、各種プログラミング言語のシリアライザーを生成することが可能です。
SBK の特徴
Protobuf は高速かつコンパクトなデータ形式です。テキストベースのフォーマットではないため、テキストエディタで読んだり編集することはできません。
SBK は冗長な情報を省略することで、ファイルサイズを比較的小さく抑える特徴があります。多くのケースでは、他の定跡ファイル形式と比べた時に同じ登録局面数に対して小さいファイルを生成します。
一方で、SBK はバイナリサーチ 3 を想定したものではないため、高速に局面を検索するにはデータをメモリに展開する必要があります。
構成要素
SBK には 4 つの message (Protobuf における構造体定義のようなもの) と 1 つの enum が定義されています。
| message 名 | 役割 | 依存先 |
|---|---|---|
| SBook | SBK 全体 | SBookState |
| SBookState | 登録局面 | SBookMove, SBookEval |
| SBookMove | 指し手 | SBookMoveEvalution 4 |
| SBookEval | 評価値と探索の情報 |
| enum 名 | 役割 |
|---|---|
| SBookMoveEvalution 4 | 指し手評価 |
次の図は message の関係をまとめたものです。青字で説明を書いていますが、 book.proto だけからこれらを読み解くことはできません。次節で詳細を説明します。
ShogiGUI の画面上では各フィールドの情報が次の図の箇所に表示されています。
SBookState の詳細仕様
ID
State の ID フィールドは BookStates 配列の添え字と一致しなければなりません。つまり、先頭の State は Id=0、 2 番目の State は Id=1、N 番目の State は Id=N-1 となります。
実際に BookConv の実装を見ると NextStateId の値を BookStates の添え字に使ってランダムアクセスで局面を探索しており、この要件を満たさないと正常に読み込まれなくなります。
Position
Position は局面の SFEN を表します。
このフィールドは optional であり、他の局面から NextStateId で到達可能な場合は省略が可能です。ただし、最初の State ( BookStates[0] ) に関しては平手初期配置の場合のみ省略可能 5 であり、それ以外の場合に Position を省略してはいけません。
冗長な Position が書かれていても問題はありませんが、SFEN は 1 局面あたり数十バイトから 100 バイトを占めるため、省略することで大幅にファイルサイズを減少させることができます。ただし、NextStateId で参照されている局面を単純に省略してしまうと、定跡ツリーが閉路(千日手)を含む場合に SFEN を復元できない局面を生じさせる可能性があります。 6 省略可能な局面を厳密に求めるには閉路を考慮した探索が必要です。
BoardKey, HandKey
BoardKey は局面のハッシュ値です。また HandKey は持ち駒の数の組み合わせと手番を表すビット列だと思われます。
これらの値の計算ロジックは非公開であり、BookConv には含まれていません。BookConv はこれらのフィールドを 0 で書き出しています。その場合、ShogiGUI は読み込み時に Position (SFEN) から値を計算するようです。
ShogiGUI のデータに対して局面を追加する際に元データの BoardKey や HandKey を残してしまうと、ShogiGUI がそのデータを読み込んだ際にハッシュ値を再計算しないらしく、追加した State が正しく反映されません。従って ShogiGUI 以外のソフトウェアには全ての State を 0 で初期化する処理が必要です。
リーフ局面の有無
BookConv では指し手の先の局面に相当する State が存在しない場合、NextStateId に -1 を代入しています。( 実装箇所 )
定跡ツリーのリーフ局面 (その局面へ至る指し手が登録されているが、その局面からの指し手は存在しない局面) に関して、コメント等の情報も無い場合はその State を含めるかどうかで情報に違いはありません。ただし、ShogiGUI は常にリーフ局面の State を書き出しており、基本的に NextStateId が -1 になることは無いようです。
情報の無い State を含めない方がファイルサイズは若干小さくなりますが、大きな効果は無いため ShogiGUI の実装に合わせる方が良いと思われます。常にリーフ局面の State を持つようにした方が、新しい局面を追加する際に親局面を逆引きする必要性がなくなるためパフォーマンス上の利点があると考えられます。
Evals
Evals は将棋 AI の探索結果を参考情報として残しておくためのフィールドで、これ自体は定跡そのものではありません。読み筋は ShogiGUI の解析コメントと同じ形式 (e.g., △3三桂(21) ▲3四飛(24) △5四歩(53) ) の文字列で表されます。
SBK のバイナリデータを解析する方法
先述の通り、 SBK は Protobuf を使っているため汎用的なテキストエディタやバイナリエディタでは解析が困難です。
筆者は ShogiHome へ SBK を実装するために SBK を YAML に変換するスクリプト を作成しました。これは TypeScript の実装ですが、protoc で生成した構造体を YAML で書き出しているだけなので、他の言語でも同様のものを簡単に作ることができると思います。
おわりに
ShogiGUI の定跡ファイル形式について詳細な解説を書いた文書はおそらくこれまで無かったと思います。コンピュータ将棋関係者の間でも関心が高まっているデータ形式なので、何かの役に立つのではないかと考えて今回この資料を作成しました。
参考
-
ShogiGUI 自体には「定跡ファイル (*.sbk)」という表記しか見当たりませんが、BookConv には大文字で「SBK」と表記されています。 ↩
-
proto ファイルを使用しても問題ないか、筆者が ShogiGUI の開発者へ問い合わせた際に CC0 を明記してくださいました。 ↩
-
やねうら王定跡フォーマットや Apery 形式はファイル内のデータを事前にソートしておくことによってメインメモリへの展開を必要としないバイナリサーチ (二分探索) を可能にしています。 ↩
-
EvalutionというスペルはEvaluationのタイポだと思われますが、 book.proto に書かれた名前をそのまま記載しています。 ↩ ↩2 -
BookConv の実装を見ると
BookStates[0].Positionが省略された場合は平手初期配置として扱うようです。 参考箇所 ↩ -
他の局面から閉路に入る経路が 1 つでもあれば問題ありませんが、閉路へ侵入する指し手が存在しない場合は閉路の全ての局面が SFEN の情報を失います。 ↩

