http://www.perlmonks.org?node_id=178676

Ok, maybe not really 'learning', more of a statistical model, perhaps even a flawed one. Many hands of Blackjack are played and results of play are reported: the score of your hand, the house's up-card, whether you should stay or hit, percent won by staying, percent won by hitting.

An 'infinite' deck is used, a better model would use a 4-deck or 8-deck shoe. It would also be useful to analyse when to split pairs and when to double down.

There are some surprising results. I thought conventional wisdom was to hit a 16 if dealer has a 7 or better, but this model suggests to only hit 16 if dealer has an 7 or Ace. Maybe I need to play more hands...

JackFoo

#!/usr/bin/perl use strict; my @DECK = qw(02 03 04 05 06 07 08 09 10 10 10 10 11); my (%grid); for (1..64000) { learn(\%grid); } for my $score (12..20) { print " You House S/H S% H%\n"; for my $house (2..11) { $house = sprintf("%2.2d", $house); my ($std, $hit, $do); my $key = "$house-$score"; if ($grid{$key}{'stot'} > 0) { $std = $grid{$key}{'swin'} / $grid{$key}{'stot'}; } if ($grid{$key}{'htot'} > 0) { $hit = $grid{$key}{'hwin'} / $grid{$key}{'htot'}; } if ($std > $hit) { $do = 'S'; } else { $do = 'H'; } $std = sprintf("%3d", ($std*100)); $hit = sprintf("%3d", ($hit*100)); print " $score $house $do $std $hit\n"; } print "\n"; } #----------------------------------------------------------- sub learn { my ($grid) = @_; my (@house, $hscore); my (@mine, $mscore); push (@house, draw()); push (@house, draw()); $hscore = score(\@house); while ($hscore > 0 && $hscore < 17) { push (@house, draw()); $hscore = score(\@house); } push (@mine, draw()); push (@mine, draw()); $mscore = score(\@mine); while ($mscore > 0 && $mscore < 21) { my $key = "$house[0]-$mscore"; if (!defined($grid->{$key})) { $grid->{$key} = {}; } if ($mscore > $hscore) { $grid->{$key}{'swin'}++; } $grid->{$key}{'stot'}++; push (@mine, draw()); $mscore = score(\@mine); if ($mscore > $hscore) { $grid->{$key}{'hwin'}++; } $grid->{$key}{'htot'}++; } } #----------------------------------------------------------- sub score { my ($cards) = @_; my ($aces, $score); for my $card (@$cards) { $score += $card; if ($card == 11) { $aces++; }; } while($score > 21 && $aces) { $score -= 10; $aces--; } if ($score > 21) { $score = 0; } return sprintf("%2.2d", $score); } #----------------------------------------------------------- sub draw { return $DECK[rand(@DECK)]; }