Un moteur d'échecs écrit en Rust, avec une interface web locale pour jouer contre lui et le regarder apprendre.
- Partie : joue contre le moteur (clic ou glisser-déposer), avec sa réflexion en direct : évaluation, profondeur, positions par seconde et ligne principale.
- Analyse : tu joues les coups des deux camps. Le moteur analyse en continu la position affichée : une flèche montre le meilleur coup, avec l'évaluation et la suite prévue. Chaque coup joué est jugé (meilleur coup, bon coup, imprécision ?!, erreur ?, gaffe ??), avec le coup que le moteur préférait. Tu peux revenir en arrière (flèches ← →), rejouer une autre suite, charger une position FEN, ou masquer le conseil pour chercher toi-même.
- Entraînement : le moteur joue contre lui-même, ajuste son évaluation, puis la nouvelle version affronte l'ancienne. Graphiques de progression, partie en direct, valeur des pièces et cartes de chaleur qui évoluent pendant l'apprentissage.
- Installer Rust (une seule fois) :
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
- Récupérer le code et lancer :
Le navigateur s'ouvre sur http://localhost:8080. La première compilation prend une minute.
git clone https://github.com/HarpeLm/chessengine.git cd chessengine cargo run --release
Toujours utiliser --release : le moteur est environ 20 fois plus rapide qu'en mode debug.
Autres commandes :
| Commande | Rôle |
|---|---|
cargo run --release -- --port 8081 |
interface sur un autre port |
cargo run --release -- uci |
mode UCI, pour brancher le moteur sur Cute Chess, Arena ou lichess-bot |
cargo run --release -- perft 6 |
compte les positions à la profondeur 6 (doit donner 119 060 324) |
cargo run --release -- bench |
vitesse de recherche du champion enregistré |
cargo test --release |
lance les tests |
Les poids appris et l'historique d'entraînement sont enregistrés dans le dossier data/. Supprime-le pour tout remettre à zéro.
| Fichier | Contenu |
|---|---|
src/board.rs |
l'échiquier : pièces, cases, lecture et écriture FEN, jouer un coup, cases attaquées, hachage Zobrist |
src/movegen.rs |
génération des coups légaux, notations UCI (e2e4) et SAN (Nf3) |
src/perft.rs |
le test perft, qui prouve que la génération des coups est exacte |
src/eval.rs |
l'évaluation classique : matériel, tables de position, pions passés, mobilité… |
src/nnue.rs |
le réseau de neurones d'évaluation (NNUE) : calcul rapide, mise à jour incrémentale, entraînement |
src/search.rs |
la recherche : alpha-bêta, approfondissement itératif, quiescence, coup nul, réductions, tri des coups |
src/tt.rs |
la table de transposition (le cache des positions déjà analysées) |
src/train.rs |
l'apprentissage par parties contre soi-même (méthode de Texel) |
src/game.rs |
la partie jouée dans le navigateur |
src/analysis.rs |
le mode analyse (les deux camps, conseil du moteur) |
src/server.rs, src/app.rs |
le serveur web local et l'état partagé |
src/uci.rs |
le protocole UCI |
web/ |
l'interface (HTML, CSS, JavaScript sans framework) |
Ordre conseillé pour lire le code : board.rs → movegen.rs → perft.rs → eval.rs → search.rs → train.rs.
L'évaluation est une somme pondérée d'environ 400 critères. Chaque critère a deux poids : un pour le milieu de partie, un pour la finale. Une génération d'entraînement se déroule en quatre étapes :
- Parties : le champion joue contre lui-même depuis des ouvertures tirées au hasard. Chaque position calme est notée avec le résultat final de la partie.
- Ajustement : une descente de gradient cherche les poids dont l'évaluation prédit le mieux ces résultats. Un rappel vers les poids actuels évite qu'ils partent n'importe où quand les données manquent.
- Match : le candidat affronte le champion. Chaque ouverture est jouée deux fois, en inversant les couleurs. S'il marque plus de 50 %, il passe à la vérification.
- Vérification : un second match, sur d'autres ouvertures. Le candidat ne devient champion que s'il gagne aussi ce match, et c'est lui qui mesure le gain d'ELO. Le premier match a servi à choisir le candidat, il surestime donc son niveau : un candidat chanceux peut le gagner sans être meilleur.
Deux points de départ sont possibles, depuis le bouton « Réinitialiser » :
- Valeurs classiques : une évaluation écrite à la main, que l'entraînement affine. Les progrès sont lents et beaucoup de candidats sont rejetés, c'est normal.
- Zéro absolu : le moteur ne connaît que les règles. Les premières générations progressent de plusieurs centaines d'ELO, et on voit apparaître la valeur des pièces et les bonnes cases.
Dans « Réinitialiser », choisis Passer au réseau de neurones. Ton champion actuel et l'historique sont conservés : un réseau va apprendre à battre ce champion.
- Architecture : 768 entrées (2 couleurs × 6 pièces × 64 cases), puis 2 × 128 neurones cachés (la position vue par les Blancs et vue par les Noirs), puis une sortie qui donne l'évaluation. Environ 99 000 paramètres.
- Rapide dans la recherche : un coup ne change que 2 à 4 entrées, donc on met à jour les neurones cachés au lieu de tout recalculer. Les calculs se font en nombres entiers.
- Données : le champion joue contre lui-même. Chaque position calme est gardée avec le score de la recherche et le résultat de la partie. Le réseau apprend à prédire un mélange des deux (75 % score, 25 % résultat).
- Premier entraînement : il faut d'abord accumuler 400 000 positions, soit quelques minutes. Ensuite, chaque génération ajoute des parties et affine le réseau. Jusqu'à 2 millions de positions sont gardées en mémoire.
- Validation : une position sur 20 n'est jamais montrée au réseau pendant l'apprentissage. Son erreur (en pointillés sur le graphique) montre si le réseau généralise ou s'il apprend par cœur.
- Adoption : comme pour la formule classique, le réseau doit gagner le match de sélection puis la vérification.
Le réseau champion est enregistré dans data/nnue.bin.
L'onglet Mesure fait jouer ton moteur contre Stockfish bridé à un niveau choisi (option UCI_Elo, de 1320 à 3190). Chaque ouverture est jouée deux fois, une fois avec chaque couleur, avec une vraie pendule. Le score donne une estimation du classement et une marge d'erreur à 95 %, qui se resserre au fil des parties.
- Installer Stockfish (une seule fois) :
brew install stockfish. L'application le trouve toute seule ; sinon, indique son chemin dans l'onglet. - Choisir un niveau (commencer vers 2000), 100 parties, cadence 30 s + 0,3.
- Ajuster : la mesure est la plus précise quand le score est proche de 50 %. Si ton moteur gagne presque tout, monte le niveau, et inversement.
L'échelle de UCI_Elo est celle des listes de moteurs (CCRL), calibrée par Stockfish à la cadence 60 s + 0,6. Ce n'est pas un classement FIDE. Stockfish est un logiciel libre (GPL) : l'utiliser comme adversaire est autorisé. Il n'est pas inclus dans ce projet, tu l'installes à part.
Lichess autorise les bots via son API officielle, avec un compte dédié. Règle absolue : n'utilise jamais ton moteur pour t'aider dans tes propres parties, c'est de la triche et le compte est banni.
- Crée un nouveau compte Lichess pour le bot. Il ne doit avoir joué aucune partie.
- Connecté avec ce compte, crée un jeton d'accès avec la permission « Play games with the bot API » : https://lichess.org/account/oauth/token/create?scopes[]=bot:play.
- Installe lichess-bot (Python 3) :
git clone https://github.com/lichess-bot-devs/lichess-bot.git cd lichess-bot python3 -m venv venv && source venv/bin/activate pip install -r requirements.txt cp config.yml.default config.yml
- Dans
config.yml, renseigne le jeton et ton moteur :Avectoken: "ton-jeton" engine: dir: "/chemin/vers/chessengine/scripts/" name: "chessengine-uci" protocol: "uci" ponder: true
ponder: true, le moteur réfléchit aussi pendant le temps de l'adversaire : il devine sa réponse et prend de l'avance, ce qui le rend plus fort sans rien changer d'autre. Le scriptscripts/chessengine-ucilance le moteur depuis le dossier du projet, pour qu'il utilise ton champion entraîné. Compile d'abord aveccargo build --release. - Transforme le compte en compte BOT (une seule fois, irréversible) :
python3 lichess-bot.py -u. - Lance le bot :
python3 lichess-bot.py. Il accepte les défis ; tu peux le défier depuis ton compte personnel, ou activer la sectionmatchmakingdeconfig.ymlpour qu'il défie d'autres bots. Son classement Lichess apparaît sur son profil après quelques parties.
Les pièces « Staunty » sont de sadsnake1, sous licence CC BY-NC-SA 4.0. Elles proviennent de lichess. Cette licence interdit l'usage commercial.
Les tables de position de départ s'inspirent de la Simplified Evaluation Function de Tomasz Michniewski (chessprogramming.org).