Version 1 of Two Way Pipe - Communicating with gnuchess.

Updated 2024-01-02 13:48:41 by WJG

WJG (02/01/23) After spending too much time reading the Expect manual and making all manner of interesting albeit fruitless web searches on the matter, I managed to achieve what I wanted to do. That is 1) run gnuchess as a background task, 2) send my moves to it, and 3) get its responses back. Anything else displayed from gnuchess (a console board) was discarded.

The two critcal lines that were needed were:

fileevent $pipe readable [list piperead $pipe]
vwait done 

I did try binding a pipewrite handler to the whenever the pipe became writeable but this produced too many callbacks, and didn't seem to work anyway. What did, and still does confuse me is why the vwait command is so important.

#  test-pipes.tcl

# !/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

package require -exact Gnocl 0.9.96

proc chess {} {
                
        global done
        global turn
        global pipe
        global ent
        global txt
        
        # simple GUI
        set box [gnocl::vBox]
        set ent [gnocl::entry -onActivate { pipewrite $pipe %t }]
        set txt [gnocl::text -baseFont {mono} -editable 0]
        set lab [gnocl::label -text "White to move." -variable msg -align left]

        $box add $ent
        $box add $txt -fill 1 -expand 1
        $box add $lab
        gnocl::window -child $box -setSize 0.25 -title gnocl-gnuchess-gui
        
        set cmd gnuchess        
        set turn 0
        
        set pipe [open "|$cmd" RDWR]

    fconfigure $pipe -buffering full -blocking 0
    fileevent $pipe readable [list piperead $pipe]
    
    vwait done ;# include this else the script will not run
    
}

proc pipewrite {pipe opt} { 

        global txt
        global turn
        global ent
        $txt insert end "[incr turn].\t$opt\t"
        $ent set ""
        $ent configure -sensitive 0
        puts $pipe $opt
        flush $pipe
}


proc piperead {pipe} { 

        global done
        global txt
        global buff
        global msg
        global ent
        
        if { [eof $pipe] } {
                catch {close $pipe}
                set done 1
                return
        }

        gets $pipe line
                
        if { [string first "My move is" $line ] == 0 } {
                $txt insert end "[lindex $line end]\n"
                set msg "White to move."
                $ent configure -sensitive 1
                $ent grabFocus
        }
        
        if { [string first "Thinking" $line ] == 0 } {
                set msg $line
        } 

}

chess