First working version of iterative deepening alpha beta
This commit is contained in:
parent
2ffd077a26
commit
aa9d13d587
2 changed files with 62 additions and 11 deletions
|
@ -155,7 +155,7 @@ class AlphabetaPlayerEngine(PlayerEngine):
|
||||||
def checkAlphaBeta(self, board, friend_move : bool, depth, alpha, beta):
|
def checkAlphaBeta(self, board, friend_move : bool, depth, alpha, beta):
|
||||||
nodes = 1
|
nodes = 1
|
||||||
leafs = 0
|
leafs = 0
|
||||||
if depth == 0 or board.is_game_over():
|
if depth == 0 or board.is_game_over() or self.interrupt_search:
|
||||||
leafs +=1
|
leafs +=1
|
||||||
return self.heuristic.get(board, self.player), nodes, leafs
|
return self.heuristic.get(board, self.player), nodes, leafs
|
||||||
|
|
||||||
|
@ -169,10 +169,10 @@ class AlphabetaPlayerEngine(PlayerEngine):
|
||||||
nodes += n
|
nodes += n
|
||||||
leafs += l
|
leafs += l
|
||||||
if alpha >= beta:
|
if alpha >= beta:
|
||||||
self.logger.debug("Alpha pruning - alpha:{} / beta:{}".format(
|
# self.logger.debug("Alpha pruning - alpha:{} / beta:{}".format(
|
||||||
alpha,
|
# alpha,
|
||||||
beta
|
# beta
|
||||||
))
|
# ))
|
||||||
return beta, nodes, leafs
|
return beta, nodes, leafs
|
||||||
return alpha, nodes, leafs
|
return alpha, nodes, leafs
|
||||||
|
|
||||||
|
@ -186,10 +186,10 @@ class AlphabetaPlayerEngine(PlayerEngine):
|
||||||
nodes += n
|
nodes += n
|
||||||
leafs += l
|
leafs += l
|
||||||
if alpha >= beta:
|
if alpha >= beta:
|
||||||
self.logger.debug("Beta pruning - alpha:{} / beta:{}".format(
|
# self.logger.debug("Beta pruning - alpha:{} / beta:{}".format(
|
||||||
alpha,
|
# alpha,
|
||||||
beta
|
# beta
|
||||||
))
|
# ))
|
||||||
return alpha, nodes, leafs
|
return alpha, nodes, leafs
|
||||||
return beta, nodes, leafs
|
return beta, nodes, leafs
|
||||||
|
|
||||||
|
@ -240,3 +240,53 @@ class MinmaxDeepeningPlayerEngine(MinmaxPlayerEngine):
|
||||||
def alarm_handler(self, signal, frame):
|
def alarm_handler(self, signal, frame):
|
||||||
self.logger.debug("Raise SIGALMR Signal")
|
self.logger.debug("Raise SIGALMR Signal")
|
||||||
self.interrupt_search = True
|
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
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from classes.Reversi import Board
|
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
|
from classes.Heuristic import ScoreHeuristicEngine, WeightHeuristicEngine, FullHeuristicEngine
|
||||||
import logging as log
|
import logging as log
|
||||||
import argparse as arg
|
import argparse as arg
|
||||||
|
@ -12,7 +12,7 @@ from classes.CustomFormater import CustomFormatter
|
||||||
Function to parse command line arguments
|
Function to parse command line arguments
|
||||||
"""
|
"""
|
||||||
def parse_aguments():
|
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']
|
heuristic_choices=['score', 'weight', 'full']
|
||||||
parser = arg.ArgumentParser('Playing Reversi with (virtual) friend')
|
parser = arg.ArgumentParser('Playing Reversi with (virtual) friend')
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ if __name__ == '__main__':
|
||||||
"minmax": MinmaxPlayerEngine,
|
"minmax": MinmaxPlayerEngine,
|
||||||
"alphabeta": AlphabetaPlayerEngine,
|
"alphabeta": AlphabetaPlayerEngine,
|
||||||
"id_minmax": MinmaxDeepeningPlayerEngine,
|
"id_minmax": MinmaxDeepeningPlayerEngine,
|
||||||
|
"id_alphabeta": AlphaBetaDeepeningPlayerEngine
|
||||||
}
|
}
|
||||||
heuristic_engine = {
|
heuristic_engine = {
|
||||||
"score": ScoreHeuristicEngine,
|
"score": ScoreHeuristicEngine,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue