コンピュータ囲碁プログラム CGF碁盤プロトコル

書き終えた。ディープ・ラーニングで囲碁プログラムやりたいが　囲碁プログラム分かんね、という人は CgfGoBan から入るのがいいのではないか。
細かなことをいうと CGF碁盤のは、プロトコルじゃなくてＡＰＩか。関数３つ覚えるだけ。

あ、そういえば　UEC杯コンピュータ囲碁大会　では　別に通信なんかできなくたって **自分が作ったソフトの画面を見ながら D3 に打ちました、とか　対局者同士で人間が手入力して対局しても構わないんだった。** この記事が全て無駄になったが、いいだろう。コンピュータ将棋から入ってくると、コンピュータ囲碁もいろいろ新鮮だ。


#今回の記事
なんかもう　UEC杯が　今年で終わってしまうが、
コンピュータ囲碁プログラム　で指し手をサーバーに送る部分を解説する。

通信用のソフトは　CGF碁盤　を使うとする。

CgfGoBan : http://www.yss-aya.com/cgfgoban_j.html

別に　わたしが書かなくても cgfthink.txt に書かれているんだが、みんな読まないだろう。

大まかに言うと、**cgfgui_thinking関数に 引数８個を渡せば（受け取れば）いい。**
あとは細かなものだ。
これでコンピュータ囲碁ソフトは　通信対戦ができる。

ちなみに　参加者はだいたい　CGF碁盤とか使ってなくて　プロトコル読んで　自力実装してくるようだ（＞＿＜）


#引数1　int　init_board[]
囲碁盤なんだが、例えば１９路盤とは　こんな感じになっている。

      ABCDEFGHJKLMNOPQRST
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19

左上から右へ、右端から１段下の左端へ。ちょうど **日本人向きのテキストエディターと同じ座標** の方向だ。
ところで　囲碁盤、将棋盤、チェス盤　の座標の振り方を見比べると　みな違って面白い。


１９路盤の周りに　**枠**　があると考えてくれ。

だから配列は　21 x 21　の部分を使うんだが、
実際には　縦21、横256　のテーブルだ。

    init_board[ y * 256 + x ]

なんで　こんなんなってるかというと、１６進表記で 0xYYXX としたいわけだ。
例えば  D3　に打ち込みたいときは 0x0304 となる。XYひっくり返ってしまうが……。

で、

- 0 空いてる交点
- 1 黒石
- 2 白石
- 3 枠

を入れる。将棋やチェスをやっていると、 **えっ、これだけ！？** と感動を覚えるところだ。実のところ　**プログラムは簡単だわ**、**何をしたら勝てるのかそもそも囲碁が分からないわ**、**適当に思考ルーチンを組んでも適当に動いてくれるわ**、**ハンディキャップの付け方は数段階あるわ**、**盤のサイズは変えれるわ**、プログラミングの教材として面白いのではないか、**中国ルールならば**。日本ルールが実装できるなら、既に強豪ソフトだと思う。

#引数2　int　kifu[][3]
棋譜。とりあえず CgfGoBan では 2048手まで、としている。まあ、500手を超えるようなら **３コウ、４コウ、５コウ　でもして永遠に石を取り合っているのだろう**。

だから配列のサイズは

    kifu[2048][3]

なんだが、１手目を[0]として 2048手目が[2047]となる。
うしろの[3]は何か。

kifu[][0] これは、石を置いた座標を入れる。さっきの 0x0304 などが入る。パスは 0。
kifu[][1] これは、石の色が入る。黒が1、白が2 だった。
kifu[][2] これは、あってもなくてもいいんだが、考えていた秒が入る。1秒考えたら1。もう2017年では強豪ソフトは 0 秒で打ってしまうんだろうが、だいたい文化的なものに触れるとき、こういう淘汰されていく部分を見るのは　味わい深い。

**簡単だろ。**

#引数3　int　tesuu
手数。

0 から始まるので、tesuu が 0 の黒番は、0 手目が打たれた盤面（初期局面）を見ながら、これから 1 手目 を打つところだ。

だから白が 40手目を打ったら tesuu は 40 で、40手目が打たれた盤面を見ながら黒がこれから 41 手目を打つことになる。

