UCI protocol for chess variants

Discussion of chess software programming and technical issues.

Moderators: hgm, chrisw, Rebel

User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

UCI protocol for chess variants

Post by Evert »

The UCI protocol was originally intended to allow chess engines (or to be explicit, orthochess engines) to communicate with a GUI. It was later slightly expanded to allow for Fischer chess (or Chess960), but that is the extent to which its chess variant support goes.

There exist at least two variations of UCI, one for Shogi (USI, originally by Tord Romstad) and one for Xiangqi (UCCI, originally by Huang Chen, I think) although apparently both can be played through variations of normal UCI as well.

There is also at least some interest in UCI engines that play (slightly modified) versions of regular chess (for instance the special Stockfish version discussed in http://www.talkchess.com/forum/viewtopic.php?t=53885).

My goal for this thread is two-fold:
  • To collect in one place, for easy reference, a description of the different UCI dialects, how they differ and how they are similar.
  • To propose, further down, a mechanism by which UCI could be used to play chess variants
This second part is not fully formed in all the details, and needs some input and discussion. Now, the XBoard protocol already exists for handing chess variants and it might be easier if everyone just adopted that. However, this is not what happens in practice: instead slight variations of UCI are developed, or variant engines communicate through UCI without being able to to communicate what variant they play. What is certainly not needed is any further proliferation of slight variations on existing protocols and different incompatible ways to do the same thing (like selecting a particular variant).
Ultimately, I hope that this will encourage more people to develop chess variant engines.

To play a chess variant, two things are needed: an engine that plays it, and a GUI that can communicate with it. Clearly, there are currently no UCI GUIs that really support chess variants, but I hope that defining a way for UCI engines to use variants can be a first step to changing that.
Probably the first GUI that would support UCI chess variant engines would actually be XBoard.

So, to kick off, here is my unified description of UCI/USI/UCCI (which is basically an edit of the original UCI spec with the differences spliced in). The most current version can be found at http://www.eglebbk.dds.nl/ustari_protocol.txt

Code: Select all

Nomenclature
------------

 UCI:
	players are called "white" and "black". White begins.
	squares are labelled a1,b1,...g8,h8, from lower left to upper right.
   Pieces are "PNBRQK", upper case for white and lower case for black.

 USI:
	players are called "white" and "black". Black begins.
	squares are labelled 9i,8i...2a,1a, from lower left to upper right.
   Pieces are "PLNSGBRK", upper case for black and lower case for white.
   (This actually matches UCI in that upper case is for the side that moves
   first).
   Promoted pieces are preceded by a "+" (so +P, +R).

 UCCI:
	players are called "white" and "black". White begins.
	squares are labelled a0,b0,...h9,i9, from lower left to upper right.
   Pieces are "PABNCRK", upper case for white and lower case for black.

Move format
-----------

In all cases, moves are encoded as <from square><to square>[<suffix>]. The
squares are encoded as mentioned above. The suffix is optional and used to
indicate promotions: it is the (lower case) letter of the promotion choice
in chess and a + in Shogi (where there is only one choice). Xiangqi doesn't
have promotions as such.

Castling is encoded as a two-step king move, or as "KxR" for Fischer chess.

Piece drops are encoded as <token>*<square>, where <token> is the upper
case piece letter and <square> is the drop square.


From GUI to engine
------------------

* uci, usi, ucci
	tell engine to use the uci (universal chess interface) or one of its
	dialects, this will be sent once as a first command after program boot
	to tell the engine to switch to uci mode.
	After receiving the uci command the engine must identify itself with the "id" command
	and send the "option" commands to tell the GUI which engine settings the engine supports if any.
	After that the engine should send "uciok" ("usiok", "ucciok") to acknowledge the uci mode.
	If no uciok is sent within a certain time period, the engine task will be killed by the GUI.

	In ucci mode, the list of options should at least include
	   "option usemillisec type check default false"
	   "option newgame type button"

* debug [ on | off ]
	switch the debug mode of the engine on and off.
	In debug mode the engine should send additional infos to the GUI, e.g. with the "info string" command,
	to help debugging, e.g. the commands that the engine has received etc.
	This mode should be switched off by default and this command can be sent
	any time, also when the engine is thinking.

* isready
	this is used to synchronize the engine with the GUI. When the GUI has sent a command or
	multiple commands that can take some time to complete,
	this command can be used to wait for the engine to be ready again or
	to ping the engine to find out if it is still alive.
	E.g. this should be sent after setting the path to the tablebases as this can take some time.
	This command is also required once before the engine is asked to do any search
	to wait for the engine to finish initializing.
	This command must always be answered with "readyok" and can be sent also when the engine is calculating
	in which case the engine should also immediately answer with "readyok" without stopping the search.

* setoption name <id> [value <x>]         (UCI, USI)
	this is sent to the engine when the user wants to change the internal parameters
	of the engine. For the "button" type no value is needed.
	One string will be sent for each parameter and this will only be sent when the engine is waiting.
	The name and value of the option in <id> should not be case sensitive
	and can inlude spaces in UCI (but not in USI).
	The substrings "value" and "name" should be avoided in <id> and <x> to allow unambiguous parsing,
	for example do not use <name> = "draw value".
	Here are some strings for the example below:
	   "setoption name Nullmove value true\n"
	   "setoption name Selectivity value 3\n"
	   "setoption name Style value Risky\n"
	   "setoption name Clear Hash\n"
	   "setoption name NalimovPath value c:\chess\tb\4;c:\chess\tb\5\n"

* setoption <id> [<x>]         (UCCI)
	this is sent to the engine when the user wants to change the internal parameters
	of the engine. For the "button" type no value is needed.
	One string will be sent for each parameter and this will only be sent when the engine is waiting.
	The name and value of the option in <id> should not be case sensitive and can NOT inlude spaces.
	The name should preferentially be all in lower case.
	Here are some strings for the example below:
	   "setoption nullmove true\n"
	   "setoption selectivity 3\n"
	   "setoption style Risky\n"
	   "setoption clear Hash\n"
	   "setoption nalimovpath c:\chess\tb\4;c:\chess\tb\5\n"

* register
	this is the command to try to register an engine or to tell the engine that registration
	will be done later. This command should always be sent if the engine	has sent "registration error"
	at program startup.
	The following tokens are allowed:
	* later
	   the user doesn't want to register the engine now.
	* name <x>
	   the engine should be registered with the name <x>
	* code <y>
	   the engine should be registered with the code <y>
	Example:
	   "register later"
	   "register name Stefan MK code 4359874324"

* ucinewgame, usinewgame      (UCI, USI)
	this is sent to the engine when the next search (started with "position" and "go") will be from
	a different game. This can be a new game the engine should play or a new game it should analyse but
	also the next position from a testsuite with positions only.
	If the GUI hasn't sent a "ucinewgame" before the first "position" command, the engine shouldn't
	expect any further ucinewgame commands as the GUI is probably not supporting the ucinewgame command.
	So the engine should not rely on this command even though all new GUIs should support it.
	As the engine's reaction to "ucinewgame" can take some time the GUI should always send "isready"
	after "ucinewgame" to wait for the engine to finish its operation.

* setoption newgame           (UCCI)
	See usinewgame above.
	Note that the engine most define this option for it to be sent.

* position [fen <fenstring> | startpos ]  moves <move1> .... <movei>    (UCI)
	set up the position described in fenstring on the internal board and
	play the moves on the internal chess board.
	if the game was played  from the start position the string "startpos" will be sent
	Note: no "new" command is needed. However, if this position is from a different game than
	the last position sent to the engine, the GUI should have sent a "ucinewgame" inbetween.

* fen <fenstring> moves <move1> .... <movei>    (UCI-cyclone)
	As "position fen" above.

* position [sfen <fenstring> | startpos ]  moves <move1> .... <movei>   (USI)
	as above, but sends sfen rather than FEN. Moves use Shogi-style square
	names.
	To be safe, it is better to not use startpos at all (not all engines
	understand it) and always set the postion using a FEN string.

* position fen <fenstring> moves <move1> .... <movei>                   (UCCI)
	as above. Uses normal FEN for Xiangqi (with piece names RNBACPK). Moves
	use Western-style square names. The square on the lower-left hand side
	of the first player ("white") is "a0", the upper-right is "i9".
	The FEN string includes fields for en-passant and castling (both -,
	obviously).
	Normally, the interface is expected to send the FEN for the position
	after the last irreversible move, and the move history from that point
	onward. This to reduce the amount of traffic between engine and GUI.
	Note there is no "startpos"!

* probe [ fen <fenstring> | startpos ] moves <move1> .... <movei> (UCCI)
	Tell the engine to spit out whatever it found about the current position
	in its hash table (using the "pophash" response). Apparently for
	debugging only. For some reason "startpos" is possible here (probably a
	mistake).

* banmoves <move1> .... <movei>  (UCCI)
	exclude the listed moves from consideration in the current position.
	This is useful for analysis, but the GUI may also use this to send moves
	that represent illegal chases. This allows engines to not implement the
	(full) chasing rules, and rely on the GUI instead.

* go                             (UCI, USI, UCCI)
	start calculating on the current position set up with the "position" command.
	There are a number of commands that can follow this command, all will be sent in the same string.
	If one command is not sent its value should be interpreted as it would not influence the search.
	* searchmoves <move1> .... <movei>
		restrict search to this moves only
		Example: After "position startpos" and "go infinite searchmoves e2e4 d2d4"
		the engine should only search the two moves e2e4 and d2d4 in the initial position.
	* draw         (UCCI)
		The engine has received a draw offer.
	* ponder
		start searching in pondering mode.
		Do not exit the search in ponder mode, even if it's mate!
		This means that the last move sent in in the position string is the ponder move.
		The engine can do what it wants to do, but after a "ponderhit" command
		it should execute the suggested move to ponder on. This means that the ponder move sent by
		the GUI can be interpreted as a recommendation about which move to ponder. However, if the
		engine decides to ponder on a different move, it should not display any mainlines as they are
		likely to be misinterpreted by the GUI because the GUI expects the
		engine to ponder on the suggested move.
	* wtime <x>          (UCI, USI)
		white has x msec left on the clock
	* btime <x>          (UCI, USI)
		black has x msec left on the clock
	* winc <x>           (UCI, USI)
		white increment per move in mseconds if x > 0
	* binc <x>           (UCI, USI)
		black increment per move in mseconds if x > 0
	* movestogo <x>      (UCI, USI)
		there are x moves to the next time control,
		this will only be sent if x > 0,
		if you don't get this and get the wtime and btime it's sudden death
	* movestogo <x>      (UCCI)
		there are x moves to the next time control,
		if x = 0 it's sudden death
	* time <x>           (UCCI)
		side to move has x left on the clock
		x is in s, unless the GUI has sent "option usemillisec true", in
		which case it is msec
	* opptime <x>        (UCCI)
		side not on move has x left on the clock
		x is in s, unless the GUI has sent "option usemillisec true", in
		which case it is msec
	* increment <x>      (UCCI)
		side-to-move increment per move in s or msec
	* oppincrement <x>   (UCCI)
		not side-to-move increment per move in s or msec
	* oppmovestogo <x>   (UCCI)
		the opponent has x moves to the next time control
	* depth <x>
		search x plies only.
	* nodes <x>
		search x nodes only,
	* mate <x>
		search for a mate in x moves
	* movetime <x>
		search exactly x mseconds
	* byoyomi <x>        (USI)
		search exactly x mseconds if the time (specified by
		wtime/btime) has been used up
	* infinite
		search until the "stop" command. Do not exit the search without being told so in this mode!

* stop
	stop calculating as soon as possible,
	don't forget the "bestmove" and possibly the "ponder" token when finishing the search

* ponderhit
	the user has played the expected move. This will be sent if the engine was told to ponder on the same move
	the user has played. The engine should continue searching but switch from pondering to normal search.

* ponderhit draw        (UCCI)
	Accept a draw offer while pondering.

* quit
	quit the program as soon as possible

* bye                   (UCCI)
	finish the calculation, then quit




Engine to GUI:
--------------

* id
	* name <x>
		this must be sent after receiving the "uci" command to identify the engine,
		e.g. "id name Shredder X.Y\n"
	* author <x>
		this must be sent after receiving the "uci" command to identify the engine,
		e.g. "id author Stefan MK\n"

* uciok, usiok, ucciok
	Must be sent after the id and optional options to tell the GUI that the engine
	has sent all infos and is ready in uci mode.

* readyok
	This must be sent when the engine has received an "isready" command and has
	processed all input and is ready to accept new commands now.
	It is usually sent after a command that can take some time to be able to wait for the engine,
	but it can be used anytime, even when the engine is searching,
	and must always be answered with "isready".

* bestmove <move1> [ ponder <move2> ]
	the engine has stopped searching and found the move <move> best in this position.
	the engine can send the move it likes to ponder on. The engine must not start pondering automatically.
	this command must always be sent if the engine stops searching, also in pondering mode if there is a
	"stop" command, so for every "go" command a "bestmove" command is needed!
	Directly before that the engine should send a final "info" command with the final search information,
	the the GUI has the complete statistics about the last search.

* bestmove <move1> [ ponder <move2> ] [ draw | resign ]  (UCCI)
	as "bestmove" above, but includes a draw offer or resignation by the engine.

* bestmove [ draw | resign ]  (UCCI)
	the engine accepts a draw offer, or resigns.

* nobestmove         (UCCI)
	The search returned no move. Either there are no legal moves (the game
	ended), or the engine was interrupted before it could produce a move.
	Also sent in response to "go depth 0", which prompts the engine to spit
	out its static evaluation of the current position.

* pophash [bestmove <move>] [lowerbound <beta> depth <depth>] [upperbound <alpha> depth <depth>]   (UCCI)
	Response to "probe". Whatever the engine found in its transposition
	table for the current position. Again apparetly meant as a debugging
	aid.
	If the position was not found, leave all fields blank.

* copyprotection
	this is needed for copyprotected engines. After the uciok command the engine can tell the GUI,
	that it will check the copy protection now. This is done by "copyprotection checking".
	If the check is ok the engine should send "copyprotection ok", otherwise "copyprotection error".
	If there is an error the engine should not function properly but should not quit alone.
	If the engine reports "copyprotection error" the GUI should not use this engine
	and display an error message instead!
	The code in the engine can look like this
	   TellGUI("copyprotection checking\n");
	   // ... check the copy protection here ...
	   if(ok)
	      TellGUI("copyprotection ok\n");
	   else
	      TellGUI("copyprotection error\n");

* registration
	this is needed for engines that need a username and/or a code to function with all features.
	Analog to the "copyprotection" command the engine can send "registration checking"
	after the uciok command followed by either "registration ok" or "registration error".
	Also after every attempt to register the engine it should answer with "registration checking"
	and then either "registration ok" or "registration error".
	In contrast to the "copyprotection" command, the GUI can use the engine after the engine has
	reported an error, but should inform the user that the engine is not properly registered
	and might not use all its features.
	In addition the GUI should offer to open a dialog to
	enable registration of the engine. To try to register an engine the GUI can send
	the "register" command.
	The GUI has to always answer with the "register" command	if the engine sends "registration error"
	at engine startup (this can also be done with "register later")
	and tell the user somehow that the engine is not registered.
	This way the engine knows that the GUI can deal with the registration procedure and the user
	will be informed that the engine is not properly registered.


* info
	the engine wants to send information to the GUI. This should be done whenever one of the info has changed.
	The engine can send only selected infos or multiple infos with one info command,
	e.g. "info currmove e2e4 currmovenumber 1" or
	     "info depth 12 nodes 123456 nps 100000".
	Also all infos belonging to the pv should be sent together
	e.g. "info depth 2 score cp 214 time 1242 nodes 2124 nps 34928 pv e2e4 e7e5 g1f3"
	I suggest to start sending "currmove", "currmovenumber", "currline" and "refutation" only after one second
	to avoid too much traffic.
	Additional info:
	* depth <x>
		search depth in plies
	* seldepth <x>
		selective search depth in plies,
		if the engine sends seldepth there must also be a "depth" present in the same string.
	* time <x>
		the time searched in ms, this should be sent together with the pv.
	* nodes <x>
		x nodes searched, the engine should send this info regularly
	* pv <move1> ... <movei>
		the best line found
	* multipv <num>
		this for the multi pv mode.
		for the best move/pv add "multipv 1" in the string when you send the pv.
		in k-best mode always send all k variants in k strings together.
	* score
		* cp <x>
			the score from the engine's point of view in centipawns.
		* mate <y>
			mate in y moves (UCI) or plies (USI).
			If the engine is getting mated use negative values for y.
		* lowerbound
	      the score is just a lower bound.
		* upperbound
		   the score is just an upper bound.
	* currmove <move>
		currently searching this move
	* currmovenumber <x>
		currently searching move number x, for the first move x should be 1 not 0.
	* hashfull <x>
		the hash is x permill full, the engine should send this info regularly
	* nps <x>
		x nodes per second searched, the engine should send this info regularly
	* tbhits <x>
		x positions where found in the endgame table bases
	* sbhits <x>
		x positions where found in the shredder endgame databases
	* cpuload <x>
		the cpu usage of the engine is x permill.
	* string <str>
		any string str which will be displayed be the engine,
		if there is a string command the rest of the line will be interpreted as <str>.
	* refutation <move1> <move2> ... <movei>
	   move <move1> is refuted by the line <move2> ... <movei>, i can be any number >= 1.
	   Example: after move d1h5 is searched, the engine can send
	   "info refutation d1h5 g6h5"
	   if g6h5 is the best answer after d1h5 or if g6h5 refutes the move d1h5.
	   if there is no refutation for d1h5 found, the engine should just send
	   "info refutation d1h5"
		The engine should only send this if the option "UCI_ShowRefutations" is set to true.
	* currline <cpunr> <move1> ... <movei>
	   this is the current line the engine is calculating. <cpunr> is the number of the cpu if
	   the engine is running on more than one cpu. <cpunr> = 1,2,3....
	   if the engine is just using one cpu, <cpunr> can be omitted.
	   If <cpunr> is greater than 1, always send all k lines in k strings together.
		The engine should only send this if the option "UCI_ShowCurrLine" is set to true.
	* message <message>  (UCCI)
	   Whatever other information the engine wants to tell the user. The GUI
	   can display this somewhere.


* option
	This command tells the GUI which parameters can be changed in the engine.
	This should be sent once at engine startup after the "uci" and the "id" commands
	if any parameter can be changed in the engine.
	The GUI should parse this and build a dialog for the user to change the settings.
	Note that not every option needs to appear in this dialog as some options like
	"Ponder", "UCI_AnalyseMode", etc. are better handled elsewhere or are set automatically.
	If the user wants to change some settings, the GUI will send a "setoption" command to the engine.
	Note that the GUI need not send the setoption command when starting the engine for every option if
	it doesn't want to change the default value.
	For all allowed combinations see the examples below,
	as some combinations of this tokens don't make sense.
	One string will be sent for each parameter.
	* name <id>
		The option has the name id.
		Certain options have a fixed value for <id>, which means that the semantics of this option is fixed.
		Usually those options should not be displayed in the normal engine options window of the GUI but
		get a special treatment. "Pondering" for example should be set automatically when pondering is
		enabled or disabled in the GUI options. The same for "UCI_AnalyseMode" which should also be set
		automatically by the GUI. All those certain options have the prefix "UCI_" except for the
		first 6 options below. If the GUI gets an unknown Option with the prefix "UCI_", it should just
		ignore it and not display it in the engine's options dialog.
		* <id> = Hash, type is spin
			the value in MB for memory for hash tables can be changed,
			this should be answered with the first "setoptions" command at program boot
			if the engine has sent the appropriate "option name Hash" command,
			which should be supported by all engines!
			So the engine should use a very small hash first as default.
		* <id> = NalimovPath, type string
			this is the path on the hard disk to the Nalimov compressed format.
			Multiple directories can be concatenated with ";"
		* <id> = NalimovCache, type spin
			this is the size in MB for the cache for the nalimov table bases
			These last two options should also be present in the initial options exchange dialog
			when the engine is booted if the engine supports it
		* <id> = Ponder, type check
			this means that the engine is able to ponder.
			The GUI will send this whenever pondering is possible or not.
			Note: The engine should not start pondering on its own if this is enabled, this option is only
			needed because the engine might change its time management algorithm when pondering is allowed.
		* <id> = OwnBook, type check
			this means that the engine has its own book which is accessed by the engine itself.
			if this is set, the engine takes care of the opening book and the GUI will never
			execute a move out of its book for the engine. If this is set to false by the GUI,
			the engine should not access its own book.
		* <id> = MultiPV, type spin
			the engine supports multi best line or k-best mode. the default value is 1
		* <id> = UCI_ShowCurrLine, type check, should be false by default,
			the engine can show the current line it is calculating. see "info currline" above.
		* <id> = UCI_ShowRefutations, type check, should be false by default,
			the engine can show a move and its refutation in a line. see "info refutations" above.
		* <id> = UCI_LimitStrength, type check, should be false by default,
			The engine is able to limit its strength to a specific Elo number,
		   This should always be implemented together with "UCI_Elo".
		* <id> = UCI_Elo, type spin
			The engine can limit its strength in Elo within this interval.
			If UCI_LimitStrength is set to false, this value should be ignored.
			If UCI_LimitStrength is set to true, the engine should play with this specific strength.
		   This should always be implemented together with "UCI_LimitStrength".
		* <id> = UCI_AnalyseMode, type check
		   The engine wants to behave differently when analysing or playing a game.
		   For example when playing it can use some kind of learning.
		   This is set to false if the engine is playing a game, otherwise it is true.
		 * <id> = UCI_Opponent, type string
		   With this command the GUI can send the name, title, elo and if the engine is playing a human
		   or computer to the engine.
		   The format of the string has to be [GM|IM|FM|WGM|WIM|none] [<elo>|none] [computer|human] <name>
		   Examples:
		   "setoption name UCI_Opponent value GM 2800 human Gary Kasparov"
		   "setoption name UCI_Opponent value none none computer Shredder"
		 * <id> = UCI_EngineAbout, type string
		   With this command, the engine tells the GUI information about itself, for example a license text,
		   usually it doesn't make sense that the GUI changes this text with the setoption command.
		   Example:
			"option name UCI_EngineAbout type string default Shredder by Stefan Meyer-Kahlen, see www.shredderchess.com"
		* <id> = UCI_ShredderbasesPath, type string
			this is either the path to the folder on the hard disk containing the Shredder endgame databases or
			the path and filename of one Shredder endgame datbase.
	   * <id> = UCI_SetPositionValue, type string
	      the GUI can send this to the engine to tell the engine to use a certain value in centipawns from white's
	      point of view if evaluating this specifix position. 
	      The string can have the formats:
	      <value> + <fen> | clear + <fen> | clearall

	* type <t>
		The option has type t.
		There are 5 different types of options the engine can send
		* check
			a checkbox that can either be true or false
		* spin
			a spin wheel that can be an integer in a certain range
		* combo
			a combo box that can have different predefined strings as a value
		* button
			a button that can be pressed to send a command to the engine
		* string
			a text field that has a string as a value,
			an empty string has the value "<empty>"
	* default <x>
		the default value of this parameter is x
	* min <x>
		the minimum value of this parameter is x
	* max <x>
		the maximum value of this parameter is x
	* var <x>
		a predefined value of this parameter is x
	Examples:
	 Here are 5 strings for each of the 5 possible types of options
	   "option name Nullmove type check default true\n"
	   "option name Selectivity type spin default 2 min 0 max 4\n"
	   "option name Style type combo default Normal var Solid var Normal var Risky\n"
	   "option name NalimovPath type string default c:\\n"
	   "option name Clear Hash type button\n"



Common incompatibilities:
-------------------------
UCI:
	many variant engines (Shogi, Xiangqi) do not understand "startpos".

USI:
	many engines only recognise the following format for the "go" command:
	"go btime %d wtime %d byoyomi %d"
	The options winc/binc/movestogo/movetime may cause unpredictabe
	behaviour, including crashes.

	many engines only respond to "isready" once, and only allow options to
	be set before receiving "isready".

	Standard options (hash, ponder) are not announced, even if they do exist
	and can be set.

UCCI:
	many engines do not accurately report the options they have. This is
	particularly problematic for "usemillisec".
	It is best to always set options explicitly and not trust the defaults.

Caveats:
--------
* In USI, mate scores are in plies. In UCI and UCCI, mate scores are in
  moves.

* In USI, the first side to move is referred to as "black" (and their clock
  is referred to by "btime")

* In UCCI, the default time unit is in seconds, but there is an option
  "usemillisec" (which should be supported by all engines, but currently
  isn't) that can be used to switch it back to one second.

* UCI option names can contain spaces and be presented in mixed caps (but
  should be matched case-insensitive).
  In USI and UCCI, option names should not contain spaces. In UCCI, they
  should also all be in lower case. The actual text that is displayed in
  the engine options is supposed to come from a "translation file".

* Make sure to send "movestogo" to UCCI engines: they may assume a default
  of 1. To set a sudden-death time control in UCCI, send "movestogo 0".
Although there are clear differences between UCI, USI and UCCI (and UCCI adds some interesting extensions to UCI), the core protocol is the same and could easily be extended to include variants. I suggest that the best way to do this is through a "standard" UCI option in the same vein as the existing UCI_ options defined in the standard:

Code: Select all

option name UCI_Variant type combo default Chess var Chess var Fischer Chess var Seirawan Chess var King-of-the-hill var Atomic var Capablanca
A GUI that doesn't know how to play a particular variant can just not include it in the combo-box. Telling the engine what variant it should play is a matter of sending

Code: Select all

setoption name UCI_Variant value <whatever>
The UCI protocol defines the encoding of normal moves and promotions, USI adds the encoding of drop moves. I think that covers all that's really needed (for Seirawan chess we need a notation for gating moves, I would suggest using the promotion suffix and allow RxK as an alternative notation for castling moves, I think that's how XBoard does it too).

There are a couple of details that would need to be worked out though:
  • Simply hard-coding a list of possibly supported variants in the protocol specs seems not very future-proof. XBoard now has "engine defined" variants, but those require some more information to be passed between engine and GUI. How best to handle this?
  • Should piece symbols be hard-coded? Globally? Or per variant? To put the problem into perspective: the Archbishop (A) of Capablanca chess is also the Hawk (H) of Seirawan chess. The Ferz of Shatranj is also the Advisor in Xiangqi and the Met of Makruk. Should we define a number of "standard" pieces (moves) and define their names for particular variants (this could be similar to XBoard's pieceToChar)?
XBoard is evolving into a system where the engine can communicate the full rules of a variant to the GUI. While I think this is great, I think we should aim for something more simple here, at least initially.

So perhaps the best for now is to define the meaning of a set of standard variants, with their pieces and startup FENs?

Thoughts? Ideas? Suggestions?
User avatar
hgm
Posts: 28202
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: UCI protocol for chess variants

Post by hgm »

Polyglot supports an extension to UCI where any engine->GUI command of the form

info string xboard XXX

would be simply passed to the GUI as

XXX

This allows UCI engines to use commands of WB protocol for all things where UCI is defective. They could for instance use it to offer draws, resign, object against illegal moves, send "setup" or "piece" commands.

I could support that command in UCI2WB too.
User avatar
hgm
Posts: 28202
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: UCI protocol for chess variants

Post by hgm »

And about Seirawan: there exists a private version of Komodo (which is of course UCI) that plays it (and Don gave me a copy for private use). It uses promotion suffixes for gating, and indeed the RxK notation for castlings that gate at the Rook square.
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: UCI protocol for chess variants

Post by Evert »

Cool!
These "extensions" are really obvious, but it's good to put them down somewhere before someone else comes up with something less obvious.

Does this version of Komodo have any way to select variant Seirawan? Either way - probably a good idea to implement some sort of "de-facto" standard way to do it...
User avatar
hgm
Posts: 28202
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: UCI protocol for chess variants

Post by hgm »

Btw, it seems there already exists a standard (check) option UCI_Chess960, which does not occur in the protocol specs above. At least, Polyglot assumes this, when handling XBoard variant fischerandom.

So making an UCI_Variant combo option sort of destroys backward compatibility. And I recall that a few other UCI options were defined here in the forum for Capablanca Chess and the like, for the benefit of ChessGUI, which supports both 10x8 Chess and UCI. (Actually a forum search on UCI_Capablanca found it at once!: http://www.talkchess.com/forum/viewtopic.php?t=26140 )

This unofficial UCI extension sets a bad precedent, as obviously these options cannot be independently chosen, and GUIs would have to be aware that they should never check more than one of them. (But I guess for UCI standard options that is not really a problem; GUIs should be aware of those.)

What is bad, however, is that the options are not really recognizable as options that set the variant. So to a GUI that does not happen to implement the variant, the option is just an unknown UCI standard option, which, depending on its policy to such options, it could ignore or put in the Engine Settings dialog.

There is also another point:

The option to play King of the Hill in the modified Stockfish is not really an option to set the variant, but more an option of the type "Variant normal selects", as I am also using in Fairy-Max w.r.t. variant fairy (to select a Chess-with-Different-Armies flavor) or variant Makruk (to select Cambodian or Ai-Wok rules). The idea of such options is that it isn't really important for the GUI to know about the rule modifications, because the variant is played with the same board and pieces, employing the same castling and e.p. rules. With in the worst case some of the pieces moving differently, which can be handled by switching off legality testing.

Playing a variant this way might lose you some accuracy in terms of SAN disambiguation. But this is more than offset by the huge advantage that you now can play it under any GUI that supports normal Chess. In particular for KOTH no difference in GUI behavior is expected upto the very point where the game finishes. That people choose this method of implementation is not so much a matter of lack of standards, but a conscious attempt to dodge the standard and make one variant masquerade as another, to be able to play it on any GUI, rather than on just one especially adapted to recognize that variant.

An alternative to variant naming would be to have options for individual game rules. UCI_Chess960 in practice is an option that switches on Fischer castling, and the associated methods for move and position notation. Which is indeed something that would need GUI support; Chess960 cannot masquerade as normal Chess on a GUI that doesn't know about Fischer castling. There could be similar options for switching on 'Hill adjudication', 'King-baring adjudication', '3-checks adjudication', 'Stalemate', 'Atomic captures', 'Seirawan gating', '10x8 board'. Some of these could work acceptably without GUI knowledge (in particular those only affecting the winning conditions), so one could argue that they don't have to be UCI standard options, in the sense that GUIs that don't know them should allow their setting through the Engine Settings dialog. For options that affect board size, number of piece types or move side effects that obviously would be a different matter.
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: UCI protocol for chess variants

Post by Evert »

hgm wrote:Btw, it seems there already exists a standard (check) option UCI_Chess960, which does not occur in the protocol specs above. At least, Polyglot assumes this, when handling XBoard variant fischerandom.

So making an UCI_Variant combo option sort of destroys backward compatibility.
Somewhat true, but the downside of a checkbox is that it only has two states. If you want to have more than one or two variants (either in an engine or in a GUI) you get a massive list of mutually exclusive (mostly) checkboxes. A combo box would be the superior way to represent that.
And I recall that a few other UCI options were defined here in the forum for Capablanca Chess and the like, for the benefit of ChessGUI, which supports both 10x8 Chess and UCI. (Actually a forum search on UCI_Capablanca found it at once!: http://www.talkchess.com/forum/viewtopic.php?t=26140 )
Ah, I didn't know that!

Worth looking into, and perhaps getting Mathias' input. If it's not too late, I think using a combo box would be a better option (perhaps as an alternative, to preserve backward compatibility), but if we're stuck with checkboxes… well, I guess we can make that work too.
What is bad, however, is that the options are not really recognizable as options that set the variant. So to a GUI that does not happen to implement the variant, the option is just an unknown UCI standard option, which, depending on its policy to such options, it could ignore or put in the Engine Settings dialog.
I agree.

Probably the most important thing is some sort of recognised or acknowledged standard way of recognising these things. Is there an official maintainer for the UCI protocol?
The option to play King of the Hill in the modified Stockfish is not really an option to set the variant, but more an option of the type "Variant normal selects", as I am also using in Fairy-Max w.r.t. variant fairy (to select a Chess-with-Different-Armies flavor) or variant Makruk (to select Cambodian or Ai-Wok rules). The idea of such options is that it isn't really important for the GUI to know about the rule modifications, because the variant is played with the same board and pieces, employing the same castling and e.p. rules. With in the worst case some of the pieces moving differently, which can be handled by switching off legality testing.
If you can switch off legality testing (do GUIs generally allow that?). There's also no way to really implement alternative victory conditions. Take King-of-the-Hill. It's up to the user to keep track of whether they've won or lost. What happens if they just kept playing after the engine has walked its king into the centre? What should the engine do if it find out that the opponent's king is in the centre and it has therefore lost, but the GUI tells it to search anyway? UCI has no well-defined way for the engine to say what has happened in this case (at least UCCI adds "nobestmove" and "resign" options).
An alternative to variant naming would be to have options for individual game rules. UCI_Chess960 in practice is an option that switches on Fischer castling, and the associated methods for move and position notation. Which is indeed something that would need GUI support; Chess960 cannot masquerade as normal Chess on a GUI that doesn't know about Fischer castling. There could be similar options for switching on 'Hill adjudication', 'King-baring adjudication', '3-checks adjudication', 'Stalemate', 'Atomic captures', 'Seirawan gating', '10x8 board'. Some of these could work acceptably without GUI knowledge (in particular those only affecting the winning conditions), so one could argue that they don't have to be UCI standard options, in the sense that GUIs that don't know them should allow their setting through the Engine Settings dialog. For options that affect board size, number of piece types or move side effects that obviously would be a different matter.
Switching on or off particular options would indeed be better in many ways than just selecting an entire package in one go, but the downside is that if I as a user want to play something out of the ordinary, I may have to select a couple of boxes rather than just selecting one well-named and well-defined variant...
User avatar
hgm
Posts: 28202
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: UCI protocol for chess variants

Post by hgm »

Evert wrote:Probably the most important thing is some sort of recognised or acknowledged standard way of recognising these things. Is there an official maintainer for the UCI protocol?
Stefan Mayer-Kahlen has this status. But he (understandably) does not feel the need to add anything that Shredder would not need, and this is why UCI de facto is a dead protocol. There have been proposals for useful extensions before (like filename or slider options, or a standard for setting Threads/Cores/Max CPUs), but they usually do not get off the ground because everyone with the exception of those proposing the extensions always say "Get SMK to endorse it, and we will use it too, but otherwise, forget it". And then nothing happens.
What should the engine do if it find out that the opponent's king is in the centre and it has therefore lost, but the GUI tells it to search anyway? UCI has no well-defined way for the engine to say what has happened in this case (at least UCCI adds "nobestmove" and "resign" options).
This is a general UCI problem that could also happen in normal Chess, when you set the engine to run in a checkmate position. The UCI specs do not state that this is forbidden. Creative use of the protocol can solve that (e.g. printing "bestmove 0000", or another illegal move such as KxK). You could have the engine 'claim' versus a human opponent by sending "info string I won!". Engines written for variants with alternative winning conditions should obviously expect these kind of situations, and be designed to handle them in a safe way that would not upset the GUIs they are targeting too much.
Switching on or off particular options would indeed be better in many ways than just selecting an entire package in one go, but the downside is that if I as a user want to play something out of the ordinary, I may have to select a couple of boxes rather than just selecting one well-named and well-defined variant...
That would only be true for variants that the GUI does not know (but can handle). In that case it seems an acceptably simple work-around. If a GUI wants to explicitly support Shatranj, then it can offer you a New Variant menu similar to XBoard's with a radio button 'Shatranj', and set the required standard options for game rules accordingly. (In this case "stalemate false", "King-baring adjudication true".)


BTW, I had a look at Elephant Eye's protocol driver, and it appears it accepts the words "on" and "off" as synonyms of "true" and "false" on check options.
User avatar
Evert
Posts: 2929
Joined: Sat Jan 22, 2011 12:42 am
Location: NL

Re: UCI protocol for chess variants

Post by Evert »

hgm wrote: Stefan Mayer-Kahlen has this status. But he (understandably) does not feel the need to add anything that Shredder would not need, and this is why UCI de facto is a dead protocol. There have been proposals for useful extensions before (like filename or slider options, or a standard for setting Threads/Cores/Max CPUs), but they usually do not get off the ground because everyone with the exception of those proposing the extensions always say "Get SMK to endorse it, and we will use it too, but otherwise, forget it". And then nothing happens.
Ok, but then's it more a "Shredder communication protocol" than a "universal protocol", isn't it?

Anyway, I guess that means that "we" should just come up with a (backward-compatible) "UCI variants" protocol, and hope that people who want to do something with chess variants and UCI adopt it (instead of making their own).
This is a general UCI problem that could also happen in normal Chess, when you set the engine to run in a checkmate position. The UCI specs do not state that this is forbidden. Creative use of the protocol can solve that (e.g. printing "bestmove 0000", or another illegal move such as KxK). You could have the engine 'claim' versus a human opponent by sending "info string I won!". Engines written for variants with alternative winning conditions should obviously expect these kind of situations, and be designed to handle them in a safe way that would not upset the GUIs they are targeting too much.
Yes, I suppose that's true.
Actually, sending "info string result: 1-0 {white mates}" could be interpreted by a GUI as a claim similar to XBoard's result claims (but this should perhaps be disabled by default).
That would only be true for variants that the GUI does not know (but can handle). In that case it seems an acceptably simple work-around. If a GUI wants to explicitly support Shatranj, then it can offer you a New Variant menu similar to XBoard's with a radio button 'Shatranj', and set the required standard options for game rules accordingly. (In this case "stalemate false", "King-baring adjudication true".)
True, but that gets us back to getting the GUI and the engine agreeing on a way to play a particular variant...
BTW, I had a look at Elephant Eye's protocol driver, and it appears it accepts the words "on" and "off" as synonyms of "true" and "false" on check options.
Hmm… it's not mentioned anywhere in the writeup that these are valid alternatives, so I'm not sure we should document that. But perhaps it is worth recognising "on" or "off" as an initial value in the option string and trigger sending "on" and "off" instead of "true" and "false" in that case.

Sjaak's communication loop recognises all sort of protocol extensions because I find them convenient, but I wouldn't want someone to document those in a "Sjaak communication protocol".
User avatar
hgm
Posts: 28202
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: UCI protocol for chess variants

Post by hgm »

Evert wrote:Ok, but then's it more a "Shredder communication protocol" than a "universal protocol", isn't it?
Sure, it has always been that. There is nothing 'universal' about it other than the name.
Anyway, I guess that means that "we" should just come up with a (backward-compatible) "UCI variants" protocol, and hope that people who want to do something with chess variants and UCI adopt it (instead of making their own).
Well, I don't think people will not pay any attention to a protocol spec if there isn't a GUI that implements that spec. And they won't even pay attention to it if it isn't the GUI that they happen to use. If they are used to running on Shredder or Chessbase, they will make something that works on Shredder or Chessbase, and that's it. Even when they would be aware of other GUIs, they would probably still not tailor their engines to those if that meant it could not run on Shredder or Chessbase.

King of the Hill is a special case, in that it was designed to de indistinguishable from Chess in game play (a trait it shares with Losers and 3-Checks). For variants like that it would be hard to convince people not to play them as 'normal', possible with some engine-defined option to enable the variant. (Which is not even needed if the engine only plays that variant.)

But very few variants are like that. If they would want to do anything 'serious', involving more piece types or different board formats, just hacking an existing engine that happens to be UCI wouldn't work anyway.
True, but that gets us back to getting the GUI and the engine agreeing on a way to play a particular variant...
Yes, but this assumes there actually is anything to select. Multi-variant engines are quite rare. A GUI that would support multiple variants obviously would need some method for the user to switch it to the right mode. A system were you simply assume that the engine will play that same variant is still workable. If people want to set the GUI for Suicide, they'd better load a Suicide engine, or they would be asking for trouble. It would be a nice gimmick if there was some protection against using a wrong engine, but it is not really essential. The only real problem would occur in the case of multi-variant engine. But that is again a step up from simple variant engines.

It would be interesting to know how Matthias solved this for his 10x8 engines in ChessGUI.
Ferdy
Posts: 4840
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: UCI protocol for chess variants

Post by Ferdy »

Would be great if an engine knows what gui it is run to too.
Something like after receiving the uciok from engine, the gui will
send,

Code: Select all

id guiname ZZZ
id guiversion YYY
If the engine does not understand (for example) the commands the gui are sending, it can send an info string message to the gui and then quit by itself. In this case gui and engine hangs are avoided. With this possibility if the gui does not send ucinewgame command at appropriate time, and if that command is critical for the engine to function properly, it is better to design an engine that will quit than to wait for undefined behaviour to happen. The engine author will take note of the guiname and guiversion, so that future engine versions can react accordingly.