File Coverage

blib/lib/Game/Cribbage/Hands.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1             package Game::Cribbage::Hands;
2              
3 5     5   38 use strict;
  5         12  
  5         209  
4 5     5   29 use warnings;
  5         8  
  5         248  
5              
6 5     5   30 use Rope;
  5         11  
  5         31  
7 5     5   2074 use Rope::Autoload;
  5         13  
  5         70  
8 5     5   3795 use Game::Cribbage::Player::Hand;
  5         22  
  5         286  
9 5     5   3077 use Game::Cribbage::Play;
  5         19  
  5         250  
10 5     5   38 use Game::Cribbage::Error;
  5         10  
  5         12803  
11              
12             property number => (
13             initable => 1,
14             writeable => 0,
15             configurable => 0,
16             enumerable => 1
17             );
18              
19             property [qw/starter play crib_player crib_complete player1 player2 player3 player4/] => (
20             initable => 1,
21             writeable => 1,
22             configurable => 0,
23             enumerable => 1,
24             );
25              
26             property cannot_play => (
27             initable => 1,
28             writeable => 1,
29             configurable => 0,
30             enumerable => 1,
31             value => {}
32             );
33              
34             property play_history => (
35             initable => 1,
36             writeable => 1,
37             configurable => 0,
38             enumerable => 1,
39             value => []
40             );
41              
42             function INITIALISED => sub {
43             my ($self, $options) = @_;
44             $self->crib_player = 'player1' if (!$options->{crib_player});
45             for (@{$options->{_game}->players}) {
46             my $player = $_->player;
47             $self->$player = Game::Cribbage::Player::Hand->new(
48             player => $player
49             );
50             }
51             $self->new_play();
52             $self;
53             };
54              
55             function add_starter_card => sub {
56             my ($self, $player, $card) = @_;
57             $self->starter = $card;
58            
59             my $scored = 0;
60             if ($card->symbol =~ m/^J$/) {
61             $scored = Game::Cribbage::Play::Score->new(
62             player => $player,
63             card => $card,
64             flipped => 1
65             );
66             push @{$self->play->scored}, $scored;
67             }
68              
69             for (qw/player1 player2 player3 player4/) {
70             if ($self->$_) {
71             $self->$_->starter = $card;
72             }
73             }
74              
75             return $scored;
76             };
77              
78             function find_player_card => sub {
79             my ($self, $card) = @_;
80             my $player;
81             for my $p (qw/player1 player2 player3 player4/) {
82             if ($self->$p) {
83             for (@{$self->$p->cards}) {
84             if ($_->match($card)) {
85             $card = $_;
86             $player = $p;
87             last;
88             }
89             }
90             }
91             }
92             return ($card, $player);
93             };
94              
95             function force_play_card => sub {
96             my ($self, $card) = @_;
97             my $player;
98             ($card, $player) = $self->find_player_card($card);
99             $card->used = 1;
100             my $scored = $self->play->force_card($player, $card);
101             $self->set_next_to_play();
102             return ($scored, $player);
103             };
104              
105             function play_card => sub {
106             my ($self, $player, $card_index) = @_;
107             my $hand = ref $player ? $player->player : $player;
108             if ($self->play->next_to_play ne $hand) {
109             return Game::Cribbage::Error->new( message => 'It is not the turn of ' . $hand );
110             }
111             my $card = ref $card_index ? $card_index : $self->$hand->get($card_index);
112             if (!$card || $card->used) {
113             die 'CARD HAS ALREADY BEEN PLAYED IN THIS ROUND';
114             }
115              
116             my $total = $self->play->total;
117             if ($card->value + $total > 31) {
118             return Game::Cribbage::Error->new( over => 1, message => 'Playing this card will make the score greater than 31');
119             }
120             $card->used = 1;
121             my $scored = $self->play->card($player, $card);
122             $self->set_next_to_play();
123             return $scored;
124             };
125              
126             function cannot_play_a_card => sub {
127             my ($self, $player) = @_;
128            
129             my $hand = ref $player ? $player->player : $player;
130             if ($self->play->next_to_play ne $hand) {
131             return Game::Cribbage::Error->new( message => 'It is not the turn of ' . $hand );
132             }
133              
134             my $current_total = $self->play->total;
135              
136             my @can_be_played;
137             for (@{$self->$hand->cards}) {
138             next if $_->used;
139             if ( $current_total + $_->value < 31 ) {
140             push @can_be_played, $_;
141             }
142             }
143              
144             return \@can_be_played if scalar @can_be_played;
145              
146             $self->set_next_to_play();
147              
148             $self->cannot_play->{$hand} = 1;
149              
150             return 1;
151             };
152              
153             function set_next_to_play => sub {
154             my ($self) = @_;
155             my $next = $self->parse_next_to_play($self->play->next_to_play);
156             $self->play->next_to_play = $next;
157             };
158              
159             function parse_next_to_play => sub {
160             my ($self, $player_string) = @_;
161             $player_string =~ m/player(\d)/;
162             my $index = $1;
163             $index++;
164             my $next = 'player' . $index;
165             if ($self->$next) {
166             return $next;
167             } else {
168             return 'player1';
169             }
170             };
171              
172             function set_player_hand_id => sub {
173             my ($self, $player, $id) = @_;
174             my $hand = ref $player ? $player->player : $player;
175             $self->$hand->id = $id;
176             return $id;
177             };
178              
179             function get_player_hand_id => sub {
180             my ($self, $player) = @_;
181             my $hand = ref $player ? $player->player : $player;
182             return $self->$hand->id;
183             };
184              
185             function get_crib_player_hand_id => sub {
186             my ($self) = @_;
187             my $hand = $self->crib_player;
188             return $self->$hand->id;
189             };
190              
191             function get_card => sub {
192             my ($self, $player, $card_index) = @_;
193             my $hand = ref $player ? $player->player : $player;
194             my $card = $self->$hand->get($card_index);
195             return $card;
196             };
197              
198             function play_score => sub {
199             my ($self) = @_;
200             return $self->play->total || 0;
201             };
202              
203             function last_play_score => sub {
204             my ($self) = @_;
205             return $self->play_history->[-2]->total || 'This is the first play';
206             };
207              
208             function new_play => sub {
209             my ($self) = @_;
210             my $next_to_play = $self->crib_player;
211             if ($self->play) {
212             $next_to_play = $self->parse_next_to_play(ref $self->play->cards->[-1]->player ? $self->play->cards->[-1]->player->player : $self->play->cards->[-1]->player);
213             }
214             $self->play = Game::Cribbage::Play->new(
215             next_to_play => $next_to_play
216             );
217             push @{$self->play_history}, $self->play;
218             };
219              
220             function next_play => sub {
221             my ($self, $game) = @_;
222              
223             # first check whether any players can play on the current 'play'
224             # if they can they must use those cards first.
225             my $current_total = $self->play->total;
226              
227             my $available_cards = 0;
228             for my $hand (qw/player1 player2 player3 player4/) {
229             if ($self->$hand) {
230             my @can_be_played;
231             for (@{$self->$hand->cards}) {
232             next if $_->used;
233             $available_cards = 1;
234             if ( $current_total + $_->value < 31 ) {
235             push @can_be_played, $_;
236             }
237             }
238             if (scalar @can_be_played) {
239             return Game::Cribbage::Error->new(
240             message => 'Cards can be played',
241             player => $hand,
242             cards => \@can_be_played
243             );
244             }
245             }
246             }
247              
248             $self->cannot_play = {};
249             # now we know cards can't be played confirm we have cards left to Play another 'play'.
250             return $game->end_hands() if !$available_cards;
251             my $scored;
252              
253             if (!$self->play->scored->[-1] || !$self->play->scored->[-1]->go) {
254             $scored = $self->play->end_play();
255             }
256              
257             $self->new_play();
258              
259             return $scored;
260             };
261              
262             function end_play => sub {
263             my ($self) = @_;
264              
265             my $scored;
266              
267             if (!$self->play->scored->[-1] || !$self->play->scored->[-1]->go) {
268             $scored = $self->play->end_play();
269             }
270              
271             $self->play = undef;
272              
273             return $scored;
274             };
275              
276             function score_hands => sub {
277             my ($self) = @_;
278             my %scored;
279             for (qw/player1 player2 player3 player4/) {
280             $scored{$_} = $self->$_->calculate_score()
281             if ($self->$_);
282             }
283             return \%scored;
284             };
285              
286             function card_exists => sub {
287             my ($self, $player, $card) = @_;
288             $player = ref $player ? $player->player : $player;
289             return $self->$player->card_exists($card);
290             };
291              
292             function set_crib_complete => sub {
293             my ($self) = @_;
294             $self->crib_complete = 1;
295             };
296              
297             function best_run_play => sub {
298             my ($self, $player) = @_;
299             $player = ref $player ? $player->player : $player;
300             return $self->$player->best_run_play($self->play);
301             };
302              
303             function next_to_play_id => sub {
304             my ($self, $game) = @_;
305             my $hand = $self->play->next_to_play;
306             return $hand;
307             };
308              
309             1;