You are on page 1of 5

;;;

;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;

============================================
CMPU-101, Spring 2014
BLACKJACK.TXT
============================================
Global Constants:
*WAITING-FOR-BET*, *WAITING-FOR-PLAY*,
*WAITING-FOR-DEALER*, *WAITING-FOR-NEXT-ROUND*,
*MIN-NUM-LEFT*
------------------------------------------------------Data Structures: BLACKJACK
------------------------------------------------------Functions:
MAKE-BLACKJACK-WR, PLACE-BET!, PREPARE-FOR-NEXT-ROUND!,
DO-WINNINGS!, HIT!, CONTINUE!, STAND!

;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;

We include additional states to facilitate the separation


of CHANGING_STATE and DISPLAYING_STATE...
--------------------------------------------------------------WAITING-FOR-BET ... waiting for user to call PLACE-BET!
WAITING-FOR-PLAY ... waiting for user to call either HIT! or STAND!
WAITING-FOR-DEALER ... waiting for user to call CONTINUE! so that
computer can continue playing dealer's hand
or compute the winnings
WAITING-FOR-NEXT-ROUND ... waiting for user to call CONTINUE so that
computer can clear table for next round.

(define
(define
(define
(define

*waiting-for-bet* 0)
*waiting-for-play* 1)
*waiting-for-dealer* 2)
*waiting-for-next-round* 3)

;;; The BLACKJACK struct


;;; ----------------------------------------------------;;; FIELDS: DECK -- a deck of cards
;;;
PLAYER -- the player's hand
;;;
DEALER -- the dealer's hand
;;;
STATE -- *WAITING-FOR-BET*, *WAITING-FOR-PLAY*,
;;;
*WAITING-FOR-DEALER*, *WAITING-FOR-NEXT-ROUND*
;;;
BET -- size of current bet
;;;
BANKROLL -- amount of money player currently has
;;;
RESULT-STR -- stores results of current round hand so that they
;;;
can be seen until user hits the CONTINUE button.
(define-struct blackjack
(deck player dealer state bet bankroll result-str))
;;;
;;;
;;;
;;;
;;;

MAKE-BLACKJACK-WR
---------------------------------------------INPUT: NUM-DECKS, the number of decks of cards to use
INIT-BANKROLL, the player's initial bankroll
OUTPUT: A blackjack struct representing the new game

(define make-blackjack-wr
(lambda (num-decks init-bankroll)
(make-blackjack (make-deck-wr (* num-decks 52))
(make-hand-wr)
;; <--- empty hand
(make-hand-wr)
;; <--- empty hand
*waiting-for-bet* ;; <--- initial state
0
;; <--- no money on table yet

init-bankroll
""
)))
;;;
;;;
;;;
;;;
;;;
;;;
;;;

;; <--- no result string yet

