File Coverage

blib/lib/Game/Cribbage/Play.pm
Criterion Covered Total %
statement 24 24 100.0
branch n/a
condition n/a
subroutine 8 8 100.0
pod n/a
total 32 32 100.0


line stmt bran cond sub pod time code
1             package Game::Cribbage::Play;
2              
3 5     5   40 use strict;
  5         12  
  5         213  
4 5     5   28 use warnings;
  5         11  
  5         365  
5              
6 5     5   34 use Rope;
  5         49  
  5         40  
7 5     5   2321 use Rope::Autoload;
  5         12  
  5         46  
8              
9 5     5   3099 use Game::Cribbage::Play::Card;
  5         20  
  5         225  
10 5     5   2697 use Game::Cribbage::Play::Score;
  5         19  
  5         246  
11 5     5   38 use Game::Cribbage::Error;
  5         9  
  5         158  
12 5     5   27 use ntheory qw/forcomb vecsum/;
  5         7  
  5         52  
13              
14              
15             property [qw/id next_to_play/] => (
16             initable => 1,
17             writeable => 1,
18             configurable => 0,
19             enumerable => 1,
20             );
21              
22             property total => (
23             initable => 1,
24             writeable => 1,
25             configurable => 0,
26             enumerable => 1,
27             value => 0
28             );
29              
30             property [qw/cards scored/] => (
31             initable => 1,
32             writeable => 1,
33             configurable => 0,
34             enumerable => 1,
35             value => []
36             );
37              
38             function test_card => sub {
39             my ($self, $player, $card) = @_;
40              
41             my $total = $self->calculate_total([@{$self->cards}, $card], 0);
42            
43             if ($total > 31) {
44             return Game::Cribbage::Error->new(
45             message => 'Total count would be greater than 31 if ' . $card->stringify . ' was to be played',
46             go => 1
47             );
48             }
49              
50             my $score = Game::Cribbage::Play::Score->new(
51             player => $player,
52             card => $card
53             );
54              
55             $self->calculate_pair($score, $card);
56              
57             $self->calculate_run($score, $card);
58              
59             $total = $self->calculate_total([@{$self->cards}, $card], 0);
60              
61             $self->calculate_hits($score, $total);
62              
63             return $score->score;
64             };
65              
66             function card => sub {
67             my ($self, $player, $card) = @_;
68              
69             my $total = $self->calculate_total([@{$self->cards}, $card], 0);
70              
71             if ($total > 31) {
72             return Game::Cribbage::Error->new(
73             message => 'Total count would be greater than 31 if ' . $card->stringify . ' was to be played',
74             go => 1
75             );
76             }
77              
78             my $score = Game::Cribbage::Play::Score->new(
79             player => $player,
80             card => $card
81             );
82              
83             $self->calculate_pair($score, $card);
84              
85             $self->calculate_run($score, $card);
86              
87             push @{$self->cards}, Game::Cribbage::Play::Card->new(
88             player => $player,
89             card => $card
90             );
91              
92             $total = $self->calculate_total($self->cards, 1);
93              
94             $self->calculate_hits($score, $total);
95              
96             if ($score->score) {
97             push @{$self->scored}, $score;
98             }
99             return $score;
100             };
101              
102             function force_card => sub {
103             my ($self, $player, $card) = @_;
104              
105             for (@{$self->cards}) {
106             if ($_->card->match($card)) {
107             return 0;
108             }
109             }
110            
111             return $self->card($player, $card);
112             };
113              
114              
115             function end_play => sub {
116             my ($self) = @_;
117              
118             return unless $self->cards->[0];
119              
120             my $score = Game::Cribbage::Play::Score->new(
121             player => $self->cards->[-1]->player,
122             card => $self->cards->[-1],
123             go => 1
124             );
125              
126             push @{$self->scored}, $score;
127              
128             return $score;
129             };
130              
131             function calculate_pair => sub {
132             my ($self, $score, $card) = @_;
133              
134             if ($self->cards->[-1] && $self->cards->[-1]->symbol eq $card->symbol) {
135             if ($self->cards->[-2] && $self->cards->[-2]->symbol eq $card->symbol) {
136             if ($self->cards->[-3] && $self->cards->[-3]->symbol eq $card->symbol) {
137             $score->pair = 3;
138             } else {
139             $score->pair = 2;
140             }
141             } else {
142             $score->pair = 1;
143             }
144             }
145              
146             return 1;
147             };
148              
149             function calculate_run => sub {
150             my ($self, $score, $card) = @_;
151             my @cards = map { $_->card } @{$self->cards};
152             my @values = map { $_->run_value } (@cards, $card);
153             my $length = scalar @values - 1;
154             my $set = 5;
155             for my $n (qw/6 5 4 3 2/) {
156             my $match = $set--;
157             next unless $n <= $length;
158             my @new = sort { $a <=> $b } @values[$length - $n .. $length];
159             my $first = $new[0];
160             for (my $i = 1; $i <= $n; $i++) {
161             $first = $first + 1;
162             if ($first != $new[$i]) {
163             $match = 0;
164             $i = $n + 1;
165             }
166             }
167             if ($match) {
168             $score->run = $match;
169             last;
170             }
171             }
172              
173             return 1;
174             };
175              
176             function calculate_total => sub {
177             my ($self, $cards, $set) = @_;
178              
179             my $total = 0;
180             for (@{ $cards }) {
181             $total += $_->value;
182             }
183             if ($set) {
184             $self->total = $total;
185             }
186              
187             return $total;
188             };
189              
190             function calculate_hits => sub {
191             my ($self, $score, $total) = @_;
192             if ($total == 15) {
193             $score->fifteen = 1;
194             } elsif ($total == 31) {
195             $score->pegged = 1;
196             $score->go = 1;
197             }
198              
199             return 1;
200             };
201              
202             1;