;;; -*-Lisp-*- (in-package :user) (use-package :kgk) ;;; ---------------------------------------------------------------------- (defun make-shoe (decks) (let* ((size (* decks 52)) (v (make-array size)) (index size) (cards (make-periodic '(1 ; ace 2 3 4 5 6 7 8 9 0 ; 2 through 10 0 0 0))) ; :j, :q, :k ) (dotimes (i size) (setf (aref v i) (pop cards))) #'(lambda (&optional shuffle) (when (or shuffle (= index size)) (setf index 0) (shuffle! v)) (unless shuffle (prog1 (aref v index) (incf index)))))) (defun sum (a b) "Determine the value of a Baccarat hand (either two or three cards)" (mod (+ a b) 10)) (defun trial (hit) (let* ((p (sum (funcall hit) (funcall hit))) ; player (d (sum (funcall hit) (funcall hit))) ; dealer (bank) ) ;; pick more cards unless one or both sides has a "natural" (unless (or (>= p 8) ; a "natural" for the player (>= d 8) ; a "natural" for the dealer ) ;; consider drawing a third card for the player (let ((p3 nil)) (when (<= p 5) (setf p3 (funcall hit)) (setf p (sum p p3))) ;; consider drawing a third card for the dealer (when (if (null p3) (<= d 5) (or (<= d 2) (and (= d 3) (/= p3 8)) (and (= d 4) (<= 2 p3 7)) (and (= d 5) (<= 4 p3 7)) (and (= d 6) (<= 6 p3 7)))) (setf d (sum (funcall hit) d))))) ;; pick the winner (cond ((= p d) :tie) ((< p d) :bank) (t :player)))) (defun play-hands (&optional (n 10000000)) "Play a million hands of Baccarat and count the winners." (let ((player-wins 0) (bank-wins 0) (tie 0) (shoe (make-shoe 8))) (dotimes (i n) (ecase (trial shoe) (:tie (incf tie)) (:bank (incf bank-wins)) (:player (incf player-wins)))) ;; report the results (values (float (/ bank-wins n)) (float (/ player-wins n)) (float (/ tie n))))) ;;; ---------------------------------------------------------------------- (defun estimate-losses (&key (commission 0.05) ;; these values came by running play-hands for 50M hands (tie-return 9) (p-bank 0.4586346) (p-player 0.4461371) (p-tie 0.0952283)) "Figure out the losses in Baccarat" (labels ((note (situation &key (player-return 0) (bank-return 0) (tie-return 0)) (format t "Select ~A and lose ~A%.~&" situation (* 100 (+ (* p-bank bank-return) (* p-player player-return) (* p-tie tie-return)))))) (note "player" :player-return 1 :bank-return -1 :tie-return 0) (note "bank" :player-return -1 :bank-return (- 1 commission) :tie-return 0) (note "tie" :player-return -1 :bank-return -1 :tie-return tie-return))) ;;; ----------------------------------------------------------------------