1. Introduction

Les échecs sont le jeu de société le plus ancien qui existe. La création de ce jeu a eu lieu au 7e siècle dans le nord-est de l’Inde. C’est également connu comme l’un des jeux les plus populaires qui y existe, surtout après la série Netflix "Le jeu de la dame" qui a incité beaucoup de personnes à apprendre les règles approfondir leurs connaissances sur le jeu. Dans ce jeu, de manière simpliste, il y a deux aspects du jeu : l’aspect tactique et l’aspect positionnel. L’aspect tactique consiste à trouver une séquence de coups qui permet à l’un des joueurs de saisir un avantage concret (c’est-à-dire un avantage matériel). Par exemple, le fait de donner une dame, rater un échec-et-mat en un coup font partie de l’aspect tactique du jeu. L’aspect positionnel du jeu est la capacité d’exploiter sur le long terme les faiblesses qui résident dans la position adverse. Des enjeux comme les ilots de pions, les colonnes ouvertes, l’occupation du centre sont des thèmes constitutifs de l’aspect positionnel. En tant que joueur d’échecs, pour pouvoir s’entraîner efficacement, il est vraiment important de développer ses capacités tactiques, car si l’adversaire fait une erreur d’ordre tactique, c’est l’occasion clef de saisir un avantage concret, et c’est cet avantage qui nous augmente la chance de gain. L’enjeu principal est d’entraîner toute une variété de langage de programmation, notamment HTML (Hypertext Markup Language), le PHP (Hypertext Preprocessor) et le MySQL (Structured Query Language). La limitation principale est qu’il sera impossible de rattraper les tricheurs qui utilisent des ordinateurs (par exemple, si un humain résous plusieurs puzzles dont la difficulté est très élevée, mais les résous en 3 secondes, c’est assez suspect).

L’idée de ce projet P est de créer un site web dans lequel un échiquier sera affiché, et une position concrète, et le but de l’utilisateur est de trouver la meilleure suite de coups. Si l’utilisateur trouve le meilleur premier coup, la réponse de l’adversaire sera automatiquement programmée et l’utilisateur doit à nouveau trouver le bon coup. Si l’utilisateur trouve la bonne suite de coups, un message comme "Bravo! Vous avez réussi!" sera affiché. Sinon, un message informant que l'utilisateur n'a pas trouvé le meilleur coup sera affiché et celui-ci pourra voir la solution ou réessayer. Ces positions seront stockées dans une base de données. De plus, l’utilisateur sera chronométré pour savoir combien cela lui aura pris (dans une vraie partie d’échecs, il y a un temps limité après tout). Finalement, un classement ELO sera attribué à l’utilisateur pour approximer son niveau avec un nombre. Il gagnera des points s’il résout la tactique et perdra des points s’il joue le mauvais coup. Le nombre de points gagné ou perdu dépend de la difficulté de la position, et du niveau de l’utilisateur. Il faut également créer des comptes facilement (avec mot de passe) afin de sauvegarder le classement ELO de l’utilisateur.

Il est important de comprendre que les puzzles tactiques ont une unique solution, qui est le meilleur coup. En général, tous les autres coups à part le meilleur coup sont considérés comme étant mauvaises, car elles nuisent la position du joueur en question directement. C’est pourquoi cela a un sens d’accepter uniquement le meilleur coup. Néanmoins, il se peut que ce meilleur coup soit trop difficile à trouver pour le niveau de l’utilisateur. C’est pourquoi il est également important d’afficher des puzzles à un écart de 300 ELO par rapport au niveau de l’utilisateur. Par exemple, si un certain utilisateur a un ELO de 1000, la difficulté du puzzle ne sera pas plus élevée que 1300 ELO (et d’au moins 700 ELO pour que le puzzle ne soit pas trop facile). Proposer un puzzle d’ELO 2000 (un joueur à 2000 ELO est considéré comme un expert) à cet utilisateur n’aurait aucun sens car l’astuce à trouver dans le puzzle ne sera pas utile pour l’utilisateur lorsqu’il joue des parties d’échecs contre des joueurs du même niveau que lui-même (c’est-à-dire 1000 ELO). J’ajoute également que cette stratégie est utilisée par les plus grands sites d’échecs (notamment chess.com, lichess.com etc.), et cette méthode est très puissante afin de progresser et de reconnaître des paternes tactiques dans une vraie partie d’échecs.

Capture-d’écran-2020-06-25-à-17.16.19.png, mai 2021
Figure 1 - Niveau ELO


Pour la partie « échiquier », le langage de programmation utilisé sera Python. Il faudra faire bon usage des librairies python-chess et pygame pour être capable d’afficher un échiquier et puis de déterminer les coups légaux.

