]> git.sesse.net Git - remoteglot/blob - Engine.pm
chess.js: Faster and smaller attacked(). (A test perft went from ~11.5 to ~7.5 secs.)
[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                 stopping => 0,
33                 chess960 => 0,
34         };
35
36         print $uciwrite "uci\n";
37         $ev->push_read(line => sub { $engine->_anyevent_handle_line(@_) });
38         return bless $engine;
39 }
40
41 sub print {
42         my ($engine, $msg) = @_;
43         print { $engine->{'write'} } "$msg\n";
44 }
45
46 sub _anyevent_handle_line {
47         my ($engine, $handle, $line) = @_;
48
49         if (!$engine->{'seen_uciok'}) {
50                 # Gobble up lines until we see uciok.
51                 if ($line =~ /^id (\S+) (.*?)\s*$/) {
52                         $engine->{'id'}->{$1} = $2;
53                 } elsif ($line =~ /^uciok$/) {
54                         $engine->{'seen_uciok'} = 1;
55                 }
56         } else {
57                 $engine->{'cb'}($engine, $line);
58         }
59         $engine->{'ev'}->push_read(line => sub { $engine->_anyevent_handle_line(@_) });
60 }
61
62 1;