Bonjour ! J'aimerais vous présenter mon moteur UCI écrit en Pascal pour le compilateur Delphi.

C'est un joueur d'échecs artificiel piloté par une application au moyen du protocole UCI.

Pour vous faire rapidement une idée du protocole UCI, voici un exemple de dialogue entre l'application principale et le moteur :

Code X : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
REM Commande "uci" : le moteur doit se présenter.
07:02:58 >> uci
07:02:58 << id name Durandal 0.0.5
07:02:58 << id author Roland Chastain
07:02:58 << option name UCI_Variant type combo default chess var capablanca var caparandom var chess var fischerandom
07:02:58 << uciok
REM Commande "isready" : le moteur doit faire savoir qu'il est prêt.
07:03:30 >> isready
07:03:30 << readyok
REM Commande "position" : le moteur reçoit la position pour laquelle un coup va lui être demandé.
07:03:30 >> position startpos moves e2e4 e7e5 g1f3 b8c6 b1c3 g8f6 d2d3
REM Commande "go" : le moteur doit jouer.
07:03:30 >> go wtime 1491186 btime 178929 winc 5000 binc 1000
07:03:30 << bestmove f8b4
07:03:35 >> isready
07:03:35 << readyok

Donc techniquement c'est une application console, qui lit l'entrée standard et écrit sur la sortie standard. Dans tous les exemples que j'ai vus de moteurs écrits en Pascal, les auteurs font des choses compliquées avec l'unité Windows, je ne sais pas trop pourquoi. Moi j'utilise ReadLn et WriteLn, et ça marche.

Il y a une contrainte, c'est que le moteur doit toujours être capable de répondre aux commandes, même quand il est en train de calculer son coup. C'est pourquoi la fonction BestMove est appelée dans un fil d'exécution séparé.

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type
  TProcessus = class(TThread)
    protected
      procedure Execute; override;
  end;
 
var
  LPos: TPosition;
  LMoveTime: cardinal;
 
procedure TProcessus.Execute;
var
  LTimeElapsed: cardinal;
  LMove: string;
begin
  LTimeElapsed := {$IFDEF FPC}GetTickCount64{$ELSE}GetTickCount{$ENDIF};
  LMove := {$IFDEF RANDOM_MOVER}RandomMove(LPos){$ELSE}BestMove(LPos, LMoveTime){$ENDIF};
  LTimeElapsed := {$IFDEF FPC}GetTickCount64{$ELSE}GetTickCount{$ENDIF} - LTimeElapsed;
  if not Terminated then
  begin
    SendToUser(Format('bestmove %s', [LMove]));
    ToLog(FormatDateTime('"Temps écoulé : "hh:nn:ss:zzz', LTimeElapsed / (1000 * SECSPERDAY)), 1);
  end;
end;
Je compile par la ligne de commande, comme ceci :

Code Batch : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
call dcc32 -CC -NSsystem -DDEBUG durandal.pas
move durandal.exe bin\debug\durandal32.exe
 
call dcc32 -CC -NSsystem durandal.pas
move durandal.exe bin\release\durandal32.exe

J'ai dans le même dossier un fichier nommé dcc32.cmd qui contient ceci :

Code Batch : Sélectionner tout - Visualiser dans une fenêtre à part
"C:\Program Files (x86)\Embarcadero\Studio\20.0\bin\DCC32.EXE" %*

Seule la version DEBUG produit des fichiers *.log.

Donc j'aurais bien aimé avoir votre avis sur mon code. Y a-t-il des choses que vous auriez faites différemment ?

Si vous voulez essayer le programme, vous avez besoin d'une application comme Tarrasch ou Mayura.

Et puis, j'aurais bien aimé que quelqu'un ait la gentillesse de bien vouloir faire pour moi une compilation Linux. J'ai cru comprendre en lisant certaines discussions que c'était possible.

Le projet complet se trouve ici :
https://github.com/rchastain/durandal