loa - Aymeric Lesert

publicité
Aymeric Lesert
28 mars 2003
Lines Of Action
I. Les règles du jeu
Lines Of Action est un jeu de plateau 8x8 opposant 2 adversaires. Chaque joueur dispose de 12 pions. Le
joueur qui a gagné est le joueur qui a réussi à connecter tous ses pions. Les joueurs jouent chacun leur tour et
déplacent un seul pion. Un pion se déplace en ligne droite (horizontal vertical ou diagonal). Il peut sauter les
pions de son camp mais pas ceux de son adversaire. Il peut s’arrêter sur un pion adverse, dans ce cas, le pion
adverse est capturé. Il se déplace du nombre de cases égal au nombre de pions de son camp ou adverse sur la
ligne de déplacement. Il doit toujours s’arrêter dans le plateau et si il n’y a pas assez de cases pour le
déplacement, le déplacement est impossible.
Situation initiale
Le blanc doit jouer
Situation terminale
II. L’algorithme Min-Max
A. Principe de base
On suppose que chaque joueur choisira son meilleur coup, le meilleur coup de l'adversaire correspondant au
moins bon coup du joueur courant.
On "remonte" de proche en proche les valeurs des feuilles (fins de parties) jusqu'à la racine (position
courante) ; on peut ainsi choisir le coup qui mène à la position la plus favorable. Cela implique, pour un coup
optimal, de parcourir tout l’arbre des solutions.
Exemple
Lines Of Action : Stratégie et Optimisation
Aymeric Lesert
28 mars 2003
Lines Of Action
B. Les optimisations
1. L’élagage Alpha-Beta
L'algorithme minimax effectue une exploration complète de l'arbre de recherche jusqu'à un niveau donné,
alors qu'une exploration partielle de l'arbre pourrait suffire. Il suffit en effet, dans l'exploration en profondeur
d'abord et de gauche à droite, d'éviter d'examiner des sous-arbres qui conduiront à des configurations dont la
valeur ne contribuera sûrement pas au calcul du gain à la racine de l'arbre.
Plus généralement, lorsque dans le parcours de l'arbre minimax, il y a modification de la valeur courante
d'un nœud, si cette valeur franchit un certain seuil, il devient inutile d'explorer la descendance encore
inexplorée de ce nœud.
On distingue deux seuils, appelés α (pour les nœuds Min) et β (pour les nœuds Max) :
 le seuil α, pour un nœud Min s, est égal à la plus grande valeur (déjà déterminée) de tous les nœuds Max
ancêtres de s ; si la valeur de s devient inférieure ou égale à α, l'exploration de sa descendance peut être
arrêtée ;
 le seuil β, pour un nœud Max s, est égal à la plus petite valeur (déjà déterminée) de tous les nœuds Min
