File Coverage

lib/Games/Checkers/Game.pm
Criterion Covered Total %
statement 21 86 24.4
branch 0 28 0.0
condition 0 22 0.0
subroutine 7 17 41.1
pod 0 9 0.0
total 28 162 17.2


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   1909 use strict;
  1         2  
  1         38  
17 1     1   6 use warnings;
  1         2  
  1         38  
18              
19             package Games::Checkers::Game;
20              
21 1     1   5 use Games::Checkers::Board;
  1         2  
  1         27  
22 1     1   5 use Games::Checkers::Constants;
  1         2  
  1         9  
23 1     1   6 use Games::Checkers::BoardTree;
  1         3  
  1         22  
24 1     1   5 use Games::Checkers::CreateMoveList;
  1         2  
  1         20  
25 1     1   6 use Games::Checkers::MoveConstants;
  1         1  
  1         8  
26              
27             sub new ($%) {
28 0     0 0   my $class = shift;
29 0           my %params = @_;
30              
31 0 0         $ENV{DUMB_CHARS} = 1 if $params{dumb_chars};
32              
33 0   0       my $title = $params{title} || "Unknown White - Unknown Black";
34 0           my $board = Games::Checkers::Board->new;
35              
36             # probe and use if available
37 0   0       my $frontend = !($params{use_term} || $ENV{USE_TERM}) && eval q{
38             use Games::Checkers::SDL;
39             Games::Checkers::SDL->new($title, $board, fullscreen => $params{fullscreen});
40             };
41              
42 0   0       my $self = {
      0        
      0        
      0        
43             title => $params{title} || $title,
44             board => $board,
45             frontend => $frontend,
46             dumb_term => $params{dumb_term},
47             level => $params{level} || 3,
48             random => $params{random} || 0,
49             max_move_num => $params{max_move_num} || 1000,
50             };
51              
52 0           bless $self, $class;
53              
54 0           $self->_init;
55             }
56              
57             sub _init ($) {
58 0     0     my $self = shift;
59              
60 0 0         if ($self->{frontend}) {
61 0           $self->{frontend}->init;
62             } else {
63 0           $| = 1;
64 0 0         print "\e[2J" unless $self->{dumb_term};
65             }
66              
67 0           $self->{move_count} = 0;
68 0           $self->{color} = White;
69              
70 0           return $self;
71             }
72              
73             sub sleep ($$) {
74 0     0 0   my $self = shift;
75 0   0       my $secs = shift || 0;
76              
77 0 0         if ($self->{frontend}) {
78 0           $self->{frontend}->sleep($secs);
79             } else {
80 0           sleep($secs);
81             }
82             }
83              
84             sub show_board ($) {
85 0     0 0   my $self = shift;
86              
87 0 0         if ($self->{frontend}) {
88 0           $self->{frontend}->show_board;
89             } else {
90 0           my $title = $self->{title};
91 0           my $indent = int((37 - length($title)) / 2);
92 0 0         print "\e[1;1H\e[?25l" unless $self->{dumb_term};
93 0           print " " x $indent, $title, "\n";
94 0           print $self->{board}->dump;
95 0 0         print "\e[?25h" unless $self->{dumb_term};
96             }
97             }
98              
99             sub can_move ($) {
100 0     0 0   my $self = shift;
101              
102 0           $self->{board}->can_color_move($self->{color});
103             }
104              
105             sub is_max_move_num_reached ($) {
106 0     0 0   my $self = shift;
107              
108 0           return $self->{move_count} >= $self->{max_move_num} * 2;
109             }
110              
111             sub choose_move ($) {
112 0     0 0   my $self = shift;
113              
114 0           my ($board, $color, $level, $random) = map {
115 0           $self->{$_}
116             } qw(board color level random);
117              
118 0           my $board_tree = Games::Checkers::BoardTree->new($board, $color, $level);
119              
120 0 0 0       my $move = $random eq 1 || $random eq ($color == White ? 'w' : 'b')
121             ? $board_tree->choose_random_move
122             : $board_tree->choose_best_move;
123              
124 0           return $move;
125             }
126              
127             sub create_move ($$$$) {
128 0     0 0   my $self = shift;
129 0           my $is_beat = shift;
130 0           my $src = shift;
131 0           my $dst = shift;
132              
133 0           my $creating_move = Games::Checkers::CreateVergeMove->new(
134             $self->{board}, $self->{color}, $is_beat, $src, $dst
135             );
136 0 0         die "Internal problem" unless $creating_move->status == Ok;
137 0           my $move = $creating_move->get_move;
138              
139 0 0         return $move == NO_MOVE ? undef : $move;
140             }
141              
142             sub show_move ($$) {
143 0     0 0   my $self = shift;
144 0           my $move = shift;
145              
146 0           my ($board, $color, $move_count) = map {
147 0           $self->{$_}
148             } qw(board color move_count);
149              
150 0 0         if ($self->{frontend}) {
151 0           $self->{frontend}->show_move($move, $color, $move_count);
152             } else {
153 0 0         printf " %02d. %s", 1 + $move_count / 2, $color == White ? "" : "... ";
154 0           print $move->dump, " \n";
155             }
156              
157 0           $board->transform($move);
158              
159 0 0         $self->{color} = $color == White ? Black : White;
160 0           $self->{move_count}++;
161             }
162              
163             sub show_result ($;$) {
164 0     0 0   my $self = shift;
165 0   0       my $message = shift || ($self->is_max_move_num_reached
166             ? "Automatic draw after $self->{max_move_num} moves."
167             : (($self->{color} == White xor $Games::Checkers::give_away)
168             ? "Black" : "White") . " won."
169             );
170              
171 0 0         if ($self->{frontend}) {
172 0           $self->{frontend}->show_result($message);
173             } else {
174 0           print "\n$message\e[0K\n";
175             }
176             }
177              
178             1;