implementing uci stop command

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
hgm
Posts: 28457
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: implementing uci stop command

Post by hgm »

My engines are WB, not UCI. They only stop the search on input while pondering. I did not implement any 'move now' command.

I added that piece of code only to show how 'unbuffered_input' has to be called. What you do when you detect input is upto you.
lucasart
Posts: 3243
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: implementing uci stop command

Post by lucasart »

elcabesa wrote:I'm going to modify the command parser of my UCI engine.
My engine is not multithreaded and I don't want now to write a thread for the search and a thread for the parser.
I have some problem with the stop command, I poll during the search for a kbhit() and everything is working nicely except I lose strength.

Do you know something faster than kbhit ?? what can I do?
You don't need multithreading for this. You just need to check whether there is something to read in stdin without actually reading it. Reading from stdin with normal I/O calls is a blocking operation (the system blocks your process, waiting for the data to arrive, if it ever does...)
This is not what you want. You want to interrogate the operating system and ask if there is something to read, and obtain the reponse immediately, if negative continue, else parse the data and if it's a "stop" command then stop the search. You basically need a function like this to interrogate every now and then (every thousand node for example):

Code: Select all

#if defined(_WIN32) || defined(_WIN64)
	#include <windows.h>
	#include <conio.h>
#else	// assume POSIX
	#include <errno.h>
	#include <unistd.h>
	#include <sys/time.h>
#endif

bool input_available()
{
#if defined(_WIN32) || defined(_WIN64)

	static bool init = false, is_pipe;
	static HANDLE stdin_h;
	DWORD val;
	
	if (!init) {
		init = true;
		stdin_h = GetStdHandle(STD_INPUT_HANDLE);
		is_pipe = !GetConsoleMode(stdin_h, &val);
	}

	if (stdin->_cnt > 0)
		return true;
	
	if (is_pipe)
		return !PeekNamedPipe(stdin_h, NULL, 0, NULL, &val, NULL) ? true : val>0;
	else
		return _kbhit();
	
#else	// assume POSIX
	
	fd_set readfds;
	FD_ZERO(&readfds);
	FD_SET(STDIN_FILENO, &readfds);
	
	struct timeval timeout;	
	timeout.tv_sec = timeout.tv_usec = 0;
	
	select(STDIN_FILENO+1, &readfds, 0, 0, &timeout);
	return FD_ISSET(STDIN_FILENO, &readfds);
#endif
}
The above code has been tested on POSIX and Windows. The Windows case is a bit more complicated, and I'm not sure it's 100% bullet proof, but it seems to work in practice.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
User avatar
hgm
Posts: 28457
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: implementing uci stop command

Post by hgm »

Oh, the stdin->_cnt is a trick I did not know! If stdin buffering was not switched off, this could be important. (But not for UCI stop, I guess.) The point is that when you read after detecting input, even if you read a signel character with getchar(), it reads all waiting input from the pipe, and buffers it. This is important in WB protocol, where the GUI typically sends time, otim and usermove command at once. So you cannot afford to resumepondering after receiving 'time' or 'otim', because the otim and usermove will already be in the buffer, and PeekNamedPipe will report no waiting input in the pipe. So you would ponder forever...