import randomfrom random import choiceimport osimport timeimport texttableclass Stack():    def __init__(self, replay, winnings):        self.start_amount = 100        self.stored_bet = 0        self.stored_end = 0        self.replay = replay        if self.replay == 0:            self.stored_end = 0   #needs to be initialized        else:            self.stored_end = self.stored_end + winnings    def load_account(self):        self.stored_end = self.start_amount    def account(self, begin, change):        end = float(begin) + float(change)        self.stored_end = end  # store class variable??        return(begin, change, end)    def bet_test(self, miss_type):        # collect's bet and check input        # miss_type should start as 0        possible_bets = ['5', '10', '15', '20', '25']        while True:            print \nWhat is your bet? (5, 10, 15, 20, 25)            bet = raw_input(' >')            if bet in possible_bets:                bet = int(bet)                if self.replay == 1:                    begin = self.stored_end                    self.stored_bet = int(bet)                    break                else:                    if bet > self.stored_end:                        print You don't have enough for that bet.                        time.sleep(2)                    else:                        begin = self.stored_end                        self.stored_bet = bet                        breakclass DECK():       def __init__(self):        suite = ('Spades', 'Hearts', 'Diamonds', 'Clubs')        rank = ('2', '3', '4', '5', '6', '7', '8', '9', '10', Jack, Queen, King, Ace)        self.full_deck = {}        n = 0        i = 0        for n in range(6):            for s in suite:                for r in rank:                    self.full_deck[i + n] = %s of %s % (r, s)                    i += 1            n += 1        self.values = {'Ace':11, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '10': 10, 'Jack': 10, 'Queen': 10, 'King': 10}        self.test_hand1 = {0: 'Ace of Spades', 1: 'Jack of Clubs' } # for testing        self.test_hand2 = {0: 'Ace of Clubs', 1: '10 of Diamonds' } # for testing        self.test_hand3 = {0: '8 of Spades', 1: '8 of Hearts'} # for testing splits        self.hand_dict = {} # this will be a dict of all the hand instances created by Hand.        self.incomplete_hands = {} # hands yet to be played        self.compltete_hands = {} # hands done being played        # re-split hands and counters        self.split_counter = 0    def hand_table(self):        # show table of hands        hands_dict = {}        bets_dict = {}        points_dict = {}        for hand in Hand.instances:            hands_dict.setdefault(hand.name, hand.hand_a)            bets_dict.setdefault(hand.name, hand.bet)            points_dict.setdefault(hand.name, hand.hand_points)        first_cards = []        second_cards = []        third_cards = []        fourth_cards = []        fifth_cards = []        bets_list = []        points_list = []        for hand in hands_dict:            first_cards.append(hands_dict[hand].get(0))            second_cards.append(hands_dict[hand].get(1))            third_cards.append(hands_dict[hand].get(2))            fourth_cards.append(hands_dict[hand].get(3))            fifth_cards.append(hands_dict[hand].get(4))            bets_list.append(Bet is %r % bets_dict[hand])            points_list.append(Points are %r % points_dict[hand])        print \n          header = hands_dict.keys()        table = texttable.Texttable()        table.header(header)        table.add_rows([first_cards, second_cards, third_cards, fourth_cards, fifth_cards, points_list, bets_list], header = False)        print table.draw()    def dhos(self):         # dealer hit or stick        os.system(clear)        #show table of hands        self.hand_table()        print  _  * 10        game.deck.d_hand.show_hand()        time.sleep(1.5)        dpoints, d_raw_points = game.deck.d_hand.points()        if dpoints < 17:            new_card = game.deck.full_deck.pop(random.choice(game.deck.full_deck.keys()))            print new_card            hl = len(game.deck.d_hand.hand_a.keys())  # hl is hand length            game.deck.d_hand.hand_a[hl] = new_card  # insert new hard into the given hand            self.dhos()        else:            game.deck.d_hand.hand_points = dpoints            game.end_game()    def deal(self):        # deal two cards each to dealer and player        dhand = {}        phand = {}        for i in range (2):            phand[i] = game.deck.full_deck.pop(random.choice(game.deck.full_deck.keys()))            dhand[i] = game.deck.full_deck.pop(random.choice(game.deck.full_deck.keys()))# actual hand                   # creat instance of Hand for player's starting hand        self.start_hand = Hand(phand, game.deck.full_deck, 0, Opening Hand)        # start_hand instance is now a member of the deck object.        # creat instance of Hand for dealer's starting hand        self.d_hand = Hand(dhand, game.deck.full_deck, 0, Dealer)        # d_hand instance is now a member of the deck object.    def split_algo(self, hand):        print hand.hand_a        # old cards        card1 = hand.hand_a[0]        card2 = hand.hand_a[1]        print card1        print card2        # new cards        card_a = self.full_deck.pop(random.choice(self.full_deck.keys()))        card_b = self.full_deck.pop(random.choice(self.full_deck.keys()))        print card_a        print card_b        #two new hands        new_hand_a = {0: card1, 1: card_a}        new_hand_b = {0: card2, 1: card_b}        if game.deck.split_counter == 0:            self.split_1 = Hand(new_hand_a, game.deck.full_deck, 0, 'Split 1')            self.split_2 = Hand(new_hand_b, game.deck.full_deck, 0, 'Split 2')            # load bets: equal to bet on first hand            self.split_1.bet = game.deck.start_hand.bet            self.split_2.bet = game.deck.start_hand.bet            split_hands_dict = {0: self.split_1, 1: self.split_2}            # find the staring hand 'test split' in this case and delete it            for x in range(len(Hand.instances)):                if Hand.instances[x-1].name == 'Opening Hand':                    del Hand.instances[x-1]        game.deck.split_counter += 1        return split_hands_dictclass Hand():    instances = [] # used to keep track of hand instances    def __init__(self, hand_a, play_deck, split_count, name): # hand_a for hand actual        Hand.instances.append(self)        self.hand_a = hand_a  # the actual hand when instance created        # self.play_deck = play_deck  #  need to move this to deck class        self.split_count = split_count        self.name = name        self.hand_points = 0        self.raw_points = 0        self.aces = 0        self.testy = self        self.status = 'incomplete'        self.bet = 0        self.stack_change = 0        self.outcome = ''        self.black_jack = 0    def show_hand(self):        print %r hand is: % self.name        for i in range(len(self.hand_a.keys())):            print self.hand_a[i]        print \n    def show_card(self, key):        return self.hand_a[key]    def points(self):          ln = len(self.hand_a.keys())        tpoints = 0        # add up all the cards with aces = 11        self.aces = 0        for i in range(ln):            card, rank = self.card_and_rank(self.hand_a[i])            # add up all the aces            if rank == 'Ace':                self.aces += 1            # deck is an object of game            tpoints = game.deck.values[rank] + tpoints            raw_points = tpoints        # check to see if there are aces in the hand.        if self.aces > 0:            for n in range(self.aces):                # check to see if the total points are more than 21.                if tpoints > 21:                    # subtract 10 points for each ace.                    tpoints = tpoints - 10          return (tpoints, raw_points)    def card_and_rank(self, card):        z = card.split()        rank = z[0]        return (card, rank)    def split_test(self):        card_a, rank_a = self.card_and_rank(self.hand_a[0])        card_b, rank_b = self.card_and_rank(self.hand_a[1])        val_a = game.deck.values[rank_a]        val_b = game.deck.values[rank_b]        if self.bet * 2 > stack.stored_end:            print You don't have enough cash to split.            time.sleep(2)            return 'no'        elif game.deck.split_counter == 1:            return 'no'        elif val_a == val_b:            return 'split'        else:            return 'no'    def hos(self):          # hos = hit or stick        os.system(clear)              self.hand_points, self.raw_points = self.points()        print \n        # show dealer's hand        print Dealer's up card is:\n%r\n % game.deck.d_hand.show_card(0)        # show starting hand        self.show_hand()        self.softness(self.hand_points, self.raw_points)                        print \nYou're bet is $%d. % stack.stored_bet        print Your stack is (less your current bet) $%d % (stack.stored_end - stack.stored_bet)        x = self.black_jack_check()        if x == 'black_jack':            self.black_jack = 1            answer = 'stick'            self.check_hand(answer)        if self.split_test() == 'split':                    answers = ['hit', 'stick', 'double', 'split']            while True:                print \nWould you like to 'hit', 'stick', 'double' down or 'split'?                if self.hand_points == 21:                    answer = 'stick'                    print You have 21!                    time.sleep(.5)                    break                else:                    answer = raw_input(' >')                    if answer in answers:                        print end of hos func                        break        else:            answers = ['hit', 'stick', 'double']            while True:                print \nWould you like to 'hit', 'stick' or 'double'?                if self.hand_points == 21:                    answer = 'stick'                    print You have 21!                time.sleep(.5)                break            else:                answer = raw_input(' >')                if answer in answers:                    print end of hos func                    break        self.check_hand(answer)    def check_hand(self, answer):        print \nYou said %r. % answer        # hit        if answer == 'hit':            self.hit()            if self.hand_points > 21:                self.status = 'completed'                print Your busted                print need to go to end game                self.status = 'completed'                return 'done'            hl = len(self.hand_a.keys())            if hl == 5:                self.status = 'completed'                return 'done'               self.hos()        # stick        elif answer == 'stick':            self.status = 'completed'            print need to call dhos and end the game        # double        elif answer == 'double':            t_bet = stack.stored_bet  # temp bet            t_end = stack.stored_end # temp stack balance (before bet)            t_bal = t_end - t_bet # what would the stack be if bet subtracted?            if t_bet > t_bal:                print You don't have enough to doule down.                print need to continue with hand - should check this when asking the question.                raw_input(Please hit enter to continue)            else:                print \nYou doubled down.                stack.stored_bet = stack.stored_bet * 2                self.bet = self.bet * 2                print Your bet is now $%d. % stack.stored_bet                self.hit()                self.show_hand()                self.status = 'completed'                time.sleep(3)        # split        elif answer == 'split':            if game.deck.split_counter == 0:                split_hands_dict = game.deck.split_algo(game.deck.start_hand)                ln = len(split_hands_dict)                for x in range(ln):                    split_hands_dict[x].hos()            else:                print Sorry, but no more splits.                time.sleep(2)        else:            print something went horribly wrong.            exit(0)         def softness(self, points, raw_points):        # returns soft hand if hand is soft        if self.aces > 0:            nap = raw_points - (self.aces * 11) # = non-ace - points            if nap + 11 < 21:                print \n%s has a soft %d % (self.name, points)                print  _  * 10                            else:                               print %s has %d points.  a % (self.name, points)                  print  _  * 10                else:            print %s has %d points. % (self.name, points)            print  _  * 10    def black_jack_check(self):        # print  _  * 10        # print \n        zz = {}        for i in range(len(self.hand_a.keys())):            card, rank = self.card_and_rank(self.hand_a[i])            # print card is %r and rank is %r % (card, rank)            zz[i] = rank            i += 1        if zz[0] == 'Ace' and zz[1] == Jack:            # print zz[0] is %r and zz[1] is %r a  % (zz[0], zz[1])            print \nBlack Jack!  You Win!\n            time.sleep(1.5)            return black_jack        elif zz[0] == 'Jack' and zz[1] == 'Ace':            # print zz[0] is %r and zz[1] is %r b % (zz[0], zz[1])            print \nBlack Jack!  You Win!\n            time.sleep(1.5)            return black_jack        else:            return 0    def hit(self):        print hit method        k = len(game.deck.full_deck.keys())        print k        new_card = game.deck.full_deck.pop(random.choice(game.deck.full_deck.keys()))        # hl = len(game.deck.start_hand.hand_a.keys())  # hl is hand length        hl = len(self.hand_a.keys())  # hl is hand length        print hl        # add new card tto hand        self.hand_a[hl] = new_card  # insert new hard into hand of the given instance.        # add new opints to self.hand_points        self.hand_points, self.raw_points = self.points()class Game():    def __init__(self):        self.hand_dict = {} # this will be a dict of all the hand instances created by Hand.        self.incomplete_hands = [] # hands yet to be played        self.compltete_hands = {} # hands done being played    def collect_hands(self):        # loops trough Hand.instances and unpacks into indivudual hands        print \nbegin collect_hands\n        i = 0        for handy in Hand.instances:            self.hand_dict.setdefault(handy.name, handy.hand_a)            i += 1        print self.hand_dict        print \n        for player in self.hand_dict:            print player            n = 0            for n in range(len(self.hand_dict[player])):                print self.hand_dict[player][n]                n += 1        print print card rows        # list of rows        first_cards = []        second_cards = []               third_cards = []        fourth_cards = []        fifth_cards = []        list_of_rows_raw = [first_cards, second_cards, third_cards, fourth_cards, fifth_cards]        for x in self.hand_dict:            first_cards.append(self.hand_dict[x][0])        for y in self.hand_dict:            second_cards.append(self.hand_dict[y][1])        table = texttable.Texttable()        header = self.hand_dict.keys()        table.header(header)        table.add_rows([first_cards, second_cards], header=False)        print table.draw()    def end_game(self):        # check to see how each completed hand did against the dealer        dpoints = self.deck.d_hand.hand_points        for hand in Hand.instances:            hand.stack_change = 0            if hand.status == 'completed':                # print hand is %r hand.name                print hand points are %r % hand.hand_points                print dpoints are %r % dpoints                print bet is %r % hand.bet                if hand.hand_points == 21:                    if hand.black_jack == 1:                        hand.stack_change = hand.stack_change + ((float(3)/2) * hand.bet)                        hand.outcome = Black Jack!!                    else:                        hand.stack_change += hand.bet                        hand.outcome = Win                elif hand.hand_points > 21:                    hand.stack_change -= hand.bet                    hand.outcome = Lose                elif dpoints > 21:                     hand.stack_change += hand.bet                    hand.outcome = Win                elif hand.hand_points < dpoints:                    hand.stack_change -= hand.bet                    hand.outcome = Lose                elif hand.hand_points > dpoints:                    hand.stack_change += hand.bet                    hand.outcome = Win                                    elif hand.hand_points == dpoints:                    hand.stack_change + 0                    hand.outcome = Push                   else:                    print not sure what to tell you                    exit(0)        self.check_score()    def check_score(self):        #check to see if player has money to play again        total_winnings = 0        for hand in Hand.instances:            total_winnings = total_winnings + hand.stack_change        if stack.stored_end + total_winnings < 0:            print You're out of cash.  Goodbye!            exit(0)        else:            stack.stored_end += total_winnings        self.replay(0, total_winnings)    def replay(self, miss_type, total_winnings):        # show table of hands        os.system(clear)        print Your hands: \n        hands_dict = {}        bets_dict = {}        outcomes_dict = {}        points_dict = {}        for hand in Hand.instances:            hands_dict.setdefault(hand.name, hand.hand_a)            bets_dict.setdefault(hand.name, hand.bet)            outcomes_dict.setdefault(hand.name, hand.outcome)            points_dict.setdefault(hand.name, hand.hand_points)        first_cards = []        second_cards = []        third_cards = []        fourth_cards = []        fifth_cards = []        bets_list = []        outcomes_list = []        points_list = []        for hand in hands_dict:            first_cards.append(hands_dict[hand].get(0))            second_cards.append(hands_dict[hand].get(1))            third_cards.append(hands_dict[hand].get(2))            fourth_cards.append(hands_dict[hand].get(3))            fifth_cards.append(hands_dict[hand].get(4))            bets_list.append(Bet is %r % bets_dict[hand])            points_list.append(Points are %r % points_dict[hand])            outcomes_list.append(outcomes_dict[hand])        header = hands_dict.keys()        table = texttable.Texttable()        table.header(header)        table.add_rows([first_cards, second_cards, third_cards, fourth_cards, fifth_cards, points_list, bets_list, outcomes_list], header = False)        print table.draw()        print \n        self.deck.d_hand.show_hand()        print Dealer's points are %r. % self.deck.d_hand.hand_points        print \nYou won $%r % total_winnings        print Your stack is now $%r\n % stack.stored_end        if stack.stored_end <=0:            print You're out of cash.  Better luck next time!            exit(0)        while True:            print \nWould you like to play again?            a = raw_input(' >')            if a == 'no':                print Thanks for playing.                print You ended up with $%d\n % stack.stored_end                exit(0)            elif a =='yes':                hil = len(Hand.instances) # hil = hand instances length                for x in range(hil):                    del Hand.instances[x-1]                time.sleep(1)                game.play_game(1, total_winnings)                 break               else:                print just 'yes' or 'no' please.                time.sleep(1)    def load_inc_hands(self):        # load first opening hand into incomplete hadns dict.        # remove dealer hand         lnth = len(Hand.instances)        for x in range(lnth):            if Hand.instances[x-1].name == 'Dealer':                del Hand.instances[x-1]        lnth = len(Hand.instances)        for z in range(lnth):            self.incomplete_hands.append(Hand.instances[z].name)    def play_game(self, replay, total_winnings):# start        self.deck = DECK()        if replay == 1:            self.stack = Stack(1 , total_winnings)        os.system(clear)        print Let's play!\n        print  _  * 10        begin = stack.stored_end  # need this here for when game is replayed        begin, change, end = stack.account(0, begin) #laod account func with initical balance        print You have $%d in your stack.\n % end        print  _  * 10        time.sleep(0.5)        play_deck = self.deck.full_deck# bet        stack.bet_test(0)        bet = stack.stored_bet# deal        self.deck.deal()# attach the bet to the starting hand        self.deck.start_hand.bet = bet        os.system(clear)        print deck has %r cads % len(play_deck.keys())        print play_game method of Game class\n                # load incomeplete hands dict        self.load_inc_hands()# go thorugh each hand and hit or stick        for hand in Hand.instances:            if hand.status == 'incomplete':                print you're stuck in the hos loop                hand.hos()      # go to dealer's hand                   self.deck.dhos()        exit(0)if __name__ == '__main__':    game = Game()    stack = Stack(0, 0)    stack.load_account()    game.play_game(0, 0)First, if there's a better way to get the code in here than copy and paste, please let me know.  Checking all the indents in python is a bit of a pain.Second, please rip up this code!  I'm trying to learn Python on my own and need all the feedback I can get.  Please comment on everything: best practices, conventions...etc.  Any and all comments welcome.
Blackjack game in Python
python;game;playing cards
Python convention is to name classes with CamelCase, not ALL_CAPSDon't use 1 and 0 for boolean values, use True and FalseDon't mix UI and logic. You should have some classes/functions that implement the rules for the game, and completely different classes/functions for the user interface.Avoid the use of mutable class variable like Hand.instancesYour classes don't seem to have a defined identity. Your Stack class seems like it should represent a stack of chips. But it also seems to be keeping track of past history a little bit? I'm really not quite sure what the replay logic is doing.The rules of the game seem to be strewn all over the code. Look at the number of places that have 21.Let's take a detailed look at one function:def bet_test(self, miss_type):    # collect's bet and check input    # miss_type should start as 0    possible_bets = ['5', '10', '15', '20', '25']Constant lists like this should be global constants.     while True:        print \nWhat is your bet? (5, 10, 15, 20, 25)        bet = raw_input(' >')        if bet in possible_bets:            bet = int(bet)I don't like reusing variables for different things. i.e. the text and number version of the bet. I'd store them in different names.            if self.replay == 1:Use if self.replay: for boolean values                begin = self.stored_endYou set begin, but you don't seem to do anything with it...                self.stored_bet = int(bet)bet is already an int                break            else:                if bet > self.stored_end:Why not use an elif here to force,                     print You don't have enough for that bet.                    time.sleep(2)                else:                    begin = self.stored_end                    self.stored_bet = bet                    breakYou've done this twice. You should rearrange the code so that it happens only once.Here's my reworking of that function:def bet_test(self, miss_type):    # collect's bet and check input    # miss_type should start as 0    possible_bets = range(5, min(25, self.stored_end+1), 5)    while True:        print \nWhat is your bet? (%s) % (, .join(possible_bets))        try:            bet = int(raw_input(' >'))        except ValueError:            pass # make them try again        else:            if bet in possible_bets:                self.stored_bet = bet                break    self.stored_bet = bet