savetz.com
 
10-Line Blackjack

Hot on the heels of the poker game, I wrote a blackjack game for the 10-line BASIC contest. It is also in TurboBASIC XL on the Atari 8-bit, and also in ten 120-character lines. I borrowed the card shuffling code from the poker game, but otherwise it’s all new code.
As always with these short programs, there were some space tradeoffs. In exchange for a wallet/calculating money, I found room to show simple card graphics. I also had to give up the custom character with the cute little “10” character. Instead, “T” represents the 10 card.
Like standard blackjack, it starts by dealing your two cards face up, one dealer card face up and one face down. You can press H to hit (take another card) or S to stand (stop taking cards.) (This version does not support doubling down or splitting hands.) After you Stand, it reveals the dealer’s face-down card and the dealer plays. The dealer follows standard Las Vegas rules: always hitting on 16 or less; always standing on 17 or more.
The biggest challenge was calculating Aces, which in Blackjack can count for either 1 or 11. When figuring the player’s score, it starts by assuming an Ace is worth 1. When the player Stands: if the player holds an ace and counting it as 11 won’t cause the player’s total to exceed 21, it adds 10 to the player’s total. On the other hand, when calculating the dealer’s score, it starts by assuming an Ace is worth 11. If after a hit the dealer’s total exceeds 21 and it holds an Ace, it reduces the dealer’s total by 10 and keeps on playing.
Here’s the code:
REM BLACKJACK - KEVIN SAVETZ - JAN 2-3 2020

DIM CARDT$(15),CARDM$(15),CARDS$(15),CARDD$(15),CARDE$(15),SUIT$(4),N$(13),U(52),D(14),NUMCARDS(1),SUM(1),V$(13),I$(1),ACES(1)

GR.0
POKE 82,0

CARDT$="\11\12\12\12\12\12\05\1E\1E\1E\1E\1E\1E\1E\1D"
CARDM$="\7C     \7C\1E\1E\1E\1E\1E\1E\1E\1D"

'CARDT$: card top
'CARDM$: card middle
'CARDS$: card middle with suit
'CARDD$: card middle with number in upper left
'CARDE$: card middle with number in lower right
'Card bottom and card back are drawn in the GOSUB area without strings to save space here

'U: Temp. storage whether a card has been placed in the deck
'D: Deck of randomized cards
'NUMCARDS: Number of Cards held by player/dealer
'SUM: SUm of player and dealer cards
'I$: storage for INKEY$ keyboard input
'ACES: Number of ACes held by player/dealer that may be counted at the other value (1/11)

N$="A23456789TJQK":'one-character card names.
V$="\01\02\03\04\05\06\07\08\09\0A\0A\0A\0A":'values of cards A-K

SUIT$="\00\10\60\7B":'heart club diamond spade

'SHUFFLE
FOR X=0 TO 14:'Fill slots. Only slotting 15 cards is faster than 52.
    N=0
    WHILE N=0:'while we haven't found a card for this slot
        Y=RAND(52):'which card might go in this slot?
        IF (U(Y)=0):'if we haven't slotted this card yet
            D(X)=Y:'slot now contains this card
            U(Y)=1:'mark card as used in a slot
            N=1:'move on to next card
        ENDIF
    WEND
NEXT X

'Deal cards
FOR HAND=0 TO 1
    FOR P=0 TO 1
        OB=HAND AND P:'if second card going to dealer, show card back (OBscure it)
        GOSUB 50
    NEXT P
NEXT HAND

'Ask Hit or Stand
WHILE I$<>"S" AND SUM(0)<22
    I$=""
    ?"\1D\C8it/\D3tand?";
    WHILE I$<>"S" AND I$<>"H"
        I$=INKEY$
    WEND

    ?"\9C":'erase old Hit/Stand query

    IF(I$="H")
        P=0:'the player is getting cards
        GOSUB 50
    ENDIF
WEND

'After player has played, while player holds an ace, and if 11 is better for the
'score than 1, add 10 to the SUm total.
WHILE ACES(0) AND SUM(0)+10<22
    ACES(0)=ACES(0)-1
    SUM(0)=SUM(0)+10
WEND

P=1:'Now dealer's turn
GOSUB 50:'reveal SEcret OBscubed card

IF ((SUM(0)=21 AND NUMCARDS(0)=2)=0):'Skip next part if player got blackjack
    WHILE (SUM(0)<22 AND SUM(1)<17):'if player hasn't busted and dealer's hand <=16
        PAUSE 60
        GOSUB 50

        'If >21 but dealer holds an ACe, change value of that ace from 11 to 1
        WHILE SUM(1)>21 AND ACES(1)
            ACES(1)=ACES(1)-1
            SUM(1)=SUM(1)-10
        WEND        
    WEND
ENDIF

'Display totals and winner
POS.0,22
?"You: ";SUM(0);"\7F\7FDealer: ";SUM(1)

'reusing CARDT$ for the summary text
CARDT$="Push"
IF SUM(0)<22
    IF SUM(1)>21 OR SUM(1)<SUM(0)
        CARDT$="You win!"
    ENDIF
    IF SUM(1)<22 AND SUM(1)>SUM(0)
        CARDT$="Dealer wins"
    ENDIF
ELSE
    CARDT$="Busted"
ENDIF
?CARDT$;

WHILE INKEY$="":WEND
RUN

50 
    CARDS$=CARDM$:CARDD$=CARDM$:CARDE$=CARDM$
    POS. NUMCARDS(P)*2+P*20,2+NUMCARDS(P)*2
    IF (P=1 AND SE):'reveal the SEcret card
        X=SE-1
        SE=0
    ELSE
        X=D(Z):'otherwise, next card in the deck
        Z=Z+1:'set pointer to next card
    ENDIF
    N=X MOD 13+1:M=X DIV 13+1

    ?CARDT$;:'card top
    IF (OB=0):'if not OBscuring card...
        CARDS$(4,4)=SUIT$(M,M):'put suit on card middle
        CARDD$(2,2)=N$(N,N):'put number on upper-right
        CARDE$(6,6)=N$(N,N):'and lower-left
        ?CARDD$;CARDM$;CARDM$;CARDS$;CARDM$;CARDM$;CARDE$;
        SUM(P)=SUM(P)+ASC(V$(N,N)):'add to player's SUm total IF card face is shown
        SUM(P)=SUM(P)+(10*P*(N=1)):'When dealer draws an ace, count it as 11
        NUMCARDS(P)=NUMCARDS(P)+1:'increment Number of Cards held by player
        ACES(P)=ACES(P)+(N=1):'numbr of ACes held by that player
    ELSE:'OBscuring card
        FOR X=1 TO 7:?"\7C.....\7C\1E\1E\1E\1E\1E\1E\1E\1D";:NEXT X:'back of card pattern
        SE=N:'save SEcret card
        OB=0:'don't OBscure next card
    ENDIF
    ?"\1A\12\12\12\12\12\03":'card bottom
RETURN