ancêtres de s. Si la valeur de s devient supérieure ou égale à β, l'exploration de sa descendance peut être
arrêtée.
L'algorithme Alpha-Beta peut être décrit informellement par la fonction suivante, qui maintient ces deux
seuils pendant le parcours de l'arbre. Une invocation de alphabeta(s, -∞, +∞) détermine une évaluation du jeu issu
de la configuration s.
Exemple :
2. Le killer-move
Cette optimisation est utilisée pour couper une branche plus tôt et, ainsi, éviter un parcours inutile dans une
branche. En général, le coup qui a coupé dans la sous-branche à gauche aura une plus grande probabilité de
couper la sous-branche courante.
Cela veut dire que le coup qui a coupé une sous-branche à un niveau est mémorisé pour ensuite être proposé
en premier dans la sous-branche de même niveau immédiatement après, dans le cas où le coup est jouable.
Ici, j’ai pris la peine d’élargir la définition du killer-move (coup-qui-tue) au coup ayant eu le poids le plus
fort (pour Max) ou le poids le moins fort (pour Min).
De même, il est possible d’étendre le nombre de coup-qui-tue par profondeur et, dans ce cas, le KillerMove
se comporte comme une pile. Il devient un ensemble de coups jouables avant les coups possibles (du plus
récent au plus ancien).
Lines Of Action : Stratégie et Optimisation
Aymeric Lesert
28 mars 2003
Lines Of Action
3. La table d’historique
Cette optimisation est utilisée pour attribuer un poids à un coup. Plus le coup est retenu comme meilleur
coup à une profondeur faible, plus son poids est élevé. Et, plus il est retenu, plus il a d’importance.
Pour que cette optimisation puisse être utilisée, il faut avoir une fonction qui attribue un indice à un coup.
Cet indice doit être unique par coup.
La table d’historique est un tableau d’entier mémorisant la somme des 2p (où p = profondeur maxi –
profondeur courante) quand un coup est retenu comme meilleur coup.
4. La table de transposition
a) Principe
Un arbre de parcours des coups aux échecs peut être vu comme un graphe, où les transpositions peuvent
retenir un cheminement déjà exploré. Une Hash-table de transposition peut être utilisée pour détecter une
situation précise et, ainsi, éviter de développer un arbre déjà parcouru.
Exemple aux échecs :
La situation après 1. e4 d6 2. d4 est la même que la situation après 1. d4 d6 2. e4.
Il s’avère que la combinatoire pour détecter ces situations est extrêment élevée. Il faudrait pour chaque
position parcourue mémoriser le plateau et à chaque nouveau coup, regarder si le nouveau plateau correspond
ou non à une plateau déjà parcouru.
La hash-table de transposition permet de répondre à cette problématique avec un temps optimal en accédant
directement à une situation. Elle est également très souvent utilisée avec l’algorithme AlphaBeta avec
profondeur itérative. Cela permet de réduire de manière très importante le recalcul de certaines situations.
b) La clé de Zobrist
Pour se faire, il faut définir une clé de Zobrist pour chaque pion différent, sur chaque case et pour chaque
joueur.
Exemple aux échecs :
Le damier fait 8x8, il y a 2 joueurs (les noirs et les blancs) et 6 pions par joueur (Tour, Fou, Pion, Roi,
Reine, Cavalier) et un pion neutre (la case vide). Il faut alors définir 8*8+8*8*2*6=832 clés de Zobrist.
Une clé de Zobrist est un nombre aléatoire sur 64 bits (si votre architecture le permet) ou 32 bits.
Une situation correspond alors au XOR de 8*8=64 clés de Zobrist représentant les pions sur le plateau.
c) La hash-table
Une hash-table peut alors mémoriser un grand nombre de situations. Mais, il faut que cette taille soit
suffisamment grande pour être significative.
d) Utilisation de la table de transposition
Un coup joué ou déjoué correspond à une seule opération le XOR de la position initiale et le XOR de la
position finale. L’accès en lecture de la table de transposition est effectué avec la lecture des coups possibles
afin de vérifier si la situation n’a pas déjà été évaluée.
Remarque : Si deux situations ont la même valeur, il est probable que cela puisse être à l’origine d’un
malentendu car, imaginons qu’une des deux situations soit une situation perdante et que l’autre est une situation
gagnante, l’algorithme risque de jouer le coup perdant en croyant qu’il est un coup gagnant.
Dans le cas où le meilleur coup évalué pour une situation n’est pas une situation terminale, le coup évalué
doit être proposé comme un KillerMove. Il est même conseillé de le positionner en tête.
5. Le Null Move
Le null-move consiste à faire comme si l’adverse ne peut pas jouer, pour vérifier si nous sommes proches
d’une situation terminale ou favorable.
Lines Of Action : Stratégie et Optimisation
Aymeric Lesert
28 mars 2003
Lines Of Action
6. La recherche de quiescence
La recherche de quiescence consiste à éliminer le phénomène d’horizon. En effet, comme la profondeur de
l’algorithme est limitée, il est impossible de voir si la branche non-terminale que nous venons d’évaluer est une
branche menant à la victoire ou à la défaite : seule l’évaluation peut le faire. Mais, dans certain cas, cette
évaluation est trompeuse, surtout si nous sommes sur une position de prise comme aux échecs.
Dans ce cas, il faut pouvoir limiter la valeur d’une situation à la valeur stable de cette dernière. Si la
situation évaluée n’est pas stable, il est peut être intéressant de rechercher une situation plus stable pour
l’évaluer. Cette stratégie dépend également du jeu.
C. L’algorithme Min/Max itératif
Cet algorithme fait appel à l’algorithme AlphaBeta décrit ci-dessus en faisant varier la profondeur maxi de
manière croissante sans réinitialiser la table de transposition, les killer-moves ou la table d’historique afin de
réutiliser à chaque fois les données calculées avant (évite de recalculer des situations peut-être déjà évaluées).
Il permet aussi de mieux maîtriser les temps de parcours.
III. Les différentes versions
A. Version 1 : Min/Max
Pour cette première version, 15 secondes est laissé à l’algorithme pour trouver un coup à jouer. Les
optimisations utilisées sont : une table de transposition, le killer-move, l’algorithme itératif et le tri des coups à
jouer. La quiescence et le Null-move n’ont pas été implémentés.
Nous matérialisons le plateau comme étant une matrice 8x8 dont chaque case peut prendre 3 états
(VIDE, PION1 ou PION2). Pour faciliter le test de situation terminale, nous mémorisons pour chaque joueur la
liste de ses segments (ensemble de pions connectés). Une situation terminale est un joueur ayant un seul
segment.
La liste des coups jouables est triée selon l’ordre suivant : le coup proposé par Zobrist, le coup proposé
comme killer-move, puis les coups dans l’ordre de calcul.
La fonction d’évaluation d’une situation est la suivante :
Nb _ segmentsNb _ pionsi
C  *

