File Coverage

lib/Games/Checkers/Iterators.pm
Criterion Covered Total %
statement 74 123 60.1
branch 2 8 25.0
condition 0 9 0.0
subroutine 24 44 54.5
pod n/a
total 100 184 54.3


line stmt bran cond sub pod time code
1             # Games::Checkers, Copyright (C) 1996-2012 Mikhael Goikhman, migo@cpan.org
2             #
3             # This program is free software: you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation, either version 3 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program. If not, see .
15              
16 1     1   5 use strict;
  1         1  
  1         40  
17 1     1   5 use warnings;
  1         1  
  1         40  
18              
19             # ----------------------------------------------------------------------------
20              
21             package Games::Checkers::LocationIterator;
22              
23 1     1   5 use Games::Checkers::BoardConstants;
  1         1  
  1         6  
24              
25             sub new ($@) {
26 4     4   5 my $class = shift;
27              
28 4         9 my $self = { loc => undef, @_ };
29              
30 4         9 bless $self, $class;
31 4         13 $self->restart;
32 4         6 return $self;
33             }
34              
35             sub last ($) {
36 0     0   0 my $self = shift;
37 0         0 return $self->{loc};
38             }
39              
40             sub next ($) {
41 0     0   0 my $self = shift;
42 0         0 my $old = $self->{loc};
43 0         0 $self->{loc} = $self->increment;
44 0         0 return $old;
45             }
46              
47             sub left ($) {
48 0     0   0 my $self = shift;
49 0         0 return $self->{loc} != NL;
50             }
51              
52             sub increment ($) {
53 0     0   0 my $self = shift;
54 0 0       0 $self->{loc} == NL ? NL : ++$self->{loc};
55             }
56              
57             sub restart ($) {
58 0     0   0 my $self = shift;
59 0         0 $self->{loc} = -1;
60 0         0 $self->increment;
61             }
62              
63             sub all ($) {
64 0     0   0 my $self = shift;
65 0         0 my @locations = ();
66 0         0 push @locations, $self->next while $self->left;
67 0         0 return @locations;
68             }
69              
70             # ----------------------------------------------------------------------------
71              
72             package Games::Checkers::PieceRuleIterator;
73              
74 1     1   5 use base 'Games::Checkers::LocationIterator';
  1         1  
  1         547  
75 1     1   5 use Games::Checkers::BoardConstants;
  1         2  
  1         4  
76              
77             sub new ($;$$) {
78 4     4   5 my $class = shift;
79              
80 4         12 my $self = $class->SUPER::new;
81 4 50       8 $self->init(@_) if @_;
82 4         186 return $self;
83             }
84              
85             sub increment ($) {
86 0     0   0 my $self = shift;
87              
88 0         0 my $loc = NL;
89 0   0     0 while ($loc == NL && $self->{dnx} < $self->destinations) {
90 0         0 $loc = $self->get_location($self->{dnx}++);
91             }
92 0         0 return $self->{loc} = $loc;
93             }
94              
95             sub restart ($) {
96 4     4   5 my $self = shift;
97 4 50       34 return unless defined $self->{src};
98 0           $self->{dnx} = 0;
99 0           $self->SUPER::restart;
100             }
101              
102             sub init ($$$) {
103 0     0     my $self = shift;
104 0           my $src = shift;
105 0           my $color = shift;
106              
107 0           $self->{src} = $src;
108 0           $self->{color} = $color;
109 0           $self->restart;
110             }
111              
112             # ----------------------------------------------------------------------------
113              
114             package Games::Checkers::PawnStepIterator;
115              
116 1     1   4 use base 'Games::Checkers::PieceRuleIterator';
  1         2  
  1         395  
117 1     1   4 use Games::Checkers::BoardConstants;
  1         2  
  1         3  
118              
119 0     0     sub destinations ($) { 2 }
120              
121 0     0     sub get_location ($$) { pawn_step->[$_[0]->{color}][$_[0]->{src}][$_[1]]; }
122              
123             # ----------------------------------------------------------------------------
124              
125             package Games::Checkers::PawnBeatIterator;
126              
127 1     1   5 use base 'Games::Checkers::PieceRuleIterator';
  1         1  
  1         380  
128 1     1   5 use Games::Checkers::BoardConstants;
  1         1  
  1         4  
129              
130 0     0     sub destinations ($) { 4 }
131              
132 0     0     sub get_location ($$) { pawn_beat->[$_[0]->{src}][$_[1]]; }
133              
134             # ----------------------------------------------------------------------------
135              
136             package Games::Checkers::KingStepIterator;
137              
138 1     1   5 use base 'Games::Checkers::PieceRuleIterator';
  1         2  
  1         395  
139 1     1   5 use Games::Checkers::BoardConstants;
  1         9  
  1         4  
140              
141 0     0     sub destinations ($) { 13 }
142              
143 0     0     sub get_location ($$) { king_step->[$_[0]->{src}][$_[1]]; }
144              
145             # ----------------------------------------------------------------------------
146              
147             package Games::Checkers::KingBeatIterator;
148              
149 1     1   5 use base 'Games::Checkers::PieceRuleIterator';
  1         2  
  1         379  
150 1     1   5 use Games::Checkers::BoardConstants;
  1         2  
  1         44  
151              
152 0     0     sub destinations ($) { 9 }
153              
154 0     0     sub get_location ($$) { king_beat->[$_[0]->{src}][$_[1]]; }
155              
156             # ----------------------------------------------------------------------------
157              
158             package Games::Checkers::Iterators;
159              
160             # globals, so that we don't need to create these all the time, just init()
161 1     1   5 use constant pawn_step_iterator => Games::Checkers::PawnStepIterator->new;
  1         1  
  1         6  
162 1     1   4 use constant pawn_beat_iterator => Games::Checkers::PawnBeatIterator->new;
  1         1  
  1         5  
163 1     1   4 use constant king_step_iterator => Games::Checkers::KingStepIterator->new;
  1         2  
  1         9  
164 1     1   9 use constant king_beat_iterator => Games::Checkers::KingBeatIterator->new;
  1         2  
  1         4  
165              
166             # ----------------------------------------------------------------------------
167              
168             package Games::Checkers::ValidKingBeatIterator;
169              
170 1     1   4 use base 'Games::Checkers::PieceRuleIterator';
  1         1  
  1         450  
171 1     1   6 use Games::Checkers::BoardConstants;
  1         1  
  1         4  
172              
173 0     0     sub destinations ($) { 9 }
174              
175 0     0     sub get_location ($$) { king_beat->[$_[0]->{src}][$_[1]]; }
176              
177             # ----------------------------------------------------------------------------
178              
179             package Games::Checkers::FigureIterator;
180              
181 1     1   5 use base 'Games::Checkers::LocationIterator';
  1         1  
  1         415  
182 1     1   4 use Games::Checkers::BoardConstants;
  1         2  
  1         4  
183              
184             sub new ($$$) {
185 0     0     my $class = shift;
186 0           my $board = shift;
187 0           my $color = shift;
188              
189 0           return $class->SUPER::new(board => $board, color => $color);
190             }
191              
192             sub increment ($) {
193 0     0     my $self = shift;
194 0           my $loc = $self->{loc};
195 0 0         return NL if $loc == NL;
196 0   0       while (++$loc != NL && (
      0        
197             !$self->{board}->occup($loc) ||
198             $self->{board}->color($loc) != $self->{color})) {}
199 0           return $self->{loc} = $loc;
200             }
201              
202             1;