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:
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é.
Je compile par la ligne de commande, comme ceci :Code:
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;
Code:
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:"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