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ノードあたりの速度を向上する修正は本節までです。
次節では探索ノード数を減らす工夫を行ないます。