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