Dreamhack-Solitaire-Medici

 view release on metacpan or  search on metacpan

lib/Dreamhack/Solitaire/Medici.pm  view on Meta::CPAN

package Dreamhack::Solitaire::Medici;
use 5.008001;
use strict;
use warnings;
no warnings 'recursion';

use base 'Dreamhack::Solitaire';
use Dreamhack::Solitaire;

our $VERSION = "0.01";

sub process {
    my ($self, %args) = @_;

    my $imax = (exists $args{'attempts'}) && ($args{'attempts'} =~ m/^[1-9]\d*$/) ? $args{'attempts'} : $self->_iterations(1+$#{$self->{'leftcards'}});

    for my $i (1..$imax) {

        my @layout = $self->add_rnd_layout();
        my @save = @layout;
        my @work = ();

        my $cardno = 0;
        while (@layout) {
            my $el = shift @layout;
            push @work, $el;
            @work = $self->_pass(0, \@work, $cardno++);
        }

        $self->{'attempts'} = $i;
        if ($#work <= 1) {
            $self->{'layout'} = \@save;
            return $self;
        }
        $self->{'convolution'} = [];
    }
    return undef;
}

sub _pass {
    my ($self, $offset, $work, $cardno) = @_;
    my @work = @$work;

    if (($offset >=0) && ($#work - $offset >= 2)) {
        my ($vr, $sr) = $self->extract($work[$#work - $offset]);
        my ($vl, $sl) = $self->extract($work[$#work - $offset - 2]);
        if (($vl eq $vr) or ($sl eq $sr)) {
            $work[$#work - $offset - 2] = $work[$#work - $offset - 1];
            splice @work, $#work - $offset - 1, 1;
            if ($cardno) {
                push @{$self->{'convolution'}}, $cardno;
            }
            @work = $self->_pass($#work-2, \@work);
        }
        else {
            @work = $self->_pass(--$offset, \@work);
        }
    }
    else {
        return @work
    }
    return @work
}

sub _iterations {
    my ($self, $cardscount) = @_;

    my $imax = 0;
    if ($cardscount <= 1) {
        $imax = 1;
    }
    else {
        $imax = 100_000;
    }
    return $imax
}

1;
__END__

=encoding utf-8

=head1 NAME

Dreamhack::Solitaire::Medici - Kit for Solitaire Medici

=head1 SYNOPSIS

    use Dreamhack::Solitaire::Medici;

    my $sol = Dreamhack::Solitaire::Medici->new();
    $sol->init_layout([qw(Jh ? Ac 10s ? ? Kd)]);
    $sol->process() or die 'Cannot build solitaire, attempts count: ', $sol->{'attempts'};

    print $sol->format();
    print "Attempts count: ", $sol->{'attempts'}, "\n";

or, for empty starting layout:

    print Dreamhack::Solitaire::Medici->new()->process()->format();

or, for russian programmers:

    print Dreamhack::Solitaire::Medici->new(lang=>'ru_RU.utf8')->process()->format();
    In this case you mast use cyrrilic cards abbr for init layout.

=head1 DESCRIPTION

The Solitaire Medici, particular using by dreamhackers/stalkers for reality management.
Chain creation carried out by bruteforce method with max attempts count one hundred thousand (default) or your own value.
Starting layout between 0 and 36 cards.

=head1 ABBR FOR DECK

=over

=item Suits 

s - Spades

c - Clubs

d - Diamonds

h - Hearts



( run in 0.750 second using v1.01-cache-2.11-cpan-71847e10f99 )