Page 1 of 1

Search Interrupt

PostPosted: 05 Aug 2005, 08:12
by Richard Allbert
Hi,

I have seen the previous post about search interruption..

Code: Select all
if(check_for_input()) {
          handle_input_if_possible();
          if_user_ask_for_abort() {
              abort = 1;
              return 0;
          }
      }


But I am really struggling with how to make the check_for_input() function. I have tried various ways of using (cin) but it is too slow, or stops. Last night, Pradu told me about PeekNamedPipe(), but I don't really understand it, even after reviewing Microsofts website.

None of my books have any of these techniques, either :?

Can anyone help? This is the last piece of functionality I need to add (having finally managed to sort fen string parsing :wink: )

Thanks,

Richard

Re: Search Interrupt

PostPosted: 05 Aug 2005, 09:06
by Roman Hartmann
Hi Albert,
I just had the same problem two days ago but meanwhile I found something that works.

Maybe you should use strcmp() rather than what I'm doing here though.

Code: Select all
int check_input()
{
   int data, bytes;
   char input[255]="", *endc;

   data = Bioskey();
   if(data)
   {
   /* taken from Beowulf */
   /* own solution with fgets didn't work */
      do {
         bytes=read(fileno(stdin),input,255);
      } while (bytes<0);
      endc = strchr(input,'\n');
      if (endc) *endc=0;
   /* end beowulf part */
      if(input[0] == 'e' && input[1] == 'x' && input[2] == 'i')
      {
         printf("search aborted\n");
         search_time = 0;
         return 1;
      }
      if(input[0] == 's' && input[1] == 't' && input[2] == 'o')
      {
         printf("search aborted\n");
         search_time = 0;
         return 1;
      }      
      if(input[0] == '.')
      {
         post_win = TRUE;
         return 0;
      }
   }
   return 0;
}


Hope that helps.
Roman

Re: Search Interrupt

PostPosted: 05 Aug 2005, 09:30
by Anonymous
You can consider to use this API:

SHORT GetAsyncKeyState(int vKey);

or this one:

SHORT GetKeyState(int nVirtKey);

You can call one of this function (or both) half a second or any second, without any significative slow down.

Stefano

Re: Search Interrupt

PostPosted: 05 Aug 2005, 10:17
by Richard Allbert
:D Thank you.!

I'll try that as soon as I get home from work :wink:

Richard

Re: Search Interrupt

PostPosted: 05 Aug 2005, 12:12
by Pallav Nawani
Roman Hartmann wrote:Hi Albert,
I just had the same problem two days ago but meanwhile I found something that works.

Code: Select all
int check_input()
{
   int data, bytes;
   char input[255]="", *endc;

   data = Bioskey();
 ...


Hope that helps.
Roman

You forgot the important part, which is the Bioskey function ;)

Re: Search Interrupt

PostPosted: 05 Aug 2005, 12:30
by Roman Hartmann
Pallav Nawani wrote:
Roman Hartmann wrote:Hi Albert,
I just had the same problem two days ago but meanwhile I found something that works.

Code: Select all
int check_input()
{
   int data, bytes;
   char input[255]="", *endc;

   data = Bioskey();
 ...


Hope that helps.
Roman

You forgot the important part, which is the Bioskey function ;)


:D True. I just assumed he had the same troubles I had which was not the bioskey part.

Roman

Below is the bioskey function I'm using.
Code: Select all
/* taken from Olithink (O. Brausch) */
int Bioskey(void)
{
   static int init = 0, pipe;
   static HANDLE inh;
   DWORD dw;

   if (!init) {
      init = 1;
      inh = GetStdHandle(STD_INPUT_HANDLE);
      pipe = !GetConsoleMode(inh, &dw);
      if (!pipe) {
         SetConsoleMode(inh, dw & ~(ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT));
         FlushConsoleInputBuffer(inh);
      }
   }
    if (pipe) {
      if (!PeekNamedPipe(inh, NULL, 0, NULL, &dw, NULL)) {
         return 1;
      }
      return dw;
   }
   else {
      GetNumberOfConsoleInputEvents(inh, &dw);
      return dw <= 1 ? 0 : dw;
   }
}

