diff --git a/src/classes/Engines.py b/src/classes/Engines.py index dd129c9..8b29dca 100644 --- a/src/classes/Engines.py +++ b/src/classes/Engines.py @@ -1,4 +1,4 @@ -import random, math, time +import random, math, time, signal class PlayerEngine: def __init__(self, player, logger, heuristic, options: dict = {}): @@ -7,6 +7,7 @@ class PlayerEngine: self.logger = logger self.heuristic = heuristic self.options = options + self.interrupt_search = False self.logger.info("Init engine {}, options:{}".format( self.__class__.__name__, self.options @@ -92,7 +93,7 @@ class MinmaxPlayerEngine(PlayerEngine): nodes = 1 leafs = 0 move = '' - 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 @@ -192,3 +193,50 @@ class AlphabetaPlayerEngine(PlayerEngine): return alpha, nodes, leafs return beta, nodes, leafs + +class MinmaxDeepeningPlayerEngine(MinmaxPlayerEngine): + + 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 + value = -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.checkMinMax(board, False, depth - 1) + if v > value: + value = v + move = m + self.logger.debug("found a better move: {} (heuristic:{})".format( + move, + value + )) + nodes += n + leafs += l + board.pop() + depth = depth + 1 + self.logger.debug("id_minmax - 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