diff --git a/README.md b/README.md index 44b9f12..bcae4fa 100644 --- a/README.md +++ b/README.md @@ -19,12 +19,34 @@ au programme via la commande `./game.py -h`. Voici quelques exemple de lancement: ```shell -# Lancement de base: les deux joueurs jouent avec le moteur aléatoire: +# Lancement de base: les deux joueurs jouent avec le moteur aléatoire et les +options de base: ./game.py # joueur noir humain et joueur blanc MinMax avec une profondeur de 5 -./game.py -b human -w minmax --depth 5 +./game.py -be human -we minmax --white-depth-exploration 5 ``` +Voici la liste des options : + + * `-be` | `--black-player-engine`: moteur utilisé par le joueur avec les pions + noirs + * `-we` | `--white-player-engine`: moteur utilisé par le joueur avec les pions + blancs + * `-bd` | `--black-depth-exploration`: niveau d'eploration de l'arbre de jeu + pour le joueur au pions noirs, valable pour les moteurs `minmax` et + `alphabeta` + * `-wd` | `--white-depth-exploration`: niveau d'eploration de l'arbre de jeu + pour le joueur au pions noirs, valable pour les moteurs `minmax` et + `alphabeta` + * `-bh` | `--black-heuristic-engine`: moteur heuristique utilisé pour + l'exploration de l'arbre de jeu du joueur noir (valable pour les moteur de + jeu `minmax` et `alphabeta`) + * `-wh` | `--black-heuristic-engine`: moteur heuristique utilisé pour + l'exploration de l'arbre de jeu du joueur blanc (valable pour les moteur de + jeu `minmax` et `alphabeta`) + +L'affichage verbeux est activé avec `-V` et les informations de débogage sont +affichée avec l'option `-d`. ## Choix d'implémentation diff --git a/src/classes/Engines.py b/src/classes/Engines.py index c3b4ea5..1c9afed 100644 --- a/src/classes/Engines.py +++ b/src/classes/Engines.py @@ -1,11 +1,15 @@ import random, math +from .Heuristic import ReversiHeuristic class PlayerEngine: def __init__(self, logger, options: dict = {}): # init logger do display informations self.logger = logger self.options = options - self.logger.info("Init engine {}".format(self.__class__.__name__)) + self.logger.info("Init engine {}, options:{}".format( + self.__class__.__name__, + self.options + )) def get_move(self, board): self.logger.info("engine: {} - player:{}".format( @@ -88,7 +92,11 @@ class MinmaxPlayerEngine(PlayerEngine): move = '' if depth == 0: leafs +=1 - return board.heuristique(), nodes, leafs + if self.options['heuristic'] == 'weight': + score = ReversiHeuristic(board).get() + else: + score = board.heuristique() + return score, nodes, leafs if friend_move: value = -math.inf @@ -150,7 +158,11 @@ class AlphabetaPlayerEngine(PlayerEngine): leafs = 0 if depth == 0 : leafs +=1 - return board.heuristique(), nodes, leafs + if self.options['heuristic'] == 'weight': + score = ReversiHeuristic(self.logger).get(board) + else: + score = board.heuristique() + return score, nodes, leafs if friend_move: value = -math.inf diff --git a/src/classes/Heuristic.py b/src/classes/Heuristic.py new file mode 100644 index 0000000..13ae8ee --- /dev/null +++ b/src/classes/Heuristic.py @@ -0,0 +1,38 @@ +class ReversiHeuristic(): + def __init__(self, logger, weight = [1, 2, 10, 20]): + self.logger = logger + self.weight = weight + + def get(self, board): + size = board.get_board_size() + score = 0 + weights = self._get_weight(size) + for pos_x in range(size): + for pos_y in range(size): + if board._board[pos_x][pos_y] == board._nextPlayer: + score += weights[pos_x][pos_y] + else: + score -= weights[pos_x][pos_y] + return score + + def _get_weight(self, size): + w = [[ 0 for _ in range(size)] for _ in range(size)] + + for pos_y in range(size): + for pos_x in range(size): + + # Elements in the corner + if pos_x in [0, size -1] and pos_y in [0,size - 1]: + w[pos_x][pos_y] = self.weight[3] + + # Elements on the border + elif pos_x in [0, size -1] or pos_y in [0, size -1]: + w[pos_x][pos_y] = self.weight[2] + + # 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): + w[pos_x][pos_y] = self.weight[1] + + else: + w[pos_x][pos_y] = self.weight[0] + return w diff --git a/src/game.py b/src/game.py index 027ab8d..7db3514 100755 --- a/src/game.py +++ b/src/game.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 + from classes.Reversi import Board from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine import logging as log @@ -11,26 +12,45 @@ Function to parse command line arguments """ def parse_aguments(): engines_choices=['random', 'human', 'minmax', 'alphabeta'] + heuristic_choices=['weight',] parser = arg.ArgumentParser('Playing Reversi with (virtual) friend') - parser.add_argument('-w', '--white-engine', + parser.add_argument('-we', '--white-engine', choices=engines_choices, help='white player engine (random)', default='random' ) - parser.add_argument('-b', '--black-engine', + parser.add_argument('-be', '--black-engine', choices=engines_choices, help='black player engine (random)', default='random' ) - parser.add_argument('-D', '--depth', - help='Minmax exploration depth', + parser.add_argument('-bd', '--black-depth-exploration', + help='Black player exploration depth (minmax or alphabeta engine)', type=int, default=3, ) + parser.add_argument('-wd', '--white-depth-exploration', + help='White player exploration depth (minmax or alphabeta engine)', + type=int, + default=3, + ) + + parser.add_argument('-bh', '--black-heuristic-engine', + help='Black player heutistic engine', + choices=['board', 'weight'], + default='board', + ) + + parser.add_argument('-wh', '--white-heuristic-engine', + help='White player heutistic engine', + choices=['board', 'weight'], + default='board', + ) + debug_group = parser.add_mutually_exclusive_group() debug_group.add_argument('-V', '--verbose', help='Verbose output', @@ -54,7 +74,6 @@ if __name__ == '__main__': print("Stating PyReverso...") args = parse_aguments() logger = log.getLogger() - print(args) # Create handler for streaming to tty (stderr / stdout) tty_handler = log.StreamHandler() tty_handler.setFormatter(CustomFormatter()) @@ -74,11 +93,14 @@ if __name__ == '__main__': args.black_engine, args.white_engine )) - options = { - 'depth': args.depth - } - wplayer = engines[args.white_engine](logger, options) - bplayer = engines[args.black_engine](logger, options) + wplayer = engines[args.white_engine](logger, { + 'depth': args.white_depth_exploration, + 'heuristic': args.white_heuristic_engine + }) + bplayer = engines[args.black_engine](logger, { + 'depth': args.black_depth_exploration, + 'heuristic': args.black_heuristic_engine + }) while ( not game.is_game_over()): if game._nextPlayer == 1: move = bplayer.get_move(game)