Re: Search Interrupt

PostPosted: 06 Aug 2005, 11:04
by Richard Allbert
OK, thanks again.

:D

Richard

Re: Search Interrupt

PostPosted: 07 Aug 2005, 11:10
by Daniel Mehrmann
Richard Allbert wrote:Hi,

I have seen the previous post about search interruption..

Code: Select all
if(check_for_input()) {
          handle_input_if_possible();
          if_user_ask_for_abort() {
              abort = 1;
              return 0;
          }
      }


But I am really struggling with how to make the check_for_input() function. I have tried various ways of using (cin) but it is too slow, or stops. Last night, Pradu told me about PeekNamedPipe(), but I don't really understand it, even after reviewing Microsofts website.

None of my books have any of these techniques, either :?

Can anyone help? This is the last piece of functionality I need to add (having finally managed to sort fen string parsing :wink: )

Thanks,

Richard


Hi Richard,

here are Homers to handle this question. You can use it for or engine if you whish :D

Code: Select all
/*
 * Chessprogram Homer
 * Copyright Daniel Mehrmann, 2003-2005
 * console.c
 */

/* WCE don't used console suff */

#include <stdio.h>

#if !defined (_WIN32_WCE) && defined (WIN32)
    #include <windows.h>

#elif !defined (_WIN32_WCE)
    /* Unix posix */
    #include <sys/time.h>
#endif

#include "homer.h"
#include "protos.h"
#include "extern.h"

/* search.c */
extern BOOL stop_search;
extern int p_depth;

/* search.h */
extern int window;

/* wb.c */
extern int ping, pong;

/* wb.c */
extern char UserMove[STD_BUFF];

/* Dummy replace for WCE: return even TRUE */
BOOL
CheckInPut(void)
{
/* Windows */
#if !defined (_WIN32_WCE) && defined (WIN32)
    static BOOL init = FALSE, pipe;
    static HANDLE StdinHandle;
    DWORD value, LastError;

    /* MS: CRT file handles */
    if (init && stdin->_cnt > 0)
        return TRUE;

    if (!init) {
        init = TRUE;
        StdinHandle = GetStdHandle(STD_INPUT_HANDLE);

        if (StdinHandle == NULL || StdinHandle == INVALID_HANDLE_VALUE) {
            #ifdef _WIN32 /* >= Win2000 */
                LastError = GetLastError();
                MessageHandle("GetStdHandle() failed" , (int)LastError);
            #else
                MessageHandle("GetStdHandle() failed" , 0);
            #endif
        }
        pipe = !GetConsoleMode(StdinHandle, &value);
        if (!pipe) {
            SetConsoleMode(StdinHandle,value &~ (ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT));
            FlushConsoleInputBuffer(StdinHandle);
        }
    }

    if (pipe) {
        if (!PeekNamedPipe(StdinHandle, NULL, 0, NULL, &value, NULL)) {
            #ifdef _WIN32 /* >= Win2000 */
                LastError = GetLastError();
                MessageHandle("PeekNamedPipe stdin failed" , (int)LastError);
            #else
                MessageHandle("PeekNamedPipe stdin failed" , 0);
            #endif
        }
        return value > 0;
   } else {
        GetNumberOfConsoleInputEvents(StdinHandle, &value);
        return value > 1;
   }
   return FALSE;

/* UNIX */
#elif !defined (_WIN32_WCE)
   fd_set rfd;
   struct timeval timeval;
   timeval.tv_sec = timeval.tv_usec = 0;
   FD_ZERO(&rfd);
   FD_SET(0, &rfd);

   return select(1, &rfd, NULL, NULL, &timeval) > 0;
#endif

/* dummy _WIN32_WCE */
#if defined (_WIN32_WCE)
   return TRUE;
#endif
}

Re: Search Interrupt

PostPosted: 07 Aug 2005, 12:02
by Richard Allbert
Thanks Daniel :)

Chat soon.

Richard

Re: Search Interrupt

