33

I'm planning on making a program that interfaces with a UCI chess engine. I've been doing some research on it, but I want to get a little more information before I get more in depth with it. I was wondering if any of you could provide a few example "exchanges" between a UCI engine and a front-end program. I'm not really concerned with the practical interface code (like sending/receiving commands), that should be simple enough. I'm just trying to get some good examples of a small game and some options. I'm using the stockfish engine currently, but I want to be able to use multiple engines.

So anyhow, I'm looking for some examples of how to play a game over UCI.

HelloWorld123456789
  • 5,299
  • 3
  • 23
  • 33
Nathan
  • 73,987
  • 14
  • 40
  • 69
  • Have you checked [the specifications](http://www.shredderchess.com/chess-info/features/uci-universal-chess-interface.html)? `All communication is done via standard input and output with text commands`. – raina77ow Jun 08 '13 at 20:38
  • I know that, I'm looking for examples of text to play a basic game. – Nathan Jun 08 '13 at 21:15

4 Answers4

40

Let's assume the GUI is facilitating a match between a human user and an engine. Let's say the user starts with e2e4. Then the commands would look something like:

// GUI: tell the engine to use the UCI protocol
uci

// ENGINE: identify  
id name Chess Engine
id author John Smith

// ENGINE: send the options that can be changed
//         in this case the hash size can have a value from 1 to 128 MB
option name Hash type spin default 1 min 1 max 128

// ENGINE: sent all parameters and is ready
uciok

// GUI: set hash to 32 MB
setoption name Hash value 32

// GUI: waiting for the engine to finish initializing
isready

// ENGINE: finished setting up the internal values and is ready to start
readyok

// GUI: let the engine know if starting a new game
ucinewgame

// GUI: tell the engine the position to search
position startpos moves e2e4

// GUI: tell the engine to start searching
//      in this case give it the timing information in milliseconds
go wtime 122000 btime 120000 winc 2000 binc 2000

// ENGINE: send search information continuously during search
//         this includes depth, search value, time, nodes, speed, and pv line
info depth 1 score cp -1 time 10 nodes 26 nps 633 pv e7e6
info depth 2 score cp -38 time 22 nodes 132 nps 2659 pv e7e6 e2e4
info depth 3 score cp -6 time 31 nodes 533 nps 10690 pv d7d5 e2e3 e7e6
info depth 4 score cp -30 time 55 nodes 1292 nps 25606 pv d7d5 e2e3 e7e6 g1f3

// ENGINE: return the best move found
bestmove d7d5

I've simplified many aspects of the interaction. A fully featured GUI will have to support lots of other commands that you can find in the UCI specification (another source). You can also look at how existing GUIs work. For example, if you use Arena, you can hit F4 to see a log of the command interaction,

Zong
  • 6,160
  • 5
  • 32
  • 46
  • 4
    Thanks! My main question is, what next? Does the chess engine maintain an internal state of the board, or would my program keep a FEN position and simply update it based on my move(e2e4) and the engine's suggested best move? If it doesn't have an internal state, I'd manually handle the FEN board position and then call for example "position CURRENT_POSITION d2d4" and wait for the best move? Or is there some internal board state that I can update? If so how? Thanks for your help, Zong Zheng Li! – Nathan Jun 09 '13 at 07:47
  • @Nathan All engines should maintain an internal board, but the GUI is still required to send the position information before every search. You can do this with `position [FEN]` or `position startpos [move sequence]`, but the latter seems to be generally preferred. – Zong Jun 09 '13 at 17:49
  • so the full move sequence since the beginning? – Nathan Jun 09 '13 at 18:01
  • @Nathan Yes, the engine should be able to parse and perform the moves. – Zong Jun 09 '13 at 18:52
  • It doesn't seem to be working. If I give it: position startpos e2e4 e7e6 d2d4 go wtime 122000 btime 120000 winc 2000 binc 2000 it responds eventually with this: bestmove e2e4 ponder e7e6 Which doesn't make sense. I do I see/change the internal board? And is how can the engine check for legality of moves? – Nathan Jun 09 '13 at 19:18
  • (the two commands I gave were on different lines, formatting in comments here isn't the best) – Nathan Jun 09 '13 at 19:19
  • 3
    @Nathan I had a similar problem and figured out that I forgot the **`moves`** keyword in `position startpos moves e2e4`. After that a subsequent `go` command responded with a move for black. – Frank S. Thomas Jul 15 '13 at 20:31
  • @FrankS.Thomas Yes, sorry about messing that up. – Zong Jul 16 '13 at 01:23
3

I have created this gist which is the best documentation I could find -- most links I found were dead

https://gist.github.com/aliostad/f4470274f39d29b788c1b09519e67372

lenik
  • 23,228
  • 4
  • 34
  • 43
Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • This is just the official UCI spec, which is also available at https://www.shredderchess.com/chess-features/uci-universal-chess-interface.html . – balu Mar 04 '23 at 23:28
3

Reverse engineer an existing engine/GUI interaction

Install the software. Tested on Ubuntu 22.10:

sudo apt install stockfish scid moreutils

Create a stockfish wrapper:

mystockfish

#!/usr/bin/env bash
rm -f /tmp/stockfish
tee -a >( ts %.S > /tmp/stockfish-in ) |
  stockfish "$@" |
  tee -a >( ts %.S > /tmp/stockfish-out )
sort -k2 -t ' ' --version-sort \
  <( sed -r 's/^/< /' /tmp/stockfish-in ) \
  <( sed -r 's/^/> /' /tmp/stockfish-out ) \
  >/tmp/stockfish

TODO: any simpler way to get a similar ouput (interleaved I/O, with each line marked if it is I or O)? My Bash-fu is not good enough! I tried:

tee -a >( sed -r 's/^/< /' >> /tmp/stockfish ) |
  stockfish "$@" |
  tee -a >( sed -r 's/^/> /' >> /tmp/stockfish )

but then the I/O is not interleaved anymore. One day I'll figure it.

Now we point our UCI compatible UI to the helper, e.g. for scid:

  • Tools
  • Analysis Engine
  • New

and select mystockfish as the helper (either entering the full path, or just basename if you placed it in your PATH.)

Now when we start a game:

  • Play
  • Serious game
  • Optionally to make things go faster: Fixed depth: 3

Now I play the following match against stockfish:

  • e2e4 e7e5
  • d2d3 d7d5
  • f2f3 g8f6

The file /tmp/stockfish contains something like the following. I manually added a few obvious blank lines to improve readability:

< 16.582386 uci
> 16.588033 Stockfish 14.1 by the Stockfish developers (see AUTHORS file)
> 16.639218 id name Stockfish 14.1
> 16.639301 id author the Stockfish developers (see AUTHORS file)
> 16.639331 
> 16.639359 option name Debug Log File type string default 
> 16.639387 option name Threads type spin default 1 min 1 max 512
> 16.639414 option name Hash type spin default 16 min 1 max 33554432
> 16.639440 option name Clear Hash type button
> 16.639467 option name Ponder type check default false
> 16.639494 option name MultiPV type spin default 1 min 1 max 500
> 16.639521 option name Skill Level type spin default 20 min 0 max 20
> 16.639547 option name Move Overhead type spin default 10 min 0 max 5000
> 16.639574 option name Slow Mover type spin default 100 min 10 max 1000
> 16.639619 option name nodestime type spin default 0 min 0 max 10000
> 16.639647 option name UCI_Chess960 type check default false
> 16.639674 option name UCI_AnalyseMode type check default false
> 16.639701 option name UCI_LimitStrength type check default false
> 16.639728 option name UCI_Elo type spin default 1350 min 1350 max 2850
> 16.639755 option name UCI_ShowWDL type check default false
> 16.639782 option name SyzygyPath type string default <empty>
> 16.639809 option name SyzygyProbeDepth type spin default 1 min 1 max 100
> 16.639836 option name Syzygy50MoveRule type check default true
> 16.639863 option name SyzygyProbeLimit type spin default 7 min 0 max 7
> 16.639890 option name Use NNUE type check default true
> 16.639917 option name EvalFile type string default nn-13406b1dcbe0.nnue
> 16.639944 uciok

< 18.825968 isready
> 18.826010 readyok

< 18.826234 position fen rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1
< 18.826317 go depth 3
> 18.826442 info string NNUE evaluation using nn-13406b1dcbe0.nnue enabled
> 18.826703 info depth 1 seldepth 1 multipv 1 score cp -19 nodes 22 nps 22000 tbhits 0 time 1 pv e7e5
> 18.826807 info depth 2 seldepth 2 multipv 1 score cp 4 nodes 43 nps 43000 tbhits 0 time 1 pv e7e5 a2a3
> 18.827150 info depth 3 seldepth 3 multipv 1 score cp -23 nodes 135 nps 67500 tbhits 0 time 2 pv e7e5 a2a3 g8e7
> 18.827231 bestmove e7e5 ponder a2a3

< 19.847364 isready
> 19.847471 readyok

< 19.848898 position fen rnbqkbnr/pppp1ppp/8/4p3/4P3/3P4/PPP2PPP/RNBQKBNR b KQkq - 0 2
< 19.849063 go depth 3
> 19.849119 info string NNUE evaluation using nn-13406b1dcbe0.nnue enabled
> 19.849387 info depth 1 seldepth 1 multipv 1 score cp 15 nodes 34 nps 34000 tbhits 0 time 1 pv b8c6
> 19.849475 info depth 2 seldepth 2 multipv 1 score cp 39 nodes 72 nps 72000 tbhits 0 time 1 pv b8c6 b1d2
> 19.849798 info depth 3 seldepth 3 multipv 1 score cp 13 nodes 205 nps 102500 tbhits 0 time 2 pv d7d5 e4d5 d8d5
> 19.849887 bestmove d7d5 ponder e4d5

< 20.868239 isready
> 20.868378 readyok

< 20.869825 position fen rnbqkbnr/ppp2ppp/8/3pp3/4P3/3P1P2/PPP3PP/RNBQKBNR b KQkq - 0 3
< 20.869973 go depth 3
> 20.870079 info string NNUE evaluation using nn-13406b1dcbe0.nnue enabled
> 20.870387 info depth 1 seldepth 1 multipv 1 score cp 174 nodes 63 nps 63000 tbhits 0 time 1 pv f8c5 e4d5
> 20.870691 info depth 2 seldepth 2 multipv 1 score cp 198 nodes 207 nps 207000 tbhits 0 time 1 pv g8e7 e4d5
> 20.871241 info depth 3 seldepth 4 multipv 1 score cp 124 nodes 462 nps 231000 tbhits 0 time 2 pv g8f6 b1c3 f8c5 e4d5
> 20.871299 bestmove g8f6 ponder b1c3

< 22.544435 stop
< 22.544537 quit
< r value false

So from this we can see what is going on exactly.

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
0

You can use nochetoengi for this. It has an option for logging the communication with chess GUI into file.

For example, use it in PyChess as engine "nochetoengi --log-file /tmp/log.txt" and you will see all the communication.

Note: works in linux only

Petr
  • 1,159
  • 10
  • 20