bj.py

'''\
Blackjack - Play.

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 stdoutstderrargv
from os import path
from datetime import datetimetimedelta
from htmlpage import htmlpage
from bj_objects import CardDeckDealerPlayer
####################################################################################################
#TODO: Validate operation!
#TODO: Try different rules.

HtmlPath = r'C:\CJS\www\root\tmp'

nbr_of_plays = 250
nbr_of_decks = 4
player_bank  = nbr_of_plays
dealer_bank  = 1000000


##================================================================================================##
def PlayBlackjack ():
    data = []
    deck = []
    dealer = Dealer(dealer_bank)
    player = Player(player_bank)
    decks_used = 0

    #TODO: Change to Log!
    fn = 'bj.out'
    fp = open(fn'w')
    try:
        print >> fp'@@: %s' % datetime.now()
        print >> fp'Bank: Player: %d, Dealer: %d' % (player.bankdealer.bank)
        print >> fp

        play = 1
        while (play <= nbr_of_playsand (100 < dealer.bankand (0 < player.bank):
            if len(deck) < 13:
                deck = CardDeck(nbr_of_decks)
                decks_used += 1
                print >> fp'New Deck: ' + str(deck)
                print >> fp

            # Play...
            dealer.new_hand()
            player.new_hand()
            print >> fp'Play: %d' % play

            # Bet...
            player.make_bet()
            print >> fp'Bet: %d  {pot: %d}' % (player.betplayer.bank)

            # Deal first card...
            player(deck())
            dealer(deck())
            # Deal second card...
            player(deck())
            dealer(deck())

            # Player plays...
            player.play_hand(deckdealerfp)
            if player.split_pair_flag:
                print >> fpplayer.p1
                print >> fpplayer.p2
            else:
                print >> fpplayer

            # Dealer plays...
            dealer.play_hand(deckplayerfp)
            print >> fpdealer

            # Payoff bets...
            if WinLose(fpdealerplayer):
                player.set_bet_level(True if 0 < player.win_lose else False)
            print >> fp'Bank: Player: %d, Dealer: %d' % (player.bankdealer.bank)

            # Data collection...
            if player.split_pair_flag:
                t1 = (playplayer.p1.win_loseplayer.p1.betplayer.bet_levelplayer.bankplayer.p1.cardsdealer.cards)
                t2 = (playplayer.p2.win_loseplayer.p2.betplayer.bet_levelplayer.bankplayer.p2.cardsdealer.cards)
                data.append(t1)
                data.append(t2)
            else:
                t = (playplayer.win_loseplayer.betplayer.bet_levelplayer.bankplayer.cardsdealer.cards)
                data.append(t)

            # loop...
            play += 1
            print >> fp

        print >> fp
        print >> fp'EXIT'
        print >> fp'@@: %s' % datetime.now()
        print >> fp'Player Bank: %6d' % player.bank
        print >> fp'Bank Change: %+5d' % (player.bank - player.original_bank)
        print >> fp'Max Bank: %5d' % player.max_bank
        print >> fp'Min Bank: %5d' % player.min_bank
        print >> fp'Card Decks: %d' % decks_used
        print >> fp'Cards remaining in deck: %d' % len(deck)
        print >> fp
        print
        print 'Total Plays: %d' % play
        print 'Bank: Player: %d, Dealer: %d' % (player.bankdealer.bank)
        print 'Bank Change: %+5d' % (player.bank - player.original_bank)
        print 'Max Bank: %5d' % player.max_bank
        print 'Min Bank: %5d' % player.min_bank
        print 'Card Decks: %d' % decks_used
        print 'Cards remaining in deck: %d' % len(deck)
        print

    except Exception as e:
        print >> fpe
        raise

    finally:
        fp.close()
        print 'wrote: %s' % fn

    return (dealerplayerdata)

##================================================================================================##
def WinLose (fpdealerplayer):
    # Split Pair...
    if player.split_pair_flag:
        player.p1.win_lose = WinLoseHand(fpdealerplayerplayer.p1)
        player.p2.win_lose = WinLoseHand(fpdealerplayerplayer.p2)
        player.win_lose = int((player.p1.win_lose + player.p2.win_lose) / 2)
    # Normal Hand...
    else:
        player.win_lose = WinLoseHand(fpdealerplayerplayer)
    return player.win_lose

##================================================================================================##
def WinLoseHand (fpdealerplayerplayer_hand):
    fmt = 'Outcome: %s'
    if player_hand.bust():
        print >> fpfmt % 'Player Busts!'
        dealer.bank += player.bet
        return -1
    if dealer.blackjack():
        if player_hand.blackjack():
            # Tie...
            print >> fpfmt % 'Blackjack Tie!'
            player.bank += player.bet
            return 0
        # Dealer wins...
        print >> fpfmt % 'Dealer Blackjack!'
        dealer.bank += player.bet
        return -1
    if player_hand.blackjack():
        # Player blackjack...
        print >> fpfmt % 'Blackjack!'
        dealer.bank -= (1.5 * player.bet)
        player.bank += (2.5 * player.bet)
        return +2
    if dealer.bust():
        # Player wins...
        print >> fpfmt % 'Dealer Busts!'
        dealer.bank -= player.bet
        player.bank += (2 * player.bet)
        return +1
    if dealer.hand == player_hand.hand:
        # Tie...
        print >> fpfmt % 'Push!'
        player.bank += player.bet
        return 0
    if dealer.hand < player_hand.hand:
        print >> fpfmt % 'Player Wins!'
        dealer.bank -= (1 * player.bet)
        player.bank += (2 * player.bet)
        return +1
    print >> fpfmt % 'Player Loses!'
    dealer.bank += player.bet
    return -1




##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class PageWriter (object):
    '''HTML Page Writer class.'''
    results = {-1:'Lose'0:'Push', +1:'Win!', +2:'BJ!'}

    def __init__ (self_player_data):
        self.ts = datetime.now()
        self.player = _player
        self.data = _data

    def create_html_page (selffilename):
        fp = open(filename'w')
        try:
            H1 = 'Blackjack'
            H2 = 'Python'
            H3 = 'Blackjack Play Log'
            SS = ['/basic.css']
            JS = []
            pg = htmlpage(H3h1=H1h2=H2csspages=SSjspages=JS)
            pg.writepage(fpself)
            #...
            print 'wrote: %s' % filename
        except Exception as e:
            raise
        finally:
            fp.close()

    def writepage (selffp):
        fp.write('<div style="font-size:medium;border-spacing:4px 0;padding:0;margin:6pt 12pt;">\n')
        fp.write('<div>%s</div>' % self.ts.strftime('%c'))
        nh = len(self.data)
        np = self.data[nh-1][0]
        fp.write('<div>Plays: %d (Hands: %d)</div>' % (np,nh))
        fp.write('<div>Player Bank: %6d (Original: %d)</div>' % (self.player.bankself.player.original_bank))
        dif = self.player.bank - self.player.original_bank
        pct = 100.0 * (self.player.bank / self.player.original_bank)
        fp.write('<div>Bank Change: <strong>%+5d</strong> (%.2f%%)</div>' % (dif,pct))
        fp.write('<div>Max Bank: %5d</div>' % self.player.max_bank)
        fp.write('<div>Min Bank: %5d</div>' % self.player.min_bank)
        fp.write('</div>\n')

        fp.write('<table style="font-size:small;border-spacing:4px 0;padding:0;border:1px solid black;margin:12pt;">\n')
        fp.write('<thead style="font-style:italic;">\n')
        fp.write('<tr>\n')
        fp.write('<th>#</th>\n')
        fp.write('<th>&raquo;&raquo;&raquo;</th>\n')
        fp.write('<th>&equiv;</th>\n')
        fp.write('<th>bet</th>\n')
        fp.write('<th>&plusmn;</th>\n')
        fp.write('<th>$$</th>\n')
        fp.write('<th style="text-align:left;">Player</th>\n')
        fp.write('<th style="text-align:left;">Dealer</th>\n')
        fp.write('</tr>\n')
        fp.write('</thead>\n')

        fp.write('<tbody>\n')
        for datum in self.data:
            r = self.results[datum[1]]
            cr = 'red' if datum[1] < 0 else ('green' if 0 < datum[1else 'blue')
            b = (datum[4] - self.player.original_bank)
            cb = 'red' if datum[4] < self.player.original_bank else 'green'
            fp.write('<tr>\n')
            fp.write('<td style="text-align:left;padding:3px 4pt;">%4d</td>\n' % datum[0])
            fp.write('<td style="color:%s;font-weight:bold;text-left:right;padding:3px 9pt 3px 6pt;">%s</td>\n' % (cr,r))
            fp.write('<td style="text-align:center;padding:3px 4pt;">%s</td>\n' % str(datum[3]))
            fp.write('<td style="font-weight:bold;text-align:right;padding:3px 9pt 3px 6pt;">%d</td>\n' % datum[2])
            fp.write('<td style="color:%s;text-align:right;padding:3px 9pt 3px 6pt;">%+.1f</td>\n' % (cb,b))
            fp.write('<td style="text-align:right;padding:3px 6pt 3px 4pt;">%.1f</td>\n' % datum[4])
            fp.write('<td style="text-align:left;padding:3px 4pt;">%s</td>\n' % str(datum[5]))
            fp.write('<td style="text-align:left;padding:3px 4pt;">%s</td>\n' % str(datum[6]))
            fp.write('</tr>\n')

        fp.write('</tbody>\n')
        fp.write('</table>\n')
        fp.write('\n')



##================================================================================================##
def do_main (*args):
    print 'main/parameters: %d' % len(args)
    filename = args[0if 0 < len(argselse 'bj_play.html'
    htmlname = path.join(HtmlPathfilename)
    # Play...
    dealerplayerdata = PlayBlackjack()
    # Print...
    pgwr = PageWriter(playerdata)
    pgwr.create_html_page(htmlname)
    return 'Done!'
####################################################################################################
def dispatch (cmd, *args):
    print 'command: %s' % cmd
    print 'arguments: %d' % len(args)
    if cmd == 'test': return do_main(*args)
    if cmd == 'main': return do_main(*args)
    return 'Nothing to do!'
####################################################################################################
if __name__ == '__main__':
    print 'autorun: %s' % argv[0]
    cmd = argv[1if 1 < len(argvelse ''
    etc = argv[2:if 2 < len(argvelse []
    obj = dispatch(cmd, *etc)
    print obj
####################################################################################################
'''eof'''