Deal with inconsistent zero padding in PGN clocks.
[remoteglot] / Engine.pm
1 #! /usr/bin/perl
2 use strict;
3 use warnings;
4 use IPC::Open2;
5
6 package Engine;
7
8 sub open {
9         my ($class, $cmdline, $tag, $cb) = @_;
10
11         my ($uciread, $uciwrite);
12         my $pid = IPC::Open2::open2($uciread, $uciwrite, $cmdline);
13
14         my $ev = AnyEvent::Handle->new(
15                 fh => $uciread,
16                 on_error => sub {
17                         my ($handle, $fatal, $msg) = @_;
18                         die "Error in reading from the UCI engine: $msg";
19                 }
20         );
21         my $engine = {
22                 pid => $pid,
23                 read => $uciread,
24                 readbuf => '',
25                 write => $uciwrite,
26                 info => {},
27                 ids => {},
28                 tag => $tag,
29                 ev => $ev,
30                 cb => $cb,
31                 seen_uciok => 0,
32         };
33
34         print $uciwrite "uci\n";
35         $ev->push_read(line => sub { $engine->_anyevent_handle_line(@_) });
36         return bless $engine;
37 }
38
39 sub print {
40         my ($engine, $msg) = @_;
41         print { $engine->{'write'} } "$msg\n";
42 }
43
44 sub _anyevent_handle_line {
45         my ($engine, $handle, $line) = @_;
46
47         if (!$engine->{'seen_uciok'}) {
48                 # Gobble up lines until we see uciok.
49                 if ($line =~ /^id (\S+) (.*?)\s*$/) {
50                         $engine->{'id'}->{$1} = $2;
51                 } elsif ($line =~ /^uciok$/) {
52                         $engine->{'seen_uciok'} = 1;
53                 }
54         } else {
55                 $engine->{'cb'}($engine, $line);
56         }
57         $engine->{'ev'}->push_read(line => sub { $engine->_anyevent_handle_line(@_) });
58 }
59
60 1;