########################################### # Blackjack.pm # Mike Schilli, 2003 (m@perlmeister.com) ########################################### use warnings; use strict; #========================================== package Blackjack::Shoe; #================= #========================================== use Algorithm::GenerateSequence; use Algorithm::Numerical::Shuffle qw(shuffle); ########################################### sub new { ########################################### my($class, @options) = @_; my $self = {nof_decks => 1, @options}; bless $self, $class; $self->reshuffle(); return $self; } ########################################### sub reshuffle { ########################################### my($self) = @_; my @cards = (Algorithm::GenerateSequence->new( [qw( Heart Diamond Spade Club )], [qw( A 2 3 4 5 6 7 8 9 10 J Q K )]) ->as_list()) x $self->{nof_decks}; $self->{cards} = shuffle \@cards; } ########################################### sub remaining { ########################################### my($self) = @_; return scalar @{$self->{cards}}; } ########################################### sub draw_card { ########################################### my($self) = @_; return shift @{$self->{cards}}; } #========================================== package Blackjack::Hand; #================= #========================================== use Quantum::Superpositions; ########################################### sub new { ########################################### my($class, @options) = @_; my $self = { cards => [], @options }; die "No shoe" if !exists $self->{shoe}; bless $self, $class; } ########################################### sub draw { ########################################### my($self) = @_; push @{$self->{cards}}, $self->{shoe}->draw_card(); } ########################################### sub count { ########################################### my($self, $how) = @_; my $counts = any(0); for(@{$self->{cards}}) { if($_->[1] =~ /\d/) { $counts += $_->[1]; } elsif($_->[1] eq 'A') { $counts = any($counts+1, $counts+11); } else { $counts += 10; } } # Delete busted hands $counts = ($counts <= 21); # Busted!! return undef if ! eigenstates($counts); return $counts unless defined $how; if($how eq "hard") { # Return minimum return int($counts <= all(eigenstates($counts))); } elsif($how eq "soft") { # Return maxium return int($counts >= all(eigenstates($counts))); } } ########################################### sub blackjack { ########################################### my($self) = @_; my $c = $self->count(); return 1 if $c == 21 and $c == 11 and @{$self->{cards}} == 2; return 0; } ########################################### sub as_string { ########################################### my($self) = @_; return "[" . join(',', map({ "@$_" } @{$self->{cards}})) . "]"; } ########################################### sub count_as_string { ########################################### my($self) = @_; return $self->busted() ? "Busted" : $self->blackjack() ? "Blackjack" : $self->count("soft"); } ########################################### sub busted { ########################################### my($self) = @_; return ! defined $self->count(); } ########################################### sub score { ########################################### my($self, $dealer) = @_; return -1 if $self->busted(); return 1 if $dealer->busted(); return 0 if $self->blackjack() and $dealer->blackjack(); return 1.5 if $self->blackjack(); return -1 if $dealer->blackjack(); return $self->count("soft") <=> $dealer->count("soft"); } 1;