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
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