I am posting this program for a friend of mine. Please send along any
enhancements or corrections.
This is a program I have written to play blackjack on the HP28s. I
am not a big Vegas gambler so it may not be up to your standards.
The dealer (hp28) and you are each dealt two cards. Both of
your cards are dealt face up, naturally, and the HP's are dealt one up
and one down, represented as "?". You can then hit or stand using H and S
on the keypad. You win by getting a higher score than the HP or by
getting five cards totalling under 21. You are allowed to make a bet
before the cards are dealt and this bet is added to or subtracted from your
current winnings stored in 'PURSE', which must be initially set to some
value before you play.
The program consists of five programs. 'ENT' is used at the beginning
to enter your bet. Your current total is displayed and you may not make a
bet exceeding this. Deal is a program to deal cards. It returns two items to
the stack. In level two is a number representing the pt. value of the card
dealt and in level one is a number or letter such as 'J', 'Q', 'K', or 'A'
representing the face cards. 'Score' merely calculates the score of the
hand in level 1. A blackjack is given a score of 1 and five cards totalling
no more than 21 is represented as a 2. 'WIN' determines who is the winner.
Finally, 'BLKJ' is the main program fitting it all together.
I am sure there are improvements just begging to be made so make
any changes you like.
'DECK' this is a matrix representing the deck
----------------------------------------------
[[1 1 1 1]
[2 2 2 2]
[3 3 3 3]
[4 4 4 4]
[5 5 5 5]
[6 6 6 6]
[7 7 7 7]
[8 8 8 8]
[9 9 9 9]
[10 10 10 10]
[11 11 11 11]
[12 12 12 12]
[13 13 13 13]
'ENT' accepts your bet
----------------------
<< CLLCD "ENTER BET" 1 DISP
"FOLLOWED BY A '.'"
2 DISP "PURSE = "
PURSE ->STR + 4 DISP ;Display messages
"" ;Set so strings can be directly added on stack
DO
DO
UNTIL KEY ;get a key input
END "" 4 DISP DUP NUM DUP
IF 48 >= SWAP 57 <= AND ;make sure it is a numerical key
THEN
+ DUP DUP DUP 3 DISP ;add to string containing the bet
->STR 'BET' STO ;store the bet so far
END
IF BET PURSE >
THEN
"TOO LARGE" 4 DISP ;assure bet is not greater than money available
DROP "" SWAP ;start building a new string
END
UNTIL "." SAME ;if don't have a "." and as long as the bet
BET PURSE <= AND ; doesn't exceed the purse get another entry
END DROP "" 3 DISP >> ;clear the area where the bet was displayed
'SCORE' calculates the score of the hand in level one. The score is returned
to level one at the end of the routine. On level two a runniing tally of
the number of ACES in the hand is kept; so that, if the total is over 21,
10 can be subtracted for each ace until there are no more aces, or the score
is under 21. The hands are represented as a list. e.g. {7 8 4}
'SCORE'
--------
<< DUP LIST-> -> c ;c is the number of cards in the hand
<< 0 0 1 c START ;aces=0, score=0 loop from 1 to number of cards
3 ROLL DUP
IF 11 == ;determine if the current card is an ace
THEN
3 ROLL 1 + 3 ROLLD ;an ace was found so increase the count
END + ;add the card value to the score
NEXT DUP
IF 21 == 2 c == AND ;determine if it's a blackjack
THEN
DROP 1 ;drop current score and replace with 1
END
WHILE DUP 21 > 3 PICK ;if the score > 21 and the hand had aces in it
0 != AND
REPEAT
10 - SWAP 1 - SWAP ;subrtract 10 and decrement the number of aces
END DUP
IF 21 <= C 5 == AND ;case of 5 cards totalling under 21
THEN
DROP 2 ;replace the current score with 2
END
SWAP DROP >> >> ;remove the ace count
'DEAL' deals one card. The card is placed on the stack twice. Level 2
contains the point value of the card and level one has a number or letter
representing the actual card. The deck is kept in a matrix 'TDECK' which
is a copy of 'DECK'. A zero is places where a card is picked from
<< DO
RAND 13 * IP 1 + ;get the row from which the card is picked
RAND 4 * IP 1 + ;get the column from which the card is picked
2 ->LIST 'INDEX' STO
'TDECK' INDEX GET
UNTIL 0 != END ;get an index until a nonzero number occurs
'TDECK' INDEX DUP2 GET ;retrieve the card from the matrix
3 ROLLD 0 PUT ;put zero in the position card comes from
{1 11 12 13} POS ;determine if it is an ace or face card
OVER POS
IF 0 != ;if its a face card or ace get its letter
THEN -> c ; equivalent
<< IF c 11 ==
THEN 10 'J' END ;it's a jack
IF c 12 ==
THEN 10 'Q' END ;it's a queen
IF c 13 ==
THEN 10 'K' END ;it's a king
IF c 1 ==
THEN 11 'A' END >> ;it's an ace
ELSE DUP END ;the pt value equals the card number
'INDEX' PURGE >>
'WIN' determines the winner
---------------------------
<< IF CSCORE 1 == ;check for the HP having blackjack
THEN
'PURSE' BET STO-
"BLACKJACK YOU LOSE"
4 DISP
ELSE
IF PSCORE 1 == ;check for the player having blackjack
THEN
BET 'PURSE' STO+
"BLACKJACK YOU WIN"
4 DISP
ELSE
IF PSCORE CSCORE > ;check for the general case of a win
CSCORE 21 > OR
PSCORE 21 <= AND
PSCORE 2 == OR ;5 cards under 21
THEN
BET 'PURSE' STO+
"YOU WIN" 4 DISP
ELSE ;player loses
'PURSE' BET STO-
"YOU LOSE"
4 DISP
END
END
END >>
'BLKJ' is the main program. The HP and player each have two representations
of their hands on the stack. One is the hand used in adding up the scores and
the other contains letters for face cards and is displayed as the hand. A sample
stack arrangement follows:
4: {A 5} ;HP's displayed hand
3: {5 11} ;HP's point hand. The numbers are reversed but doesn't matter
2: {J K} ;player's displayed hand
1: {10 10} ;player's point hand
Because of this there is a lot of stack manipulation.
'BLKJ' is the main program
--------------------------
<< DO
ENT "PURSE = " PURSE ->STR
+ 1 DISP "BET = " BET
->STR + 2 DISP 1 WAIT
DECK 'TDECK' STO ;"shuffle" the cards
DEAL { } + DUP "?" + ;HP's hand to be displayed
->STR 2 DISP SWAP { } +
DEAL 4 ROLL + 3 ROLLD + ;both of the HP's hands are on the stack
SCORE 'CSCORE' STO ;get the HP's point total
DEAL DEAL { } + 3
ROLL + DUP ->STR 3 DISP ;1st hand of player hand displayed and on stack
3 ROLLD { } + + ;point representation is now on stack
SCORE 'PSCORE' STO ;get the players score
IF CSCORE 1 !=
PSCORE 1 != AND THEN ;don't go further if there is a blackjack
"(H)IT OR (S)TAND?"
1 DISP "H"
WHILE "H" SAME
PSCORE 21 <= AND
PSCORE 2 != AND
REPEAT ;loop until the player stands, busts, or wins
DO UNTIL KEY END DUP ;wait for input
IF "H" SAME THEN
3 ROLLD DEAL 4 ROLLD ;"H" in level 1 must be moved out of the way
+ 3 ROLLD + DUP 3 ;dealt another card
DISP SWAP SCORE
'PSCORE' STO 3 ROLL
END
END DROP2
IF PSCORE 21 <=
PSCORE 2 != AND THEN ;if player hasn't automatically won or busted
OVER 2 DISP ;display the HP's full hand
WHILE CSCORE 17 < ;HP stands on 17 or above always
REPEAT ;deal a card to the HP
DEAL 4 ROLL + DUP
2 DISP 3 ROLLD +
SCORE 'CSCORE' STO
END
END
ELSE
4 PICK 2 DISP ;player busted or won so display HP's full hand
END WIN
"AGAIN? (Y/N)" 1 DISP
DO UNTIL KEY END
UNTIL "N" SAME END
CLEAR {PSCORE CSCORE ;do some clean up
TDECK BET} PURGE ABORT >>
That's it. I have played it and haven't found any bugs. I double checked
this file for typos but that doesn't mean there aren't any left. Hopefully
you can type this in with no problems but I can't guarantee it.
John Fredine
fredine@en.ecn.purdue.edu