Skip to content

Commit b79ab35

Browse files
committed
add blackjack
1 parent 4e6a6f9 commit b79ab35

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

src/blackjack/blackjack.lisp

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
(in-package #:tpd2.game.blackjack)
2+
3+
(defparameter +one-deck+
4+
(loop for s in +suits+ append (loop for i below +cards-per-suit+ collect (make-card :suit s :value i))))
5+
6+
(defparameter +decks-per-shoe+ 2)
7+
(defparameter +reshuffle-proportion+ 1/6)
8+
9+
(defstruct hand
10+
cards
11+
(stake 0))
12+
13+
(defgame blackjack (coin-game)
14+
(shoe)
15+
(defplayer ()
16+
((hands nil)))
17+
(:game-name "Blackjack")
18+
(:advertised nil))
19+
20+
(my-defun blackjack reshuffle ()
21+
(my announce :shuffle)
22+
(setf (my shoe) (random-shuffle (loop repeat +decks-per-shoe+ append +one-deck+))))
23+
24+
(my-defun blackjack take-card ()
25+
(pop (my shoe)))
26+
27+
(my-defun blackjack take-cards (&optional (num 2))
28+
(loop repeat num collect (my take-card)))
29+
30+
(defun cards-value (cards)
31+
(loop for card in cards
32+
for c = (card-value card)
33+
summing (min 10 (1+ c))))
34+
35+
(my-defun hand value ()
36+
(cards-value (my cards)))
37+
38+
(my-defun hand bust ()
39+
(< 21
40+
(my value)))
41+
42+
(defun cards-best-value (cards)
43+
(let ((other 0) (aces 0))
44+
(loop for card in cards
45+
for c = (card-value card)
46+
do
47+
(if (zerop c)
48+
(incf aces)
49+
(incf other (min 10 (1+ c)))))
50+
(loop for ac in
51+
(let ((min aces))
52+
(list* min (loop repeat aces collect (incf min 9))))
53+
for val = (+ ac other)
54+
when (>= 21 val)
55+
maximizing val)))
56+
57+
(my-defun hand blackjack ()
58+
(= 21 (cards-best-value (my cards))))
59+
60+
(my-defun blackjack 'play ()
61+
(with-its-type (p blackjack-player)
62+
(with-game
63+
(loop
64+
65+
(when (> (* +reshuffle-proportion+ +decks-per-shoe+ +cards-per-suit+ (length +suits+)) (length (my shoe)))
66+
(my reshuffle)
67+
(my new-state))
68+
69+
(with-join-spawn/cc ()
70+
(loop for p in (my players)
71+
do
72+
(let-current-values (p)
73+
(spawn/cc ()
74+
(setf (its hands p) (list (make-hand :stake (my move :select-new-stake p `(:integer 0 ,(max 1 (its coins p)))))))))))
75+
76+
(loop for p in (my players)
77+
do (setf (its hands p) (delete-if (lambda (h) (zerop (hand-stake h))) (its hands p))))
78+
79+
(loop for p in (my players)
80+
do (loop for h in (its hands p)
81+
do (setf (hand-cards h) (my take-cards 2))))
82+
83+
(loop for p in (my players)
84+
do (loop for h in (its hands p) do
85+
(loop
86+
while (my move :hit p :boolean)
87+
do (push (my take-card) (hand-cards h))
88+
(when (hand-blackjack h)
89+
(my announce :blackjack :player p :hand h)
90+
(return))
91+
(when (hand-bust h)
92+
(my announce :bust :player p :hand h)
93+
(return)))))
94+
95+
(let (hand)
96+
(loop while (> 17 (cards-value hand))
97+
do (let ((c (my take-card)))
98+
(debug-assert c (hand me (my shoe)))
99+
(push c hand)
100+
(my announce :dealer :card c)))
101+
(let ((val (cards-best-value hand)))
102+
(loop for p in (my players)
103+
do (loop for h in (its hands p)
104+
for pval = (cards-best-value (hand-cards h))
105+
do (its give-coins p
106+
(cond ((or (zerop pval) (> val pval))
107+
(- (hand-stake h)))
108+
((= pval val)
109+
0)
110+
((= 21 pval)
111+
(* 3/2 (hand-stake h)))
112+
(t
113+
(hand-stake h))))))))))))
114+
115+
(my-defun hand 'object-to-ml ()
116+
(<div :class "blackjack-hand"
117+
(loop for c in (my cards)
118+
do (output-object-to-ml c))
119+
(<p :class "stake" (my stake))
120+
(when (my cards)
121+
(<p :class "value" "Value " (cards-best-value (my cards)))
122+
(cond ((my bust)
123+
(<p :class "bust" "Bust."))
124+
((my blackjack)
125+
(<p :class "blackjack" "Blackjack!"))))))
126+
127+
(my-defun blackjack-player 'object-to-ml ()
128+
(<div :class "blackjack-player"
129+
(call-next-method)
130+
(loop for h in (my hands)
131+
do (output-object-to-ml h))))

0 commit comments

Comments
 (0)