Blackjack.pm 001 ########################################### 002 # Blackjack.pm 003 # Mike Schilli, 2003 (m@perlmeister.com) 004 ########################################### 005 use warnings; use strict; 006 007 #========================================== 008 package Blackjack::Shoe; #================= 009 #========================================== 010 011 use Algorithm::GenerateSequence; 012 use Algorithm::Numerical::Shuffle 013 qw(shuffle); 014 015 ########################################### 016 sub new { 017 ########################################### 018 my($class, @options) = @_; 019 020 my $self = {nof_decks => 1, @options}; 021 022 bless $self, $class; 023 $self->{cards} = $self->reshuffle(); 024 return $self; 025 } 026 027 ########################################### 028 sub reshuffle { 029 ########################################### 030 my($self) = @_; 031 032 my @cards = 033 (Algorithm::GenerateSequence->new( 034 [qw( Heart Diamond Spade Club )], 035 [qw( A 2 3 4 5 6 7 8 9 10 J Q K )]) 036 ->as_list()) x $self->{nof_decks}; 037 038 return shuffle \@cards; 039 } 040 041 ########################################### 042 sub remaining { 043 ########################################### 044 my($self) = @_; 045 046 return scalar @{$self->{cards}}; 047 } 048 049 ########################################### 050 sub draw_card { 051 ########################################### 052 my($self) = @_; 053 054 return shift @{$self->{cards}}; 055 } 056 057 #========================================== 058 package Blackjack::Hand; #================= 059 #========================================== 060 use Quantum::Superpositions; 061 062 ########################################### 063 sub new { 064 ########################################### 065 my($class, @options) = @_; 066 067 my $self = { cards => [], @options }; 068 069 die "No shoe" if !exists $self->{shoe}; 070 bless $self, $class; 071 } 072 073 ########################################### 074 sub draw { 075 ########################################### 076 my($self) = @_; 077 078 push @{$self->{cards}}, 079 $self->{shoe}->draw_card(); 080 } 081 082 ########################################### 083 sub count { 084 ########################################### 085 my($self, $how) = @_; 086 087 my $counts = any(0); 088 089 for(@{$self->{cards}}) { 090 if($_->[1] =~ /\d/) { 091 $counts += $_->[1]; 092 } elsif($_->[1] eq 'A') { 093 $counts = any($counts+1, 094 $counts+11); 095 } else { 096 $counts += 10; 097 } 098 } 099 # Delete busted hands 100 $counts = ($counts <= 21); 101 102 # Busted!! 103 return undef if ! ownstates($counts); 104 105 return $counts unless defined $how; 106 107 if($how eq "hard") { 108 # Return minimum 109 return int($counts <= 110 all(ownstates($counts))); 111 } elsif($how eq "soft") { 112 # Return maximum 113 return int($counts >= 114 all(ownstates($counts))); 115 } 116 } 117 118 ########################################### 119 sub blackjack { 120 ########################################### 121 my($self) = @_; 122 123 my $c = $self->count(); 124 125 return 1 if $c == 21 and $c == 11 and 126 @{$self->{cards}} == 2; 127 return 0; 128 } 129 130 ########################################### 131 sub as_string { 132 ########################################### 133 my($self) = @_; 134 135 return "[" . join(',', map({ "@$_" } 136 @{$self->{cards}})) . "]"; 137 } 138 139 ########################################### 140 sub count_as_string { 141 ########################################### 142 my($self) = @_; 143 144 return $self->busted() ? 145 "Busted" : $self->blackjack() ? 146 "Blackjack" : $self->count("soft"); 147 } 148 149 ########################################### 150 sub busted { 151 ########################################### 152 my($self) = @_; 153 154 return ! defined $self->count(); 155 } 156 157 ########################################### 158 sub score { 159 ########################################### 160 my($self, $dealer) = @_; 161 162 return -1 if $self->busted(); 163 164 return 1 if $dealer->busted(); 165 166 return 0 if $self->blackjack() and 167 $dealer->blackjack(); 168 169 return 1.5 if $self->blackjack(); 170 171 return -1 if $dealer->blackjack(); 172 173 return $self->count("soft") <=> 174 $dealer->count("soft"); 175 } 176 177 1;