Compare commits
3 commits
45abd8c7eb
...
e49e737ec0
Author | SHA1 | Date | |
---|---|---|---|
e49e737ec0 | |||
c3ac347364 | |||
1c039106d9 |
4 changed files with 109 additions and 15 deletions
26
README.md
26
README.md
|
@ -19,12 +19,34 @@ au programme via la commande `./game.py -h`. Voici quelques exemple de
|
||||||
lancement:
|
lancement:
|
||||||
|
|
||||||
```shell
|
```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
|
./game.py
|
||||||
|
|
||||||
# joueur noir humain et joueur blanc MinMax avec une profondeur de 5
|
# 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
|
## Choix d'implémentation
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import random, math
|
import random, math
|
||||||
|
from .Heuristic import ReversiHeuristic
|
||||||
|
|
||||||
class PlayerEngine:
|
class PlayerEngine:
|
||||||
def __init__(self, logger, options: dict = {}):
|
def __init__(self, logger, options: dict = {}):
|
||||||
# init logger do display informations
|
# init logger do display informations
|
||||||
self.logger = logger
|
self.logger = logger
|
||||||
self.options = options
|
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):
|
def get_move(self, board):
|
||||||
self.logger.info("engine: {} - player:{}".format(
|
self.logger.info("engine: {} - player:{}".format(
|
||||||
|
@ -88,7 +92,11 @@ class MinmaxPlayerEngine(PlayerEngine):
|
||||||
move = ''
|
move = ''
|
||||||
if depth == 0:
|
if depth == 0:
|
||||||
leafs +=1
|
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:
|
if friend_move:
|
||||||
value = -math.inf
|
value = -math.inf
|
||||||
|
@ -150,7 +158,11 @@ class AlphabetaPlayerEngine(PlayerEngine):
|
||||||
leafs = 0
|
leafs = 0
|
||||||
if depth == 0 :
|
if depth == 0 :
|
||||||
leafs +=1
|
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:
|
if friend_move:
|
||||||
value = -math.inf
|
value = -math.inf
|
||||||
|
|
38
src/classes/Heuristic.py
Normal file
38
src/classes/Heuristic.py
Normal file
|
@ -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
|
42
src/game.py
42
src/game.py
|
@ -1,4 +1,5 @@
|
||||||
#!/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
|
from classes.Engines import RandomPlayerEngine, HumanPlayerEngine, MinmaxPlayerEngine, AlphabetaPlayerEngine
|
||||||
import logging as log
|
import logging as log
|
||||||
|
@ -11,26 +12,45 @@ 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',]
|
||||||
parser = arg.ArgumentParser('Playing Reversi with (virtual) friend')
|
parser = arg.ArgumentParser('Playing Reversi with (virtual) friend')
|
||||||
|
|
||||||
parser.add_argument('-w', '--white-engine',
|
parser.add_argument('-we', '--white-engine',
|
||||||
choices=engines_choices,
|
choices=engines_choices,
|
||||||
help='white player engine (random)',
|
help='white player engine (random)',
|
||||||
default='random'
|
default='random'
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument('-b', '--black-engine',
|
parser.add_argument('-be', '--black-engine',
|
||||||
choices=engines_choices,
|
choices=engines_choices,
|
||||||
help='black player engine (random)',
|
help='black player engine (random)',
|
||||||
default='random'
|
default='random'
|
||||||
)
|
)
|
||||||
|
|
||||||
parser.add_argument('-D', '--depth',
|
parser.add_argument('-bd', '--black-depth-exploration',
|
||||||
help='Minmax exploration depth',
|
help='Black player exploration depth (minmax or alphabeta engine)',
|
||||||
type=int,
|
type=int,
|
||||||
default=3,
|
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 = parser.add_mutually_exclusive_group()
|
||||||
debug_group.add_argument('-V', '--verbose',
|
debug_group.add_argument('-V', '--verbose',
|
||||||
help='Verbose output',
|
help='Verbose output',
|
||||||
|
@ -54,7 +74,6 @@ if __name__ == '__main__':
|
||||||
print("Stating PyReverso...")
|
print("Stating PyReverso...")
|
||||||
args = parse_aguments()
|
args = parse_aguments()
|
||||||
logger = log.getLogger()
|
logger = log.getLogger()
|
||||||
print(args)
|
|
||||||
# Create handler for streaming to tty (stderr / stdout)
|
# Create handler for streaming to tty (stderr / stdout)
|
||||||
tty_handler = log.StreamHandler()
|
tty_handler = log.StreamHandler()
|
||||||
tty_handler.setFormatter(CustomFormatter())
|
tty_handler.setFormatter(CustomFormatter())
|
||||||
|
@ -74,11 +93,14 @@ if __name__ == '__main__':
|
||||||
args.black_engine,
|
args.black_engine,
|
||||||
args.white_engine
|
args.white_engine
|
||||||
))
|
))
|
||||||
options = {
|
wplayer = engines[args.white_engine](logger, {
|
||||||
'depth': args.depth
|
'depth': args.white_depth_exploration,
|
||||||
}
|
'heuristic': args.white_heuristic_engine
|
||||||
wplayer = engines[args.white_engine](logger, options)
|
})
|
||||||
bplayer = engines[args.black_engine](logger, options)
|
bplayer = engines[args.black_engine](logger, {
|
||||||
|
'depth': args.black_depth_exploration,
|
||||||
|
'heuristic': args.black_heuristic_engine
|
||||||
|
})
|
||||||
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)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue