First implementation of Iterative Deepening MinMax

This commit is contained in:
Yorick Barbanneau 2023-12-17 17:37:07 +01:00
parent e506bcdab9
commit 437f05c8b2
3 changed files with 77 additions and 4 deletions

View file

@ -70,9 +70,24 @@ class MinmaxPlayerEngine(PlayerEngine):
class RandomPlayerEngine(PlayerEngine):
def get_move(board):
# [...]
```
Il est ainsi plus aisé de tester les moteur dans notre programme de base.
Quatre moteur "joueurs" sont implémentés :
* `Human` pour gérer des joueurs humain, une saisir utilisateur est demandée
sous la forme `<pos_x><pos_y>`. Il est aussi possible d'afficher le plateau
avec la commande `print` ou les coups possibles avec `help`;
* `Ramdom` va choisir aléatoirement le coup à jouer en fonction des coups;
possibles;
* `Minmax` utilise *MinMax* pour déterminer le coup à jouer avec une profondeur
maximale définie;
* `AphaBeta` utilise *AlphaBeta* pour déterminer le coup à jouer avec une
profondeur maximale définie;
* `IterativeDeepeningMinmax` utilise Minmax avec un temps maximum autorisé
Le choix de ces moteur se fait en ligne de commande avec
### Classes HeuristicsEngine

View file

@ -1,4 +1,4 @@
import random, math
import random, math, time
class PlayerEngine:
def __init__(self, player, logger, heuristic, options: dict = {}):
@ -189,3 +189,58 @@ class AlphabetaPlayerEngine(PlayerEngine):
))
return alpha, nodes, leafs
return beta, nodes, leafs
class MinmaxDeepeningPlayerEngine(PlayerEngine):
def get_move(self, board):
super().get_move(board)
value = -math.inf
nodes = 1
leafs = 0
move = ''
start_time = time.time()
for m in board.legal_moves():
board.push(m)
v, n, l = self.checkMinMax(board, False, start_time)
if v > value:
value = v
move = m
self.logger.debug("found a better move: {} (heuristic:{})".format(
move,
value
))
nodes += n
leafs += l
board.pop()
return move
def checkMinMax(self, board, friend_move:bool, start_time):
nodes = 1
leafs = 0
move = ''
if time.time() >= start_time + self.options['time_limit'] or board.is_game_over():
leafs +=1
return self.heuristic.get(board, self.player), nodes, leafs
if friend_move:
value = -math.inf
for m in board.legal_moves():
board.push(m)
v, n, l = self.checkMinMax(board, False, start_time)
if v > value:
value = v
nodes += n
leafs += l
board.pop()
else:
value = math.inf
for m in board.legal_moves():
board.push(m)
v, n, l = self.checkMinMax(board, True, start_time)
if v < value:
value = v
board.pop();
nodes += n
leafs += l
return value, nodes, leafs

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
from classes.Reversi import Board
from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine
from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine, MinmaxDeepeningPlayerEngine
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']
engines_choices=['random', 'human', 'minmax', 'alphabeta', 'id_minmax']
heuristic_choices=['score', 'weight', 'full']
parser = arg.ArgumentParser('Playing Reversi with (virtual) friend')
@ -78,6 +78,7 @@ if __name__ == '__main__':
"human": HumanPlayerEngine,
"minmax": MinmaxPlayerEngine,
"alphabeta": AlphabetaPlayerEngine,
"id_minmax": MinmaxDeepeningPlayerEngine,
}
heuristic_engine = {
"score": ScoreHeuristicEngine,
@ -117,6 +118,7 @@ if __name__ == '__main__':
),
{
'depth': args.white_depth_exploration,
'time_limit': 10
}
)
bplayer = player_engines[args.black_engine](
@ -129,6 +131,7 @@ if __name__ == '__main__':
),
{
'depth': args.black_depth_exploration,
'time_limit': 10
}
)
while ( not game.is_game_over()):