File Coverage

blib/lib/Chess/Opening/Book.pm
Criterion Covered Total %
statement 53 57 92.9
branch 22 36 61.1
condition 4 6 66.6
subroutine 6 7 85.7
pod 2 2 100.0
total 87 108 80.5


line stmt bran cond sub pod time code
1             #! /bin/false
2              
3             # Copyright (C) 2019 Guido Flohr ,
4             # all rights reserved.
5              
6             # This program is free software. It comes without any warranty, to
7             # the extent permitted by applicable law. You can redistribute it
8             # and/or modify it under the terms of the Do What the Fuck You Want
9             # to Public License, Version 2, as published by Sam Hocevar. See
10             # http://www.wtfpl.net/ for more details.
11              
12             # Make Dist::Zilla happy.
13             # ABSTRACT: Read chess opening books in polyglot format
14              
15             package Chess::Opening::Book;
16             $Chess::Opening::Book::VERSION = '0.3';
17 3     3   27 use common::sense;
  3         6  
  3         14  
18              
19 3     3   1333 use Locale::TextDomain 'com.cantanea.Chess-Opening';
  3         38160  
  3         17  
20              
21 3     3   57023 use Chess::Opening::Book::Entry;
  3         6  
  3         2685  
22              
23             sub new {
24 0     0 1 0 require Carp;
25              
26 0         0 Carp::croak(__"Chess::Opening::Book is an abstract base class");
27             }
28              
29             sub lookupFEN {
30 56     56 1 262 my ($self, $fen) = @_;
31              
32 56 50       154 my $key = $self->_getKey($fen) or return;
33 56 50       183 my ($first, $last) = $self->_findKey($key) or return;
34              
35 56         207 my $entry = Chess::Opening::Book::Entry->new($fen);
36 56         162 foreach my $i ($first .. $last) {
37 133         323 $entry->addMove($self->_getEntry($i));
38             }
39              
40 56         141 return $entry;
41             }
42              
43             sub _pieces {
44             # Polyglot style piece encodings.
45 130     130   823 p => 0,
46             P => 1,
47             n => 2,
48             N => 3,
49             b => 4,
50             B => 5,
51             r => 6,
52             R => 7,
53             q => 8,
54             Q => 9,
55             k => 10,
56             K => 11,
57             }
58              
59             sub _parseFEN {
60 65     65   120 my ($whatever, $fen) = @_;
61              
62 65         403 my @tokens = split /[ \t\r\n]+/, $fen;
63 65 50       198 return if 6 != @tokens;
64              
65 65         105 my %result;
66 65         283 @result{'ranks', 'on_move', 'castling', 'ep', 'hmc', 'next_move'} = @tokens;
67 65         154 $result{on_move} = lc $result{on_move};
68 65 50 66     256 return if $result{on_move} ne 'w' && $result{on_move} ne 'b';
69 65 50       157 return if $result{next_move} <= 0;
70              
71 65 100       321 if ('-' eq $result{castling}) {
    50          
72 1         2 $result{castling} = {};
73             } elsif ($result{castling} !~ /^[KQkq]+$/) {
74 0         0 return;
75             } else {
76 64         224 $result{castling} = {map { $_ => 1 } split //, $result{castling}};
  253         613  
77             }
78 65 100       214 if ($result{ep} ne '-') {
79 30 100       68 if ($result{on_move} eq 'b') {
80 21 50       82 return if $result{ep} !~ /^[a-h]3$/;
81             } else {
82 9 50       38 return if $result{ep} !~ /^[a-h]6$/;
83             }
84             }
85 65 50       212 return if $result{hmc} !~ /^(?:0|[1-9][0-9]*)$/;
86 65 50       191 return if $result{next_move} !~ /^[1-9][0-9]*$/;
87              
88 65         254 my @ranks = split /\//, delete $result{ranks};
89 65 50       154 return if 8 != @ranks;
90              
91 65         91 my $rank = 8;
92 65         95 my $file;
93 65         120 $result{pieces} = [];
94 65         157 my %pieces = $whatever->_pieces;
95 65         162 foreach my $token (@ranks) {
96 520         699 $file = ord 'a';
97 520         1188 foreach my $char (split //, $token) {
98 2623 100 66     7464 if ($char ge '1' && $char le '8') {
    50          
99 544         823 $file += $char;
100 544 50       1003 return if $file > ord 'i';
101             } elsif (exists $pieces{$char}) {
102 2079 50       3327 return if $file > ord 'h';
103 2079         2424 push @{$result{pieces}}, {
  2079         6486  
104             piece => $char,
105             field => (chr $file) . $rank,
106             };
107 2079         3560 ++$file;
108             } else {
109 0         0 return;
110             }
111             }
112 520         940 --$rank;
113             }
114              
115 65         728 return %result;
116             }
117              
118             1;