PLACE-BET!
---------------------------------------INPUT: GAME, a blackjack game
BET, a numerical bet (0 < BET <= player's bank)
OUTPUT: Don't care
SIDE-EFFECT: Changes state of blackjack game
(but only if BET is appropriate, etc.)

(define place-bet!
(lambda (game bet)
(let ((decko (blackjack-deck game))
(hando (blackjack-player game))
(dlr (blackjack-dealer game)))
(cond
;; Case 1: Not a good time to place a bet
((not (eq? (blackjack-state game)
*waiting-for-bet*))
(printf "Sorry... illegal to attempt to place a bet now!~%"))
;; Case 2: Illegal bet amount
((or (<= bet 0) (> bet (blackjack-bankroll game)))
(printf "Sorry... illegal bet amount!~%"))
;; Case 3: Good bet
(#t
;; Update the state
(set-blackjack-state! game *waiting-for-play*)
;; accept the bet
(set-blackjack-bankroll! game
(- (blackjack-bankroll game) bet))
(set-blackjack-bet! game bet)
;; deal cards to player and dealer
(deal-card-deck-hand! decko hando)
(deal-card-deck-hand! decko hando)
(deal-card-deck-hand! decko dlr)
(deal-card-deck-hand! decko dlr)
)))
;; Return VOID (Don't care)
(void)))

;;;
;;;
;;;
;;;

*MIN-NUM-LEFT*
---------------------------------------If fewer than this many cards remains in deck
then deck will be shuffled prior to starting a new round.

(define *min-num-left* 15)


;;;
;;;
;;;
;;;
;;;
;;;
;;;

PREPARE-FOR-NEXT-ROUND!
------------------------------------INPUT: GAME, a BLACKJACK struct
OUTPUT: None
SIDE EFFECT: Destructively modifies GAME struct in preparation for
the next round of play: shuffles if necessary, sets the state to
*waiting-for-bet*, clears the hands, and clears the bet.

(define prepare-for-next-round!
(lambda (game)
;; shuffle if necessary
(if (< (deck-num-left (blackjack-deck game))
*min-num-left*)
(shuffle! (blackjack-deck game))
#t)
(set-blackjack-state! game *waiting-for-bet*)
;; clear the hands and the bet
(reset-hand! (blackjack-player game))
(reset-hand! (blackjack-dealer game))
(set-blackjack-bet! game 0)))
;;;
;;;
;;;
;;;
;;;
;;;

DO-WINNINGS!
------------------------------------INPUT: GAME, a blackjack struct
OUTPUT: None
SIDE EFFECTS: Determines who won the current round and
distributes winnings accordingly.

(define do-winnings!
(lambda (game)
;; Some convenient local variables to make subsequent code simpler...
(let* ((plr (blackjack-player game))
(dlr (blackjack-dealer game))
(plr-val (hand-value plr))
(dlr-val (hand-value dlr))
(bet (blackjack-bet game)))
(cond
;; Case 1: Player LOSES!
((or (busted? plr)
(and (not (busted? dlr))
(> dlr-val plr-val)))
;; player loses bet (already deducted from bankroll)
(set-blackjack-result-str! game "YOU LOSE!!")
)
;; Case 2: Neither busted and it's a TIE!
((and (not (busted? dlr))
(= plr-val dlr-val))
(set-blackjack-result-str! game "TIE!")
;; add bet back to bankroll
(set-blackjack-bankroll! game
(+ bet (blackjack-bankroll game))))
;; Case 3: Player WINS!
((or (busted? dlr)
(< dlr-val plr-val))
;;(printf "YOU WIN!~%")
(set-blackjack-result-str! game "YOU WIN!")
;; add *DOUBLE* the bet back to player's bankroll
(set-blackjack-bankroll! game
(+ (* 2 bet)
(blackjack-bankroll game))))
;; Case 4: ERROR!
(#t
(printf "UMMM... Error in do-winnings!!~%")))

;; No matter what happened, we need to change state of game:


(set-blackjack-state! game *waiting-for-next-round*)
)))
;;;
;;;
;;;
;;;
;;;
;;;

HIT!
---------------------------------INPUT: GAME, a blackjack struct
OUTPUT: None
SIDE EFFECTS: Destructively modifies game by dealing one card to
player and, if the player busts, changing the state of the game.

(define hit!
(lambda (game)
(let* ((state (blackjack-state game))
(decko (blackjack-deck game))
(plr (blackjack-player game))
(dlr (blackjack-dealer game)))
(cond
;; Case 1: Inappropriate time for HIT action...
((not (eq? state *waiting-for-play*))
(printf "Sorry... can't hit at this time!~%"))
;; Case 2: Happy time for hitting!
(#t
;; deal one card to player's hand
(let ((new-card (deal-card-deck-hand! decko plr)))
(cond
;; Case 1: Player busted!
((busted? plr)
;; This string will be displayed in the RESULT-MSG box
(set-blackjack-result-str! game
"Whoops! You busted and lost your bet
!")
(set-blackjack-state! game *waiting-for-next-round*))
;; Case 2: Player not yet busted!
(#t
;; Nothing to do here... still must wait for player to play
#t)))))
;; Return VOID (Don't care)
(void))))
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;
;;;

CONTINUE!
----------------------------------------INPUT: GAME, a blackjack struct
OUTPUT: None
SIDE EFFECTS: This function is called when the state of the game
is either *waiting-for-dealer* or *waiting-for-next-round*.
In either case, the computer is in charge of playing out the dealer's
hand or clearing the table for the next round. This function does
one step of work and, if necessary, the player will have to hit the
CONTINUE button again to do the next step, and so on. Eventually,
the dealer's hand will be finished and the table will be cleared
for the next round.

(define continue!
(lambda (game)
(let* ((dlr (blackjack-dealer game))
(plr (blackjack-player game))
(state (blackjack-state game))
(decky (blackjack-deck game)))
(cond
;; Case 1: Wrong state for this action...
((or (eq? state *waiting-for-bet*)
(eq? state *waiting-for-play*))
(printf "Sorry... invalid action (can't *continue*)~%"))
;; Case 2: STATE = *WAITING-FOR-NEXT-ROUND*...
((eq? state *waiting-for-next-round*)
;; Clear the table in preparation for the next round...
(prepare-for-next-round! game))
;; Case 3: STATE = *WAITING-FOR-DEALER*... but dealer finished...
((or (busted? dlr) (>= (hand-value dlr) 17))
;; Check who won and distribute winnings accordingly...
(do-winnings! game))
;; Case 4: STATE = *WAITING-FOR-DEALER*... but dealer not finished...
(#t
;; Deal one card to dealer's hand
(deal-card-deck-hand! decky dlr)
;; Player will have to hit the CONTINUE button to get more stuff done..
.
)))
;; return VOID
(void)))

;;;
;;;
;;;
;;;
;;;
;;;

STAND!
------------------------------------INPUT: GAME, a BLACKJACK struct
OUTPUT: None
SIDE EFFECT: Player stands with current hand;
Computer then plays out dealer's hand and sees who won.

(define stand!
(lambda (game)
(cond
;; Case 1: Inappropriate time for the STAND action...
((not (eq? (blackjack-state game) *waiting-for-play*))
(printf "Sorry... not legal to STAND at this time!~%"))
;; Case 2: Happy time for STANDING...
(#t
;; Player stands... therefore, change state to *wait-for-dealer*
;; and call continue!
(set-blackjack-state! game *waiting-for-dealer*)
;; if you leave out the following expression, the player
;; will have to hit the CONTINUE button an extra time...
(continue! game)))
;; return VOID
(void)))

You might also like