Last modified on Fri Mar 3 09:40:59 PST 2000 by mann
This document is a set of rough notes on the protocol that xboard and WinBoard use to communicate with gnuchessx and other chess engines. These notes may be useful if you want to connect a different chess engine to xboard. Throughout the notes, "xboard" means both xboard and WinBoard except where they are specifically contrasted.
There are two reasons I can imagine someone wanting to do this:
In case (2), if you are using xboard, you will need to configure the "Zippy" code into it, but WinBoard includes this code already. See the file zippy.README in the xboard or WinBoard distribution for more information.
These notes are unpolished, but I've attempted to make them complete in this release. If you notice any errors, omissions, or misleading statements, let me know.
I'd like to hear from everyone who is trying to interface their own chess engine to xboard/WinBoard. Please email me, mann@pa.dec.com. Also, please join the mailing list for authors of xboard/WinBoard compatible chess engines. You can do that by sending mail to chess-engines-subscribe@jpunix.com. You can then post to the list by sending mail to chess-engines@jpunix.com. The list is moderated to prevent spam.
An xboard chess engine runs as a separate process from xboard itself, connected to xboard through a pair of anonymous pipes. The engine does not have to do anything special to set up these pipes. xboard sets up the pipes itself and starts the engine with one pipe as its standard input and the other as its standard output. The engine then reads commands from its standard input and writes responses to its standard output. This is, unfortunately, a little more complicated to do right than it sounds; see section 6 below.
And yes, contrary to some people's expectations, exactly the same thing is true for WinBoard. Pipes and standard input/output are implemented in Win32 and work fine. You don't have to use DDE, COM, DLLs, BSOD, or any of the other infinite complexity that Microsoft has created just to talk between two programs. A WinBoard chess engine is a Win32 console program that simply reads from its standard input and writes to its standard output. See sections 5 and 6 below for additional details.
(I think this means that you can't write a chess engine in MS Visual Basic, because Visual Basic can't create console applications. But why would anyone want to write a chess engine in Visual Basic?)
To diagnose problems in your engine's interaction with xboard, use the -debug flag on xboard's command line to see the messages that are being exchanged. In WinBoard, these messages are written to the file WinBoard.debug instead of going to the screen.
You can turn debug mode on or off while WinBoard is running by pressing Ctrl+Alt+F12. You can turn debug mode on or off while xboard is running by binding DebugProc to a shortcut key (and pressing the key!); see the instructions on shortcut keys in the xboard man page.
While your engine is running under xboard/WinBoard, you can send a command directly to the engine by pressing Shift+1 (xboard) or Alt+1 (WinBoard 4.0.3 and later). This brings up a dialog that you can type your command into. Press Shift+2 (Alt+2) instead to send to the second chess engine in Two Machines mode. On WinBoard 4.0.2 and earlier, Ctrl+Alt is used in place of Alt; this had to be changed due to a conflict with typing the @-sign on some European keyboards.
Originally, xboard was just trying to talk to the existing command-line interface of gnuchess, designed for people to type commands to. So the communication protocol is very ad-hoc. (The reason why there is a gnuchessx that's different from gnuchessr is buried in the mists of time, before I started working on xboard, but I think it was due to someone working around a stupid bug in xboard by changing gnuchess instead of fixing the bug. The differences are tiny.) It's now tough to change the interface, because xboard and gnuchess are separate programs, and I don't want to force people to upgrade them together to versions that match.
Things have changed a bit now that there are many more engines that work with xboard. I've had to make the protocol description more precise, and I've added some features that GNU Chess does not support. In the latest version, I've specified a standard semantics for many commands that differs in some details from what GNU Chess provides, but is easier to work with. In the future I may release a modified GNU Chess that conforms exactly to this protocol.
Due to some Microsoft brain damage that I don't understand, WinBoard does not work with chess engines that were compiled to use a DOS extender for 32-bit addressing. (Probably not with 16-bit DOS or Windows programs either.) WinBoard works only with engines that are compiled for the Win32 API. You can get a free compiler that targets the Win32 API from http://sourceware.cygnus.com/cygwin/. I think DJGPP 2.x should also work if you use the RSXNTDJ extension, but I haven't tried it. Of course, Microsoft Visual C++ will work. Most likely the other commercial products that support Win32 will work too (Borland, etc.), but I have not tried them.
Beware of using buffered I/O in your chess engine. The C stdio library, C++ streams, and the I/O packages in most other languages use buffering both on input and output. That means two things. First, when your engine tries to write some characters to xboard, the library stashes them in an internal buffer and does not actually write them to the pipe connected to xboard until either the buffer fills up or you call a special library routine asking for it to be flushed. (In C stdio, this routine is named fflush.) Second, when your engine tries to read some characters from xboard, the library does not read just the characters you asked for -- it reads all the characters that are currently available (up to some limit) and stashes any characters you are not yet ready for in an internal buffer. The next time you ask to read, you get the characters from the buffer (if any) before the library tries to read more data from the actual pipe.
Why does this cause problems? First, on the output side, remember that your engine produces output in small quantities (say, a few characters for a move, or a line or two giving the current analysis), and that data always needs to be delivered to xboard/WinBoard for display immediately. If you use buffered output, the data you print will sit in a buffer in your own address space instead of being delivered.
You can usually fix the output buffering problem by asking for the buffering to be turned off. In C stdio, you do this by calling setbuf(stdout, NULL). A more laborious and error-prone method is to carefully call fflush(stdout) after every line you output; I don't recommend this. In C++, you can try cout.rdbuf()->setbuf(NULL, 0), but I'm not sure this is guaranteed to work; see your C++ system's documentation. Alternatively, you can carefully call cout.flush() after every line you output.
Another way to fix the problem is to use unbuffered operating system calls to write directly to the file descriptor for standard output. On Unix, this means write(1, ...) -- see the man page for write(2). On Win32, you can use either the Unix-like _write(1, ...) or Win32 native routines like WriteFile.
Second, on the input side, you are likely to want to poll during your search and stop it if new input has come in. If you implement pondering, you'll need this so that pondering stops when the user makes a move. You should also poll during normal thinking on your move, so that you can implement the "?" (move now) command, and so that you can respond promptly to a "result", "force", or "quit" command if xboard wants to end the game or terminate your engine. Buffered input makes polling more complicated -- when you poll, you must stop your search if there are either characters in the buffer or characters available from the underlying file descriptor.
The most direct way to fix this problem is to use unbuffered operating system calls to read (and poll) the underlying file descriptor directly. On Unix, use read(0, ...) to read from standard input, and use select() to poll it. See the man pages read(2) and select(2). (Don't follow the example of GNU Chess and use the FIONREAD ioctl to poll for input. It is not very portable; that is, it does not exist on all versions of Unix, and is broken on some that do have it.) On Win32, you can use either the Unix-like _read(0, ...) or the native Win32 ReadFile() to read. Unfortunately, under Win32, the function to use for polling is different depending on whether the input device is a pipe, a console, or something else. (More Microsoft brain damage here -- did they never hear of device independence?) For pipes, you can use PeekNamedPipe to poll (even when the pipe is unnamed). For consoles, you can use GetNumberOfConsoleInputEvents. For sockets only, you can use select(). It might be possible to use WaitForSingleObject more generally, but I have not tried it. Some code to do these things can be found in Crafty's utility.c, but I don't guarantee that it's all correct or optimal.
A second way to fix the problem might be to ask your I/O library not to buffer on input. It should then be safe to poll the underlying file descriptor as descrbed above. With C, you can try calling setbuf(stdin, NULL). However, I have never tried this. Also, there could be problems if you use scanf(), at least with certain patterns, because scanf() sometimes needs to read one extra character and "push it back" into the buffer; hence, there is a one-character pushback buffer even if you asked for stdio to be unbuffered. With C++, you can try cin.rdbuf()->setbuf(NULL, 0), but again, I have never tried this.
A third way to fix the problem is to check whether there are characters in the buffer whenever you poll. C I/O libraries generally do not provide any portable way to do this. Under C++, you can use cin.rdbuf()->in_avail(). This method has been reported to work with EXchess. Remember that if there are no characters in the buffer, you still have to poll the underlying file descriptor too, using the method descrbed above.
A fourth way to fix the problem is to use a separate thread to read from stdin. This way works well if you are familiar with thread programming. This thread can be blocked waiting for input to come in at all times, while the main thread of your engine does its thinking. When input arrives, you have the thread put the input into a buffer and set a flag in a global variable. Your search routine then periodically tests the global variable to see if there is input to process, and stops if there is. WinBoard and my Win32 ports of ICC timestamp and FICS timeseal use threads to handle multiple input sources.
Engines that run on Unix need to be concerned with two Unix signals: SIGTERM and SIGINT. This applies both to engines that run under xboard and (the unusual case of) engines that WinBoard remotely runs on a Unix host using the -firstHost or -secondHost feature. It does not apply to engines that run on Windows, because Windows does not have Unix-style signals.
First, when an engine is sent the "quit" command, it is also given a SIGTERM signal shortly afterward to make sure it goes away. If your engine reliably responds to "quit", and the signal causes problems for you, you should ignore it by calling signal(SIGTERM, SIG_IGN) at the start of your program.
Second, xboard will send an interrupt signal (SIGINT) at certain times when it believes the engine may not be listening to user input (thinking or pondering). WinBoard currently does this only when the engine is running remotely using the -firstHost or -secondHost feature, not when it is running locally. You probably need to know only enough about this grungy feature to keep it from getting in your way.
The SIGINTs are basically tailored to the needs of GNU Chess on systems where its input polling code is broken or disabled. Because they work in a rather peculiar way, it is recommended that you simply ignore SIGINT when running under Unix in xboard mode. You can do this by having your engine call signal(SIGINT, SIG_IGN). Alternatively, you can configure your personal copy of xboard to not send SIGINT by running configure with the --disable-sigint option. This won't help you if you give your engine to other people who don't want to recompile their xboard and possibly break its interaction with GNU Chess.
Here are details for the curious. If xboard needs to send a command when it is the chess engine's move (such as before the "?" command), it sends a SIGINT first. If xboard needs to send commands when it is not the chess engine's move, but the chess engine may be pondering (thinking on its opponent's time) or analyzing (analysis or analyze file mode), xboard sends a SIGINT before the first such command only. Another SIGINT is not sent until another move is made, even if xboard issues more commands. This behavior is necessary for GNU Chess. The first SIGINT stops it from pondering until the next move, but on some systems, GNU Chess will die if it receives a SIGINT when not actually thinking or pondering.
There are two reasons why WinBoard does not send the Win32 equivalent of SIGINT (which is called CTRL_C_EVENT) to local engines. First, the Win32 GNU Chess port does not need it. Second, I could not find a way to get it to work. Win32 seems to be designed under the assumption that only console applications, not windowed applications, would ever want to send a CTRL_C_EVENT. (More Microsoft brain damage.)
All commands from xboard to the engine end with a newline (\n), even where that is not explicitly stated. All your output to xboard must be in complete lines; any form of prompt or partial line will cause problems.
At the beginning of each game, xboard sends an initialization string. This is currently "new\nrandom\n" unless the user changes it with the initString or secondInitString option.
xboard normally reuses the same chess engine process for multiple games. At the end of a game, xboard will send the "force" command (see below) to make sure your engine stops thinking about the current position. It will later send the initString again to start a new game. If your engine can't play multiple games, give xboard the -xreuse (or -xreuse2) command line option to disable reuse. xboard will then ask the process to quit after each game and start a new process for the next game.
wildcastle | Shuffle chess where king can castle from d file |
---|---|
nocastle | Shuffle chess with no castling at all |
fischerandom | FischeRandom (not supported yet) |
bughouse | Bughouse, ICC/FICS rules |
crazyhouse | Crazyhouse, ICC/FICS rules |
losers | Win by losing all pieces or getting mated (ICC) |
suicide | Win by losing all pieces including king (FICS) |
twokings | Weird ICC wild 9 |
kriegspiel | Kriegspiel (not really supported) |
atomic | Atomic (not really supported) |
3check | Win by giving check 3 times (not supported) |
unknown | Unknown variant (not supported) |
If needed for purposes of board display in force mode (where the engine is not participating in the game) the time clock should be associated with the last color that the engine was set to play, the otim clock with the opposite color.
If you can't handle the time and otim commands, you can ignore them (that is, treat them as no-ops); or better, send back "Error (unknown command): time" the first time you see "time", and xboard will realize you don't implement the command.
When xboard sends your engine a move, it always sends coordinate algebraic notation. There is no command name; the notation is just sent as a line by itself. Examples:
Normal moves: | e2e4 |
Pawn promotion: | e7e8q |
Castling: | e1g1, e1c1, e8g8, e8c8 |
Bughouse drop: | P@h3 |
ICS Wild 0/1 castling: | d1f1, d1b1, d8f8, d8b8 |
FischerRandom castling: | o-o, o-o-o (future) |
If your engine can't handle this kind of output, change the routine SendMoveToProgram in backend.c to send the kind of notation you need. If you define SAN_TO_PROGRAM, your engine will be sent Standard Algebraic Notation (as defined by the PGN standard); for example, e4, Nf3, exd5, Bxf7+, Qxf7#, e8=Q, O-O, or P@h3. (The P@h3 notation is a nonstandard extension to SAN.) In the future, I may make SAN_TO_PROGRAM a runtime option if there is demand for it.
xboard doesn't reliably detect illegal moves, because it does not keep track of castling unavailablity due to king or rook moves, or en passant availability. If xboard sends an illegal move, send back an error message so that xboard can retract it and inform the user; see the section "Commands from the engine to xboard".
It is also permissible for your engine to move immediately if it gets any command while thinking, as long as it processes the command right after moving, but it's preferable if you don't do this. For example, xboard may send post, nopost, easy, hard, force, or quit while the engine is on move.
result 1-0 {White mates}
Here are some notes on interpreting the "result" command. Some apply only to playing on ICS ("Zippy" mode).
If you won but did not just play a mate, your opponent must have resigned or forfeited. If you lost but were not just mated, you probably forfeited on time, or perhaps the operator resigned manually. If there was a draw for some nonobvious reason, perhaps your opponent called your flag when he had insufficient mating material (or vice versa), or perhaps the operator agreed to a draw manually.
You will get a result command even if you already know the game ended -- for example, after you just checkmated your opponent. In fact, if you send the "RESULT {COMMENT}" command (discussed below), you will simply get the same thing fed back to you with "result" tacked in front. You might not always get a "result *" command, however. In particular, you won't get one in local chess engine mode when the user stops playing by selecting Reset, Edit Game, Exit or the like.
c | change current piece color, initially white |
---|---|
Pa4 (for example) | place pawn of current color on a4 |
xa4 (for example) | empty the square a4 (not used by xboard) |
# | clear board |
. | leave edit mode |
The edit command does not change the side to move. To set up a black-on-move position, xboard uses the following command sequence:
new force a2a3 edit <edit commands> .
This sequence is used for compatibility with engines that do not interpret the "black" command according to the specification above; see "Idioms" below.
After an edit command is complete, if a king and a rook are on their home squares, castling is assumed to be available to them. En passant capture is assumed to be illegal on the current move regardless of the positions of the pawns. The clock for the 50 move rule starts at zero, and for purposes of the draw by repetition rule, no prior positions are deemed to have occurred.
name mann
rating 2600 1500
xboard now supports bughouse engines when in Zippy mode. See zippy.README for information on Zippy mode and how to turn on the bughouse support. The bughouse move format is given above. xboard sends the following additional commands to the engine when in bughouse mode. Commands to inform your engine of the partner's game state may be added in the future.
partner mann
holding [PPPRQ] []
holding [PPPRQ] [R] BR
Illegal move: e2e4 Illegal move (in check): Nf3 Illegal move (moving into check): e1g1
Generally, xboard will never send an ambiguous move, so it does not matter whether you respond to such a move with an Illegal move message or an Error message.
Error (ambiguous move): Nf3 Error (unknown command): analyze Error (command not legal now): undo Error (too many parameters): level 1 2 3 4 5 6 7
Note: versions of xboard prior to 3.6.11beta do not parse the "Error" format. To ease the transition, it is acceptable to use the "Illegal move" format for all errors, even if the command given was not a move.
Note: versions of xboard prior to 3.6.11beta do not parse the above format, so you may want to use the old "NUMBER ... MOVE" format temporarily. See the section "Idioms and backward compatibility features" below.
For the actual move text from your chess engine (in place of MOVE above), xboard will accept any kind of unambiguous algebraic format, including coordinate notation, SAN, and some slight variants of SAN. You don't have to send the pure coordinate notation that xboard sends to your engine; xboard parses the output with its general-purpose move parser, which was built to extract human-typed game scores from netnews messages. For example, the following will all work:
e2e4 e4 Nf3 ed exd exd5 Nxd5 Nfd3 e8q e8Q e8=q e8(Q) e7e8q o-o O-O 0-0
and many more.
0-1 {Black mates} 1-0 {White mates} 1/2-1/2 {Draw by repetition} 1/2-1/2 {Stalemate}
xboard relays the result to the user, the ICS, the other engine in Two Machines mode, and the PGN save file as required.
If the user asks your engine to "show thinking", xboard sends your engine the "post" command. It sends "nopost" to turn thinking off. In post mode, your engine sends output lines to show the progress of its thinking. The engine can send as many or few of these lines as it wants to, whenever it wants to. Typically they would be sent when the PV (principal variation) changes or the depth changes. The thinking output should be in the following format:
ply score time nodes pvWhere:
ply | Integer giving current search depth. |
---|---|
score | Integer giving current evaluation in centipawns. |
time | Current search time in centiseconds (ex: 1028 = 10.28 seconds). |
nodes | Nodes searched. |
pv | Freeform text giving current "best" line. You can continue the pv onto another line if you start each continuation line with at least four space characters. |
Example:
9 156 1084 48000 Nf3 Nc6 Nc3 Nf6
Meaning:
9 ply, score=1.56, time = 10.84 seconds, nodes=48000, PV = "Nf3 Nc6 Nc3 Nf6"Longer example from actual Crafty output:
4 109 14 1435 1. e4 d5 2. Qf3 dxe4 3. Qxe4 Nc6 4 116 23 2252 1. Nf3 Nc6 2. e4 e6 4 116 27 2589 1. Nf3 Nc6 2. e4 e6 5 141 44 4539 1. Nf3 Nc6 2. O-O e5 3. e4 5 141 54 5568 1. Nf3 Nc6 2. O-O e5 3. e4
You can use the PV to show other things; for instance, while in book, Crafty shows the observed frequency of different reply moves in its book. In situations like this where your engine is not really searching, start the PV with a '(' character:
0 0 0 0 (e4 64%, d4 24%)
GNU Chess output is very slightly different. The ply number is followed by an extra nonblank character, and the time is in seconds, not hundredths of seconds. For compatibility, xboard accepts the extra character and takes it as a flag indicating the different time units. Example:
2. 14 0 38 d1d2 e8e7 3+ 78 0 65 d1d2 e8e7 d2d3 3& 14 0 89 d1d2 e8e7 d2d3 3& 76 0 191 d1e2 e8e7 e2e3 3. 76 0 215 d1e2 e8e7 e2e3 4& 15 0 366 d1e2 e8e7 e2e3 e7e6 4. 15 0 515 d1e2 e8e7 e2e3 e7e6 5+ 74 0 702 d1e2 f7f5 e2e3 e8e7 e3f4 5& 71 0 1085 d1e2 e8e7 e2e3 e7e6 e3f4 5. 71 0 1669 d1e2 e8e7 e2e3 e7e6 e3f4 6& 48 0 3035 d1e2 e8e7 e2e3 e7e6 e3e4 f7f5 e4d4 6. 48 0 3720 d1e2 e8e7 e2e3 e7e6 e3e4 f7f5 e4d4 7& 48 0 6381 d1e2 e8e7 e2e3 e7e6 e3e4 f7f5 e4d4 7. 48 0 10056 d1e2 e8e7 e2e3 e7e6 e3e4 f7f5 e4d4 8& 66 1 20536 d1e2 e8e7 e2e3 e7e6 e3d4 g7g5 a2a4 f7f5 8. 66 1 24387 d1e2 e8e7 e2e3 e7e6 e3d4 g7g5 a2a4 f7f5 9& 62 2 38886 d1e2 e8e7 e2e3 e7e6 e3d4 h7h5 a2a4 h5h4 d4e4 9. 62 4 72578 d1e2 e8e7 e2e3 e7e6 e3d4 h7h5 a2a4 h5h4 d4e4 10& 34 7 135944 d1e2 e8e7 e2e3 e7e6 e3d4 h7h5 c2c4 h5h4 d4e4 f7f5 e4f4 10. 34 9 173474 d1e2 e8e7 e2e3 e7e6 e3d4 h7h5 c2c4 h5h4 d4e4 f7f5 e4f4
If your engine is pondering (thinking on its opponent's time) in post mode, it can show its thinking then too. In this case your engine may omit the hint move (the move it is assuming its opponent will make) from the thinking lines if and only if it sends xboard the move in the usual "Hint: xxx" format before sending the first line.
xboard supports three styles of time control: conventional chess clocks, the ICS-style incremental clock, and an exact number of seconds per move.
In conventional clock mode, every time control period is the same. That is, if the time control is 40 moves in 5 minutes, then after each side has made 40 moves, they each get an additional 5 minutes, and so on, ad infinitum. At some future time it would be nice to support a series of distinct time controls. This is very low on my personal priority list, but code donations to the xboard project are accepted, so feel free to take a swing at it. I suggest you talk to me first, though.
The command to set a conventional time control looks like this:
level 40 5 0 level 40 0:30 0
The 40 means that there are 40 moves per time control. The 5 means there are 5 minutes in the control. In the second example, the 0:30 means there are 30 seconds. The final 0 means that we are in conventional clock mode.
The command to set an incremental time control looks like this:
level 0 2 12
Here the 0 means "play the whole game in this time control period", the 2 means "base=2 minutes", and the 12 means "inc=12 seconds". As in conventional clock mode, the second argument to level can be in minutes and seconds.
At the start of the game, each player's clock is set to base minutes. Immediately after a player makes a move, inc seconds are added to his clock. A player's clock counts down while it is his turn. Your flag can be called whenever your clock is zero or negative. (Your clock can go negative and then become positive again because of the increment.)
A special ICS rule: if you ask for a game with base=0, the clocks really start at 10 seconds instead of 0. xboard itself does not know about this rule currently, so it may pass the 0 on to the engine instead of changing it to 0:10.
ICS also has time odds games. With time odds, each player has his own (base, inc) pair, but otherwise things work the same as in normal games. The Zippy xboard accepts time odds games but ignores the fact that the opponent's parameters are different; this is perhaps not quite the right thing to do, but gnuchess doesn't understand time odds. Time odds games are always unrated.
The command to set an exact number of seconds per move looks like this:
st 30
This means that each move must be made in 30 seconds. Time not used on one move does not accumulate for use on later moves.
xboard supports analyzing fresh games, edited positions, and games from files. However, all of these look the same from the chess engine's perspective. Basically, the engine just has to respond to the "analyze" command. If your engine does not support analyze mode, it should print the error message "Error (unknown command): analyze" in response to the "analyze" command.
To enter analyze mode, xboard sends the command sequence "post", "white" or "black", "analyze". Analyze mode in your engine should be similar to force mode, except that your engine thinks about what move it would make next if it were on move. Your engine should accept the following commands while in analyze mode:
If the user selects "Periodic Updates", xboard will send the string ".\n" to the chess engine periodically during analyze mode, unless the last PV received began with a '(' character.
The chess engine should respond to ".\n" with a line like this:
stat01: time nodes ply mvleft mvtotWhere:
time | Elapsed search time in centiseconds (ie: 567 = 5.67 seconds). |
---|---|
nodes | Nodes searched so far. |
ply | Search depth so far. |
mvleft | Number of moves left to consider at this depth. |
mvtot | Total number of moves to consider. |
Example:
stat01: 1234 30000 7 5 30
Meaning:
After 12.34 seconds, I've searched 7 ply/30000 nodes, there are a total of 30 legal moves, and I have 5 more moves to search before going to depth 8.
Implementation of the "." command is OPTIONAL. If the engine does not respond to the "." command with a "stat01..." line, xboard will stop sending "." commands. If the engine does not implement this command, the analysis window will use a shortened format to display the engine info.
To give the user some extra information, the chess engine can output the strings "++\n" and "--\n", to indicate that the current search is failing high or low, respectively. You don't have to send anything else to say "Okay, I'm not failing high/low anymore." xboard will figure this out itself.
Some engines have variant interpretations of the force/go/white/black, time/otim, and hard/easy command sets. New engines should not use these interpretations, but in order to accommodate existing engines, xboard is currently very conservative about how it uses these commands. Only the following idioms are currently used.
To support older engines, certain additional commands from the engine to xboard are also recognized. (These are commands by themselves, not values to be placed in the comment field of the PGN result code.) These forms are not recommended for new engines; use the PGN result code commands or the resign command instead:
Command | Interpreted as |
---|---|
White resigns | 0-1 {White resigns} |
Black resigns | 1-0 {Black resigns} |
White | 1-0 {White mates} |
Black | 0-1 {Black mates} |
Draw | 1/2-1/2 {Draw} |
computer mates | 1-0 {White mates} or 0-1 {Black mates} |
opponent mates | 1-0 {White mates} or 0-1 {Black mates} |
computer resigns | 0-1 {White resigns} or 1-0 {Black resigns} |
game is a draw | 1/2-1/2 {Draw} |
checkmate | 1-0 {White mates} or 0-1 {Black mates} |
Commands in the above table are recognized if they begin a line and arbitrary characters follow, so (for example) "White mates" will be recognized as "White", and "game is a draw by the 50 move rule" will be recognized as "game is a draw". All the commands are case-sensitive.
An alternative move syntax is also recognized:
Command | Interpreted as |
---|---|
NUMBER ... MOVE | move MOVE |
Here NUMBER means any string of decimal digits, optionally ending in a period. MOVE is any string containing no whitespace. In this command format, xboard requires the "..." even if your engine is playing White. A command of the form NUMBER MOVE will be ignored. This odd treatment of the commands is needed for compatibility with gnuchessx. The original reasons for it are lost in the mists of time, but I suspect it was originally a bug in the earliest versions of xboard, before I started working on it, which someone "fixed" in the wrong way, by creating a special version of gnuchess (gnuchessx) instead of changing xboard.
Any line that contains the words "offer" and "draw" is recognized as "offer draw".
The "Illegal move" message is recognized even if spelled "illegal move" and even if the colon (":") is omitted. This accommodates GNU Chess 4.0.77, which prints messages like "Illegal move (no matching move)e2e4", and old versions of Crafty, which print just "illegal move".
In Zippy mode, for compatibility with existing versions of Crafty, xboard passes through to ICS any line that begins "kibitz", "whisper", "tell", or "draw". Do not use this feature in new code.
Before the "sd DEPTH" command, xboard also sends the command "depth\nDEPTH", for the benefit of GNU Chess. Note the newline in the middle of this command. Ugh.
For the benefit of GNU Chess, if an "st TIME"-style time control is being used, TIME is also given to the engine as a command-line argument when it is started. Ugh.