First working version of iterative deepening alpha beta

This commit is contained in:
Yorick Barbanneau 2023-12-19 22:02:55 +01:00
parent 2ffd077a26
commit aa9d13d587
2 changed files with 62 additions and 11 deletions

View file

@ -155,7 +155,7 @@ class AlphabetaPlayerEngine(PlayerEngine):
def checkAlphaBeta(self, board, friend_move : bool, depth, alpha, beta):
nodes = 1
leafs = 0
if depth == 0 or board.is_game_over():
if depth == 0 or board.is_game_over() or self.interrupt_search:
leafs +=1
return self.heuristic.get(board, self.player), nodes, leafs
@ -169,10 +169,10 @@ class AlphabetaPlayerEngine(PlayerEngine):
nodes += n
leafs += l
if alpha >= beta:
self.logger.debug("Alpha pruning - alpha:{} / beta:{}".format(
alpha,
beta
))
# self.logger.debug("Alpha pruning - alpha:{} / beta:{}".format(
# alpha,
# beta
# ))
return beta, nodes, leafs
return alpha, nodes, leafs
@ -186,10 +186,10 @@ class AlphabetaPlayerEngine(PlayerEngine):
nodes += n
leafs += l
if alpha >= beta:
self.logger.debug("Beta pruning - alpha:{} / beta:{}".format(
alpha,
beta
))
# self.logger.debug("Beta pruning - alpha:{} / beta:{}".format(
# alpha,
# beta
# ))
return alpha, nodes, leafs
return beta, nodes, leafs
@ -240,3 +240,53 @@ class MinmaxDeepeningPlayerEngine(MinmaxPlayerEngine):
def alarm_handler(self, signal, frame):
self.logger.debug("Raise SIGALMR Signal")
self.interrupt_search = True
class AlphaBetaDeepeningPlayerEngine(AlphabetaPlayerEngine):
def get_move(self, board):
super().get_move(board)
self.interrupt_search = False
# Get an alarm signal to stop iterations
signal.signal(signal.SIGALRM, self.alarm_handler)
signal.alarm(self.options['time_limit'])
depth = 1
alpha = -math.inf
beta = math.inf
nodes = 1
leafs = 0
move = None
# We can go deeper than blank place in our board, then we must get
# numbers of avaible place
max_depth = (board.get_board_size()**2) - (
board.get_nb_pieces()[0] + board.get_nb_pieces()[1])
# Iterate depth while our alarm does not trigger and there is enougth
# avaiable move to play
while not self.interrupt_search and depth <= max_depth:
for m in board.legal_moves():
board.push(m)
v, n, l = self.checkAlphaBeta(board, False, depth - 1, alpha, beta)
board.pop()
nodes += n
leafs += l
if v >= alpha:
alpha = v
move = m
self.logger.debug("found a better move: {} (heuristic:{})".format(
move,
alpha
))
depth = depth + 1
self.logger.debug("id_alphabeta - depth reached: {} | max depth : {}".format(
depth - 1,
max_depth
))
return move
def alarm_handler(self, signal, frame):
self.logger.debug("Raise SIGALMR Signal")
self.interrupt_search = True

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
from classes.Reversi import Board
from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine, MinmaxDeepeningPlayerEngine
from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine, MinmaxDeepeningPlayerEngine, AlphaBetaDeepeningPlayerEngine
from classes.Heuristic import ScoreHeuristicEngine, WeightHeuristicEngine, FullHeuristicEngine
import logging as log
import argparse as arg
@ -12,7 +12,7 @@ from classes.CustomFormater import CustomFormatter
Function to parse command line arguments
"""
def parse_aguments():
engines_choices=['random', 'human', 'minmax', 'alphabeta', 'id_minmax']
engines_choices=['random', 'human', 'minmax', 'alphabeta', 'id_minmax', 'id_alphabeta']
heuristic_choices=['score', 'weight', 'full']
parser = arg.ArgumentParser('Playing Reversi with (virtual) friend')
@ -79,6 +79,7 @@ if __name__ == '__main__':
"minmax": MinmaxPlayerEngine,
"alphabeta": AlphabetaPlayerEngine,
"id_minmax": MinmaxDeepeningPlayerEngine,
"id_alphabeta": AlphaBetaDeepeningPlayerEngine
}
heuristic_engine = {
"score": ScoreHeuristicEngine,