• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

Redirection of Input from Winboard

Started by Olav Bergesen, January 30, 2013, 10:31:28 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Olav Bergesen

Hello,

PBCC 6.03 help file says about CON.STDIN.LINE this:
  "If input redirection is not in effect, CON.STDIN.LINE reads data from the keyboard"

How do I redirect CON.STDIN.LINE so it can receive input from the Winboard front-end chess game application?

Thanks for your support!

--

OB

Ross Boyd

Olav, redirection is not supported by STDIN/STDOUT according to the help file.
In order to accomplish what you want you need to write your own IO routines using AllocConsole() and GetStdHandle().
Fortunately for you I write chess engines too  ;D and here's a small console class that works ok.
I use it from PBWin. Its untested with PBCC (but it should also work).

Note you can poll for input during your Winboard search every 2048 nodes (or so) using the method IsInputAvailable()
eg.

function search(alpha, beta, depth) as long
incr nodes
if (nodes and 2048) = 0 then
   if cons.IsInputAvailable(IsPipeClosed) then
       ' Read input
       s = cons.ReadStdIn()
       ' Process input...
       ' Set stop_search flag if s = "stop" etc etc
   end if       
end if
'  the usual chess search code follows here...
' if depth <= 0 then
' function = qsearch(alpha,beta,depth)
' exit function
' end if
' generate moves
' for each move
' makemove
' score = -search(-beta,-alpha,depth-1)
' undomove
' if stop_search then ' terminate search (out of time or user quits)
' exit function
' end if
' if score > alpha then
' alpha = score
' if score > beta then
'  exit move loop
' end if
' end if
' next 
' function = alpha
end function

Below is an example of the main parse loop (its UCI but you'll know how to adapt it to Winboard. )
It should get you started.

Have fun Olav!!
Ross


#compile exe
#dim all
#include "windows.inc"
#include "ConsoleClass.inc"

global cons as InterfaceConsole

function pbmain() as long
   local s as string
   cons = class "ClassConsole" '

   do
      s = cons.ReadStdin() ' Note: This is a blocking command

      select case parse$(s, " ", 1)
      case "uci"
         cons.printf("id name Carnage 0.1\n")
         cons.printf("id author Ross Boyd\n")
         cons.printf("uciok\n")
      case "isready"
         cons.printf("readyok\n")
      case "go"
         ' UCIGo(s)  ' start a search
      case "stop"
         exit loop
      case "quit"
         exit loop
      case else
      end select

   loop

   cons = nothing
end function

' ==============================================================================
' CONSOLECLASS.INC
' ==============================================================================
'
' Description: Very minimal CONSOLE IO class
'              Just handles read/write and redirected anonymous pipes
'              Suitable for a chess engine under Arena or Winboard.
' ==============================================================================
' Updated       By   Changes
' ------------------------------------------------------------------------------
' Dec 10, 2012  JHB  Initial version
' ==============================================================================

#include once "windows.inc"

class ClassConsole

   instance hStdIn as dword
   instance hStdOut as dword
   instance IsPiped as long
   instance szReadBuffer as stringz * 2048

   class method create()

      local dwFlag as dword
      local s as string
      local e as long

      if isfalse AllocConsole() then
         exit method
      end if

      hStdIn     = GetStdHandle(%STD_INPUT_HANDLE)
      if hStdIn = %INVALID_HANDLE_VALUE then
         e = GetLastError()
         ' ? Using$("Error (#) getting standard input handle",e)
      end if

      hStdOut    = GetStdHandle(%STD_OUTPUT_HANDLE)
      if hStdOut = %INVALID_HANDLE_VALUE then
         e = GetLastError()
         ' ? Using$("Error (#) getting standard output handle",e)
      end if

      IsPiped    = (GetFileType(hStdIn) = %FILE_TYPE_PIPE)

      ' Only in console input mode (not inside Arena etc)
      if IsPiped = 0 and GetConsoleMode(hStdIn, dwFlag) then
         ' Stop resize and mouse events from being placed in input queue
         SetConsoleMode(hStdIn, (dwFlag and (not ((%ENABLE_MOUSE_INPUT or %ENABLE_WINDOW_INPUT)))))
         ' Must flush twice otherwise we get some garbage when typing to the console interactively
         FlushConsoleInputBuffer(hStdIn)
         FlushConsoleInputBuffer(hStdIn)
      end if
   end method


   class method destroy()
      FreeConsole()
   end method

   interface InterfaceConsole
      inherit iunknown

      ' ===============
      ' Public Methods
      ' ===============
      method IsInputAvailable(byref IsPipeClosed as long) as long
         local dwFlag as dword
         local e as long

         if IsPiped then
            if isfalse PeekNamedPipe(hStdIn,byval 0,byval 0,byval 0, dwFlag, (0)) then
               e = GetLastError()
               ' Detect Pipe closure
               IsPipeClosed  = -1
               method = -1
               exit method
            end if
            method = dwflag > 2
         else
            GetNumberOfConsoleInputEvents(hStdIn, dwFlag)
            method = dwflag > 1
         end if
      end method

      method WriteStdout(byref s as string)
         local byteswritten as dword
         WriteFile(hStdOut, byval strptr(s), len(s), byteswritten, byval 0)
      end method

      method ReadStdIn() as string
         local s as string
         local dwCharsRead as dword
         local lRet as long

         lRet = ReadFile(hStdIn, byval varptr(szReadBuffer), sizeof(szReadBuffer), dwCharsRead, byval 0)
         s = left$(szReadBuffer, dwCharsRead)
         method = extract$(s, any $crlf)
      end method

      method printf(byval s as string)
         replace "\n" with $lf in s
         Me.WriteStdout(s)
      end method
   end interface
end class