Implement heuristics classes

This commit is contained in:
Yorick Barbanneau 2023-12-16 23:02:36 +01:00
parent 3784faeaed
commit a1812aaedf
3 changed files with 63 additions and 38 deletions

View file

@ -1,10 +1,10 @@
import random, math import random, math
from .Heuristic import ReversiHeuristic
class PlayerEngine: class PlayerEngine:
def __init__(self, logger, options: dict = {}): def __init__(self, logger, heuristic, options: dict = {}):
# init logger do display informations # init logger do display informations
self.logger = logger self.logger = logger
self.heuristic = heuristic
self.options = options self.options = options
self.logger.info("Init engine {}, options:{}".format( self.logger.info("Init engine {}, options:{}".format(
self.__class__.__name__, self.__class__.__name__,
@ -91,11 +91,7 @@ class MinmaxPlayerEngine(PlayerEngine):
move = '' move = ''
if depth == 0: if depth == 0:
leafs +=1 leafs +=1
if self.options['heuristic'] == 'weight': return self.heuristic.get(board), nodes, leafs
score = ReversiHeuristic(board).get()
else:
score = board.heuristique()
return score, nodes, leafs
if friend_move: if friend_move:
value = -math.inf value = -math.inf
@ -157,11 +153,7 @@ class AlphabetaPlayerEngine(PlayerEngine):
leafs = 0 leafs = 0
if depth == 0 : if depth == 0 :
leafs +=1 leafs +=1
if self.options['heuristic'] == 'weight': return self.heuristic.get(board), nodes, leafs
score = ReversiHeuristic(self.logger).get(board)
else:
score = board.heuristique()
return score, nodes, leafs
if friend_move: if friend_move:
value = -math.inf value = -math.inf

View file

@ -1,12 +1,30 @@
class ReversiHeuristic(): class HeuristicEngine:
def __init__(self, logger, weight = [1, 2, 10, 20]): def __init__(self, logger, options):
self.logger = logger self.logger = logger
self.weight = weight self.options = options
self.logger.info("Heuristic engine {}, options:{}".format(
self.__class__.__name__,
self.options
))
def get():
raise NotImplementedError
class ScoreHeuristicEngine(HeuristicEngine):
def get(board):
return board.heuristique()
class WeightHeuristicEngine(HeuristicEngine):
def get(self, board): def get(self, board):
size = board.get_board_size() score = get_weight(board)
return score
def get_weight(self, board):
score = 0 score = 0
weights = self._get_weight(size) size = board.get_board_size()
weights = self._get_weight_array(size)
for pos_x in range(size): for pos_x in range(size):
for pos_y in range(size): for pos_y in range(size):
if board._board[pos_x][pos_y] == board._nextPlayer: if board._board[pos_x][pos_y] == board._nextPlayer:
@ -14,25 +32,28 @@ class ReversiHeuristic():
else: else:
score -= weights[pos_x][pos_y] score -= weights[pos_x][pos_y]
return score return score
def _get_weight(self, size):
w = [[ 0 for _ in range(size)] for _ in range(size)]
def _get_weight_array(self, size):
w = [[ 0 for _ in range(size)] for _ in range(size)]
padding = size // 5
center = size // 2
for pos_y in range(size): for pos_y in range(size):
for pos_x in range(size): for pos_x in range(size):
# Elements in the corner # Elements in the corner
if pos_x in [0, size -1] and pos_y in [0,size - 1]: if pos_x in [0, size -1] and pos_y in [0,size - 1]:
w[pos_x][pos_y] = self.weight[3] w[pos_x][pos_y] = self.weight[2]
# Elements on the border # Elements on the border
elif pos_x in [0, size -1] or pos_y in [0, size -1]: elif pos_x in [0, size -1] or pos_y in [0, size -1]:
w[pos_x][pos_y] = self.weight[2] w[pos_x][pos_y] = self.weight[1]
# Element the center # Element the center
elif pos_x in range( int(size // 2 - 2), size // 2 + 2) and pos_y in range( size // 2 - 2, size // 2 + 2): elif pos_x in range( center - padding, center + padding) and pos_y in range(center - padding, center + padding):
w[pos_x][pos_y] = self.weight[1]
else:
w[pos_x][pos_y] = self.weight[0] w[pos_x][pos_y] = self.weight[0]
return w return w
class FullHeuristicEngine(WeightHeuristicEngine):
def get(self, board):
return self.get_weight(board) + board.heuristique()

View file

@ -2,6 +2,7 @@
from classes.Reversi import Board from classes.Reversi import Board
from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine
from classes.Heuristic import ScoreHeuristicEngine, WeightHeuristicEngine, FullHeuristicEngine
import logging as log import logging as log
import argparse as arg import argparse as arg
from classes.CustomFormater import CustomFormatter from classes.CustomFormater import CustomFormatter
@ -12,7 +13,7 @@ Function to parse command line arguments
""" """
def parse_aguments(): def parse_aguments():
engines_choices=['random', 'human', 'minmax', 'alphabeta'] engines_choices=['random', 'human', 'minmax', 'alphabeta']
heuristic_choices=['weight',] heuristic_choices=['score', 'weight', 'full']
parser = arg.ArgumentParser('Playing Reversi with (virtual) friend') parser = arg.ArgumentParser('Playing Reversi with (virtual) friend')
parser.add_argument('-we', '--white-engine', parser.add_argument('-we', '--white-engine',
@ -41,13 +42,13 @@ def parse_aguments():
parser.add_argument('-bh', '--black-heuristic-engine', parser.add_argument('-bh', '--black-heuristic-engine',
help='Black player heutistic engine', help='Black player heutistic engine',
choices=['board', 'weight'], choices= heuristic_choices,
default='board', default='board',
) )
parser.add_argument('-wh', '--white-heuristic-engine', parser.add_argument('-wh', '--white-heuristic-engine',
help='White player heutistic engine', help='White player heutistic engine',
choices=['board', 'weight'], choices=heuristic_choices,
default='board', default='board',
) )
@ -65,12 +66,17 @@ def parse_aguments():
Main Function Main Function
""" """
if __name__ == '__main__': if __name__ == '__main__':
engines = { player_engines = {
"random": RandomPlayerEngine, "random": RandomPlayerEngine,
"human": HumanPlayerEngine, "human": HumanPlayerEngine,
"minmax": MinmaxPlayerEngine, "minmax": MinmaxPlayerEngine,
"alphabeta": AlphabetaPlayerEngine, "alphabeta": AlphabetaPlayerEngine,
} }
heuristic_engine = {
"score": ScoreHeuristicEngine,
"weight": ScoreHeuristicEngine,
"full": ScoreHeuristicEngine,
}
print("Stating PyReverso...") print("Stating PyReverso...")
args = parse_aguments() args = parse_aguments()
logger = log.getLogger() logger = log.getLogger()
@ -93,14 +99,20 @@ if __name__ == '__main__':
args.black_engine, args.black_engine,
args.white_engine args.white_engine
)) ))
wplayer = engines[args.white_engine](logger, { wplayer = player_engines[args.white_engine](
'depth': args.white_depth_exploration, logger,
'heuristic': args.white_heuristic_engine heuristic_engine[args.white_heuristic_engine],
}) {
bplayer = engines[args.black_engine](logger, { 'depth': args.white_depth_exploration,
'depth': args.black_depth_exploration, }
'heuristic': args.black_heuristic_engine )
}) bplayer = player_engines[args.black_engine](
logger,
heuristic_engine[args.black_heuristic_engine],
{
'depth': args.black_depth_exploration,
}
)
while ( not game.is_game_over()): while ( not game.is_game_over()):
if game._nextPlayer == 1: if game._nextPlayer == 1:
move = bplayer.get_move(game) move = bplayer.get_move(game)