Forum: Ruby IO buffering problem

Posted by Andrew W. (andrew_w)
on 2013-03-15 23:35
(Received via mailing list)
All,
I'm writing a chess program that has a simple text-based interface. It's
designed to be run by another program, which has a nice UI. Here's the
program as it stands now, whittled to the simplest possible use case:

i = 0
moves = ["a7a6","a6a5","a5a4","a4a3"]
$stdin.each do |command|
  if command.start_with?("protover")
    $stdout.puts "feature ping=0 setboard=1 ics=1 usermove=1"
  elsif command.start_with?("usermove")
    $stdout.puts "move #{moves[i]}"
    i+=1
  end
  $stdout.flush
end

The "protover" thing is needed to tell the UI program how to initialize 
the
protocol, and then every time a move is made, the UI program sends
"usermove <some move>" to my program, which responds with "move <my 
move>".

If I run this by itself, I can happily enter a few 'usermove' commands
manually, and get any number of canned moves back. However, when I run 
this
under the UI, I get an Interrupt:

bin/winboard.rb:3:in `each': Interrupt
from bin/winboard.rb:3:in `<main>'

I know that the UI program is pretty reliable, so I'm missing something 
in
the way that I'm handling IO buffering or something. If you want the 
nitty
gritty details, you can see them at
http://www.gnu.org/software/xboard/engine-intf.html . I'm running on
MacOSX. Any suggestions?
Posted by Garthy D (Guest)
on 2013-03-16 01:57
(Received via mailing list)
Hi Andrew,

On 16/03/13 09:04, Andrew Wagner wrote:
>    elsif command.start_with?("usermove")
> If I run this by itself, I can happily enter a few 'usermove' commands
> MacOSX. Any suggestions?
Is it possible that you aren't processing one of the commands from the
program, and the program is terminating your script, perhaps after a
timeout or incorrect response? I'm wondering what would show up if you
added this:

else
   $stderr.print "Unknown command: '#{command}'\n"

just before the second-last line. Are you handling every incoming
command as it expects?

Incidentally, you could always turn those if statements into case/when,
something like:

case command
when /^protover/
...
when /^usermove/
...
else
   $stderr.print "Unknown command: '#{command}'\n"
end

This might make it easier if there are a lot of commands you need to
respond to.

Cheers,
Garth
Posted by Garthy D (Guest)
on 2013-03-16 01:59
(Received via mailing list)
Sorry, *third* last line.
Posted by Andrew W. (andrew_w)
on 2013-03-16 02:10
(Received via mailing list)
Thanks for the response. I really don't have to handle every incoming
response. I put in the line you suggested, and it did indeed identify a
number of commands that are "unknown". But that's ok, as far as I can 
tell.

As for "if" vs. "case", in my real program, I did something even more
general:
https://github.com/arwagner/tdchess/blob/master/li... .
This lets you plug in any command handlers you want. I plan on having a
library of handlers for different commands, maybe a nice DSL or 
something
for creating new ones, etc. Obviously, I shortened all of that to 
isolate
this problem.


On Fri, Mar 15, 2013 at 7:57 PM, Garthy D <
Posted by Andrew W. (andrew_w)
on 2013-03-16 02:17
(Received via mailing list)
Ha, I fixed it. You were almost right, Garthy, the UI was
seemingly-randomly sending me SIGINTs. I had to tell it in the protocol
initializer not to do that. Very odd.
Posted by Garthy D (Guest)
on 2013-03-16 02:23
(Received via mailing list)
Hi Andrew,

Happy to be able to help, even if only indirectly. :)

Also check out "trap" ("Signal.trap") if you can usefully catch and use
those SIGINTs. Perhaps they're tied to certain commands like "force" in
the protocol in case you need to stop "thinking" on a move? That's a
wild guess based on a two-minute reading of the protocol though.

Cheers,
Garth
Posted by Andrew W. (andrew_w)
on 2013-03-16 02:34
(Received via mailing list)
Yep, I think you're dead-on right. Thanks again.


On Fri, Mar 15, 2013 at 8:23 PM, Garthy D <
Posted by Garthy D (Guest)
on 2013-03-16 02:56
(Received via mailing list)
Hi Andrew,

No problem at all. :) I hope to have the opportunity to be utterly
annihilated by your completed program in chess some day. ;)

Cheers,
Garth
Posted by Robert Klemme (robert_k78)
on 2013-03-17 17:24
(Received via mailing list)
On Fri, Mar 15, 2013 at 11:34 PM, Andrew Wagner 
<wagner.andrew@gmail.com> wrote:
>   elsif command.start_with?("usermove")
> If I run this by itself, I can happily enter a few 'usermove' commands
> Any suggestions?
At top of script

$stdout.sync = true

Cheers

robert
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.