import random
import copy
 
## Constants
HIT, STAND = 1, 2
ACE = 1
CLUBS, DIAMONDS, HEARTS, SPADES = 1, 2, 3, 4
IN_PLAY, DEALER_BLACKJACK, PLAYER_BLACKJACK, PUSH, WIN, LOSE, BUST = 1, 2, 3, 4, 5, 6, 7
RESULTS = [None, "In play", "Dealer blackjack", "Player blackjack",
           "Push", "Win", "Lose", "Bust"]
SUITS = ["Clubs","Diamonds","Hearts","Spades"]
RANKS = ["Ace","2","3","4","5","6","7","8","9","10","Jack","Queen","King"]
 
 
class GameState:
    def __init__(self):
        self.playerCards = []
        self.dealerCards = []
        self.money = 0
        self.result = None
        self.deck = Deck()
     
 
class Card:
    def __init__(self, rank, suit):
        self.rank = rank
        self.suit = suit
 
    def __repr__(self):
        return "%s of %s" % (RANKS[self.rank-1], SUITS[self.suit-1])
 
 
class Deck:
    def __init__(self):
        self.deck = []
         
        for s in range(1,5):
            for r in range(1,14):
                self.deck.append(Card(r,s))
                 
        random.shuffle(self.deck)
         
    def Deal(self, num=1):
        if num==1:
            return self.deck.pop(random.randint(0,len(self.deck)-1))
        else:
            cards = []
            for n in range(0,num):
                cards.append(self.Deal())
            return cards
 
     
class Blackjack:
    def Count(self, cards):
        sum = [0]
        for c in cards:
            if c.rank == ACE:
                k = len(sum)
                for n in range(0,k):
                    sum[n] += 1
                    sum.append(sum[n]+10)
                sum = list(set(sum))
            else:
                for n in range(0,len(sum)):
                    if c.rank >= 10:
                        sum[n] += 10
                    else:
                        sum[n] += c.rank
        sum.sort()
        return sum
 
    def Trim(self, cards):
        trimmed = []
        for n in cards:
            if n <= 21:
                trimmed.append(n)
        if trimmed == []:
            trimmed = [min(cards)]
        return trimmed
     
    def Action(self, action, s):
        state = copy.deepcopy(s)
        if action == STAND:
            dealerVals = self.Count(state.dealerCards)
            while max(dealerVals) < 17:
                state.dealerCards.append(state.deck.Deal())
                dealerVals = self.Trim(self.Count(state.dealerCards))
            if max(dealerVals) > 21 or max(dealerVals) < max(self.Trim(self.Count(state.playerCards))):
                state.result = WIN
                state.money += 1
            elif max(dealerVals) == max(self.Trim(self.Count(state.playerCards))):
                state.result = PUSH
            else:
                state.result = LOSE
                state.money -= 1
        elif action == HIT:
            state.playerCards.append(state.deck.Deal())
            if min(self.Count(state.playerCards)) > 21:
                state.result = BUST
                state.money -= 1
 
        return state
 
    def NewHand(self):
        state = GameState()
        state.dealerCards = state.deck.Deal(2)
        state.playerCards = state.deck.Deal(2)
         
        if (max(self.Count(state.dealerCards)) == 21 and
            max(self.Count(state.playerCards)) == 21):
            state.result = PUSH
        elif max(self.Count(state.dealerCards)) == 21:
            state.result = DEALER_BLACKJACK
            state.money -= 1
        elif max(self.Count(state.playerCards)) == 21:
            state.result = PLAYER_BLACKJACK
            state.money += 2
        else:
            state.result = IN_PLAY
 
        return state
 
         
def main():
    bj = Blackjack()
    money = 0
    action = None
     
    while True:
        state = bj.NewHand()
        print "Dealer shows: %s" % state.dealerCards[0]
        print "Your cards: %s" % state.playerCards
 
        if state.result == PUSH:
            print "Dealer shows: %s" % state.dealerCards
            print "PUSH"
        elif state.result == DEALER_BLACKJACK:
            print "Dealer shows: %s" % state.dealerCards
            print "Dealer blackjack! <img src="http://trevorcappallo.com/wp-includes/images/smilies/icon_sad.gif" alt=":(" class="wp-smiley"> "
            money += state.money
        elif state.result == PLAYER_BLACKJACK:
            print "Dealer shows: %s" % state.dealerCards
            print "You got a blackjack! <img src="http://trevorcappallo.com/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley"> "
            money += state.money
        else:
            while state.result == IN_PLAY:
                print "\nYour move (1 for hit, 2 for stand, any other to quit):",
                action = input()
                if action != 1 and action != 2:
                    return
 
                state = bj.Action(action, state)
                print "Your cards: %s" % state.playerCards
                if state.result != IN_PLAY:
                    print "Dealer cards: %s" % state.dealerCards
                    print "Result: %s" % RESULTS[state.result]
                    money += state.money
        print "\nYour balance: %i" % money
        print "---------------------------------------------------------"
             
             
if __name__ == '__main__':
    main()