できるだけChatGPTだけで作るリバーシ(オセロ)ソフト その5-2
ちょっと間が開いたけど、実際には意外と色々試したりしています。
探索関数を変えてみた
本来なら強化学習用に使うであろう方法を用いていたので、より実践向けの探索方法に変えてみました。
今回は新規のチャットを始め、以下のプロンプトを入れてSearchAndEvaluation関数を貼り付けてみました。
その回答が、次の通り。
以下にアルファベータ法を利用してリバーシの探索関数を変更しました。アルファベータ法は、ゲーム木の深さを制限しながら最適な手を見つけるための方法です。深さ制限を使用しない場合、アルファベータ法は通常のミニマックスアルゴリズムと同じになります。この方法は、不要なノードを探索することなくゲーム木を探索し、計算時間を大幅に削減します。
以下はアルファベータ法を実装したコードの変更部分です:
class SearchAndEvaluation:
# [中略]
def alpha_beta_search(self, board, player, depth, alpha, beta):
if depth == 0 or not self.get_possible_moves(board, player):
return self.evaluate(board), None
best_move = None
if player == self.player: # Maximizer
max_eval = -float('inf')
for move in self.get_possible_moves(board, player):
simulated_board = [row[:] for row in board]
self.place_piece(move[0], move[1], player, board=simulated_board, actual=True)
eval_value, _ = self.alpha_beta_search(simulated_board, -player, depth-1, alpha, beta)
if eval_value > max_eval:
max_eval = eval_value
best_move = move
alpha = max(alpha, eval_value)
if beta <= alpha:
break
return max_eval, best_move
else: # Minimizer
min_eval = float('inf')
for move in self.get_possible_moves(board, player):
simulated_board = [row[:] for row in board]
self.place_piece(move[0], move[1], player, board=simulated_board, actual=True)
eval_value, _ = self.alpha_beta_search(simulated_board, -player, depth-1, alpha, beta)
if eval_value < min_eval:
min_eval = eval_value
best_move = move
beta = min(beta, eval_value)
if beta <= alpha:
break
return min_eval, best_move
def simulate(self):
_, best_move = self.alpha_beta_search(self.board, self.player, self.depth, -float('inf'), float('inf'))
return best_move
# [中略]
これにより、`simulate`関数をアルファベータ法を使用してベストな手を求めるように変更しました。また、深さ制限が導入されているため、探索の深さが指定された深さに達するか、利用可能な手がない場合に探索が終了します。
呼び元は深さを3にして、再度対局させてみました。
意外と競った感じになりましたが、序盤からあっさり角を取らせるなどまだまだ考え方を変える必要がありそうです。
ただ、アルファベータ法でやった方がいいかなというのが今回の結果です。
ちなみに、読みの深さを7にするとかえって弱くなったので、現状は3が最適かな?
またしばらく色々テストしながら、どうやったらこの状況を打破できるか考えていこうと思います。