Paul wrote (on the computer-go list):
About asynchronous move generation.
I'd propose something like this. Add some form for asynchronous responses. E.g. '=[id] ...' means success, '?[id] ...' means error (this is as now) and '%[id] ...' means asynchronous response. Maybe for asynchronous commands it makes sense to make id mandatory. Responses must not be mixed, i.e. you cannot start a synchronous response inside asynchronous or vice versa (else they will be impossible to parse properly.)
This is in the same direction I've been thinking. To make it consistent with GTP version 2 and fully backwards compatible it can be designed like this:
* Asynchronous responses from the engine are encoded like Paul proposes but with "!" as first character (there is precedence in a protocol GTP was originally inspired by). Naturally one response must be complete before starting on another, whether synchronous or asynchronous.
* Asynchronous messages may only be sent as responses to asynchronous commands. Thus a GTP version 2 controller would never become confused by asynchronous responses it knows nothing about since it would only send synchronous commands.
* Asynchronous responses have the same id as the command initiating them. The id may as usual be omitted by the controller if it is confident that it don't need it.
* An asynchronous command must first be acknowledged by a synchronous response (would usually be an empty response if there are no problems and otherwise an error response).
* An asynchronous command may additionally have zero, one, or multiple asynchronous responses, depending on the nature of the command and the situation. For example an asynchronous genmove command would normally have one asynchronous response, but zero if the command is aborted. A command requesting debug output could produce any number of asynchronous responses.
* Whether an engine is capable of doing asynchronous responses can as usual be tested by known_command or list_commands to see whether it supports specific (asynchronous) commands.
* The asynchronous genmove command would be named async_genmove. In contrast to the normal genmove command it would only generate a move, not actually play it. (To keep sanity and avoid undos when the ordering of move generation and abort command depends on race conditions.)
* To abort the asynchronous genmove, the controller should send the (synchronous) command abort_async_genmove. If the engine has not returned the asynchronous genmove response before responding to the abort command, it is no longer allowed to return a move. I'm open for discussion on the exact name and whether it should return an error if the move had already been sent (I don't think it should).
Example 1: Asynchronous genmove with an intervening synchronous command. Command 3 is sent after receiving the asynchronous move. Controller: 1 async_genmove black 2 version 3 play black E5
Engine: =1
=2 4.0
!1 E5
=3
Example 2: Asynchronous genmove, aborted. The controller plays an own move instead. Controller: 1 async_genmove black 2 abort_async_genmove 3 play black C3
Engine: =1
=2
=3
Example 2b (BAD): Like example 2, but the engine makes an incorrect response. Controller: 1 async_genmove black 2 abort_async_genmove 3 play black C3
Engine: =1
=2
!1 E5
=3
Example 3: Like example 2, but abort command comes too late. Controller: 1 async_genmove black 2 abort_async_genmove 3 play black C3
Engine: =1
!1 E5
=2
=3
Example 4: Asynchronous genmove sent to an engine not supporting it. Controller: 1 async_genmove black
Engine: ?1 unknown command
/Gunnar