URL:     https://linuxfr.org/users/n_e/journaux/ecrire-un-moteur-d-echecs-surhumain-partie-1
Title:   Ecrire un moteur d'échecs surhumain - Partie 1
Authors: n_e
Date:    2026-09-27T19:14:37+02:00
Tags:    
Score:   6


Bonjour Nal,

Je me suis dit qu'il serait intéressant d'écrire un moteur d'échecs capable de battre n'importe quel humain. Pourquoi ?

- le résultat est impressionnant
- c'est difficile mais réalisable
- et surtout, c'est instructif

A ce stade, je n'ai pas commencé à coder le moteur cible (mais j'ai codé un prototype). Je vais vous parler de mes choix et vous donner un peu de contexte sur les moteurs d'échecs.

# Les types de moteurs d'échecs

Aujourd'hui il existe deux types de moteur d'échecs : les moteurs "classiques", dont le plus connu et le plus performant est Stockfish, et les moteurs dans la lignée d'AlphaZero, qui est connu pour avoir atteint un niveau surhumain par auto-apprentissage (en jouant contre soi-même), et qui est un descendant de AlphaGo, qui a été le premier logiciel de Go à battre les meilleurs joueurs mondiaux.

Dans les deux cas, le principe de base des moteurs est qu'on leur donne une position en entrée, et ils retournent le meilleur coup en sortie. Le fonctionnement réel est évidemment plus complexe, avec notamment les calculs réalisés pour les coups précédents d'une même partie réutilisés, la gestion du temps, etc.

Les moteurs classiques utilisent une recherche de type minimax, associée à une fonction d'évaluation qui donne un score à chaque position rencontrée au cours de la recherche.

Les moteurs de type AlphaZero utilisent une recherche MCTS (Monte Carlo Tree Search), qui explore par échantillonnage, en se basant sur les probabilités retournées par la fonction d'évaluation, qui est un réseau neuronal qui retourne la probabilité que chaque coup possible soit le meilleur.

# Mon choix de moteur

Je vais partir sur un moteur classique. Simplement parce que c'est ce que je préfère, mais aussi parce que ça se prête également mieux à commencer par quelque chose de basique et l'améliorer au fur et à mesure.

A noter que les moteurs classiques ne sont pas anciens ou obsolètes : Stockfish est actuellement le moteur le plus puissant, il est possible d'utiliser des réseaux neuronaux ou de faire de l'auto-apprentissage.

# Mes choix techniques

Je vais écrire le moteur en Rust. Initialement, je voulais l'écrire en JavaScript sur Node.js car c'est le langage que j'utilise le plus, et j'aime bien montrer qu'il est rapide. Cependant je ne vais pas partir sur Node.js pour plusieurs raisons :

- Bien que ce soit possible d'obtenir un moteur final performant (Stockfish transpilé en JavaScript a des performances "correctes"), les premières versions naïves du moteur seront lentes, ce qui va être problématique pour faire des parties en cadences très rapides (qui sont nécessaires pour tester les améliorations du moteur)

- La technique performante pour faire des opérations sur l'échiquier est d'utiliser des bitmaps de 64bits (on a de la chance, un échiquier fait 64 cases), et JavaScript ne gère presque pas les entiers de 64bits

- L'optimiseur des dernières versions de V8 est très agressif, ce qui rend le profilage d'une fonction optimisée quasi-impossible (la fonction principale et celles qu'elle appelle sont optimisés en une seule grosse fonction, et on ne voit que ça dans les profils)

Quant à Rust vs C++ ou autre, ce n'est qu'une question de préférence.

# L'optimisation et la détection de bugs d'un moteur d'échecs

Commençons par la détection de bugs : l'approche "comme pour un programme classique" ne marche pas, car sauf pour les bugs les plus grossiers, l'impact d'un bug va juste être une légère baisse de niveau. Par exemple, si la matrice indiquant les meilleures positions des pions est à l'envers, les pions seront parfois moins bien placés, mais pas forcément vu qu'une recherche plus profonde pourra trouver la bonne position car la bonne position a des avantages tactiques.

La détection de bugs se traite donc de la même façon que l'optimisation : on fait une modification, on regarde si la modification augmente le niveau de jeu, et si c'est le cas on la merge.

# Les prochaines étapes

Les prochaines étapes sont la conséquence du paragraphe précédent : avant de faire quoi que ce soit de compliqué, il faut pouvoir évaluer l'effet d'une modification, ce qui concrètement se fait avec un outil comme [cutechess-cli](https://manpages.ubuntu.com/manpages/xenial/man6/cutechess-cli.6.html), qui parle au moteur avec le protocole UCI.

Les prochaines étapes seront donc le strict nécessaire pour obtenir un moteur qui joue des coups légaux et peut être utilisé avec cutechess-cli :

- générateur de coups (à partir d'une position on génère tous les coups légaux)

- recherche negamax basique

- fonction d'évaluation basique (par exemple somme de la valeur des pièces)

- approfondissement itératif basique et gestion de la pendule

- protocole UCI

Ensuite on pourra commencer les optimisations, a priori les plus basiques et importantes sont :

- ajouter des notions positionnelles basiques à la fonction d'évaluation (bon positionnement des pièces, etc.)

- alpha-beta pruning (on ne calcule pas les branches qui sont forcément meilleures pour l'adversaire ou pires pour nous que celles déjà calculées)

- classement des coups (on calcule d'abord les coups qu'on anticipe être les meillleurs, ce qui permet à l'algorithme alpha-beta de retirer un maximum de branche)

- quiescence search (si on arrête la recherche au milieu d'un échange, alors qu'on a capturé une pièce mais on n'a pas été recapturés, l'évaluation va dire qu'on a une pièce de plus. L'algo. en question continue la recherche jusqu'à ce que la position soit stable)