Figure 2 - ChessTrainer chess.com

2. Matériel et méthodes

2.1. Matériel

Hardware:

  • iMac

Software:

  • Mac OS X
  • Python version 3.8.2
  • IDLE
  • python-chess
  • Chessnut
  • pygame
  • PHP
  • PHPMyAdmin
  • MySQL
  • Apache

2.2. Méthode

2.2.1. Installation des softwares web

Apache
$ brew services install httpd
PHP
$ brew install php@7.3
MySQL
$ brew install mariadb
PHPMyAdmin
$ brew install phpmyadmin

2.2.2. Lancement des services web

Apache
$ brew services start httpd
PHP
$ brew start php@7.3
MySQL
$ brew start mariadb
PHPMyAdmin
$ brew start phpmyadmin

2.2.3. Installation Python 3.8.2 et librairies

$ brew install python@3.8
$ pip install pygame
$ pip install chess
$ pip install Chessnut

Python 3.8 a dû être installé, car python-chess ne fonctionne qu'à partir des versions supérieures ou égales à 3.7.

2.2.4. Création d'un système qui permet la création d'un utilisateur

Pour commencer, il faut créer une table mySQL (base de donnée sous le nom de paqc_johannwilliams et le nom de la table comme users_tb) dans lequel nous stockons les informations de l'utilisateur de la manière suivante

Structure de la table de base de données
Screenshot 2021-05-11 at 11.31.16.png, mai 2021
Tableau 1 - MySQL variables


La base de donnée et la table MySQL ont été créées sur PHPMyAdmin, qui est accessible sur http://camera250.ddns.net:65003/phpmyadmin/ (username: root, password: root).

A l'aide du PHP, il sera possible de récolter les informations dans la base de donnée et de l'exploiter pour vérifier si le mot de passe inséré par l'utilisateur est correct ou pas.

Contenu de la table de la base de données
Screenshot 2021-05-11 at 09.47.25.png, mai 2021
Tableau 2 - MySQL avec les informations sur les comptes


2.2.5. Code Python du ChessTrainer

Tout d'abord, il faut une banque de donnée qui contient des milliers de positions tactiques avec les solutions des puzzles. Pour ce faire, j'en ai trouvé un sur Internet (http://gorgonian.weebly.com/uploads/1/7/2/2/17221082/cts2.pgn) qui contient très exactement 17814 positions tactiques. L'idée est qu'une position peut être décrite à l'aide d'une FEN (Forsyth-Edwards Notation). La composition d'une FEN est assez complexe:

Par exemple, pour déterminer le tour du joueur, il faudra prendre le 12 caractère de la fin. S'il c'est un "w", c'est au tour des blancs ("w" pour White) et si c'est un "b", c'est au tour des noirs ("b" pour Black). Ensuite, maintenant, à l'aide d'un petit code Python, il sera possible de créer deux fichiers .txt. Le premier (Tactics.FEN_db.txt) avec toutes les positions FEN et une deuxième(db_array_solutions.txt) avec les solutions des tactiques (sauf le seul coup, qui permet de donner un contexte à la position pour l'utilisateur).

De plus, il faut prendre des images d'internet de chacune des pièces d'échecs, afin de pouvoir les afficher l'échiquier. Attention, avec mon code, il est important que les images soit dans le même directory que le code! Ensuite, pour pouvoir coder, l'idée est d'effectuer un mélange entre pygame et python-chess. Pour afficher l'échiquier avec les pièces et reconnaître la position des cliques de la souris, il faut utiliser pygame, et pour pouvoir empêcher à l'utilisateur de jouer des coups illégaux, il faut se munir de la librairie python-chess. Finalement, la librairie Chessnut est utilisée pour recevoir la position des pièces sous format FEN.

2.2.6. Exécuter le code Python dans du web

