package Games::Solitaire::Verify::Freecells; use warnings; use strict; =head1 NAME Games::Solitaire::Verify::Freecells - a class for representing the Freecells in games such as Freecell, Baker's Game, or Seahaven Towers =head1 VERSION Version 0.01 =cut our $VERSION = '0.08'; use base 'Games::Solitaire::Verify::Base'; use Games::Solitaire::Verify::Exception; use Games::Solitaire::Verify::Card; use List::Util qw(first); __PACKAGE__->mk_accessors(qw( _count _cells )); =head1 SYNOPSIS use Games::Solitaire::Verify::Freecells; # For internal use. =head1 FUNCTIONS =cut sub _input_from_string { my $self = shift; my $str = shift; if ($str !~ m{\AFreecells:}gms) { Games::Solitaire::Verify::Exception::Parse::State::Freecells->throw( error => "Wrong Freecell String", ); } for my $pos (0 .. ($self->count()-1)) { if ($str =~ m{\G (..)}gms) { my $card_s = $1; $self->assign($pos, $self->_parse_freecell_card($card_s)) } else { Games::Solitaire::Verify::Exception::Parse::State::Freecells->throw( error => "Wrong Freecell String", ); } } } sub _init { my ($self, $args) = @_; if (! exists($args->{count})) { die "The count was not specified for the freecells"; } $self->_count($args->{count}); $self->_cells([(undef) x $self->_count()]); if (exists($args->{string})) { return $self->_input_from_string($args->{string}); } return; } sub _parse_freecell_card { my ($self, $s) = @_; return ( ($s eq q{ }) ? undef() : Games::Solitaire::Verify::Card->new( { string => $s, } ) ); } =head2 $self->count() Returns the number of cells. =cut sub count { my $self = shift; return $self->_count(); } =head2 $self->cell($index) Returns the card in the freecell with the index $index . =cut sub cell { my ($self, $idx) = @_; return $self->_cells()->[$idx]; } =head2 $self->assign($index, $card) Sets the card in the freecell with the index $index to $card, which should be a L object. =cut sub assign { my ($self, $idx, $card) = @_; $self->_cells()->[$idx] = $card; return; } =head2 $self->to_string() Stringifies the freecells into the Freecell Solver solution display notation. =cut sub to_string { my $self = shift; return "Freecells:" . (($self->count() == 0) ? " " : join("", map { " " . (defined($_) ? $_->to_string() : " ") } map { $self->cell($_) } (0 .. ($self->count()-1)) )); } =head2 $self->cell_clone($pos) Returns a B of the card in the position $pos . =cut sub cell_clone { my ($self, $pos) = @_; my $card = $self->cell($pos); return defined($card) ? $card->clone() : undef(); } =head2 $self->clear($pos) Clears/empties the freecell at position $pos . =cut sub clear { my ($self, $pos) = @_; undef($self->_cells()->[$pos]); return; } =head2 $board->clone() Returns a clone of the freecells, with all of their cards duplicated. =cut sub clone { my $self = shift; my $copy = __PACKAGE__->new( { count => $self->count(), } ); foreach my $pos (0 .. ($self->count()-1)) { $copy->assign($pos, $self->cell_clone($pos)); } return $copy; } =head2 $self->num_empty() Returns the number of empty freecells. =cut sub num_empty { my $self = shift; my $count = 0; foreach my $fc_idx (0 .. ($self->count()-1) ) { if (!defined($self->cell($fc_idx))) { $count++; } } return $count; } =head1 AUTHOR Shlomi Fish, C<< >> =head1 BUGS Please report any bugs or feature requests to C, or through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc Games::Solitaire::Verify::Column You can also look for information at: =over 4 =item * RT: CPAN's request tracker L =item * AnnoCPAN: Annotated CPAN documentation L =item * CPAN Ratings L =item * Search CPAN L =back =head1 ACKNOWLEDGEMENTS =head1 COPYRIGHT & LICENSE Copyright 2008 Shlomi Fish. This program is released under the following license: MIT/X11 ( L ). =cut 1; # End of Games::Solitaire::Verify::Move