diff --git a/report/imgs/SOURCES.md b/report/imgs/SOURCES.md index 8a4d93f..6a0bf28 100644 --- a/report/imgs/SOURCES.md +++ b/report/imgs/SOURCES.md @@ -8,3 +8,4 @@ via les liens suivants : | othello_premiercoup | https://excalidraw.com/#json=8Qrf8cCcZJAbc3aEGH0Ts,1vsG--6hIFzSNFfZ0KOZPw | | othello_impl_hh | https://excalidraw.com/#json=vXWZ8gtrSJxhbVfsYShL5,rcEwGNHajCftNAf8WE6HNQ | | othello_impl_ma | https://excalidraw.com/#json=_h19rWJkN7KVWVU9whOta,NJMrSs_iE6WA_-hIS424-w | +| othello_impl_tests | https://excalidraw.com/#json=VULFJjSMNplq_foUgXNTK,1O9ed6u0bSw1Kf25mT_wRg | diff --git a/report/presentation/slides.tex b/report/presentation/slides.tex index 4999f56..2750bae 100644 --- a/report/presentation/slides.tex +++ b/report/presentation/slides.tex @@ -24,6 +24,7 @@ \usepackage{minted} % intégration code \usemintedstyle{emacs} +\newminted[pseudocode]{python}{autogobble,linenos,fontsize=\scriptsize,escapeinside=!!} \title[IA pour Othello]{\href{https://jj.up8.site/AA/ProjetsAA.pdf}{Projet} - IA pour le jeu d'Othello} \author{\href{mailto:anri.kennel@etud.univ-paris8.fr}{Anri Kennel} | L3-A} @@ -95,6 +96,7 @@ \item Liste chaînée \item<3-> Coups \item<4-> Propriétés + \item<5-> Jeu \end{itemize} \column{\rcolumn} % colonne de droite \begin{overprint} @@ -124,7 +126,7 @@ \end{figure} \onslide<3> \begin{figure} - \vspace{30mm} + \vspace{27mm} \begin{minted}[autogobble,linenos,fontsize=\scriptsize]{c} Coups *action_possible_joueur (Jeton *plateau[LONGEUR][LARGEUR], @@ -150,24 +152,219 @@ \end{minted} \caption*{Propriétés du jeu} \end{figure} + \onslide<5> + \begin{figure} + \vspace{25mm} + \begin{minted}[autogobble,linenos,fontsize=\scriptsize]{c} + /* Gère le coup d'un joueur en faisant les + changements nécessaire au jeu + * Renvoie 0 en cas de coup illégal */ + int jeu_joueur(Jeu *jeu, + const int case_i, + const int case_j, + const int couleur); + \end{minted} + \caption*{Jeu d'un joueur} + \end{figure} \end{overprint} \end{columns} - \onslide<3>{\hspace{3cm} Pour \textbf{tout} les joueurs} + \vspace{-1cm} + \onslide<3>{\hspace{3cm}Pour \textbf{tous} les joueurs} + \onslide<5>{\hspace{-45mm}Tous les joueurs s'en servent pour jouer} \end{frame} \subsection*{Minimax} -\begin{frame}{Algorithme minimax} - TODO! +\begin{frame}[fragile]{Algorithme minimax} + \begin{onlyenv}<3> + \begin{pseudocode} + def minimax(jeu, profondeur, joueur_actuel, gagnant, resultat): + ! !possibilites = recuperation_possibilites(jeu, joueur_actuel) + ! !if (possibilites == 0): + ! ! joueur_actuel = ennemi(joueur_actuel) + ! ! possibilites = recuperation_possibilites(jeu, joueur_actuel) + ! ! if (possiblites == 0): + ! ! return heuristique(jeu, gagnant) + ! !if (joueur_actuel == gagnant): + ! ! resultat = -INFINI + ! !else: + ! ! resultat = +INFINI + ! !profondeur = profondeur - 1 + ! !resultat_tmp = resultat + ! !for (i in possibilites): + ! ! copie_jeu = jeu + ! ! joue_coup(i, joueur_actuel) + ! ! if (profondeur > 0): + ! ! minimax(copie_jeu, profondeur, ennemi(joueur_actuel), gagnant, resultat_tmp) + ! ! else: + ! ! resultat_tmp.score = heuristique(copie_jeu, gagnant) + \end{pseudocode} + \end{onlyenv} + \begin{onlyenv}<4> + \vspace{5mm} + \begin{pseudocode} + ! !# toujours dans la boucle... + ! ! if (joueur_actuel == gagnant): # MAX + ! ! if (resultat_tmp.score >= score): + ! ! resutat.score = resultat_tmp.score + ! ! resultat.position = i + ! ! else: # MIN + ! ! if (resultat_tmp.score <= score): + ! ! resultat.score = score + ! ! resultat.position = i + \end{pseudocode} + Notre heuristique ressemble à ceci : + \begin{pseudocode} + def heuristique(jeu, joueur): + ! !res = jeu.J1.nombre_jeton - jeu.J2.nombre_jeton + ! !if (jeu.J1 == joueur): + ! ! return res + ! !return -res + \end{pseudocode} + \end{onlyenv} + \begin{columns}[onlytextwidth] + \def\rcolumn{50mm} % taille colonne de droite + \column{\linewidth-\rcolumn-1cm} % colonne de gauche + \begin{itemize} + \item<1-2> Utilises les fonctions déjà définis + \item<2> Ressemble à la fonction pour les humains + \end{itemize} + \column{\rcolumn} % colonne de droite + \begin{overprint} + \onslide<2> + \begin{figure} + \vspace{15mm} + \begin{minted}[autogobble,linenos,fontsize=\scriptsize]{c} + void action_joueur_minimax + (Jeu *jeu, const int couleur, + const int profondeur); + \end{minted} + \vspace{1mm} + \begin{minted}[autogobble,linenos,firstnumber=last,fontsize=\scriptsize]{c} + void action_joueur_humain + (Jeu *jeu, + const int couleur); + \end{minted} + \caption*{Définition de minimax comparé à celle pour les humains} + \end{figure} + \end{overprint} + \end{columns} + \onslide<2>{\hspace{25mm}$\Rightarrow$ Utilisation de fonctions auxiliaires} \end{frame} \subsection*{Alpha-bêta} -\begin{frame}{Algorithme alpha-bêta} - TODO! +\begin{frame}[fragile]{Algorithme alpha-bêta} + \begin{onlyenv}<2> + \begin{pseudocode} + def alphabeta(jeu, profondeur, joueur_actuel, gagnant, resultat, note, qui): + ! !possibilites = recuperation_possibilites(jeu, joueur_actuel) + ! !if (possibilites == 0): + ! ! joueur_actuel = ennemi(joueur_actuel) + ! ! possibilites = recuperation_possibilites(jeu, joueur_actuel) + ! ! if (possiblites == 0): + ! ! return heuristique(jeu, gagnant) + ! !if (joueur_actuel == gagnant): + ! ! resultat = -INFINI + ! !else: + ! ! resultat = +INFINI + ! !profondeur = profondeur - 1 + ! !resultat_tmp = resultat + ! !coupure = false + ! !for (i in possibilites): + ! ! if (coupure): + ! ! return resultat_tmp + \end{pseudocode} + \end{onlyenv} + \begin{onlyenv}<3> + \begin{pseudocode} + ! !# toujours dans la boucle... + ! ! copie_jeu = jeu + ! ! joue_coup(i, joueur_actuel) + ! ! if (profondeur > 0): + ! ! alphabeta(copie_jeu, profondeur, ennemi(joueur_actuel), gagnant, resultat_tmp, resultat, joueur_actuel) + ! ! else: + ! ! resultat_tmp.score = heuristique(copie_jeu, gagnant) + ! ! if (joueur_actuel == gagnant): + ! ! if (qui == ennemi(gagnant) and score_tmp.score >= note): + ! ! coupure = true + ! ! resultat = +INFINI + ! ! else: + ! ! if (resultat_tmp.score >= resultat.score): + ! ! resutat.score = resultat_tmp.score + ! ! resultat.position = i + ! ! if (resultat.score == +INFINI): + ! ! coupure = true + \end{pseudocode} + \end{onlyenv} + \begin{onlyenv}<4> + \vspace{10mm} + \begin{pseudocode} + ! !# toujours dans la boucle... + ! ! else: + ! ! if (qui == gagnant and score_tmp.score <= note): + ! ! coupure = true + ! ! resultat = -INFINI + ! ! else: + ! ! if (resultat_tmp.score <= resultat.score): + ! ! resutat.score = resultat_tmp.score + ! ! resultat.position = i + ! ! if (resultat.score == -INFINI): + ! ! coupure = true + \end{pseudocode} + Avec la même heuristique que minimax + \end{onlyenv} + \begin{itemize} + \item<1> Ressemble à minimax, seule différence : + \begin{itemize} + \item argument \texttt{note} : score précédent + \item argument \texttt{qui} : joueur à qui la note appartient + \end{itemize} + \end{itemize} \end{frame} \section{Comparaison} -\begin{frame}{Comparaison d'efficacité} - TODO! +\begin{frame}[fragile]{Comparaison d'efficacité} + \only<3> { + \vspace{25mm} + \begin{itemize} + \item À profondeur égale: + \begin{itemize} + \item même taux de victoire + \item alpha-bêta beaucoup plus rapide + \end{itemize} + \end{itemize} + + En temps raisonnable, minimax peut aller jusqu'à une profondeur de 5 + alors qu'alpha-bêta peut aller jusqu'à 8.\\ + $\Rightarrow$ Avantage pour alpha-bêta + } + \begin{columns}[onlytextwidth] + \def\rcolumn{60mm} % taille colonne de droite + \column{\linewidth-\rcolumn+1mm} % colonne de gauche + \begin{itemize} + \item<1-2> Implémentation dans \texttt{test.c}. + \item<2> Vitesse et victoires + \end{itemize} + \column{\rcolumn-5mm} % colonne de droite + + \begin{overprint} + \onslide<1> + \begin{figure} + \includegraphics[width=\rcolumn]{../imgs/othello_impl_tests.png} + \caption*{Tests : \texttt{./othello --test}} + \end{figure} + \onslide<2> + \vspace{15mm} + \begin{figure} + \begin{minted}[autogobble,linenos,fontsize=\scriptsize]{c} + void run_tests(void) { + speed_test(6, 8); + winrate_test(5, 7); + } + \end{minted} + \caption*{Fonction lançant les tests} + \end{figure} + \end{overprint} + \end{columns} \end{frame} \appendix