I cannot help but compare GTP to UCI for chess. It's a complete protocol but very simple. And it makes it easy to just plug an engine into a powerful GUI interface.
The philosophy is a little different. GTP expects the engine to track state but UCI puts all the burden on the controller. You can have a totally brain dead engine if you want to and UCI does all the work (or I should say the complexity is in the controller.)
For example UCI sends the complete board state to the engine as part of the command to search a new board position (as a list of moves from a specified starting position which defaults to the opening position.) But GTP expects both the engine and the controller to stay in sync in this regard.
In UCI the engine will search a move, but is never expected to execute it. Once the engine finishes searching the move the engine can take a coffee break or completely clear the board and start computing PI if it wants to. Eventually the controller will tell it to search another positions - which will happen to be a position with the move executed as well as the opponents move if it is playing a game. Or ....
It's common for chess interfaces to support multiple games simultaneously. The engine is totally oblivious. The user may have 10 positions in a tabbed window and can move to a completely different game with the illusion that all these games are in progress. (This is possible with GTP too, but must be more carefully managed and is not as natural.)
Thinking on the opponents time can be done in either protocol, but is completely managed by the engine with GTP. With UCI it is managed by the controller and is handled like any other position. The engine receives a command to search and doesn't know or care if it's thinking on the opponents time. However the engine can communicate some decisions to the controller such as which move to ponder on (and will subsequently get an order to search this position.) If the engine doesn't like this arrangement it can do it's own thing without fuss.
When I decided I needed this in order to have a good GUI for my chess program, I had misgivings about a couple of things:
1. The asynchronous protocol I believed would be a big can of worms.
2. The idea of sending all the moves of the game on EVERY move seemed heavy.
Neither issue posed any problems and the asynchronous protocol causes no hard to track bugs or any of the things I worried about. You will see that no chess programmer complains about this and it's a necessary evil if you want something that is truly powerful and supports such basics as being able to cleanly abort a search.
Sending the state before every move sounds heavy, but it's a blessing in disguise. It makes everything extremely simple. Your engine never has to worry about tracking game state in any way. The loop is very simple - you are given a position to search and you search it and that's it.
In my mind I considered alternatives to sending state like because you can have hundreds of moves in GO. I worked out a very simple protocol that doesn't change UCI conceptually. It requires the engine to maintain aliases that represent sequences of moves but it's dirt simple to maintain in an engine. But I don't really think it's even necessary, especially when communication is over a fast network or a simple pipe. If I ever were to design such a system I would make it cooperative - the engine simply makes whatever associations it wants and the controller can use these to save communication bandwidth. Or the programmer can be lazy and ignore this completely.
I don't know why I'm explaining UCI - probably because it's a better protocol and I would like to see something like this for GO. I am not someone who advocates throwing out something that has become a widely used standard - but I would like to see a more sophisticated GTP that incorporates these tried and true ideas - as a stepping stone to something better in the future. My question is how could you end up at something very UCI-like in GO while maintaining backward compatibility for a substantially length of time or forever?
I don't see the computer GO community as even being aware that a lot is missing. I am reminded of my excitement in the old DOS days of using a multi-tasking operating system and the confused look on my friends faces - "so what if the computer can do 2 things at the same time - how can that possibly benefit you, you can only do one thing at a time?" They thought I was being idealistic and impractical.
In the future, GTP will have these things or else someone else will come along with a better protocol that will (probably gradually) replace it. It would be much better if it's GTP that moves this way since Gnugo has because a kind of defacto standards committee for computer Go.
- Don
On Thu, 2007-08-23 at 16:29 +0200, A van Kessel wrote:
I'm afraid, we basically mean the same thing. I have always commented on GTP that it is not designed for angines to 'play a game' it is intended (and designed) to send commands to engines, and expect them to reply with the appropiate responses. The engine has no notion of a game; it is supposed to respond to isolated requests. One of Gunnar's design principles was to keep the amount of shared state (between engine and controller) as small as possible. Basically there is only initialised+size+komi+board-contents. The timing is more or less optional, and is communicated on a per-move basis. This leaves most of the timekeeping to the controller (arbiter or bridge). This will cause al lot of business-logic to be forced into the bridge (or arbiter) program, but it wil keep the protocol itself relatively small. (and: yes, most engines will have more flags to tweak than the protocol has defined, but there are always private extensions, caommandline-arguments and config-files.
AvK