bj_objects.py
'''\
Blackjack - Card Deck.
Cards are integer values from 1 (Ace) to 10.
Rules:
0 - null
1 - stay
2 - hit
3 - double
4 - split pair
5 - bust
6 - push
7 - win (got 21)
8 - blackjack (player)
9 - blackjack (dealer)
Developer@Sonnack.com
March 2016
'''
from sys import stdout, stderr
from random import random, shuffle
from bj_rulz import RuleHard, RuleSoft, RuleSplit
CardDeck52 = 4 * [1+card if card < 10 else 10 for card in range(13)]
shuffle(CardDeck52)
CardDeck4 = 4 * CardDeck52
shuffle(CardDeck4)
def NewDeck (nbr_of_decks):
suit = [1+card if card < 10 else 10 for card in range(13)]
deck = 4 * suit
decks = nbr_of_decks * deck
shuffle(decks)
return decks
class CardDeck (object):
'''Card Deck class.'''
def __init__ (self, _nbr_of_decks):
self.deck = 4 * [1+c if c < 10 else 10 for c in range(13)]
self.nd = _nbr_of_decks
self.reset()
def reset (self):
self.cards = self.nd * self.deck
shuffle(self.cards)
shuffle(self.cards)
def __call__ (self):
if len(self):
return self.cards.pop()
def __str__ (self):
return str(self.cards)
def __len__ (self):
return len(self.cards)
class Cards (object):
'''Card Hand class.'''
def __init__ (self):
self.initialize()
def initialize (self):
self.cards = []
self.hand = 0
self.counts = [0]
def blackjack (self):
'''True if hand is A+10.'''
if len(self.cards) == 2:
if len(self.counts) == 2:
if self.counts[1] == 21:
return True
return False
def win (self):
'''True if any count is 21.'''
for n in self.counts:
if n == 21:
return True
return False
def bust (self):
'''True if face value is > 21.'''
if 21 < self.counts[0]:
return True
return False
def count_cards (self):
'''count: [face-value, 10+face, 20+face,...]'''
self.counts = [sum(self.cards)]
self.hand = self.counts[0]
a = 10
for c in self.cards:
if c == 1:
t = self.hand + a
self.counts.append(t)
if t <= 21:
self.hand = t
a += 10
def __len__ (self):
return len(self.cards)
def __call__ (self, card):
'''Add card to hand.'''
self.cards.append(card)
self.count_cards()
def __str__ (self):
p = len(self) * ' %2d'
q = len(self.counts) * ', %d'
s = 'Cards: [%s] {%s}' % (p[1:], q[2:])
t = tuple(self.cards + self.counts)
return s % t
def __repr__ (self):
s = '{cards:%d, hand:%d, face:%d, bust:%s, win:%s, bj:%s}'
t = (len(self), self.hand, self.counts[0], self.bust(), self.win(), self.blackjack())
return s % t
class CardHand (Cards):
'''Participant Card Hand class.'''
def __init__ (self, _bank):
super(CardHand,self).__init__()
self.bank = float(_bank)
class Dealer (CardHand):
'''Dealer's Hand class.'''
hard_stay = 17
soft_stay = 17
def __init__ (self, bank):
super(Dealer,self).__init__(bank)
def new_hand (self):
super(Dealer,self).initialize()
def play_hand (self, deck, player, fp):
if self.blackjack() or player.blackjack() or player.bust():
return
while not self.bust():
if self.win():
break
if self.hard_stay <= self.counts[0]:
break
if 1 < len(self.counts):
n = self.counts[1]
if self.soft_stay <= n <= 21:
break
self(deck())
def __str__ (self):
r = super(Dealer,self).__str__()
return 'Dealer %s' % r
class Player (CardHand):
'''Player's Hand class.'''
def __init__ (self, pot):
super(Player,self).__init__(pot)
self.bet_level = 1
self.original_bank = float(pot)
self.min_bank = float(pot)
self.max_bank = float(pot)
self.new_hand()
def new_hand (self):
super(Player,self).initialize()
self.bet = float(0)
self.win_lose = 0
self.split_pair_flag = False
self.p1 = None
self.p2 = None
def play_hand (self, deck, dealer, fp):
if dealer.blackjack() or self.blackjack():
return
if (self.cards[0] == self.cards[1]) and (self.bet <= self.bank):
self.split_pair_flag = RuleSplit(fp, dealer, self)
if self.split_pair_flag:
self.split_pair(deck, dealer, fp)
return
if 1 < len(self.counts):
rule = RuleSoft(fp, dealer, self)
else:
rule = RuleHard(fp, dealer, self)
if rule == 3:
self.double_down()
print >> fp, 'Double Down: %d {pot: %d}' % (self.bet, self.bank)
self(deck())
return
while (rule == 2) or (rule == 3):
self(deck())
if 1 < len(self.counts):
rule = RuleSoft(fp, dealer, self)
else:
rule = RuleHard(fp, dealer, self)
def split_pair (self, deck, dealer, fp):
self.p1 = Player(0)
self.p2 = Player(0)
self.p1.bet = self.bet
self.p2.bet = self.bet
self.bank -= self.bet
self.p1(self.cards[0])
self.p2(self.cards[1])
self.p1(deck())
self.p2(deck())
if 1 < len(self.p1.counts):
rule = RuleSoft(fp, dealer, self.p1)
else:
rule = RuleHard(fp, dealer, self.p1)
while (rule == 2) or (rule == 3):
self.p1(deck())
if 1 < len(self.p1.counts):
rule = RuleSoft(fp, dealer, self.p1)
else:
rule = RuleHard(fp, dealer, self.p1)
if 1 < len(self.p2.counts):
rule = RuleSoft(fp, dealer, self.p2)
else:
rule = RuleHard(fp, dealer, self.p2)
while (rule == 2) or (rule == 3):
self.p2(deck())
if 1 < len(self.p2.counts):
rule = RuleSoft(fp, dealer, self.p2)
else:
rule = RuleHard(fp, dealer, self.p2)
def make_bet (self):
'''Place a bet according to bet-level.'''
self._track_min_max()
self._bet_level()
self.bet = self.bet_level
if self.bank < self.bet:
self.bet = self.bank
self.bank -= self.bet
def double_down (self):
'''Double-Down on bet.'''
if self.bet <= self.bank:
self.bet += self.bet
self.bank -= self.bet
def set_bet_level (self, win_flag):
'''Set next bet-level.'''
if win_flag:
if 5 <= self.bet_level:
self.bet_level = 5
return
if 3 <= self.bet_level:
self.bet_level = 5
return
if 2 <= self.bet_level:
self.bet_level = 3
return
if 1 <= self.bet_level:
self.bet_level = 2
return
self.bet_level = 1
def _bet_level (self):
'''Normalize bet-level.'''
if 5 <= self.bet_level:
self.bet_level = 5
return
if 3 <= self.bet_level:
self.bet_level = 3
return
if 2 <= self.bet_level:
self.bet_level = 2
return
self.bet_level = 1
def _track_min_max (self):
'''Track minimum and maximum bank.'''
if self.bank < self.min_bank:
self.min_bank = self.bank
if self.max_bank < self.bank:
self.max_bank = self.bank
def __str__ (self):
r = super(Player,self).__str__()
return 'Player %s' % r
'''eof'''