背景
2015年1月から、ごいたのコンピュータ対戦プログラムを書いていたが、約1ヶ月が経過したところで手続き型コーディングによる改善に限界を感じるようになった。その後に半月ほど、総当りプログラムができないものかと思考していたが、これも計算困難だと判断した。このため抜本的な改善のために、教師データを収集して機械学習をするべきとの考えに至った。
機械学習用の教師データを収集するために、ごいたの棋譜をプログラミングと親和性の高い形式で記録する必要性がある。本稿では、機械学習のためのごいたの棋譜データの保存形式を提案する。
モデルゲーム
棋譜の定義の前に、説明のためのモデルゲームを示す。
モデルゲームA(最短)
player | hand |
---|---|
0. Alice(dealer) | 王玉香香香香しし |
1. Bob | 飛飛金金金金しし |
2. Carol | 角銀銀銀銀ししし |
3. Dave | 角馬馬馬馬ししし |
turn | Alice | Bob | Carol | Dave |
---|---|---|---|---|
1st | ☗し☖香 | なし | なし | なし |
2nd | ☗し☖香 | なし | なし | なし |
3rd | ☗香☖香 | なし | なし | なし |
4th | ☗王☖玉 |
モデルゲームB(最長)
player | hand |
---|---|
0. Alice(dealer) | 王玉飛香香香しし |
1. Bob | 飛金金金金銀しし |
2. Carol | 角銀銀銀馬ししし |
3. Dave | 角馬馬馬香ししし |
turn | Alice | Bob | Carol | Dave |
---|---|---|---|---|
1st | ☗王☖香 | なし | なし | なし |
2nd | ☗玉☖香 | なし | なし | なし |
3rd | ☗し☖香 | なし | なし | ☖香☖馬 |
4th | なし | なし | なし | ☗し☖馬 |
5th | なし | なし | なし | ☗し☖馬 |
6th | なし | なし | ☖馬☖銀 | なし |
7th | なし | なし | ☗し☖銀 | なし |
8th | なし | なし | ☗し☖銀 | なし |
9th | なし | ☖銀☖金 | なし | なし |
10th | なし | ☗し☖金 | なし | なし |
11th | なし | ☗し☖金 | なし | なし |
12th | なし | ☗金☖飛 |
Aliceの手駒は王1枚以上香3枚し1枚であるため、実は配駒時に勝利が確定しているのだが、勘違いしてこのような棋譜になったとする。
定義
駒:piece
次のように、0-9までの数値で保存する。(仮に手入力をする場合であっても、テンキーのみでタイプができる方が効率が良いと判断したため。)王と玉は、機械学習においては違いが意味をなさないため、同じ値として扱う。
1:王 or 玉, 2:飛, 3:角, 4:金, 5:銀, 6:馬, 7:香, 8:し 9:裏 0:なし
プレイヤー番号:player number
順に0, 1, 2, 3とする。0の対面は2。相手チームは0の次の番のプレイヤーが1、残りのプレイヤーが3となる。通常のゲームでは、親はプレイヤー0から始まる。
0:Alice(dealer), 1:Bob, 2:Carol, 3:Dave
Machine-readableなごいたの棋譜
ごいたは不完全情報ゲームであるため、対戦プロトコルと棋譜とで別の定義をする必要がある。ここでは棋譜を定義する。
JSONを利用する。
対局の名前:match name(MAY)
"title":"◯×大会予選1回戦第1局"
開始/終了日時:start/end time(MAY)
ISO 8601に従う。開始日時もしくは終了日時の片方のみの記載も可。
"start_time":"2004-04-01T12:00Z" "end_time":"2004-04-01T12:00+09:00"
プレイヤー名:player name(MAY)
プレイヤー番号順に記入する。
"players":["Alice", "Bob", "Carol", "Dave"]
棋譜:record of a round(MUST)
数字を連結して表現する。ダブルクオートで囲う。可視性を高めるために"-"を適宜挿入してもよい。ごいたのルールを考慮すると、ゲーム終了の棋譜は、最短で17個、最大59個の数字の連結となる。モデルゲームAを表現すると次のようになる。
"record":"87000870007700011" もしくは、 "record":"87-0-0-0-87-0-0-0-77-0-0-0-11"
モデルゲームBを表現すると次のようになる。
"record":"17000170008700760008600086006500085000850054000840008400042"
勝敗の決していない途中の局面も可。なおゲーム開始時の状態であれば次のようになる。
"record":""
配駒:hands of 4 players(MUST)
8個の数字の連結とする。親から順に4人分の駒を記載する。ダブルクオートで囲う。モデルゲームAであれば、
"hands":["11777788", "22444488", "35555888", "36666888"]
モデルゲームBであれば、
"hands":["11277788", "24444588", "35556888", "36667888"]
となる。必須ではないが、昇順にソートしておくのが望ましい。
親:dealer(SHOULD)
親のプレイヤー番号。省略された場合には自動的に0とする。
"dealer":0
スコア:score(SHOULD)
ゲーム開始前の得点。
"score":[120, 90]
勝者:winner of a round(SHOULD)
その局に勝利したプレイヤーの番号。親が勝利した場合は、
"winner":0
となる。まだ勝負が決していない途中の局面の棋譜の場合は、0,1,2,3以外の値を持つ。省略された場合も、勝負が決していないとする。
"winner":-1
5し:goshi(SHOULD)
5しを宣言したプレイヤーの番号。最大2個まで。なお6し、7し、8しが発生したとしても、ここには記載しない。省略された場合には5しのプレイヤーはいなかったものとする。
"goshi":[] #5しはいない "goshi":[0] #親のAliceが5し "goshi":[1, 2] #BobとCarolが5し
棋譜の例
モデルゲームA(が2回連続で発生した場合)
{
"title":"モデルゲームA",
"start_time":"2015-04-01T12:00+09:00",
"end_time":"2015-04-01T12:20+09:00",
"players":["Alice", "Bob", "Carol", "Dave"],
"round":{
"dealer":0,
"score":[0, 0],
"hands":["11777788", "22444488", "35555888", "36666888"],
"record":"87000870007700011",
"winner":0,
"goshi":
},
"round":{
"dealer":0,
"score":[100, 0],
"hands":["11777788", "22444488", "35555888", "36666888"],
"record":"87000870007700011",
"winner":0,
"goshi":
}
}
モデルゲームB
{"round":{"hands":["11277788","24444588","35556888","36667888"],"record":"17000170008700760008600086006500085000850054000840008400042","winner":0}}