オセロの棋譜にも使えるファイル形式SGFとは

# はじめに
オセロAdvent Calendar 21日目、私の4つ目の記事になります。本当は4つ目の記事は22日目向けに既に書いていて、それで私の記事は終わる予定だったのですが、17日目のhajipongさんの記事「[連盟公式データをAPIで連携させる計画の話](https://qiita.com/hajipong/items/12ea7fb1370aedf1876e)」を読んで、書いておいた方が良さそうなネタを1つ思い出したので急きょ書くことにしました。

それはhajipongさんの記事でも触れられていたSGF(Smart Game Format)というファイル形式についてです。

# SGFとは
SGFというのはボードゲームの棋譜をテキストで表すファイル形式で、主に囲碁でよく使われているようです。オセロの棋譜にももちろん使えます。

英語ではありますが[公式サイト](https://www.red-bean.com/sgf/)もあり、リファレンスも充実しているので、詳しい仕様は公式サイトを見てください。で終わってしまうとさすがに怒られそうなので、この記事ではSGFの概要と特徴について説明したいと思います。

## 普及している？
ファイル形式について考える場合、そのファイル形式がどのくらい普及しているのかがまず気になりますね。マイナーな形式だとうまく流通できません。

オセロの棋譜形式と言えばF5D6C3...のように座標を並べた形式が定番です。SGFはそこまで普及はしていませんが、それでも有力なオセロアプリであるEdaxやWZebraで入出力をサポートしています。以下はWZebraの画面です。
![wzebra.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202945/96e06959-694d-614e-fc4c-947da1a37500.png)
このように、SGF形式もある程度は普及しているようです。

実は筆者が開発しているアプリ「棋譜Box」でも内部的にSGF形式で棋譜を保存しています（ただし、内部で保存しているだけで今のところ入出力の機能はありません）

なお、他にもGGFなどといった有力なファイル形式もあるようです。

## どんなファイル形式？
こんな感じです。（何となく見出しと会話が始まってしまった気がしますが、直前に読んだ記事の影響でしょうか・・・:sweat_smile:）

```
(;FF[4]GM[2]SZ[8]AP[KifuBox:2.3.0]DT[2019-12-20]EV[サンプル]PB[黒番選手]BR[5d]PW[白盤選手]WR[2d]RE[0]GC[試合のコメント];AB[e4][d5]AW[d4][e5];B[f5];W[d6];B[c3];W[d3];B[c4];W[f4];B[c5];W[b3];B[c2];W[b4]C[FJT定石];B[e3];W[e6];B[c6];W[f6];B[a5];W[a4];B[b5];W[a6];B[d7];W[c7];B[e7];W[e8];B[b6];W[d8];B[g3];W[f7];B[g5];W[d1];B[c1];W[b1];B[g6];W[a7];B[g8];W[h6];B[h5];W[f8];B[c8];W[h4];B[g4];W[b2];B[a1];W[b7];B[e1];W[h3];B[a2];W[h7];B[a3];W[g2];B[a8];W[b8];B[g7];W[h8];B[h2];W[h1];B[g1];W[f3];B[f2];W[f1];W[e2];B[d2])
```
何となく後半は黒番(B)と白番(W)の棋譜が並んでいる感じですが、他にも色々情報量がありそうですね。次項以降で特徴として説明します。

ちなみにこの棋譜の進行は有名なドロー進行です。筆者は昇段がかかった試合で引き分け勝ち権利を持っていないにも関わらずこの進行を最後まで打ち切ってしまって昇段を逃したことがあります。何をやっているんでしょうね？

# SGFの特徴
## 日付や大会名、選手名の情報が入れられる
上の例でいうと、この辺です。

```
DT[2019-12-20]EV[サンプル]PB[黒番選手]BR[5d]PW[白盤選手]WR[2d]
```
`EV`というのはEventのことで大会名を入れておく用の項目です。`PB`と`PW`は黒白の選手名(PはPlayerのことですね)、`BR`と`WR`で段級位も記録することができます(RはRankのことです)。`5d`は五段のことですが、この書式もSGFで決まっています。ありがたいです。

## コメントも入れられる
最初の方に`GC[試合のコメント]`とあったのは試合全体に対するコメントです。あと、`;W[b4]C[FJT定石];`のように手に対してコメントを入れることもできます[^1]。ありがたいです。

[^1]: `C`は単純なコメントですが、良い手とか悪い手とかを表す専用のプロパティもあるようです。さらには、盤面に矢印や記号を描くためのプロパティもあります。

## 評価値も残せる
上のサンプルには入れませんでしたが、`;W[f4]V[6];`みたいな感じで局面ごとの評価値を残しておくこともできます。`V[6]`というのが黒番から見て+6ということを表しています(白が有利な場合はマイナスになります)。評価値の計算は時間がかかることが多いですから、ファイルとして残しておけると嬉しいです。とてもありがたいことですね。

## 返し忘れや返し過ぎにも対応できる
`B`や`W`は黒や白の通常の着手を表しますが、`AB[g3]`とか`AW[g2]`のような形で手とは関係なく黒石や白石を置くことができます(Add BlackとかAdd Whiteの略です[^2]。これを使えば、黒石だった石を強制的に白にしたりできるので、返し忘れや返し過ぎを表現できるのです。何ならAE(Add Empty)で石を消すこともできます。

[^2]: 通常の手である`B`や`W`はmove propertyと呼ばれているのに対して、盤面を変更する目的の`AB``AW``AE`などはsetup propertyと呼ばれています。SGFでは`;`でノードを区切っていますが、moveとsetupは同ノードに入れてはいけないなど細かい決まりがあるようです。詳細は[公式サイト](https://www.red-bean.com/sgf/)を見てください。

```
AB[e4][d5]AW[d4][e5];B[f5];AW[e5]
```

最初の`AB[e4][d5]AW[d4][e5]`は先ほどのサンプルにもありましたが、これは返し忘れとかではなく単に初期配置に置いたということです。そのあと黒がf5に打った時に、`AW[e5]`がありますが、本当は返って黒になるはずだったe5を返し忘れて白いままだったので強制的に白にした、という意味です。謎棋譜ですね。

オセロの天敵、返し忘れや返し過ぎにも対応できてありがたいことです。

## その気になれば二手連続打ちしても大丈夫
`PL[B]`とすれば強制的に黒番にすることもできます。間違って二手連続で同じ方が打ってしまったり、打てるのにパスしたりというカオスな試合が発生しても表現できます。はい、実は筆者は先日の大会で打てるのにパスするという大失態をやらかしました。このプロパティがないとその試合の棋譜を表現できないところでした。ありがたいことです。

## ということは問題図とかも表現できますね？
はい、できます。`AB`とか`AW`で石を置いて`PL`で手番を指定すれば、先日発売された『[髙橋晃大のオセロ必勝手筋100](https://www.amazon.co.jp/髙橋晃大のオセロ必勝手筋100-髙橋-晃大/dp/4839969361)』のような問題図を作ることもできます。その後の答えの手順や解説コメントもこれまで書いたことから入れられることがわかりますね。何とありがたいことでしょう。

## 今なら検討手順(分岐)も保存可能です
だんだん通販番組をやっている気分になってきました。
試合の棋譜を保存した後、ここでこう打っていればこうなっていたのか、とか実際の進行とは異なる手順を保存しておきたいこともあるかもしれません。さっき書いた問題図であれば、失敗進行とかも保存したいですよね。これもSGFならできるんです。

```
;B[f5];W[d6](;B[c3](;W[d3];B[c4])(;W[f4];B[f6]))(;B[c5];W[f4];B[e3]))
```
これは以下のような分岐を表現したものです。わかりますかね？そう、虎定石と龍定石と兎定石の分岐です（そっちじゃない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202945/69759710-0b89-32ab-2c61-be9dc12f5c67.png)
これで検討手順も保存しておけますし、`C`で検討コメントも入れられますし、ありがたいことです。

## えっ、日付は入れられるのに時刻は入れられないんですか？
最初の方で試合の日付が入れられることは書きましたが、残念ながら時刻を入れるプロパティは用意されていません。これだとオンライン対戦の試合を保存したりするときに何となく不便じゃないですか？
でも大丈夫です。プライベートプロパティとして、標準にないプロパティを追加しても良いことになっているのです。これで時刻情報も保存しておけます。何でもできそうですね。

## でも、お高いんでしょう？
高いとか安いとか意味がわかりませんが、こんなに便利そうなSGFでも課題はあります。
1個上で書いたプライベートプロパティで若干嫌な予感がした方もいると思いますが、プライベートプロパティを使って何かの情報を記録した場合、自分で作ったアプリでは読むことができても、他のアプリには無視されてしまいます。（むしろ知らないプロパティは無視するように実装する必要があります）

これはプライベートプロパティに限ったことではなく、標準で用意されているプロパティもアプリによって対応していたりしていなかったりすることがあります。例えば返し忘れとか返し過ぎとかアプリ側で対応できていなければ当然ファイルがそうなっていても読めませんし、コメント機能がそもそもなければファイルに書いてあっても当然無視されます。アプリの作りによっては無視されたプロパティは、棋譜を再保存したりすると消えたりするでしょう。むしろ大体そうなると思います。

筆者が開発しているアプリ「棋譜Box」では、現時点では外部への入出力を行っておらず、自分で書いて自分で読んでいるだけなのでこの問題には巻き込まれませんが、hajipongさんが述べられていたような構想でSGFを流通させようとした場合にこの問題とどう向き合うかを考えなければならない時がやってくると思います。

# おわりに
簡単ですが、SGFの特徴と課題について書いてみました。初めにも書きましたが、詳しい説明は[公式サイト](https://www.red-bean.com/sgf/)にありますので、本記事で興味を持った方はご参照いただければと思います。

今日の記事はこれで終わりですが、明日また別記事をアップする予定なのでそちらもよろしくお願いします。