par , 30/01/2016 à 10h00 (1653 Affichages)
Les amateurs de jeu d'échecs sur ordinateur connaissent au moins de nom le protocole UCI (pour Universal Chess Interface) qui permet à des logiciels comme Arena, Lucas Chess ou encore Tarrasch de communiquer avec les moteurs supportant le protocole en question.
Je voudrais vous présenter aujourd'hui le programme Cute Chess, qui est un excellent moyen de se familiariser avec le protocole UCI. Cute Chess est disponible sous trois formes : une application graphique, une application console et une bibliothèque. Je parlerai ici de l'application console, que j'ai utilisée sous Windows.
Voici un premier script, que j'ai nommé exemple1.cmd. Ce script demande à Cute Chess de faire s'affronter deux moteurs, Fruit et Pharaon. Chaque moteur disposera d'une seconde par coup.
1 2 3 4 5 6 7 8 9
| @echo off
set cc=c:\chess\cutechess\cutechess-cli.exe
%cc% ^
-debug ^
-engine name=PHARAON cmd=pharaon.exe dir=c:\chess\pharaon ^
-engine name=FRUIT cmd=fruit_21.exe dir=c:\chess\fruit ^
-each proto=uci st=1 > %~dpn0.log |
L'option "-debug" permet de connaître toutes les instructions échangées entre Cute Chess et les deux moteurs. Voici le contenu du fichier exemple1.log :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
| 41 >PHARAON(0): uci
48 >FRUIT(1): uci
221 <FRUIT(1): Fruit 2.1 UCI by Fabien Letouzey
226 <FRUIT(1): id name Fruit 2.1
241 <FRUIT(1): id author Fabien Letouzey
255 <FRUIT(1): option name Hash type spin default 16 min 4 max 1024
264 <FRUIT(1): option name Ponder type check default false
271 <FRUIT(1): option name OwnBook type check default true
275 <FRUIT(1): option name BookFile type string default book_small.bin
280 <FRUIT(1): option name NullMove Pruning type combo default Fail High var Always var Fail High var Never
288 <FRUIT(1): option name NullMove Reduction type spin default 3 min 1 max 3
294 <FRUIT(1): option name Verification Search type combo default Endgame var Always var Endgame var Never
302 <FRUIT(1): option name Verification Reduction type spin default 5 min 1 max 6
303 <FRUIT(1): option name History Pruning type check default true
304 <FRUIT(1): option name History Threshold type spin default 60 min 0 max 100
306 <FRUIT(1): option name Futility Pruning type check default false
308 <FRUIT(1): option name Futility Margin type spin default 100 min 0 max 500
309 <FRUIT(1): option name Delta Pruning type check default false
310 <FRUIT(1): option name Delta Margin type spin default 50 min 0 max 500
311 <FRUIT(1): option name Quiescence Check Plies type spin default 1 min 0 max 2
313 <FRUIT(1): option name Material type spin default 100 min 0 max 400
315 <FRUIT(1): option name Piece Activity type spin default 100 min 0 max 400
316 <FRUIT(1): option name King Safety type spin default 100 min 0 max 400
318 <FRUIT(1): option name Pawn Structure type spin default 100 min 0 max 400
320 <FRUIT(1): option name Passed Pawns type spin default 100 min 0 max 400
321 <FRUIT(1): uciok
322 >FRUIT(1): isready
341 <FRUIT(1): readyok
931 <PHARAON(0): id name Pharaon 3.5.1
933 <PHARAON(0): id author Franck ZIBI
934 <PHARAON(0): option name Nullmove type check default true
936 <PHARAON(0): option name Ponder type check default true
939 <PHARAON(0): option name Clear Hash type button
941 <PHARAON(0): option name Hash type spin min 1 max 1024 default 64
944 <PHARAON(0): option name NalimovPath type string default ;./TB;C:\CHESS\TB;d:\Pharaon\tb;
946 <PHARAON(0): option name NalimovCache type spin min 1 max 32 default 4
948 <PHARAON(0): option name Number of threads type spin min 1 max 4 default 1
950 <PHARAON(0): option name UCI_Chess960 type check default false
951 <PHARAON(0): copyprotection checking
953 <PHARAON(0): copyprotection ok
953 <PHARAON(0): uciok
954 >PHARAON(0): isready
964 <PHARAON(0): readyok
Started game 1 of 1 (PHARAON vs FRUIT)
965 >PHARAON(0): ucinewgame
966 >PHARAON(0): position startpos
967 >FRUIT(1): ucinewgame
968 >FRUIT(1): position startpos
968 >PHARAON(0): isready
996 <PHARAON(0): readyok
997 >PHARAON(0): go movetime 1000
1070 <PHARAON(0): bestmove g1f3
1071 >FRUIT(1): position startpos moves g1f3
1072 >FRUIT(1): isready
1073 <FRUIT(1): readyok
1073 >FRUIT(1): go movetime 1000
1075 <FRUIT(1): info depth 1 seldepth 0 score cp 1 time 0 nodes 0 pv d7d5
1076 <FRUIT(1): info time 0 nodes 0 nps 0 cpuload 0
1077 <FRUIT(1): info hashfull 0
1078 <FRUIT(1): bestmove d7d5
1078 >PHARAON(0): position startpos moves g1f3 d7d5
1079 >PHARAON(0): isready
1106 <PHARAON(0): readyok
1107 >PHARAON(0): go movetime 1000
1226 <PHARAON(0): bestmove d2d4
1227 >FRUIT(1): position startpos moves g1f3 d7d5 d2d4
1228 >FRUIT(1): isready
1229 <FRUIT(1): readyok
1229 >FRUIT(1): go movetime 1000
1230 <FRUIT(1): info depth 1 seldepth 0 score cp 1 time 0 nodes 0 pv g8f6
1231 <FRUIT(1): info time 0 nodes 0 nps 0 cpuload 0
1232 <FRUIT(1): info hashfull 0
1233 <FRUIT(1): bestmove g8f6
1233 >PHARAON(0): position startpos moves g1f3 d7d5 d2d4 g8f6
1234 >PHARAON(0): isready
1245 <PHARAON(0): readyok
1245 >PHARAON(0): go movetime 1000
1311 <PHARAON(0): bestmove c2c4
1312 >FRUIT(1): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4
1313 >FRUIT(1): isready
1313 <FRUIT(1): readyok
1314 >FRUIT(1): go movetime 1000
1314 <FRUIT(1): info depth 1 seldepth 0 score cp 1 time 0 nodes 0 pv e7e6
1316 <FRUIT(1): info time 0 nodes 0 nps 0 cpuload 0
1317 <FRUIT(1): info hashfull 0
1318 <FRUIT(1): bestmove e7e6
1318 >PHARAON(0): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6
1319 >PHARAON(0): isready
1338 <PHARAON(0): readyok
1339 >PHARAON(0): go movetime 1000
1405 <PHARAON(0): bestmove g2g3
1405 >FRUIT(1): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3
1407 >FRUIT(1): isready
1407 <FRUIT(1): readyok
1408 >FRUIT(1): go movetime 1000
1408 <FRUIT(1): info depth 1 seldepth 0 score cp 1 time 0 nodes 0 pv d5c4
1410 <FRUIT(1): info time 0 nodes 0 nps 0 cpuload 0
1410 <FRUIT(1): info hashfull 0
1411 <FRUIT(1): bestmove d5c4
1411 >PHARAON(0): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4
1413 >PHARAON(0): isready
1432 <PHARAON(0): readyok
1433 >PHARAON(0): go movetime 1000
1482 <PHARAON(0): bestmove d1a4
1483 >FRUIT(1): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4 d1a4
1485 >FRUIT(1): isready
1485 <FRUIT(1): readyok
1486 >FRUIT(1): go movetime 1000
1486 <FRUIT(1): info depth 1 seldepth 0 score cp 1 time 0 nodes 0 pv b8d7
1488 <FRUIT(1): info time 0 nodes 0 nps 0 cpuload 0
1489 <FRUIT(1): info hashfull 0
1489 <FRUIT(1): bestmove b8d7
1490 >PHARAON(0): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4 d1a4 b8d7
1491 >PHARAON(0): isready
1510 <PHARAON(0): readyok
1511 >PHARAON(0): go movetime 1000
1566 <PHARAON(0): bestmove f1g2
1567 >FRUIT(1): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4 d1a4 b8d7 f1g2
1569 >FRUIT(1): isready
1569 <FRUIT(1): readyok
1570 >FRUIT(1): go movetime 1000
1571 <FRUIT(1): info depth 1 seldepth 0 score cp 1 time 0 nodes 0 pv a7a6
1572 <FRUIT(1): info time 0 nodes 0 nps 0 cpuload 0
1573 <FRUIT(1): info hashfull 0
1573 <FRUIT(1): bestmove a7a6
1574 >PHARAON(0): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4 d1a4 b8d7 f1g2 a7a6
1576 >PHARAON(0): isready
1604 <PHARAON(0): readyok
1605 >PHARAON(0): go movetime 1000
1667 <PHARAON(0): bestmove b1c3
1668 >FRUIT(1): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4 d1a4 b8d7 f1g2 a7a6 b1c3
1669 >FRUIT(1): isready
1670 <FRUIT(1): readyok
1671 >FRUIT(1): go movetime 1000
1673 <FRUIT(1): info depth 1 seldepth 0 score cp 1 time 0 nodes 0 pv f8e7
1674 <FRUIT(1): info time 0 nodes 0 nps 0 cpuload 0
1675 <FRUIT(1): info hashfull 0
1676 <FRUIT(1): bestmove f8e7
1676 >PHARAON(0): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4 d1a4 b8d7 f1g2 a7a6 b1c3 f8e7
1678 >PHARAON(0): isready
1682 <PHARAON(0): readyok
1682 >PHARAON(0): go movetime 1000
1740 <PHARAON(0): bestmove f3e5
1741 >FRUIT(1): position startpos moves g1f3 d7d5 d2d4 g8f6 c2c4 e7e6 g2g3 d5c4 d1a4 b8d7 f1g2 a7a6 b1c3 f8e7 f3e5
1742 >FRUIT(1): isready
1743 <FRUIT(1): readyok
1743 >FRUIT(1): go movetime 1000
1781 <FRUIT(1): info depth 1
1782 <FRUIT(1): info depth 1 seldepth 4 score cp -107 time 0 nodes 9 pv a6a5 e5c4
1784 <FRUIT(1): info depth 1 seldepth 8 score cp -41 time 0 nodes 86 pv b7b5
1787 <FRUIT(1): info depth 1 seldepth 8 time 0 nodes 270 nps 0
1788 <FRUIT(1): info depth 2
1790 <FRUIT(1): info depth 2 seldepth 10 score cp -97 time 0 nodes 649 pv b7b5 c3b5 d7e5 d4e5
1792 <FRUIT(1): info depth 2 seldepth 10 score cp -46 time 0 nodes 792 pv e8g8 e5c4
1795 <FRUIT(1): info depth 2 seldepth 10 time 16 nodes 1014 nps 0
1796 <FRUIT(1): info depth 3
1798 <FRUIT(1): info depth 3 seldepth 10 score cp -18 time 16 nodes 1261 pv e8g8 e5c4 f6g4
1800 <FRUIT(1): info depth 3 seldepth 10 time 16 nodes 1559 nps 0
1802 <FRUIT(1): info depth 4
1808 <FRUIT(1): info depth 4 seldepth 10 score cp -41 time 32 nodes 3763 pv e8g8 e5c4 d7b6 c4b6 c7b6
1816 <FRUIT(1): info depth 4 seldepth 16 time 32 nodes 6387 nps 0
1817 <FRUIT(1): info depth 5
1835 <FRUIT(1): info depth 5 seldepth 16 score cp -34 time 47 nodes 13033 pv e8g8 e5c4 c7c6 e1g1 f6d5
1909 <FRUIT(1): info depth 5 seldepth 16 score cp -27 time 125 nodes 41478 pv c7c6 e5d7 c8d7 a4c4 e8g8 c1f4
1911 <FRUIT(1): info depth 5 seldepth 16 time 125 nodes 42190 nps 0
1912 <FRUIT(1): info depth 6
2008 <FRUIT(1): info depth 6 seldepth 16 score cp 0 time 219 nodes 80552 pv c7c6 a4c4 d7e5 d4e5 f6d7 c1f4 e8g8
2027 <FRUIT(1): info depth 6 seldepth 16 time 250 nodes 87686 nps 0
2028 <FRUIT(1): info depth 7
2168 <FRUIT(1): info depth 7 seldepth 18 score cp -15 time 391 nodes 144156 pv c7c6 a4c4 d7e5 d4e5 f6d5 e1g1 e8g8 f1d1
2291 <FRUIT(1): info depth 7 seldepth 18 score cp 0 time 500 nodes 193528 pv e8g8 e5c4 c7c5 c1e3 c5d4 e3d4 d7c5 a4d1
2361 <FRUIT(1): info depth 7 seldepth 18 time 579 nodes 222914 nps 0
2362 <FRUIT(1): info depth 8
2579 <FRUIT(1): info depth 8 seldepth 20 score cp 0 time 797 nodes 318570 pv e8g8 e5d7 c8d7 a4c4 c7c6 e1g1 b7b5 c4d3 f6d5
2691 <FRUIT(1): info depth 8 seldepth 20 time 907 nodes 365608 nps 0
2692 <FRUIT(1): info depth 9
2800 <FRUIT(1): info time 1016 nodes 410000 nps 403543 cpuload 1000
2801 <FRUIT(1): info hashfull 53
2802 <FRUIT(1): info time 1016 nodes 410000 nps 403543 cpuload 1000
2803 <FRUIT(1): info hashfull 53
2804 <FRUIT(1): bestmove e8g8 ponder e5d7
2804 >PHARAON(0): isready
2805 >FRUIT(1): isready
2805 <FRUIT(1): readyok
2807 <PHARAON(0): readyok
Finished game 1 (PHARAON vs FRUIT): 1-0 {Black loses on time}
Score of PHARAON vs FRUIT: 1 - 0 - 0 [1.000] 1
ELO difference: inf
Finished match
2810 >PHARAON(0): quit
2811 >FRUIT(1): quit |
Comme vous pouvez le remarquer, Fruit a été disqualifié pour avoir dépassé le délai imparti. Pour éviter cet inconvénient, on peut utiliser l'option "timemargin" (dont la valeur s'exprime en millisecondes ) :
1 2 3 4 5
| %cc% ^
-debug ^
-engine name=PHARAON cmd=pharaon.exe dir=c:\chess\pharaon ^
-engine name=FRUIT cmd=fruit_21.exe dir=c:\chess\fruit ^
-each proto=uci st=1 timemargin=1000 > %~dpn0.log |
Cette fois, la partie va à son terme. Mais le fichier exemple2.log est trop volumineux pour être reproduit ici !
Cute Chess est également capable de produire un fichier PGN. Pour cela, il faut utiliser l'option "-pgnout" :
1 2 3 4 5
| %cc% ^
-engine name=PHARAON cmd=pharaon.exe dir=c:\chess\pharaon ^
-engine name=FRUIT cmd=fruit_21.exe dir=c:\chess\fruit ^
-each proto=uci st=1 timemargin=1000 ^
-pgnout %~dpn0.pgn > %~dpn0.log |
Voici le contenu du fichier exemple3.pgn :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| [Event "?"]
[Site "?"]
[Date "2016.01.30"]
[Round "1"]
[White "PHARAON"]
[Black "FRUIT"]
[Result "0-1"]
[ECO "A04"]
[Opening "Reti Opening"]
[PlyCount "82"]
[TimeControl "1/move"]
1. Nf3 c5 {+0.01/1 0.002s} 2. e4 d6 {+0.01/1 0.001s} 3. d4 cxd4 {+0.01/1 0.001s}
4. Nxd4 Nf6 {+0.01/1 0.001s} 5. Nc3 a6 {+0.01/1 0.001s} 6. f4
Nbd7 {+0.01/1 0.001s} 7. a4 Nc5 {+0.22/9 1.0s} 8. Bc4 {+0.03/6 0.96s}
Bg4 {+0.30/8 1.0s} 9. Nf3 {-0.02/7 1.0s} Qa5 {+0.28/8 1.0s}
10. Bd2 {0.00/6 1.0s} Qb6 {+0.53/8 1.0s} 11. Bc1 {-0.28/6 1.0s}
Ncxe4 {+0.96/8 1.0s} 12. Nxe4 {-0.51/7 1.0s} Nxe4 {+0.96/8 1.0s}
13. Bxf7+ {-0.46/7 0.77s} Kxf7 {+1.08/9 0.99s} 14. Qd5+ {-0.61/8 1.0s}
e6 {+0.88/10 1.0s} 15. Qxe4 {-0.61/8 1.0s} Be7 {+0.90/8 1.0s}
16. a5 {-0.44/7 1.1s} Qb5 {+0.82/8 1.0s} 17. Ng5+ {-0.58/6 0.69s}
Bxg5 {+1.16/9 1.0s} 18. fxg5 {-0.61/8 0.95s} Bf5 {+1.15/9 1.0s}
19. Qd4 {-0.69/7 0.76s} Rhc8 {+1.34/8 1.00s} 20. c3 {-1.84/7 1.7s}
Rc4 {+1.81/9 1.0s} 21. Qd2 {-1.91/7 0.81s} Qe5+ {+2.18/8 1.0s}
22. Kd1 {-1.66/7 1.0s} Kg8 {+2.32/7 1.0s} 23. h3 {-1.74/7 1.0s}
Rf8 {+2.37/8 1.0s} 24. g4 {-1.86/7 1.0s} Be4 {+2.63/8 1.0s}
25. Rg1 {-2.88/7 1.4s} Rf3 {+3.44/7 0.99s} 26. Qe1 {-3.24/7 1.0s}
Qd5+ {+3.30/7 1.0s} 27. Bd2 {-3.11/8 1.0s} Rxh3 {+3.42/7 1.0s}
28. Qf2 {-3.43/7 1.2s} Rf3 {+3.65/8 1.0s} 29. Qb6 {-3.28/7 1.0s}
Qd3 {+3.69/8 1.0s} 30. Ke1 {-3.51/7 1.0s} Bg6 {+8.51/7 1.0s}
31. Qd8+ {-9.19/6 0.71s} Rf8 {+13.10/9 1.0s} 32. Qxf8+ {-12.68/7 1.2s}
Kxf8 {+11.75/4 0.009s} 33. Rf1+ {-12.82/9 1.0s} Ke7 {+13.26/9 1.0s}
34. Rf4 {-13.20/9 1.0s} Qg3+ {+13.41/8 1.0s} 35. Kd1 {-13.76/9 1.0s}
Rxf4 {+M13/7 1.0s} 36. Bxf4 {-M12/11 0.69s} Qf3+ {+M11/8 1.0s}
37. Kd2 {-M10/16 0.76s} Qf2+ {+M9/13 1.0s} 38. Kd1 {-M8/35 0.70s}
Bc2+ {+M7/38 1.0s} 39. Kc1 Bb3 {+M5/39 1.00s} 40. Bxd6+ {-M4/35 0.080s}
Kxd6 {+M3/39 0.99s} 41. c4 {-M2/35 0.062s} Qc2# {+M1/38 1.0s, Black mates} 0-1 |
On peut ensuite visualiser la partie en ouvrant le fichier PGN avec ChessBase Reader (par exemple).
Il est également possible d'enregistrer les données de configuration des moteurs dans un fichier JSON, qui doit être nommé engines.json et se trouver dans le répertoire courant. Voici le mien :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| [
{
"command" : "fruit_21.exe",
"name" : "Fruit 2.1",
"protocol" : "uci",
"workingDirectory" : "c:\\chess\\fruit"
},
{
"command" : "pharaon.exe",
"name" : "Pharaon 3.5.1",
"protocol" : "uci",
"workingDirectory" : "c:\\chess\\pharaon"
}
] |
La ligne de commande devient alors :
1 2 3 4
| %cc% ^
-engine conf="Fruit 2.1" ^
-engine conf="Pharaon 3.5.1" ^
-each proto=uci st=1 timemargin=1000 > %~dpn0.log |
Cute Chess a encore d'autres options mais ce message étant déjà bien long, je vous renvoie à l'aide incluse dans le programme :
Je n'ai pas pu essayer la version graphique de Cute Chess, car les auteurs ne fournissent pas de fichier binaire pour cette version et malheureusement je ne maîtrise pas les outils nécessaires à la compilation de cette application. Si quelqu'un sait comment la compiler et veut bien le faire, sa contribution sera bienvenue.