A l'aide de la commande exec, nous arrivons à faire exécuter le code Python après s'être connecté (http://camera250.ddns.net:65003/loginpage.php). Pour pouvoir rendre ce lien accessible au public, le domaine "camera250.ddns.net" a été enregistré gratuitement dans le site noip.com et le client de noip est installé à l'intérieur le réseau local. Ensuite, un port forward a dû être effectué, du port TCP :65003 au port TCP :8080 (sur le iMac, qui se trouve dans le réseau local). Or, le gros souci avec cette approche est le suivant: lorsqu'un utilisateur qui ne trouve pas dans le même sous-réseau que le mien, alors le code Python va quand même s'exécuter, mais sur mon ordinateur à la place de l'ordinateur de l'utilisateur.

3. Résultats

Tout d'abord, lorsque le fichier Python est tout seul exécuté, alors dans la grande majorité des cas, le code fonctionne. Il y a juste dans les cas limites (les situations "en-passant", de roque ou de promotions) qui ne marchent pas dans tous les cas (en revanche, ces cas limites prennent place à peu près 1/10 car il n'est pas très commun d'avoir une tactique, dont la solution consiste à roquer, effectuer une prise en passant ou une promotion).

ChessTrainer lorsque l'utilisateur donne le mauvais coup

Figure 3 - Un message d'erreur s'affiche lorsque l'utilisateur a joué le mauvais coup

ChessTrainer lorsque l'utilisateur donne le bon coup

Figure 4 - Un message de confirmation s'affiche lorsque l'utilisateur a joué le bon coup

Or, le gros problème, c'est, lorsqu'un utilisateur qui ne trouve pas dans le même sous-réseau que le mien, alors le code Python va quand même s'exécuter, mais sur mon ordinateur à la place de l'ordinateur de l'utilisateur.

4. Discussion

4.1.Critique du travail

Premièrement, ce travail est une version très simplifiée du résultat que nous voulions. En effet, le système d'ELO n'a pas été mise en place à cause de la complexité des divers problèmes rencontrés dans le cadre du projet, qui m'a fait perdre beaucoup de temps, sur des éléments auxquels je ne m'attendais pas du tout à dépenser tant de temps. Au moins, la base du projet est faite, mais l'aspect pédagogique de cette application n'est pas du tout remplie, à cause du manque de fonctionnalités qui permettrait d'expliquer les erreurs de l'utilisateur et comme les corriger. De plus, il se peut qu'un débutant tombe sur des tactiques de niveau très élevé et vice versa, car le programme n'a pas de système d'ELO, ce qui perd de la valeur au programme, qui est censé aider à la progression du joueur. Finalement, à travers ce projet, j'ai découvert des méthodes plus efficace à debugger un code, typiquement en utilisant des "print(variable)" afin de comprendre où exactement se cache mes erreurs de code.



4.2.Problèmes rencontrés

4.2.1. Le début du projet

J'ai eu particulièrement du mal à débuter ce projet. Je ne savais pas par où commencer. Au début, je pensais que la librairie python-chess donnait accès à un échiquier sur lequel il est possible de déplacer les pièces à l'aide du curseur, mais après plusieurs de recherche de lecture attentive de la documentation de python-chess, je me suis rendu compte qu'il est impossible de faire tout le projet à l'aide d'uniquement la librairie python: il me fallait une librairie pour afficher l'image et puis ensuite être capable de détecter la position du curseur par rapport à l'interface. Au début, j'étais convaincu que Matplotlib était une bonne idée, mais j'ai dû très rapidement abandonner cette idée car le simple fait d'afficher les images des pièces sur un échiquier sur Matplotlib paraissait compliquée. Après plusieurs heures de recherche, je m'étais rendu compte que pygame était une solution qui semblait pouvoir tenir pour un tel projet, et c'est effectivement le cas.

4.2.2. Python et le web

C'est le problème qui m'a fait perdre le plus de temps. L'approche de coder le ChessTrainer sur Python n'est pas une si mauvaise idée que cela si on compte l'utiliser localement. En revanche, lorsqu'on parle de web et d'intégrer avec du PHP, il est nécessaire d'utiliser framework, comme Flask, qui permet le mélange entre Python et HTML. Le souci, c'est que Flask n'est pas fait pour ce type de projets à cause de la librairie pygame.

4.2.3. Manière de séparer les informations voulues dans plusieurs fichiers txt.

Un élément qui m'a fait perdre une bonne quantité de temps, c'est que ce fichier est en fait mal rédigé. En effet, il y a des bouts dans le texte qui ne contiennent pas de solutions pour certaines tactiques, ainsi il faut être extrêmement prudent lorsque nous créons notre propre fichier avec les informations que nous cherchions. Un simple code Python ne résoud pas directement l'affaire car il faut bien faire attention de ne pas prendre les positions FEN dont le fichier n'a pas les solutions, sinon tout sera décalé, ce qui est très problématique. De plus, il y a aussi quelques tactiques, dont les solutions ont une longueur de 10 coups, ainsi les solutions de telles positions s'écrivent sur deux lignes et non un, donc il faut une fois de plus bien faire attention de bien mettre une solution pour exactement une ligne, afin d'être organisé lorsque nous trions les informations.

Screenshot 2021-05-11 at 08.32.07.png, mai 2021
Figure 5 - Erreurs dans le code


Screenshot 2021-05-11 at 08.32.24.png, mai 2021
Figure 6 - Espace en trop


4.2.4. Python et les différentes manières de noter les coups

Une difficulté que j'ai rencontré lorsque j'ai dû coder la partie Python, c'est qu'il a fallu plusieurs manières différentes de noter des coups, et puis des dictionnaires pour effectuer des transitions entre les manières de noter les coups. Il y a

  • La représentation standard de noter les coups. Par exemple, si nous bougons notre cavalier de la case b1 à la case c3, on notera le coup "Nc3"
  • La représentation des coups sur python-chess. Si on reprend le même exemple qu'avant, le coup se notera comme "b1c3"
  • La représentation des coups sur gs.board, qui est une liste (dont ses 8 éléments sont des listes également) qui change d'état après chaque coup. C'est cette liste qui permet le display des pièces sur l'échiquier. Ainsi, il faut être aisément capable de convertir une case sous forme de coordonnées (par exemple, les coordonnées de la case "b1" sont (6,0)) en une case

Donc, lorsque le code a été écrit, il a été vraiment important pour moi, de bien analyser la situation afin d'éviter de ne pas mélanger les pinceaux avec les notations.

4.3. Améliorations

Premièrement, si nous restons sur du Python, une fonctionnalité intéressante à mettre en oeuvre serait de donner la possibilité à l'utilisateur de continuer ou arrêter lorsqu'il a résolu un puzzle d'échecs, et qu'il ne serait pas nécessaire d'exécuter le code à nouveau pour pouvoir afficher une nouvelle position. De plus, il serait bien que les messages apparaissent directement sur l'interface plutôt que sur IDLE. Maintenant, concernant le système d'ELO, il est serait tout-à-fait possible de le faire sur Python, mais dans ce cas, il faudrait trouver une banque de données qui contient déjà d'avance les difficultés des puzzles d'échecs en ELO, ce qui est une piste totalement possible. En revanche, dans ce cas, il serait plus malin d'effectuer le projet sur le web à 100%. En effet, dans ce cas, les tables MySQL facilitent grandement la tâche si l'échiquier est générée sur du PHP. Je ne m'attendais pas à avoir tant de soucis sur le mélange Python-WEB. Ainsi. c'est une raison de plus pour effectuer le projet entièrement sur le web. Certes, nous n'aurons plus python-chess, mais en revanche, PHP a une libraire Games_Chess.php, qui joue le même rôle qui python-chess, mais c'est une librairie PHP et non Python. Un autre avantage en procédant ainsi est la suivante: il est plus simple d'effectuer un système de classement, vu que tout est relié à MySQL. En effet, l'ELO sera un nombre automatiquement initialisé à 1200 lorsque le compte est créé (l'ELO se trouvera dans le tableau users_tb) et pour afficher un classement, ce n'est que l'histoire d'une requête MySQL. En continuant d'aller dans cette direction, il sera également possible d'effectuer un historique des puzzles qui ont été tentés par l'utilisateur, à l'aide d'une table MySQL à nouveau.