i 1
Max( X
ij
Cx , Yij C y )
j 1
Nb _ pions _ joueurs
8
8
(Pij*Cij) où (Cx,Cy) = Centre de gravité du joueur
i 1 j 1
Remarques : Cette version est un piètre adversaire. Ses coups sont prévisibles et facilement déjouables.
De plus, elle est peut optimisée et est gourmande en temps de calcul.
Lines Of Action : Stratégie et Optimisation
Aymeric Lesert
28 mars 2003
Lines Of Action
B. Version 2 : Apprentissage
L’idée qui a été exploitée dans cette version est la possibilité pour le jeu d’apprendre à jouer face à un
joueur humain. A chaque partie, il mémorise les coups menant à la victoire et à la défaite. Pour chacune des
coups, on mesure la profondeur la plus courte vers la défaite et vers la victoire. Quand l’ordinateur doit jouer, il
calcule les coups possibles et consulte sa base de données des situations pour évaluer le meilleur coup à jouer.
Le meilleur coup à jouer est celui qui est le plus proche de sa victoire et les plus éloignés de sa défaite.
J’avais posé comme hypothèse que plus l’écart était grand, plus il était probable que la solution était bonne.
Remarques : Après quelques tests, il s’est avéré que cette stratégie était mauvaise. La grande quantité
d’informations à retenir et le manque de visibilité ne permettait pas d’aboutir à une solution convenable. Elle
évitait de faire deux fois la même erreur mais n’était pas futée pour trouver la victoire !
C. Version 3 : Min/Max
Cette version est une reprise de la version 1. Lors de la liste des coups jouables, nous attribuons un poids
à chaque coup pour faciliter l’ordonnancement : Nombre de pions adverses – Nombre de pions du joueur
courant autour de la case à jouer.
La fonction d’évaluation du plateau est plus complexe que la fonction de la version 1 :
Nb _ segmentsNb _ pionsi
C jc  *

i 1
Max( X
ij
Nb _ pions _ joueurs
Nb _ segmentsNb _ pionsi
C ja  *
Cx , Yij C y )
j 1

i 1
Max( X
ij
Cx , Yij C y )
j 1
Nb_ pions _ joueurs
8
8
(Pij*Cij) pour le joueur courant
i 1 j 1
8
8
(Pij*Cij) pour le joueur adverse
i 1 j 1
P K1*(C ja C jc) K2*(Nb_ segments ja  Nb_ segments jc) K3*(
Nb_ pions ja
Nb_ pions jc

)
Nb_ segments ja Nb_ segments jc
Remarques : Cette version est un adversaire intéressant. Ses coups sont moins prévisibles. Mais, il n’est
pas encore un adverse de taille. A vrai-dire, je pense que cette fonction n’est pas mauvaise. L’enjeu est de
déterminer les coefficients à attribuer à chacun des composants du calcul du plateau.
D. Version 4 : Algorithme Génétique
Dans cette version, l’idée est de laisser faire le hasard. On dispose d’un certain nombre d’indicateurs
(ici, 14). Il faut également disposer d’un générateur aléatoire de fonctions mathématiques, de fonctions de
mutations et de croisements de ces fonctions. Pour un joueur, nous posons deux fonctions, la première fonction
est celle de l’évaluation d’un coup et la deuxième est l’évaluation d’un plateau.
Ensuite, il suffit de générer une population d’une dizaine d’individus et de les confronter sous forme de
tournoi (en utilisant l’algorithme Min/Max). A la fin de chaque tournoi (une génération), nous gardons les
meilleurs individus. Nous les croisons ou les mutons et nous injectons de temps en temps de nouveaux
individus.
En théorie, cette technique doit permettre de converger vers un individu de plus en plus fort. Puis, après
quelques générations, nous pouvons nous y confronter pour voir si elle est pas trop mauvaise.
Remarques : Malheureusement, je n’ai pas pu montrer la validité de ce genre de procéder.
Lines Of Action : Stratégie et Optimisation
Aymeric Lesert
28 mars 2003
Lines Of Action
IV. Références
Les régles du jeu : http://www.andromeda.com/people/ddyer/loa/
Lines Of Action : http://games.cs.ualberta.ca/webgames/loa/
Explications de la table de transposition : http://www.seanet.com/~brucemo/topics/hashing.htm
Explications de la clé de Zobrist : http://www.seanet.com/~brucemo/topics/zobrist.htm
Pour l’algorithme MinMax et AlphaBeta : http://www-poleia.lip6.fr/~ralaivo/dauphine/projets/node23.html
Lines Of Action : Stratégie et Optimisation
Téléchargement