Well, if you read my original post, then i was all wrong about the problem. The real problem was in sub score when i called score again to evaluate the player/dealers score after a ace was changed from worth 11 to worth 1. Thanks Fever for noticing that the problem had nothing to do with the original score call in sub dealtwo. Well now, with the updated code there is another problem. I get a deep recursion (more then 100 calls of a subroutine from itself) error when i run this and the hand sub score is evaluating has an ace in it. In case you dont know the format of the cards it is suit space card, so 10 of hearts would be
. there might be a problem with the regex in sub score. Thanks again, all suggestions welcome!
#!/usr/bin/perl -w
use strict;
my (%def, %value, @deck, @playerhand, @dealerhand);
#####
# define the symbols for each card and each cards value
#####
%def = (
"h" => "hearts",
"c" => "clubs",
"d" => "diamonds",
"s" => "spades",
"j" => "jack",
"q" => "queen",
"k" => "king",
"a" => "ace", # ace with a value of 11
"1" => "ace" # ace with a value of 1
);
foreach ( 1 .. 10, qw/ j q k a / ) {
if ( !/[j, q, k, a]/ ) {
$value{$_} = $_;
} elsif ( /a/ ) {
$value{$_} = 11;
} else {
$value{$_} = 10;
}
}
#####
# create the deck, shuffle it, and then deal the first hand
#####
createdeck( \@deck );
shuffledeck( \@deck );
for (0 .. 1) {
push @playerhand, shift @deck;
push @dealerhand, shift @deck;
}
dealtwo( \%def, \@deck, \@playerhand, \@dealerhand, \%value );
#####
# the main dealing routine
#####
sub dealtwo {
my ($def, $deck, $playerhand, $dealerhand, $value) = @_;
my ($hos, $score, $card);
print "You were dealt:\n";
foreach ( @$playerhand ) {
/^(\w) (\w+)$/i;
if ( exists $$def{$2} ) { # since not all possible cards ar
+e in %def, if it isn't print it straight
$card = $$def{$2};
} else {
$card = $2
}
print " " . $card . " of " . $$def{$1} . "\n";
}
$score = score( $playerhand, 0, $value );
print "Your are showing: " . $score . "\n\n";
print "\nThe dealer was dealt:\n";
$$dealerhand[0] =~ /^(\w) (\w+)$/i; # only show one card of the de
+alers hand until the player is done
if ( exists $$def{$2} ) {
$card = $$def{$2};
} else {
$card = $2
}
print " " . $card . " of " . $$def{$1} . "\n";
$score = score( $dealerhand, 1, $value );
print "He is showing: " . $score . "\n\n";
print "Hit or Stay?";
$_=<>;
chomp;
if (/h/i) {
push @$playerhand, shift @$deck;
dealtwo($def, $deck, $playerhand, $dealerhand, $value); # anot
+her "hit or stay" for player
} else {
end($def, $deck, $playerhand, $dealerhand, $value); # call the
+ dealer logic
}
}
#####
# shuffle deck (fisher yates)
#####
sub shuffledeck {
my ($deck) = @_;
my ($i, $j);
for ($i = @$deck; --$i; ) {
$j = int rand ($i+1);
next if $i == $j;
@$deck[$i,$j] = @$deck[$j,$i];
}
}
#####
# create deck
#####
sub createdeck {
my ($deck) = @_;
my ($i, $j);
foreach $i ( qw/ h d c s / ) {
foreach $j ( 2 .. 10, qw/ j q k a / ) {
push @$deck, "$i $j";
}
}
}
#####
# calculate the score, and do some win/lose logic
#####
sub score {
my ($hand, $dop, $value) = @_; # $dop says wether to return 1
+ or all cards, 0 for player
my ($score, $ace, $i); # 1 for dealer in sub dealtwo
+and 2 for dealer in sub end
$ace = 0; # weher
foreach (@$hand) {
/^(\w) (\w+)$/i;
$ace=1 if $2 eq "a";
$score += $$value{$2};
}
if ($score > 21 and $ace == 1) { #lines in question
for ($i = @$hand; --$i;) { #lines in questi
+on
@$hand[$i] =~ s/^(\w) a$/$1 1/i; #lines in question
}
score( $hand, $dop, $value );
}
if ($score > 21 and $dop == 0 and $dop != 2) {
lose($score);
exit();
}
if ($score == 21 and $dop == 0 and $dop != 2 ) {
win($score);
exit();
}
if ($score < 21 and $#$hand == 5 ) {
win2($score);
exit();
}
@$hand[0] =~ /^(\w) (\w+)$/i;
if ( $dop == 1 ) {
return $$value{$2};
} else {
return $score;
}
}
#####
# player loses
#####
sub lose {
my ($score) = @_;
print "Your are showing: " . $score . "\n";
print "You lose!"
}
#####
# player wins
#####
sub win {
my ($score) = @_;
print "Your are showing: " . $score . "\n";
print "You win!"
}
#####
# player wins by having 5 cards under 21
#####
sub win2 {
my ($score) = @_;
print "Your are showing: " . $score . " and have 5 cards!\n";
print "You win!"
}
#####
# dealer subroutine
#####
sub end {
my ($def, $deck, $playerhand, $dealerhand, $value) = @_;
my ($score, $card);
$score = score( $dealerhand, 2, $value );
print "\nThe dealer was dealt:\n";
foreach ( @$dealerhand ) {
/^(\w) (\w+)$/i;
if ( exists $$def{$2} ) {
$card = $$def{$2};
} else {
$card = $2
}
print " " . $card . " of " . $$def{$1} . "\n";
}
print "He is showing: " . $score . "\n\n";
while ( $score < 17 ) { #if the dealers score is
+ less then 17 then hit
print "The dealer hits!\n";
push @$dealerhand, shift @$deck;
$score = score( $dealerhand, 2, $value );
print "\nThe dealer was dealt:\n";
foreach ( @$dealerhand ) {
/^(\w) (\w+)$/i;
if ( exists $$def{$2} ) {
$card = $$def{$2};
} else {
$card = $2
}
print " " . $card . " of " . $$def{$1} . "\n";
}
print "He is showing: " . $score . "\n\n";
}
print "The deal stays!\n\n";
if ($score > score( $playerhand, 2, $value ) and $score < 22) {
lose( score( $playerhand, 2, $value ) );
} elsif ($score < score( $playerhand, 2, $value ) ) {
win( score( $playerhand, 2, $value ) );
} elsif ($score == score( $playerhand, 2, $value ) ) {
print "You are showing " . score( $playerhand, 2, $value ) .
+"\n";
print "You push!";
exit();
} elsif ($score > 21) {
print "You win,the dealer is over 21\n";
}
}