keith@sfu_css.cs.sfu (08/07/87)
I wrote this blackjack game as more an exercise in NeWS programming
more than a useful game (that's why it is posted here and not in
comp.sources.games). Hopefully you will find the ideas used within
the program useful although the code is relatively horrible.
You are free to do whatever you want to do to this.
Keith Vincent
Laboratory for Computer and Communication Research (LCCR)
Simon Fraser University
Burnaby, B.C. Canada V5A 1S6
E-Mail - { ubc-vision }
...! { uw-beaver } !lccr!keith
{ sun }
############## CUT HERE #################
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./black.c`
then
echo "writing ./black.c"
cat > ./black.c << 'George_George_George_of_the_Jungle'
#include <black.h>
#define PLAYER 0
#define SPLIT 1
#define DEALER 2
#define UP 1
#define DOWN 0
#define SUIT(c) (((c) & 0xF0) >> 4)
#define VALUE(c) ((((c) & 0x0F) > 10) ? 10 : ((c) & 0x0F))
int deck[52];
int hand[3][52];
int count[3];
int points[3];
int play_chips = 500;
int deck_card_count = 0;
int deal_down = -1;
int split = 0;
int wager;
main(argc, argv)
int argc;
char **argv;
{
char cwager[99];
char buff[99];
long t;
int playing = 1;
int tag;
int dummy;
ps_open_PostScript();
time(&t);
srandom(getpid() + (int)((t >>16) +t));
ps_init();
ps_flush_PostScript();
init_deck();
shuffle(); /* shuffle the cards */
wager = 1;
ps_set_wager(wager);
while(playing)
{
count[PLAYER] = 0;
count[SPLIT] = 0;
count[DEALER] = 0;
deal_down = -1;
split = 0;
ps_message("");
ps_hit_ok();
ps_stand_ok();
ps_wager_ok();
ps_split_no();
ps_newgame_no();
card(PLAYER, UP);
card(DEALER, DOWN);
deal_down = hand[DEALER][0];
card(PLAYER, UP);
card(DEALER, UP);
while(1)
{
if ((hand[PLAYER][0] & 0x0F) == (hand[PLAYER][1] & 0x0F))
ps_split_ok();
ps_flush_PostScript();
if (ps_hit())
{
ps_wager_no();
ps_split_no();
switch (split)
{
case 0 : /* no split */
card(PLAYER, UP);
if (points[PLAYER] > 21)
{
calc_winner();
}
break;
case 1 : /* first of split hands */
card(PLAYER, UP);
if (points[PLAYER] > 21)
{
ps_message("Play second hand");
ps_split_second();
split++;
}
break;
case 2 : /* second of split hands */
card(SPLIT, UP);
if (points[SPLIT] > 21 && points[PLAYER] > 21)
{
calc_winner();
}
else if (points[SPLIT] > 21)
{
ps_hit_no();
ps_wager_no();
ps_flip_card(deal_down & 0x0F, SUIT(deal_down));
deal_down = -1;
while (points[DEALER] <= 16)
card(DEALER, UP);
calc_winner();
}
break;
}
}
if (ps_split())
{
split = 1;
count[PLAYER] = 1;
count[SPLIT] = 1;
hand[SPLIT][0] = hand[PLAYER][1];
ps_clear_cards();
redraw_cards();
ps_split_first();
ps_split_no();
}
if (ps_stand())
{
ps_split_no();
if (split == 1)
{
ps_split_second();
split++;
}
else
{
ps_hit_no();
ps_wager_no();
ps_flip_card(deal_down & 0x0F, SUIT(deal_down));
deal_down = -1;
while (points[DEALER] <= 16)
card(DEALER, UP);
calc_winner();
}
}
if (ps_wager(cwager))
{
wager = atoi(cwager);
}
if (ps_paint())
{
redraw_cards();
}
if (ps_newgame())
{
ps_hit_ok();
ps_stand_ok();
ps_newgame_no();
ps_split_no();
ps_clear_cards();
break;
}
else if (ps_quit())
{
sprintf(buff, "You leave with %d dollars", play_chips);
ps_message(buff);
ps_flush_PostScript();
playing = 0;
break;
}
}
}
ps_close_PostScript();
exit(0);
}
card(who, up)
int who, up;
{
int c, i;
int ace = 0;
if (deck_card_count > 51)
shuffle();
c = deck[deck_card_count++];
hand[who][count[who]] = c;
points[who] = 0;
for (i = 0; i <= count[who]; i++)
{
if (VALUE(hand[who][i]) == 1)
ace++;
points[who] += VALUE(hand[who][i]);
}
for (i = 0; i < ace; i++)
if (points[who] < 12)
points[who] += 10;
ps_show_card(who, up, count[who], SUIT(c), (c & 0x0F), split);
count[who]++;
}
redraw_cards()
{
int i;
if (split == 0)
{
for(i = 0; i < count[PLAYER]; i++)
ps_show_card(PLAYER, UP, i, SUIT(hand[PLAYER][i]), (hand[PLAYER][i]) & 0x0F, 0);
}
else
{
for(i = 0; i < count[PLAYER]; i++)
ps_show_card(PLAYER, UP, i, SUIT(hand[PLAYER][i]), (hand[PLAYER][i]) & 0x0F, 1);
for(i = 0; i < count[SPLIT]; i++)
ps_show_card(SPLIT, UP, i, SUIT(hand[SPLIT][i]), (hand[SPLIT][i]) & 0x0F, 2);
}
if (deal_down != -1)
ps_show_card(DEALER, DOWN, 0, SUIT(hand[DEALER][0]), (hand[DEALER][0]) & 0x0F, 0);
else
ps_show_card(DEALER, UP, 0, SUIT(hand[DEALER][0]), (hand[DEALER][0]) & 0x0F, 0);
for(i = 1; i < count[DEALER]; i++)
ps_show_card(DEALER, UP, i, SUIT(hand[DEALER][i]), (hand[DEALER][i]) & 0x0F, 0);
}
init_deck()
{
int i, j;
int n = 0;
for (i=1; i < 5; i++)
for (j = 1; j < 14; j++)
{
deck[n++] = ((i & 0x0F) << 4) | (j & 0x0F);
}
}
shuffle()
{
int i, j, c;
long random();
for(i=52-1;i>=0;i--)
{
j = random() % 52;
if (i != j)
{
c = deck[i];
deck[i] = deck[j];
deck[j] = c;
}
}
deck_card_count = 0;
}
calc_winner()
{
int res = 0, res2 = 0;
if (points[PLAYER] > 21)
res = -1;
else if (points[DEALER] > 21)
res = 1;
else if (points[PLAYER] > points[DEALER])
res = 1;
else if (points[PLAYER] == points[DEALER])
res = 0;
else
res = -1;
if(split != 0)
{
if (points[SPLIT] > 21)
res2 = -1;
else if (points[DEALER] > 21)
res2 = 1;
else if (points[SPLIT] > points[DEALER])
res2 = 1;
else if (points[SPLIT] == points[DEALER])
res2 = 0;
else
res2 = -1;
if (res == 0)
{
if (res2 == 0)
ps_message("Both hands push");
else if (res2 == -1)
ps_message("One push, one loss");
else if (res2 == 1)
ps_message("One push, one win");
}
else if (res == 1)
{
if (res2 == 0)
ps_message("One win, one push");
else if (res2 == -1)
ps_message("One win, one loss");
else
ps_message("Two wins");
}
else
{
if (res2 == 0)
ps_message("One loss, one push");
else if (res2 == -1)
ps_message("Two losses");
else
ps_message("One loss, one win");
}
}
else
{
if (res == 0)
ps_message("Push");
else if (res == 1)
ps_message("You win");
else
ps_message("Dealer wins");
}
play_chips = play_chips + wager * (res + res2);
ps_set_chips(play_chips);
ps_newgame_ok();
ps_hit_no();
ps_stand_no();
}
George_George_George_of_the_Jungle
else
echo "will not over write ./black.c"
fi
if `test ! -s ./black.cps`
then
echo "writing ./black.cps"
cat > ./black.cps << 'George_George_George_of_the_Jungle'
#define TAG_HIT 901
#define TAG_STAND 902
#define TAG_NEWGAME 903
#define TAG_QUIT 904
#define TAG_WAGER 905
#define TAG_PAINT 906
#define TAG_SPLIT 907
cdef ps_hit() => TAG_HIT ()
cdef ps_stand() => TAG_STAND ()
cdef ps_newgame() => TAG_NEWGAME ()
cdef ps_quit() => TAG_QUIT ()
cdef ps_wager(string v) => TAG_WAGER (v)
cdef ps_paint() => TAG_PAINT ()
cdef ps_split() => TAG_SPLIT ()
cdef ps_message(string s)
(%) [s] /printf messages send
cdef ps_set_wager(v)
wager begin
/ItemValue v 20 string cvs def
end
[wager] paintitems
cdef ps_set_chips(v)
(Chips:%) [v] /printf chips send
cdef ps_split_ok()
/notify-split { TAG_SPLIT tagprint } def
cdef ps_split_no()
/notify-split {} def
cdef ps_wager_ok()
/notify-wager { TAG_WAGER tagprint ItemValue typedprint } def
cdef ps_wager_no()
/notify-wager {} def
cdef ps_hit_ok()
/notify-hit { TAG_HIT tagprint } def
cdef ps_hit_no()
/notify-hit {} def
cdef ps_stand_ok()
/notify-stand { TAG_STAND tagprint } def
cdef ps_stand_no()
/notify-stand {} def
cdef ps_newgame_ok()
/notify-newgame { TAG_NEWGAME tagprint } def
cdef ps_newgame_no()
/notify-newgame {} def
cdef ps_split_first()
gsave
20 40 moveto
0 10 rlineto 10 0 rlineto 0 5 rlineto 10 -10 rlineto
-10 -10 rlineto 0 5 rlineto -10 0 rlineto
0 0 0 rgbcolor setcolor fill
grestore
cdef ps_split_second()
gsave
20 40 moveto
0 10 rlineto 10 0 rlineto 0 5 rlineto 10 -10 rlineto
-10 -10 rlineto 0 5 rlineto -10 0 rlineto
FillColor setcolor fill
20 100 moveto
0 10 rlineto 10 0 rlineto 0 5 rlineto 10 -10 rlineto
-10 -10 rlineto 0 5 rlineto -10 0 rlineto
0 0 0 rgbcolor setcolor fill
grestore
cdef ps_clear_cards()
gsave
FillColor setcolor
0 0 moveto 400 150 rect fill
0 300 moveto 400 150 rect fill
grestore
cdef ps_flip_card(val, suit)
gsave
1 1 1 rgbcolor setcolor
50 320 moveto 50 110 rect fill
55 410 moveto
0 0 0 rgbcolor setcolor
TF card-val val 1 sub get show
SF card-suit suit 1 sub get show
50 320 moveto 50 110 rect stroke
grestore
cdef ps_show_card(who, up, cnt, suit, val, split)
can setcanvas
/this-startx cnt 1 add 50 mul def
who 2 lt
{ split 0 eq
{/this-starty 20 def /hgt 110 def}
{ split 1 eq
{ /this-starty 20 def /hgt 50 def }
{ /this-starty 80 def /hgt 50 def } ifelse
} ifelse
}
{ /this-starty 320 def /hgt 110 def}
ifelse
gsave
0 0 0 rgbcolor setcolor
up 0 eq
{
gsave
can /Color get
{ 1 0 0 rgbcolor }
{ .9 .9 .9 rgbcolor } ifelse
setcolor
5 this-startx this-starty 60 hgt rrectpath fill
0 0 0 rgbcolor setcolor
this-startx 30 add this-starty hgt 2 div add 5 add moveto
TF
(Keith's) cshow
this-startx 30 add this-starty hgt 2 div add 5 sub moveto
(Casino) cshow
grestore
}
{
gsave
1 1 1 rgbcolor setcolor
5 this-startx this-starty 60 hgt rrectpath fill
this-startx 5 add this-starty hgt 20 sub add moveto
0 0 0 rgbcolor setcolor
TF card-val val 1 sub get show
SF card-suit suit 1 sub get show
grestore
} ifelse
5 this-startx this-starty 60 hgt rrectpath stroke
grestore
cdef ps_init()
systemdict /Item known not { (NeWS/liteitem.ps) run } if
1 setlinequality
3 setlinewidth
/this-startx 0 def
/this-starty 0 def
/hgt 110 def
/TF { /Times-Bold findfont 12 scalefont setfont } def
/SF { /Symbol findfont 12 scalefont setfont } def
/card-val [(A) (2) (3) (4) (5) (6) (7) (8) (9) (10) (J) (Q) (K)] def
/card-suit [<A7> <A8> <A9> <AA>] def
/notify-hit { } def
/notify-stand { } def
/notify-newgame { } def
/notify-wager { } def
/notify-split { } def
/createitems
{
/items 10 dict dup begin
/split (SPLIT) /notify-split can 40 40 /new ButtonItem send
450 200 /move 3 index send def
/hit (HIT) /notify-hit can 40 40 /new ButtonItem send
450 150 /move 3 index send def
/stand (STAND) /notify-stand can 40 40 /new ButtonItem send
450 100 /move 3 index send def
/newgame (NEW GAME) /notify-newgame can 40 40 /new ButtonItem send
450 50 /move 3 index send def
/quit (QUIT) {TAG_QUIT tagprint} can 40 40 /new ButtonItem send
450 0 /move 3 index send def
/wager (Wager:) (1 ) /Right /notify-wager can 50 0
/new TextItem send 450 250 /move 3 index send def
/chips /panel_text (Chips:5000 ) /Right {} can 80 0
/new MessageItem send dup begin
/ItemFrame 1 def
/ItemBorder 4 def
end 450 300 /move 3 index send def
/messages /panel_text () /Right {} can 500 0
/new MessageItem send dup begin
/ItemFrame 1 def
/ItemBorder 4 def
end 10 500 /move 3 index send def
end def
/wager items /wager get def
/chips items /chips get def
/messages items /messages get def
} def
/slideitem
{
gsave
dup 4 1 roll
/moveinteractive exch send
/bbox exch send
grestore
} def
/main
{
/win framebuffer /new DefaultWindow send def
{
/PaintClient {FillColor fillcanvas items paintitems TAG_PAINT tagprint} def
/FrameLabel (Black Jack) def
} win send
200 200 600 600 /reshape win send
/can win /ClientCanvas get def
/FillColor can /Color get
{0 1 0 rgbcolor}
{.5 .5 .5 rgbcolor} ifelse
def
createitems
/slidemgr [
items {
exch pop dup /ItemCanvas get
MiddleMouseButton [items FillColor 6 -1 roll /slideitem cvx] cvx
DownTransition 4 -1 roll eventmgrinterest
} forall
] forkeventmgr def
/map win send
/itemmgr items forkitems def
} def
main
George_George_George_of_the_Jungle
else
echo "will not over write ./black.cps"
fi
echo "Finished archive 1 of 1"
exit