Bonanzaの駒の価値はどこに書かれているのか その1
Bonanzaで駒割を計算するときの、駒の価値はどこに書かれているのかというのは、簡単なようで少しトリッキーです。今回はこの問題について説明します。
まず、駒自体の価値は、param.hでdefineされています。
#define DPawn 87 /* 174 */ #define DLance 232 /* 464 */ #define DKnight 257 /* 514 */ #define DProPawn 534 /* 621 */ #define DProLance 489 /* 721 */ #define DSilver 369 /* 738 */ #define DProKnight 510 /* 767 */ #define DProSilver 495 /* 864 */ #define DGold 444 /* 888 */ #define DBishop 569 /* 1138 */ #define DRook 642 /* 1284 */ #define DHorse 827 /* 1396 */ #define DDragon 945 /* 1587 */ #define DKing 15000
param.hというファイル自体は、実は自動生成されるファイルで、棋譜からの学習時に、学習した駒の価値を書きだすコードが書かれています。(learn2.c)
ゆえに、param.hというファイルを直接編集したところで次回の学習のときに上書きされてしまいます。
さて、これらの値はどこで使われているかと言うと、ini関数(ini.c)で次のようにp_valueの初期化に使われています。
p_value[15+pawn] = DPawn; p_value[15+lance] = DLance; p_value[15+knight] = DKnight; p_value[15+silver] = DSilver; p_value[15+gold] = DGold; p_value[15+bishop] = DBishop; p_value[15+rook] = DRook; p_value[15+king] = DKing; p_value[15+pro_pawn] = DProPawn; p_value[15+pro_lance] = DProLance; p_value[15+pro_knight] = DProKnight; p_value[15+pro_silver] = DProSilver; p_value[15+horse] = DHorse; p_value[15+dragon] = DDragon;
見ての通り、p_valueが駒の価値が入っている配列です。p_valueのpはpieceの頭文字で、valueは「値」ではなく、「価値」の意味でしょう。こうやって、変数名の意味を正しく理解するとソースの読解がしやすくなります。
さて、15というオフセット値が加算されているのは、Bonanzaでは駒をsigned(符号型)で表現するため、先手の駒は1〜15であり、後手の駒は-1〜-15という負の数になります。ゆえに、本来なら p_value [ abs(piece) ]と書くべきところですが、保木さんは、このabsにかかるコストが許せなかったのでしょう。ゆえに、absをせずとも、先手と後手の駒の価値を直接求められるように 15というオフセット値を加算するようにしてあるわけです。
ちなみに、後手の駒に対するp_valueの値も符号はマイナスではなく、プラスです。
このことは、set_derivative_param関数(ini.c)を見ればわかります。
p_value[15-pawn] = p_value[15+pawn]; p_value[15-lance] = p_value[15+lance]; p_value[15-knight] = p_value[15+knight]; p_value[15-silver] = p_value[15+silver]; p_value[15-gold] = p_value[15+gold]; p_value[15-bishop] = p_value[15+bishop]; p_value[15-rook] = p_value[15+rook]; p_value[15-king] = p_value[15+king]; p_value[15-pro_pawn] = p_value[15+pro_pawn]; p_value[15-pro_lance] = p_value[15+pro_lance]; p_value[15-pro_knight] = p_value[15+pro_knight]; p_value[15-pro_silver] = p_value[15+pro_silver]; p_value[15-horse] = p_value[15+horse]; p_value[15-dragon] = p_value[15+dragon];
一見すると、(pawnの値は1ですから) p_value[15]の値がセットされていないかのように見えますが、int関数で最初に次のようにゼロ初期化されているので心配ありません。
for ( i = 0; i < 31; i++ ) { p_value[i] = 0; }
つづく