XCI : Extensible Chess Interface
1 State Transition Diagram (Key States)
2 General Types
<string> ::= <word>
<string> ::= "\"" <word> (<word>)+ "\"";
- all XCI communication (not just <string> types) is UTF-8 encoded
- multiword <string> must be quoted
- example :
king-safety
- example :
"pawn shield weight"
<int> ::= ["+" | "-"] ("0" ... "9")+
<pos-int> ::= ("1" ... "9") ("0" ... "9")*
- integers can be positive, zero, or negative
- positive integers must be greater or equal to 1
- example :
-123
<id> ::= <word>
- ids function like variables/constants (in programming languages)
- example :
pawnShieldWeight
<square> ::= <file> <rank>
- example :
e1
- example :
j4
(file j in CRC)
<move> ::= <square> <square> [<promotion-type> | "k"]
<move> ::= <custom-move>
<move-list> ::= <move>+
- castling must be disambiguated in the case where the king moves only 1 square to castle
- otherwise, castling is indicated by specifying the king's from-square and to-square
- example :
d7d8q
(pawn promotion to queen)
- example :
c1h1
(h-side/O-O castling in FRC position 4k3/8/8/8/8/8/8/2K4R w K - 0 1
; note : white king and rook still on start squares)
- example :
f1g1k
(disambiguated castling in FRC position 4k3/8/8/8/8/8/8/5K1R w K - 0 1
; note : white king and rook still on start squares)
- example :
a2a3 a2a4 b2b3 b2b4
(movelist)
<score> ::= "score" (("cp" <int>) | ("mate" <int>)) ["lowerbound" | "upperbound"]
- always from engine's point of view
- example :
score cp 120
(exactly 120 centipawns = 1.20 pawns)
- example :
score cp 120 lowerbound
(at least 120 centipawns)
- example :
score mate 4
(mate in 4 moves--not plies)
- example :
score mate -3
(opponent can mate in 3 moves)
<position> ::= <x-fen>
<position> ::= <custom-position>
- X-FEN position encoding (for Standard/FRC/CRC)
- reference : Reinhard Scharnagl http://www.chessbox.de/
- example :
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
(Standard starting position)
- example :
4k3/8/8/8/8/8/8/2K2RR1 w Kg - 0 1
(disambiguates which rook white can castle h-side/O-O by specifying the file; note : white rook on f1 is not on its start square)
<annotation> ::= "!!" | "!" | "!?" | "?!" | "?" | "??" | "normal"
- used for possible annotation of book moves
- convention :
!!
> !
> !?
> normal
> ?!
> ?
> ??
<custom-info> ::= "name" <id> "value" <value>
- used for custom engine output in thinking info or book info
- example :
info ... name MoveOrderPercentage value 98
<result> ::= "1-0" | "0-1" | "1/2-1/2" | "inprogress" | "*"
- example :
1-0
(white wins)
- example :
0-1
(black wins)
- example :
1/2-1/2
(draw)
- example :
inprogress
(game is still in progress)
- example :
*
(game is over but no result)
<value> ::= <int> | <id> | <string> | "true" | "false" | <searchpath>
- used for setting option values, custom output values, translations
- example :
452
(int)
- example :
king-safety
(id)
- example :
engine.log
(string, e.g., filename for log file)
- example :
true
(value for check/boolean type)
- example :
c:\chess\tb;d:\tb
(searchpath)
<searchpath> ::= <string> (";" <string>)*
- used for specifying options like tablebase search path
- example :
c:\chess\tb;d:\tb
3 Commands from GUI to Engine
xci
<xci-command> ::= "xci"
- engine should switch to XCI mode, perform any initialization, enter WAIT state
- response :
readyok
(after ready to process further commands)
level
<level-command> ::= <time-control>
<level-command> ::= "white" <time-control> "black" <time-control>
<time-control> ::= (<tournament-control>)+ [<sudden-death-control>] ["ponder"]
<time-control> ::= <sudden-death-control> ["ponder"]
<tournament-control> ::= <pos-int> "/" <pos-int> ["+" <pos-int>]
<sudden-death-control> ::= <int> ["+" <pos-int>]
- tells engine full time control information
- times are in seconds
- increments are added before the move
- ponder option indicates that engine will be allowed to ponder during opponents turn
- white/black option allows for different time controls for white and black ("time odds")
- if level does not end with sudden-death control, the last tournament control is assumed to repeat
- example :
level 40/300
(40 moves in 300 seconds, repeating, both colors, no pondering)
- example :
level 40/300+12 ponder
(40/300 plus 12 second increment before each move, repeating, both colors, pondering)
- example :
level 40/300 40/300 300+5
(40/300, 40/300, game in 300 seconds plus 5 second increment, both colors, no pondering)
- example :
level white 300+12 ponder black 10
(white : G/300+12 pondering, black : G/10 (seconds!) no pondering)
setoption
<setoption-command> ::= "setoption" "name" <id> "value" <value>
<setoption-command> ::= "setoption" "name" <id> ("input" <id> "value" <value>)*
- set a particular value for an option
- input/value pairs are specified when a button-type option requested those inputs from the user
- example :
setoption name king-safety value 90
- example :
setoption name king-safety value 90
- example :
setoption name playingStyle value styleRisky
- example :
setoption name VerballyAnnotateGame input gameFile value c:\temp\game1.pgn input analysisDepth value 4
position
<position-command> ::= (<position> | "startpos")
- set new position
- engine can infer that new game (or game fragment) has started (i.e., it's as if received
result *
)
- example :
position startpos
(starting position for current variant)
- example :
position nbqrkrbn/pppppppp/8/8/8/8/PPPPPPPP/NBQRKRBN w KQkq - 0 1
(possible FRC start position)
result
<result-command> ::= "result" <result> ["{" <string> "}"]
- signals end of current game
- engine can perform (book) learning at this point
- example :
result 1-0 {Black resigns}
(white wins because black resigns)
go
<go-move-command> ::= "go" "move" <move>
<go-undo-command> ::= "go" "undo"
<go-think-command> ::= "go" "think" <go-time-info> <go-constraint-info> ["drawoffer"]
<go-ponder-command> ::= "go" "ponder" ["suggestedmove" <move>]
<go-analyze-command> ::= "go" "analyze" <go-constraint-info>
<go-continue-command> ::= "go" "continue" "move" <move> <go-time-info> <go-constraint-info> ["drawoffer"]
<go-time-info> ::= "wtime" <int> "btime" <int> "winc" <int> "binc" <int> "movestogo" <int>
<go-constraint-info> ::= ["searchmoves" <move-list>] ["depth" <int>] ["nodes" <int>] ["mate" <int>] ["movetime" <int>]
- either update internal board or start a computation
- times are in milliseconds (ms)
- depth is in plies
- mate target depth is in moves
- searchmoves limits search to the following movelist (optional?)
-
go move
- make move on internal board
- engine doesn't start thinking
-
go undo
- undo last move on internal board
- engine doesn't start thinking
-
go think
- start computing best move
- response :
info ...
(book line, thinking lines, status updates)
- response :
offerdraw
(note : continue thinking)
- response :
acceptdraw
(allowed if drawoffer
specified; note : continue thinking)
- response :
claimdraw
(note : continue thinking)
- response :
bestmove ...
(final response after stop
received or a search constraint is met)
- example :
go think wtime ... btime ... winc ... binc ... movestogo ... drawoffer
-
go ponder
- start pondering (thinking on opponent's time)
- a suggested ponder move might be suggested (but engine is not required to use the suggestion)
- response :
info pondermove ...
(current pondermove, i.e., prediction of opponent's next move)
- response :
info ...
(book line, thinking lines, status updates)
- response :
readyok
(final response if stop
received)
- example :
go ponder
- example :
go ponder suggestedmove ...
-
go analyze
- start analyzing position
- allows engine's analysis thinking to be different from game thinking (e.g., symmetric vs asymmetric evaluation)
- response :
info ...
(book line, thinking lines, status updates)
- response :
bestmove ...
(final response after stop
received or a search constraint is met)
- example :
go analyze
(infinite analysis)
- example :
go analyze depth 12
(analyze up to depth 12)
-
go continue
- engine makes move on internal board and enters THINK state
- sent while engine is pondering to give engine a chance to continue current search "in place" (e.g., if engine's pondermove was correct)
- updated time and drawoffer information and is also sent to engine
- example :
go continue move ... wtime ... btime ... winc ... binc ... movestogo ... drawoffer
get
<get-command> ::= "get" ("book" | "startpos" | "movelist" | "result" | "pieceplacement" | "boardsize")
- get info from engine
-
get book
- get book info from engine
- response :
info book ...
-
get startpos
- get a legal starting position info from engine
- useful when GUI doesn't officially support variant and needs to use an engine as the "referee"
- response :
info startpos ...
-
get movelist
- get list of legal moves from engine
- useful when GUI doesn't officially support variant and needs to use an engine as the "referee"
- response :
info movelist ...
-
get result
- get result from engine
- useful when GUI doesn't officially support variant and needs to use an engine as the "referee"
- response :
info result ...
-
get pieceplacement
- get current placement of pieces from engine (i.e., first field of X-FEN)
- useful when GUI doesn't officially support variant and needs to use an engine as the "referee"
- response :
info pieceplacement ...
-
get boardsize
- get a legal starting position info from engine
- useful when GUI doesn't officially support variant and needs to use an engine as the "referee"
- response :
info boardsize ...
isready
<isready-command> ::= "isready"
- used for synchronizing engine and GUI
- engine should respond immediately when in THINK, PONDER, or ANALYZE state
- engine should respond only after processing all prior commands when in WAIT state
- response :
readyok
stop
<stop-command> ::= "stop"
- engine should stop computation as soon as possible
- response :
bestmove ...
(if in THINK or ANALYZE state)
- response :
readyok
(if in PONDER state)
quit
<quit-command> ::= "quit"
- engine should quit (shut down, exit) as soon as possible
4 Commands from Engine to GUI
readyok
<readyok-command> ::= "readyok"
- used for synchronizing engine and GUI
- sent in response to
isready
acceptdraw
<acceptdraw-command> ::= "acceptdraw"
- accepts opponent's draw offer while in THINK state (if previous
go think
or go continue
command contained a drawoffer
)
- note : engine continues to think and assumes game has not ended yet (in case offer was withdrawn)
offerdraw
<offerdraw-command> ::= "offerdraw"
- offer draw to opponent while in THINK state
- the draw offer is valid for one move (i.e., can be accepted during opponent's next think)
- note : engine continues to think and assumes game has not ended yet (since opponent might not except draw)
claimdraw
<claimdraw-command> ::= "claimdraw"
- claim (optional) draw by 3-fold repetition or 50-move rule while in THINK state
- note : engine continues to think and assumes game has not ended yet (since claim might not be correct)
- note : engine must send a best move that leads to the draw for the claim to be valid (if draw position is about to appear)
resign
<resign-command> ::= "resign"
- resign while in THINK state
- note : engine stops thinking and enters WAIT state
message
<message-command> ::= "message" ("error" | "comment") <id>
- send message from engine to user
- after sending an error, engine enters WAIT state
- comments might be used for explaining why engine is resigning, declining draw offer, etc.
- comments might be used for chatter with the (human) user
- example :
message error unknown-command
- example :
message comment rejectDrawTooEarly
bestmove
<bestmove-command> ::= "bestmove" <move>
- send best move after thinking in THINK or ANALYZE state
- must be sent if engine receives a
stop
command or a search constraint (e.g., number of nodes) is met
- example :
bsetmove e2e4
info
<info-command> ::= "info" "book" "XCI_null"
<info-command> ::= "info" "book" ("move" <move> (<book-move-info>)*)+
<book-move-info> ::= "winpercentage" <int>
<book-move-info> ::= "playpercentage" <int>
<book-move-info> ::= "count" <int>
<book-move-info> ::= "wins" <int>
<book-move-info> ::= "losses" <int>
<book-move-info> ::= "draws" <int>
<book-move-info> ::= "annotation" <annotation>
<book-move-info> ::= "score" <score>
<book-move-info> ::= <custom-info>
<info-command> ::= "info" "startpos" (<position> | "XCI_null")
<info-command> ::= "info" "movelist" (<move-list> | "XCI_null")
<info-command> ::= "info" "result" (<result> | "XCI_null")
<info-command> ::= "info" "pieceplacement" (<pieceplacement> | "XCI_null")
<info-command> ::= "info" "boardsize" ((<int> "x" <int>) | "XCI_null")
<info-command> ::= "info" (<pv-info>)* (<status-info>)* (<custom-info>)* ["string" <string>]
<info-command> ::= "pondermove" <move>
<pv-info> ::= "depth" <int>
<pv-info> ::= "seldepth" <int>
<pv-info> ::= "time" <int>
<pv-info> ::= "nodes" <int>
<pv-info> ::= "pv" <move-list>
<pv-info> ::= "multipv" <int> <move-list>
<pv-info> ::= "hashpv" <move-list>
<pv-info> ::= <score>
<status-info> ::= "currmove" <move>
<status-info> ::= "currmovenumber" <int>
<status-info> ::= "refutation" <move> <move-list>
<status-info> ::= "currline" <int> <move-list>
<status-info> ::= "currline" <move-list>
<status-info> ::= "hashfull" <int>
<status-info> ::= "nps" <int>
<status-info> ::= "tbhits" <int>
<status-info> ::= "cpuload" <int>
- display search (or other) information
-
info book | startpos | movelist | result | pieceplacement | boardsize
- display book or other information in response to
get ...
command
- example :
info book XCI_null
(no book information available for this position)
- example :
info book move e2e4 wins 10 losses 6 draws 4 move d2d4 wins 8 losses 6 draws 5
- example :
info startpos XCI_null
(engine cannot provide start position)
- example :
info startpos rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
(Standard start position)
- example :
info movelist XCI_null
(engine cannot provide list of legal moves)
- example :
info movelist a2a3 a2a4 b2b3 b2b4 ...
- example :
info result XCI_null
(engine cannot provide result)
- example :
info result inprogress
(game still in progress)
- example :
info pieceplacement XCI_null
(engine cannot provide piece placement)
- example :
info pieceplacement rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR
- example :
info boardsize XCI_null
(engine cannot provide board size)
- example :
info boardsize 10x8
(board is 10 files by 8 ranks)
-
thinking/status lines
- display thinking or other status information while in THINK, ANALYZE, or PONDER state
- should send all info related to a particular pv in one
info
command
- when sending pvs in thinking lines while in PONDER state, include the ponder move as the first move of the pv
- example :
info ... depth 12 ...
(search depth is 12 plies)
- example :
info ... seldepth 17 ...
(selective depth is 17 plies)
- example :
info ... score cp 50 ...
(score is 50 centipawns (0.5 pawns) from engine's point of view)
- example :
info ... time 2450 ...
(time searched is 2450 milliseconds (ms))
- example :
info ... nodes 12050 ...
(nodes searched is 12050 nodes)
- example :
info ... pv e2e4 e7e5 g1f3
(list of moves in principle variation)
- example :
info ... multipv 2 d2d4 d7d5 c2c4
(list of moves in 2nd best principle variation)
- example :
info ... hashpv e4e5 f6d5
(portion of principle variation from hash table; not already included in pv ...
part)
- example :
info pondermove e7e5
(engine is pondering on e7e5)
- example :
info currmove e7e5 currmovenumber 1
(engine is searching e7e5, which is 1st move)
- example :
info refutation e4e5 f6g4 ...
(move e4e5 is refuted by line starting with f6g4)
- example :
info currline 2 e2e4 e7e5 ...
(engine is searching line e2e4 e7e5 on CPU number 2)
- example :
info ... hashfull 94 ...
(hash table is 94% full)
- example :
info ... nps 102177 ...
(engine is searching 102177 nodes per second)
- example :
info ... tbhits 2040 ...
(engine had 2040 endgame tablebase hits)
- example :
info ... cpuload 985 ...
(engine had 985 permill of CPU load = 98.5%)
5 Options File and Translations
option
<option-command> ::= "option" "name" <id> "type" <option-type> "description" <id>
<option-type> ::= "check" "default" ("true" | "false")
<option-type> ::= "spin" "default" <int> "min" <int> "max" <int>
<option-type> ::= "combo" "default" <id> ("var" <id>)+
<option-type> ::= "button" ("input" <id>)* ["output"]
<option-type> ::= "string" ["default" <string>]
<option-type> ::= "searchpath" ["default" <searchpath>]
<option-type> ::= "filename" ["default" <string>]
<input-type> ::= "input" "name" <id> "type" <option-type> "prompt" <id>
- tell GUI what parameters can be changed in the engine
- these options are stored in a file called
options.xci
button
options are more like "commands" send to the engine
button
commands can request input from the user (that the GUI will get)
button
commands can specify that they will generate output (info string ...
lines followed by readyok
)
- example :
option name anti-human type check default false description anti-human-description
- example :
option name kingSafety type check min 10 max 200 default 100 description kingSafetyDescription
- example :
option name playing-style type combo default style-normal var style-normal var style-solid var style-agressive description playing-style-description
- example :
input name analysisDepth type spin default 3 min 1 max 100 prompt depthPrompt
- example :
option name VerballyAnnotateGame type button input analysisDepth description annotateDescription
info
<info-command> ::= "info" "name" <id> "description" <id>
- define a custom information type (for book info or thinking lines)
- these custom types are stored in a file called
options.xci
- example :
info name moveOrderPercent description moveOrderDescription
message
<message-command> ::= "message" "name" <id>
- define a message id
- example :
message name rejectDrawTooEarly
(message engine would send if rejecting draw)
translation
<translation-command> ::= <id> <string>
- all custom IDs defined by the engine can have translations contained in files named
options.xy
where xy
is the two-character ISO639 language code (e.g., en
for English)
- GUI infers supported languages by looking for translation files in same directory as engine executable
- example :
XCI_Name "Simple Engine 1.0"
(line in options.en
)
- example :
king-safety "King Safety"
(line in options.en
)
- example :
rejectDrawTooEarly "Sorry, the game's just begun!"
(line in options.en
)
6 Standard Options/IDs
Options
- these are standard options with standard meanings
- if the engine includes one or more of these options in its
options.xci
file, it means that the engine supports them
- note : the GUI should not display "XCI" prefix
- note : the GUI doesn't need to display
XCI_OpponentName/Computer/Rating
,
XCI_Hash
, type spin (size of hash/transposition table)
XCI_ClearHash
, type button (clear hash/transposition table)
XCI_NalimovPath
, type searchpath (endgame tablebase paths)
XCI_NalimovCache
, type spin (endgame tablebase cache)
XCI_OwnBook
, type check (use own opening book)
XCI_MultiPV
, type spin, default 1 (display k-best pvs)
XCI_ShowCurrLine
, type check, default false (display current line)
XCI_ShowRefutations
, type check, default false (display refutations)
XCI_LimitStrength
, type check, default false (limit playing strength to XCI_Elo
)
XCI_Elo
, type spin (only applies when XCI_LimitStrength
is true)
XCI_OpponentName
, type string (name of opponent)
XCI_OpponentComputer
, type check (opponent is computer--not human)
XCI_OpponentRating
, type spin (rating of opponent)
XCI_Variant
, type combo var Standard var FRC var CRC ... (chess variant)
IDs
XCI_Name
(engine's name)
XCI_Author
(author)
XCI_Country
(country)
XCI_About
(description)