理屈には適っているが　感覚的には　すごく　ややこしい。むしろ **棋譜配列のインデックス** とでも思ってた方が楽か。

#引数4　int　black_turn
これから黒が石を置く（着手する）というときに 1 が入っている。そうでなければ 0。要するに黒番なら 真、白番なら 偽。

プログラムを組んでるときに　石の色と間違えて　白の手番こないな、とか思ったりするが　紛らわしいと思ったら　好きなように改造しよう。

#引数5　int　board_size
盤面のサイズ。１９路盤（じゅーきゅーろばん）なら 19、９路盤なら 9。

もう分かってても　１手ごとに毎回　送られてくる。

#引数6　double　komi
囲碁は先手有利で、黒番と　白番では　黒が有利なので、白にハンディーキャップをあげようというもの。また、**0.5 を付ける** という工夫によって　互先（たがいせん。初期局面でハンディーキャップの黒石を置いてないやつ）では持碁（じご。引き分け）を　無くしている。置き碁（おきご。初期局面でハンディーキャップの黒石を置いてあるやつ）では持碁になる可能性がある。

コミはプレイヤーの実力差ではなく、先手後手の有利不利を埋めるためのハンディーキャップで、プロ棋士が年度の黒白の勝率を見て調整している。
特にルールは無いので、盤のサイズが変わっても　１９路盤でも９路盤でも　コミはそのまんまで構わない。

黒は有利を拡大して逃げ切ろうとするし、白は技芸を使って追い抜こう、というのが囲碁のゲーム性。

中国ルールでは　コミ7.5、日本ルールでは コミ6.5。
囲碁盤の目の数は奇数で、黒手番の方が１手多く回ってくる理屈なので、単純に考えれば、理屈上黒は石１つ多く置ける。
中国ルールでは石、日本ルールでは囲んだスペースに着目して勝ち負けを決めるので、中国ルールでは黒に１石分有利に出てしまうのでコミが１多い。
つまり　中国ルールも　日本ルールもこれで　コミでは大差ない。

ちょっと疲れたので　休憩してから続きを書く。

#引数7　int　endgameType
うむ……、インスタント・コーヒーがうまい……。お湯がコーヒーに変わるのだから　コーヒーに変えない手はないぜ☆

ところで　この引数は　終局処理フラグで　0～3　あるんだが、何なのかというと　囲碁は最後に　この石は死んでる、この石は生きている、と判定するんだが **画面上の石に　〇×　を付けたいよね** という話しだ。空き地も、黒のか白のかダメなのか印を付けたい。

この cgfgui_thinking関数の引数にセットした内容は CgfGoBan という碁盤画面に送り返されるんだが、「おいコンピューター、石の生き死に返せよ」とかいうときに画面から思考エンジンに 1 とか返ってくるわけだ。

- 0 （プレイ中）思考しろよ
- 1 （終局処理）石の生き死に返せよ。空き地は黒、白、ダメのどれか返せよ
- 2 （テスト用）局面評価を返せよ、？とか▲とか記号はいくつかあるんで使えよ
- 3 （テスト用）マス目に数字を付けろよ、５３手目の石とかよく使うだろ

というのが入って関数が呼び出される。

#引数8　int　endgameBoard[]
これがだから endgameType 引数に対応して　黒の〇とか　数字とかを入れる囲碁盤だ。

内容としては、

- 0 石が活、あるいは分かんないとき
- 1 石が死
- 2 セキで活（未使用なので 0 を使うこと）
- 3 空き地は白地
- 4 空き地は黒地
- 5 空き地はダメ

## セキとは
セキというのは　石を置いたら取り返されるのが分かっているので置きたくないから白黒どっちもずっと空き地にしているところだ。

だから囲碁の石は実際のところ　活き石、死に石　の他に　セキ石　というのがある。セキ石は 活き石 としてカウントしよう、ということだ。

**中国ルールでは**　セキ（石を置きたくない空き地）が残ったら　黒のものか白のものか囲まれている４方向（または枠）を見て　黒だけに囲まれていれば黒のもの、白だけに囲まれていれば白のもの、どちらのものとも言えないものは　白黒半分ずつ点数を分ける。