PostPosted: 07 Aug 2005, 19:54
by Anonymous
Daniel, you use a function "MessageHandle()". I can neither find it in my Windows programming book, nor on msdn.microsoft.com.

You use the stdin->_cnt check at the outer level of your function. This has the disadvantage, that you probably cannot use input redirection efficiently anymore. Asumme you store something like:

st 10
setboard somefen
go
quit

in a file input.txt. Now it can be handy to start an engine by

engine < input.txt

(It can be very useful for debugging/testing). Your function will probably return true during the search and stop the search (The "quit" is already available).

Not checking for stdin->_cnt is also not reliable in my experience, when using Standard C i/o functions (it will work when using low level Unixish _read()). So the check should be inside the if (pipe), I think.

BTW. Some compilers do not support indented #if etc. Indenting with the spaces after the "#" will work everywhere.

Code: Select all
#  ifdef SOMETHING /* Will work practically everywhere */
#  endif

  #ifdef SOMETHING /* Some c90 compilers will refuse to compile this */
  #endif


Cheers,
Dieter

Re: Search Interrupt

PostPosted: 07 Aug 2005, 20:25
by Anonymous
I fear it was me, who posted some code years ago, that has the stdin->_cnt check outside the if (pipe) ...

It is actually not that trivial to get it correct and well working under all circumstances. I think we can see three different situations:

a) under GUI with input redirected (the "pipe situation")
b) manually operated in "console mode"
c) input redirected from the command line

All three cases should be handled well. My suggestion under Windows: For a) use the stdin->_cnt and then the PeekNamedPipe stuff. For b) and c) old _kbhit() should do (#include <console.h>).

Ooops,
Dieter

Re: Search Interrupt

PostPosted: 07 Aug 2005, 20:44
by Alessandro Scotti
On my site (WWW button below) there is a free library that can handle input under Windows and Unix (so far tested on Linux and Mac OS X) and works fairly well.

Re: Search Interrupt

PostPosted: 07 Aug 2005, 21:13
by Daniel Mehrmann
Dieter B?r?ner wrote:Daniel, you use a function "MessageHandle()". I can neither find it in my Windows programming book, nor on msdn.microsoft.com.

You use the stdin->_cnt check at the outer level of your function. This has the disadvantage, that you probably cannot use input redirection efficiently anymore. Asumme you store something like:

st 10
setboard somefen
go
quit

in a file input.txt. Now it can be handy to start an engine by

engine < input.txt

(It can be very useful for debugging/testing). Your function will probably return true during the search and stop the search (The "quit" is already available).

Not checking for stdin->_cnt is also not reliable in my experience, when using Standard C i/o functions (it will work when using low level Unixish _read()). So the check should be inside the if (pipe), I think.

BTW. Some compilers do not support indented #if etc. Indenting with the spaces after the "#" will work everywhere.

Code: Select all
#  ifdef SOMETHING /* Will work practically everywhere */
#  endif

  #ifdef SOMETHING /* Some c90 compilers will refuse to compile this */
  #endif


Cheers,
Dieter


Hi Dieter,

well, MessageHandle is a function of my own :)

Code: Select all
void
MessageHandle(char *message, int ReturnCode)
{
    char SendOut[8 * STD_BUFF];

    printf("\n");

   /* non UCI */
    if (gameData.output < 3)
        sprintf(SendOut, "info %s,  rc = %d \n", message, ReturnCode);
   /* UCI */
    else
        sprintf(SendOut, "info string %s,  rc = %d \n", message, ReturnCode);


    LogOutPut(SendOut);

    printf(SendOut);
    fflush(stdout);
}


I have no problems with my macros. My gcc, MSVC and Intel CC has no problems with it.

Best,
Daniel

Re: Search Interrupt

PostPosted: 08 Aug 2005, 17:21
by Richard Allbert
Thank you, thank you, thank you, all, for the replies :D :D :D

Finally, Lime's search can be interrupted.

I have used an adapted version of Homer's code - the search simply returns 0 for any keypress/input :wink:

I am really grateful for the replies - now UCI can be implemented!!

Richard