| 4.4 終盤探索のリーフ展開 |
本節では、終盤探索時に最後の1手の処理を修正します。
「最後の1手」というのは、空きマスが1箇所しかないときの手という意味です。
空きマスが1箇所しかない場合には、着手して1手戻す必要はありません。
現在の石差と、空きマスに着手した場合に返す石の数とから、最終の石差を計算できるためです。
例えば空きマスが1箇所の時点で黒番の時には以下のような処理を行ないます。
それでは終盤探索の修正を行ないましょう。
修正する関数はCom_EndSearch()だけです。
修正前はin_depthが0のときに石差を返す処理を行なっていました。
修正後はin_depthが1のときに前述の処理を行ないます。
static int Com_EndSearch(Com *self, int in_depth, int in_alpha, int in_beta, int in_color, int in_opponent, int in_pass, int *out_move)
{
MoveList *p;
int value, max = in_alpha;
int can_move = 0;
int move;
/* 残り1マスのときには着手せず返せる石数のみを調べる */
if (in_depth == 1) {
self->Node++;
p = self->Moves->Next;
value = Board_CountFlips(self->Board, in_color, p->Pos);
max = Board_CountDisks(self->Board, in_color) - Board_CountDisks(self->Board, in_opponent);
if (value > 0) {
*out_move = p->Pos;
return max + value + value + 1;
}
value = Board_CountFlips(self->Board, in_opponent, self->Moves->Next->Pos);
if (value > 0) {
*out_move = PASS;
return max - value - value - 1;
}
*out_move = NOMOVE;
return max;
}
*out_move = NOMOVE;
for (p = self->Moves->Next; p; p = p->Next) {
if (Board_Flip(self->Board, in_color, p->Pos)) {
RemoveList(p);
if (!can_move) {
*out_move = p->Pos;
can_move = 1;
}
value = -Com_EndSearch(self, in_depth - 1, -in_beta, -max, in_opponent, in_color, 0, &move);
Board_Unflip(self->Board);
RecoverList(p);
if (value > max) {
max = value;
*out_move = p->Pos;
if (max >= in_beta) {
return in_beta;
}
}
}
}
if (!can_move) {
if (in_pass) {
*out_move = NOMOVE;
self->Node++;
max = Board_CountDisks(self->Board, in_color) - Board_CountDisks(self->Board, in_opponent);
} else {
*out_move = PASS;
max = -Com_EndSearch(self, in_depth, -in_beta, -max, in_opponent, in_color, 1, &move);
}
}
return max;
}
今回の修正によって数%ですが速度が向上しているようです。
探索時1ノードあたりの速度を向上する修正は本節までです。
次節では探索ノード数を減らす工夫を行ないます。