5. Conclusion

L'objectif n'a été que partiellement atteint. En effet, le concept de retirer une tactique d'une banque de donnée et puis d'être capable de créer un programme qui vérifie la validité de nos coups n'est pas complet, car le programme effectue des bugs dans le cas de prises en passant, de roques ou de promotions . De plus, le système d'ELO n'a pas été mis en place, et l'idée de mettre en place tout ce système sur un site web n'a pas été réussi. Ce que j'en tire de ce projet est que mélanger du PHP et du Python est une mauvaise idée et ne fait que de compliquer la tâche plutôt que de la facilite. Donc, il aurait été plus correct d'effectuer l'échiquier à l'aide de PHP. De plus, une telle approche m'aurait permis de créer beaucoup plus facilement plusieurs fonctionnalités qui nécessitent des tables MySQL, dont les données peuvent être facilement être stockées/manipulées à l'aide de commandes PHP.

Références

  1. Documentation python-chess: https://python-chess.readthedocs.io/en/latest/
  2. https://python-chess.readthedocs.io/en/latest/core.html
  3. Documentation Chessnut: https://pypi.org/project/Chessnut/
  4. Banque de données positions tactiques: https://lichess.org/forum/lichess-feedback/download-tactics-database
  5. Source d'inspiration pour le projet: https://www.chess.com/puzzles/rated
  6. Games.chess basics: https://pear.php.net/manual/en/package.structures.games-chess.intro.php
  7. Vidéo Système login-password: https://www.youtube.com/watch?v=WYufSGgaCZ8