このとき、どちらのものでもない２つの空き地が残っていたら、白１、黒１と仲良く折半。
どちらのものでもない３つの空き地が残っていたら　白1.5、黒1.5 と分けるわけだが、ここで 0.5 という端数が出てくる。これが原因で　コミの0.5が無かった時代には　引き分け（持碁）があった。

**日本ルールでは**　セキに絡んでいる石や空き地は数えない。冷たいものだ。

セキによって　**中国ルールと日本ルールとで勝敗がひっくり返る**ことはある。

だから　おおまかに言うと、囲碁のルールをしっかり取り入れていれば　それはもう強豪ソフト、でも　強豪ソフトじゃなくても　まあ　だいたい石は置けるよね、勝敗の計算を間違ってたりするけど、ということだ。

## 勝敗の計算を間違っていて、コンピュータ・プログラミングと言えるのか？
という疑問が当然出てくると思うんだが、**勝敗の計算ができるんならそれは囲碁が強いということだ** というのが、どういうことか説明しよう。

盤上に最後の石まで置けば、石の数でも空き地の数でも、数えることはできるだろう。ひとーつ、ふたーつ、みっつ。**オセロみたいにまだここからひっくり返せる** という局面であれば、ひっくり返して、ひっくり返らなくなるまで石を置けば。

しかし　そこまで打たなくても　お互いが納得したところで対局終了するのが囲碁のゲーム性の１つだ。じゃあ、どこで納得するのか。**強豪なら早く納得するだろうし、初心者なら打つところがなくなるまで打ってから最後に石なり空き地なりを数えるだろう。** な？　ほら分かった。

だから　**人間の実力以上のソフト**なら　人間が対局終了した局面の勝敗の計算をできるだろうし、
**人間の実力以下のソフト**なら　人間が対局終了した局面をみても「まだまだこれからだろ！もっと指せ」と思う。別に人間に限らず　先に勝敗判定できる方は強い、**その勝敗判定が合ってれば**の話しだが。勝敗が合ってるのか合ってないのかどう判定するのか、また堂々めぐりだが……。

理屈上、最後は 弱い方に付き合って、強い方は相手が納得するまで　しばらく打ち続けることになると思うんだが、そんな経験したことないんで分からないぜ。**勝敗が計算できるんなら強豪ソフト。** 納得するまで説明は続く。

で、**中国ルールは納得行かなかったら石が置けなくなるまで最後まで指してよい** ので、コンピューター同士の対戦にはちょうどいい。しかし中国ルールでも納得したところで勝敗を計算しろと言われたら　問題点は同じだが。

囲碁おもろ☆

で　第８引数　なんだが、**図形を置く**というのもある。

- 0: 何も描かない
- 1: 三角形
- 2: 四角
- 3: 円
- 4: ×
- 5: "？"の記号
- 6: 横線
- 7: 縦線
- 8: 斜め、左上から右下
- 9: 斜め、左下から右上
- 0x1000: 黒で描く（色指定)
- 0x2000: 白で描く (色指定）

で、最後の色指定なんだが、

    0x1000 | 1

と論理和を取れば　黒の三角　といった指定になる。

最後に　第８引数　は、**数字を置く**というのもある。

0 以外の正の整数が描画されるのかと思う。２桁の数字は置けるが、３桁はどうだったか。

#返り値
返り値は　石を置く場所。0x0304 とか。パスなら 0。

#これでもうだいたい CgfGoBan を使えるのではないか
盤さえ読めれば　数字を返せばいいだけだｗｗｗ

あとは自殺手やコウなど　ちょっとだけ　囲碁のルールを覚えればいける。

他に　**初期化** と **終了処理** のための関数があるが　説明は省略するｗｗｗ

CgfGoBan をいじっている様子は　別のブログでも書いた。
http://kifuwarabe.warabenture.com/2015/12/14/%E3%80%90%E5%9B%B2%E7%A2%81%E3%80%91%E3%81%8D%E3%81%B5%E3%82%8F%E3%82%89%E3%81%B9%E3%81%8C%E3%83%9D%E3%83%8A%E3%83%B3%E3%82%B6%EF%BC%88%E3%81%AE%E5%BC%9F%EF%BC%89%E3%82%92%E5%80%92%E3%81%99%E2%98%86-3/

なんとなく分かるだろう。