2022-11-28 09:08:35 +01:00
|
|
|
|
\documentclass{article}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
\usepackage[T1]{fontenc} % encodage
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\renewcommand{\familydefault}{\sfdefault} % police en sans-serif
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\usepackage[french]{babel} % langue
|
|
|
|
|
\frenchsetup{SmallCapsFigTabCaptions=false}
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\usepackage[hidelinks]{hyperref} % liens cliquable dans la table des matières
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\usepackage{graphicx} % images
|
|
|
|
|
\usepackage{caption}
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\usepackage[a4paper, left=20mm, top=20mm]{geometry} % dimensions de la page
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
|
|
|
|
\usepackage{minted} % intégration code
|
|
|
|
|
\usemintedstyle{emacs}
|
|
|
|
|
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\title{Projet - IA pour le jeu d'Othello
|
|
|
|
|
\thanks{\href{https://jj.up8.site/AA/ProjetsAA.pdf}{Sujet 35}}}
|
|
|
|
|
\author{\href{mailto:anri.kennel@etud.univ-paris8.fr}{Anri Kennel}
|
|
|
|
|
\thanks{Numéro d'étudiant : 20010664}\, (L3-A)
|
|
|
|
|
\\Algorithmique avancée $\cdot$ Université Paris 8}
|
2022-11-28 09:08:35 +01:00
|
|
|
|
\date{Année universitaire 2022-2023}
|
|
|
|
|
|
|
|
|
|
\begin{document}
|
|
|
|
|
\maketitle
|
|
|
|
|
\tableofcontents
|
|
|
|
|
\clearpage
|
|
|
|
|
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\section{Projet}
|
|
|
|
|
Ce projet présente une implémentation d'un jeu d’Othello ainsi que deux
|
|
|
|
|
intelligences artificielles jouant; l'une selon un algorithme minimax et l'autre
|
|
|
|
|
via élagage alpha-bêta. Il y a aussi une comparaison d'efficacité des IA à
|
|
|
|
|
différentes profondeurs de jeu.
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-11-30 19:39:49 +01:00
|
|
|
|
\section{Implémentation}
|
|
|
|
|
\subsection{Othello}
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\subsubsection{Règles du jeu}
|
|
|
|
|
L'Othello est un jeu qui se joue sur un plateau de 8x8 où deux couleurs, les noirs
|
|
|
|
|
et les blancs s'affrontent. Les noirs commencent la partie. Quand aucun joueur
|
|
|
|
|
ne peut jouer, la partie s'arrête.
|
|
|
|
|
|
|
|
|
|
Au début d'une partie le plateau ressemble à la \autoref{fig:init}.
|
|
|
|
|
|
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\centering
|
|
|
|
|
\includegraphics[width=0.35\textwidth]{imgs/othello_init.png}
|
|
|
|
|
\caption{Début d'une partie}
|
|
|
|
|
\label{fig:init}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
\subsubsection{Exemple d'une partie}
|
|
|
|
|
Chaque joueur doit poser un pion de sa couleur sur une case vide de l’othellier,
|
|
|
|
|
il faut prendre en sandwich les pions ennemis, peu importe la direction. Une fois
|
|
|
|
|
posé, les pions prient en sandwich sont récupérés par le joueur qui vient de jouer.
|
|
|
|
|
|
|
|
|
|
Dans la configuration du début, les cases pouvant être joué par les noirs sont
|
|
|
|
|
indiqués en rouge dans la \autoref{fig:prem}.
|
|
|
|
|
|
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\centering
|
|
|
|
|
\includegraphics[width=0.35\textwidth]{imgs/othello_premiercoup.png}
|
|
|
|
|
\caption{Possibilités au premier coup}
|
|
|
|
|
\label{fig:prem}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
Mon implémentation du jeu indique au joueur les coups possibles (c'est-à-dire les
|
|
|
|
|
cases rouges). Le joueur doit indiquer les coordonnées où il veut poser son jeton
|
|
|
|
|
et les changements se font automatiquement. Chaque joueur joue chacun son tour et
|
|
|
|
|
passe son tour si aucun coup lui est possible. La partie s'arrête si le plateau
|
|
|
|
|
est plein ou si aucun joueur ne peut jouer, cf. \autoref{fig:human}. Les jetons
|
|
|
|
|
blancs sont notés \texttt{B} et les jetons noirs \texttt{N}.
|
|
|
|
|
|
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\centering
|
|
|
|
|
\includegraphics[width=0.35\textwidth]{imgs/othello_impl_player.jpg}
|
|
|
|
|
\caption{Demande au joueur de jouer}
|
|
|
|
|
\label{fig:human}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
Si un coup illégale est joué, le jeu refuse le coup et demande au joueur de
|
|
|
|
|
choisir un autre coup.
|
2022-11-30 19:39:49 +01:00
|
|
|
|
|
|
|
|
|
\subsubsection{Problèmes rencontrés}
|
2022-12-01 16:33:24 +01:00
|
|
|
|
Mon enjeu numéro 1 était d'éviter tout problème de mémoire. Pour cela dans le
|
2022-12-01 18:54:33 +01:00
|
|
|
|
\texttt{Makefile} il y a un label \texttt{dev} qui permet d'ajouter plein de flags
|
|
|
|
|
pour \texttt{gcc}, notamment \texttt{fanalyzer} et \texttt{fsanitize=undefined} qui
|
2022-12-01 16:33:24 +01:00
|
|
|
|
permettent de trouver plein de problèmes relatifs à la mémoire. Aussi j'ai utilisé
|
|
|
|
|
\texttt{Valgrind} (avec les flags \texttt{g} et \texttt{Og} pour \texttt{gcc} et
|
2022-12-01 18:54:33 +01:00
|
|
|
|
les flags \texttt{leak-check=full}, \texttt{show-leak-kinds=all},
|
|
|
|
|
\texttt{track-origins=yes} et \texttt{s} pour \texttt{Valgrind}) me permettant
|
2022-12-01 16:33:24 +01:00
|
|
|
|
d'avoir un maximum d'avertissements et d'informations me permettant de débugger
|
|
|
|
|
tous les problèmes.
|
2022-12-01 18:54:33 +01:00
|
|
|
|
\\\\
|
|
|
|
|
Aussi, je voulais rendre mon code modulable, pour tester plus facilement. Ainsi
|
|
|
|
|
la taille du plateau est complètement modulable, aussi les couleurs des joueurs
|
|
|
|
|
(cf. \autoref{cod:plateau}).
|
2022-12-01 16:33:24 +01:00
|
|
|
|
|
2022-12-01 18:54:33 +01:00
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\centering
|
|
|
|
|
\begin{minipage}{0.8\textwidth}
|
|
|
|
|
\begin{minted}[autogobble,linenos]{c}
|
|
|
|
|
/* Une case est soit vide, soit occupé par un des joueurs, noir ou blanc */
|
|
|
|
|
enum CASE { VIDE = ' ', BLANC = 'B', NOIR = 'N' };
|
|
|
|
|
\end{minted}
|
|
|
|
|
|
|
|
|
|
\begin{minted}[autogobble,linenos,firstnumber=last]{c}
|
|
|
|
|
/* Propriété globale du jeu */
|
|
|
|
|
enum PLATEAU { LONGEUR = 8, LARGEUR = 8 };
|
|
|
|
|
\end{minted}
|
|
|
|
|
\end{minipage}
|
|
|
|
|
\caption{Début de \texttt{jeu.h}}
|
|
|
|
|
\label{cod:plateau}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
Enfin, sachant qu'il faut aussi implémenter des IAs, j'ai fait en sorte que le jeu
|
|
|
|
|
du joueur humain ne soit pas complètement lié au fonctionnement du jeu. Le projet
|
|
|
|
|
est donc séparé en plusieurs fichiers/fonctions (cf. \autoref{tree:project}).
|
|
|
|
|
|
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\centering
|
|
|
|
|
\begin{minipage}{0.15\textwidth}
|
|
|
|
|
\begin{minted}[autogobble,frame=lines,rulecolor=gray]{mcf}
|
|
|
|
|
- includes
|
|
|
|
|
|-- humain.h
|
|
|
|
|
|-- jeu.h
|
|
|
|
|
|-- joueur.h
|
|
|
|
|
|-- liste.h
|
|
|
|
|
|-- plateau.h
|
|
|
|
|
\-- utils.h
|
|
|
|
|
- src
|
|
|
|
|
|-- humain.c
|
|
|
|
|
|-- jeu.c
|
|
|
|
|
|-- joueur.c
|
|
|
|
|
|-- liste.c
|
|
|
|
|
|-- main.c
|
|
|
|
|
|-- plateau.c
|
|
|
|
|
\-- utils.c
|
|
|
|
|
\end{minted}
|
|
|
|
|
\end{minipage}
|
|
|
|
|
\caption{Arborescence du projet sans l'implémentation des IA}
|
|
|
|
|
\label{tree:project}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
Tout ce qui est relatif à un joueur humain est dans \texttt{humain.h}. Le fichier
|
|
|
|
|
\texttt{joueur.h} ne contient rien spécifique à un joueur humain.
|
|
|
|
|
|
|
|
|
|
\newpage
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\subsection[Minimax]{Algorithme minimax}
|
|
|
|
|
\subsubsection{Algorithme}
|
2022-12-01 18:54:33 +01:00
|
|
|
|
L'idée de l'algorithme minimax est de calculer tous les coups possibles pour
|
|
|
|
|
chaque coup possible et d'aller le plus loin possible dans les "et si" pour faire
|
|
|
|
|
le coup qui nous rapportera le plus de points dans le futur.
|
|
|
|
|
|
|
|
|
|
Le problème de cet algorithme c'est qu'il est difficilement réalisable. En mémoire,
|
|
|
|
|
on doit copier le plateau plusieurs fois (pour chaque "et si"). La complexité est
|
|
|
|
|
de $\Theta(c^{n})$ avec $c$ les coups légaux et $n$ la profondeur de jeu, donc
|
|
|
|
|
lorsque l'on utilise cet algorithme on doit garder notre profondeur de test
|
|
|
|
|
relativement basse.
|
|
|
|
|
|
|
|
|
|
Aussi, l'algorithme est dépendant d'une fonction d'évaluation, c'est elle qui
|
|
|
|
|
décide si le coup est bien ou non, plus elle est précise plus le coup décidé sera
|
|
|
|
|
meilleur.
|
2022-11-30 19:39:49 +01:00
|
|
|
|
|
|
|
|
|
\subsubsection{Exemple d'utilisation}
|
2022-12-01 18:54:33 +01:00
|
|
|
|
L'utilisation de l'algorithme est simple. Il suffit d'appeller une seule fonction
|
|
|
|
|
et elle jouera un coup (cf. \autoref{cod:minimax_def}).
|
|
|
|
|
\begin{figure}[h]
|
|
|
|
|
\centering
|
|
|
|
|
\begin{minipage}{0.8\textwidth}
|
|
|
|
|
\begin{minted}[autogobble,linenos]{c}
|
|
|
|
|
/* Joue le tour d'après l'algorithme minimax */
|
|
|
|
|
void action_joueur_minimax(Jeu *jeu, const int couleur);
|
|
|
|
|
\end{minted}
|
|
|
|
|
\end{minipage}
|
|
|
|
|
\caption{Déclaration de minimax, dans \texttt{minimax.h}}
|
|
|
|
|
\label{cod:minimax_def}
|
|
|
|
|
\end{figure}
|
|
|
|
|
|
|
|
|
|
Pour l'utiliser, il faut l'appeller dans la fonction qui s'occupe du déroulement
|
|
|
|
|
du jeu.
|
2022-11-30 19:39:49 +01:00
|
|
|
|
|
|
|
|
|
\subsubsection{Problèmes rencontrés}
|
|
|
|
|
% TODO avec code d'illustration
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-12-01 16:33:24 +01:00
|
|
|
|
\subsection[Alpha-Bêta]{Élagage alpha-bêta}
|
|
|
|
|
\subsubsection{Algorithme}
|
2022-11-30 19:39:49 +01:00
|
|
|
|
% TODO expliquer fonctionnement alphabeta
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-11-30 19:39:49 +01:00
|
|
|
|
\subsubsection{Exemple d'utilisation}
|
|
|
|
|
% TODO expliquer comment l'utiliser
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-11-30 19:39:49 +01:00
|
|
|
|
\subsubsection{Problèmes rencontrés}
|
|
|
|
|
% TODO avec code d'illustration
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-11-30 19:39:49 +01:00
|
|
|
|
\section{Comparaison d'efficacité}
|
|
|
|
|
% TODO
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
|
|
|
|
\section{Discussion}
|
2022-11-30 19:39:49 +01:00
|
|
|
|
% TODO
|
2022-11-28 09:08:35 +01:00
|
|
|
|
|
2022-12-01 18:54:33 +01:00
|
|
|
|
\newpage
|
|
|
|
|
\appendix
|
|
|
|
|
\listoffigures
|
|
|
|
|
|
2022-11-28 09:08:35 +01:00
|
|
|
|
\end{document}
|