Two Way Pipe - Communicating with gnuchess.

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

HE 2024-01-02: You need vwait to enter the event loop in tclsh. If you would use wish it is started automatically.

On your other page with a similar topic (Problem: Two way Communications using Pipes, a Tk GUI and terminal Application.) you used package Tk. This package starts, as far as I know, the Tcl event loop itself and you don't need to start it with vwait.

test-pipes.tcl doesn't use Tk. Instead it use gnocl.

In the documentaion is "gnocl::mainLoop" mentioned which is missing too in test-pipes.tcl. I don't know if this command also starts the Tcl eventloop. I have no gnocl installed on my computer to check this.

WJG (03/01/24) HE, thanks for taking the time to drop by and take a look at this page. Much appreciated.