home *** CD-ROM | disk | FTP | other *** search
- From: cs00chs@unccvax.uncc.edu (charles spell)
- Newsgroups: alt.sources
- Subject: Atlantic City blackjack v1.0
- Message-ID: <2833@unccvax.uncc.edu>
- Date: 11 Oct 90 23:37:03 GMT
-
-
-
- Here is an Atlantic city blackjack game I hacked together one weekend before
- going to Atlantic City. To compile (System V only):
-
- cc bj.c -o bj -lcurses
-
- A small contribution will be appreciated...I will send out fixes/enhancements
- if there is enough monetary interest...
-
- ---cut here---cut here---cut here---cut here---cut here---cut here---cut here-
- #include <curses.h>
- #include <ctype.h>
- #include <signal.h>
- /*****************************************************************************
- * You may freely distribute this file as long as the contents of this file
- * have not been altered in any way or form. If you decide that you would like
- * to re-distribute a change, please send to me for testing first - this keeps
- * one current tested version out there...
- *
- * If you enjoy or find the program (in part or whole) useful,
- * please send a contribution to:
- * John J. Ribera, Jr.
- * 9505-J University Terrace Dr.
- * Charlotte, NC 28262
- * Voice: (704) 549-5571
- * Please send suggestions, comments, complaints, ideas, etc... to the author
- * at the address above or e-mail : uunet!mcnc!unccvax!cs00chs
- */
-
- /*****************************************************************************
- * NAME Oct 90
- * bj - a blackjack program
- *
- * SYNOPSIS
- * bj
- *
- * DESCRIPTION
- * This is an eight-deck Atlantic City blackjack game for system V. Splits and
- * double downs are supported. No insurance. Use the Spacebar to Hit and CR to
- * stand if desired. A redeal will occur when half of the all decks are used.
- * bj uses terminfo GRAPHICS capablities - iff they are activated.
- *
- * NOTE
- * The program looks much nicer if you have the smacs=, rmacs= and acsc=
- * capabilities in your terminfo database...but it will still work
- * without them...
- *
- * How to add graphics capabilities for vt100, vt101 and vt102 emulators:
- * Type the following commands (re-start here if anything goes wrong):
- * csh> setenv TERM vt100 # vt100 is an example-use TERM name youre that
- * csh> mkdir ~/term # emulates a vt10[012] (in terminfo database)
- * csh> infocmp > ~/term/info # this will create a terminfo source file.
- * csh> setenv TERMINFO ~/term # Tell curses to use the database in ~/term
- * csh> tic ~/term/info # Ignore warnings (if any)...
- * Edit the ~/term/info file and add the following line to the proper entry:
- * -go to the entry that emulates vt100 (eg. vt100,vt101, vt102)
- * -add the following line to it...
- * smacs=\E(0\E)0, rmacs=\E(B\E)B, acsc=jjkkllmmnnqqssttuuvvww++\,\,,
- * -save it and type the following command:
- * csh> tic ~/term/info
- *
- * For non vt100 emulators you must read your terminal reference manual and
- * terminfo(5) to set it up properly. Some old terminals do not have a text
- * graphics mode - i.e. you cannot see the pretty graphics.
- *
- * BUGS
- * There are a few bugs. These will be fixed on the next version iff there is
- * enough mmonetary interest. The dealer continues to deal to himself even
- * after the outcome of a score is certain. No insurance. After the first
- * shuffle, the WIN-LOSE is not displayed properly.
- *
- * AUTHOR
- *
- * (E-mail: uunet!mcnc!unccvax!cs00chs)
- * John J. Ribera, Jr.
- * 9505-J University Terrace Dr.
- * Charlotte, NC 28262
- * Voice: (704) 549-5571
- *
- * If you find this program or any part of it useful please send a
- * contribution to the above address. This will allow you to receive
- * the most recent fixes and versions. Make checks payable to
- * John J. Ribera, Jr.
- */
-
- /* flags for get_str() and get_chr()... */
- #define CLR_FLD 0x0001
- #define INIT_ONKEY 0x0010
- #define MAP_UPPER 0x0002
- #define MAP_LOWER 0x0004
- #define AUTO_RET 0x0008
- #define NOPAD 0x0020
- #define NOECHO 0x0040
- #define BEEP 0x0080
-
- /* keystroke defines for readablity.... */
- #define ESC 0x1b
- #define CR '\r'
- #define NL '\n'
- #define BS '\b'
-
- #define MAX_HANDS 3
- #define DECKS 8
- #define DEALER 0
- #define DOWN 0
- #define UP 1
- #define WIN 0x0001
- #define LOSE 0x0002
- #define PUSH 0x0004
- #define BJ 0x0008
- #define GETCNT(i) (short) abs((int) (getcnt(i)))
- typedef struct
- {
- short amt;
- short bet;
- short cnt;
- short cards[13];
- char name[9+1];
- WINDOW *win;
- } HAND;
-
- HAND Hand[MAX_HANDS];
- short Hands = 2;
- short *Cards;
- short Cur_card;
- main()
- {
- short i, n, cnt, pcnt, dcnt;
- short decks, cmp, bet;
- short *cards, *shuffle();
- short getcnt(), bj(), getbet();
- char *cardtype();
- char input[3], *ptr;
- void done();
- void inithand(), disphand();
-
- signal(SIGINT, done);
- initscr();
- noecho();
- crmode();
-
- for (n = 0; n < MAX_HANDS; n++)
- inithand(n);
-
- srand(time((long *) 0));
- while (TRUE)
- {
- clearok(stdscr, TRUE);
- refresh();
- for (i = 0; i < Hands; i++)
- disphand(i);
- wstandout(Hand[DEALER].win);
- mvwprintw(Hand[DEALER].win, 0, 1, " B L A C K J A C K ");
- wstandend(Hand[DEALER].win);
- wprintw(Hand[DEALER].win, " by clt2!jjr... (press DEL to quit)");
- mvwprintw(Hand[DEALER].win, 5, 1, "Shuffle...");
- wrefresh(Hand[DEALER].win);
- sleep(2);
- Cards = shuffle((decks = DECKS));
- Cur_card = 0;
- while (Cur_card < decks * 52 / 2)
- {
- for (i = 1;Hands > 2; Hands--, i++)
- werase(Hand[i+1].win), wrefresh(Hand[i+1].win);
- Hands = 2;
- for (n = 1; n < Hands; n++)
- {
- if (!getbet(n))
- done();
- Hand[n].cnt = 0;
- disphand(n);
- }
- Hand[DEALER].cnt = 0;
- disphand(DEALER);
- getcard(1); getcard(DEALER);
- getcard(1); getcard(DEALER);
- getcard(1);
- if (Hands > 2)
- {
- getcard(2);
- getcard(2);
- }
- getcard(DEALER);
- for (dcnt = GETCNT(DEALER), i = 1; i < Hands; i++)
- {
- if ((pcnt = GETCNT(i)) > 21 || dcnt > 21)
- cmp = (pcnt > 21) ? LOSE : WIN;
- else if (pcnt == dcnt)
- cmp = (bj(i)) ? BJ : PUSH;
- else
- cmp = (pcnt > dcnt) ? (bj(i) ? BJ : WIN) : LOSE;
- switch (cmp)
- {
- case WIN:
- Hand[i].amt += Hand[i].bet;
- Hand[DEALER].amt -= Hand[i].bet;
- ptr = " WIN ";
- break;
- case BJ:
- Hand[i].amt += Hand[i].bet + (Hand[i].bet / 2);
- Hand[DEALER].amt -= (Hand[i].bet + Hand[i].bet / 2);
- ptr = " WIN ";
- break;
- case PUSH:
- ptr = " PUSH ";
- break;
- case LOSE:
- Hand[DEALER].amt += Hand[i].bet;
- Hand[i].amt -= Hand[i].bet;
- ptr = " LOSE ";
- break;
- }
- dispbet(i);
- dispbet(DEALER);
- wrefresh(Hand[i].win); wrefresh(Hand[0].win);
- wstandout(Hand[i].win); mvwprintw(Hand[i].win, 2, 20, ptr);
- wstandend(Hand[i].win); wrefresh(Hand[i].win);
- }
- }
- promptfor("New deck...press return to continue...", ptr, 1, "", CLR_FLD);
- }
- }
- void
- inithand(n)
- short n;
- {
-
- Hand[n].win = newwin((n == DEALER) ? 7 : 5,0,(n == DEALER) ? 0 : n * 5 + 2, 0);
- Hand[n].amt = (DEALER == n ) ? 0 : 1000;
- Hand[n].bet = 0L;
- Hand[n].cnt = 0;
- strcpy(Hand[n].name, getlogin());
- strcpy(Hand[DEALER].name, "Dealer");
- }
- /*******************************************************************************
- * shuffle will return a static pointer to an array of random shorts with a range
- * of 0 to 52 * 'decks'. If 'decks' is > 10, then 10 decks will be returned.
- * If 'decks' is < 1 then one shuffled deck will be returned.
- */
- short *
- shuffle(decks)
- short decks;
- {
- static short deck[52 * 10 + 1];
- short mark[52 * 10 + 1];
- short card;
- short cnt = 0;
-
- memset(mark, '\0', sizeof(mark));
- memset(deck, '\0', sizeof(deck));
-
- decks = (decks < 1) ? 1 : ((decks > 10) ? 10 : decks);
- while (cnt < 52 * decks)
- if ((card = (short) rand() % (52 * decks)) >= 0 && !mark[card])
- deck[cnt++] = card, mark[card] = 1;
- deck[cnt] = -1;
- return(deck);
- }
- /******************************************************************************
- * cardtype will return a 3 character string that specifies which card 'card'
- * represents. Character [1] of the returned string specifies the cardinality
- * of 'card' and character [2] specifies the suit of 'card'.
- */
- char *
- cardtype(card)
- short card;
- {
- static char value[27] = " A 2 3 4 5 6 7 8 910 J Q K";
- static char suit[4] = "SHCD";
- static char type[4];
-
- strncpy(type, &value[((card % 52) / 4) << 1], 2);
- type[2] = suit[card & 3];
- type[3] = 0;
- return(type);
- }
-
- int
- boxit(win, rows, cols, brow, bcol)
- WINDOW *win;
- short rows;
- short cols;
- short brow;
- short bcol;
- {
- short i;
-
- wrefresh(win);
- wattron(win, A_ALTCHARSET);
- mvwaddch(win, brow, bcol, ACS_ULCORNER);
- mvwaddch(win, brow+rows-1, bcol, ACS_LLCORNER);
- for (i=bcol+1; i < bcol+cols-1; i++)
- {
- mvwaddch(win, brow, i, ACS_HLINE);
- mvwaddch(win, brow+rows-1, i, ACS_HLINE);
- }
- mvwaddch(win, brow, i, ACS_URCORNER);
- mvwaddch(win, brow+rows-1, i, ACS_LRCORNER);
- for (i=brow+1; i < rows-1; i++)
- {
- mvwaddch(win, i, bcol, ACS_VLINE);
- mvwprintw(win, i, bcol+1, "%*.*s", cols-2, cols-2, "");
- mvwaddch(win, i, bcol+cols-1, ACS_VLINE);
- }
- wrefresh(win);
- wattroff(win, A_ALTCHARSET);
- }
-
- void
- getcard(hand)
- short hand;
- {
- char c, getact();
- char *sel, *cardtype();
- char ctype1[5], ctype2[5];
- short getcard();
- void dispcard();
- void dispbet();
-
- if (Hand[hand].cnt < 2)
- {
- Hand[hand].cards[Hand[hand].cnt++] = nextcard();
- dispcard(hand, Hand[hand].cnt-1, (hand==DEALER&&Hand[0].cnt==2)?DOWN:UP);
-
- return;
- }
- if (hand == DEALER)
- {
- dispcard(DEALER, 1, UP);
- while (GETCNT(DEALER) < 17 || getcnt(DEALER) < 0 && GETCNT(DEALER) == 17)
- {
- Hand[DEALER].cards[Hand[DEALER].cnt++] = nextcard();
- dispcard(DEALER, Hand[DEALER].cnt-1, UP);
- }
- return;
- }
- if (GETCNT(hand) == 21)
- return;
- strcpy(ctype1, cardtype(Hand[hand].cards[0]));
- strcpy(ctype2, cardtype(Hand[hand].cards[1]));
- sel = (Hands < MAX_HANDS && ctype1[1]==ctype2[1]) ? "HSDP0123 " : "HSD123 ";
- if ((c = getact(hand, sel)) == 'S')
- return;
- if (c == 'P')
- {
- Hands++;
- Hand[hand].cnt--;
- Hand[hand+1].bet = Hand[hand].bet;
- Hand[hand+1].cards[0] = Hand[hand].cards[1];
- Hand[hand+1].cnt = 1;
- Hand[hand+1].bet = Hand[hand].bet;
- Hand[hand+1].amt = 0L;
- dispbet(hand);
- disphand(hand + 1);
- dispcard(hand + 1, 0, UP);
- }
- Hand[hand].cards[Hand[hand].cnt++] = nextcard();
- dispcard(hand, Hand[hand].cnt-1, UP);
- /*
- if (GETCNT(hand) >= 21)
- return;
- */
- if (c == 'P')
- {
- if (getact(hand, "^HSD123 ") == 'S')
- return;
- Hand[hand].cards[Hand[hand].cnt++] = nextcard();
- dispcard(hand, Hand[hand].cnt-1, UP);
- }
- if (c == 'D')
- {
- Hand[hand].bet *= 2;
- dispbet(hand);
- dispbet(DEALER);
- return;
- }
-
- while (GETCNT(hand) < 21)
- {
- if ((c=getact(hand, "^HS12 ")) == 'S')
- return;
- Hand[hand].cards[Hand[hand].cnt++] = nextcard();
- dispcard(hand, Hand[hand].cnt-1, UP);
- }
- return;
- }
-
- short
- getcnt(hand)
- short hand;
- {
- char *type;
- char *strchr();
- short cnt, acecnt;
- short i;
-
- for (i = 0, cnt = acecnt = 0; i < Hand[hand].cnt; i++)
- {
- type = cardtype(Hand[hand].cards[i]);
- if (strchr("KQJ0", type[1]))
- cnt += 10;
- else if (strchr("23456789", type[1]))
- cnt += type[1] - '0';
- else
- cnt += 11, acecnt++;
- }
- while (acecnt--)
- if (cnt > 21)
- cnt -= 10;
- return(acecnt>0 ? -cnt : cnt);
- }
-
- char
- getact(hand, valact)
- short hand;
- char *valact;
- {
- char prompt[80];
- char choice[2];
- char sel[5];
-
- strcpy(sel, "PHSD");
- sprintf(prompt, "Enter choice %s (Hit, Stand", Hand[hand].name);
- if (strchr(valact, 'D'))
- strcat(prompt, ", Double");
- if (strchr(valact, 'P'))
- strcat(prompt, ", sPlit");
- strcat(prompt, "): ");
- strcpy(choice, "S");
- promptfor(prompt, choice, 1, valact, MAP_UPPER|AUTO_RET);
- if (strchr("0123", choice[0]))
- choice[0] = sel[choice[0] - '0'];
- return(choice[0]);
- }
-
- short
- getbet(hand)
- short hand;
- {
- char prompt[80];
- char bet[9];
- int atoi();
-
- if (Hand[hand].bet > 500)
- Hand[hand].bet = 500;
- sprintf(prompt, "Enter bet %s: ($2 - $500, 0 to quit) ", Hand[hand].name);
- do
- {
- sprintf(bet, "%hd", Hand[hand].bet);
- promptfor(prompt, bet, 5, "0123456789", INIT_ONKEY);
- Hand[hand].bet = (long)atoi(bet);
- if (!Hand[hand].bet)
- return((short) 0);
- } while (Hand[hand].bet % 2 || Hand[hand].bet > 500);
- dispbet(hand);
- return(Hand[hand].bet);
- }
-
- long
- dispbet(hand)
- short hand;
- {
- short i;
-
- if (hand == DEALER)
- for (i = 1, Hand[DEALER].bet = 0; i < Hands; i++)
- Hand[DEALER].bet += Hand[i].bet;
-
- mvwprintw(Hand[hand].win,2,1,"stakes : %5hd", Hand[hand].bet);
- mvwprintw(Hand[hand].win,3,1,"credit : %+5hd", Hand[hand].amt);
- wrefresh(Hand[hand].win);
- return(Hand[hand].bet);
- }
-
- void
- dispcard(hand, card, up)
- short hand;
- short card;
- short up;
- {
- short bcol, val;
- short bj();
- char c,type[5];
-
- bcol = 40 + (card - 2) * 3;
- wstandout(Hand[hand].win);
- boxit(Hand[hand].win, (short) 5, (short) 5, (short) 0, (short) bcol);
- if (up)
- {
- strcpy(type, cardtype(Hand[hand].cards[card]));
- c = type[2]; type[2] = 0;
- mvwprintw(Hand[hand].win, 1, bcol+1, &type[(type[0] == ' ') ? 1 : 0]);
- mvwprintw(Hand[hand].win, 2, bcol+2, "%c", c);
- mvwprintw(Hand[hand].win, 3, bcol+2, type);
- wrefresh(Hand[hand].win);
- wstandend(Hand[hand].win);
- wrefresh(Hand[hand].win);
- mvwprintw(Hand[hand].win, 1, 13, "%5hd", (val = GETCNT(hand)));
- if (GETCNT(hand) > 21)
- mvwprintw(Hand[hand].win, 1, 21, "BUST ");
- if (bj(hand))
- mvwprintw(Hand[hand].win, 1, 21, "BLACKJACK! ");
- }
- wstandend(Hand[hand].win);
-
- wrefresh(Hand[hand].win);
- }
-
- void
- disphand(hand)
- short hand;
- {
- short i;
- for (i = 0; i < 5; i++)
- wmove(Hand[hand].win, i, 1), wclrtoeol(Hand[hand].win);
- mvwprintw(Hand[hand].win, 1, 1, "%-10.10s: ", Hand[hand].name);
- if (hand < 2)
- dispbet(hand);
- wrefresh(Hand[hand].win);
- }
-
- void
- promptfor(prompt, input, max, vchrs, flags)
- char *prompt;
- char *input;
- short max;
- long flags;
- {
- char *strchr();
- wmove(Hand[DEALER].win, 5, 1);
- while (*prompt)
- if (strchr(vchrs, *prompt) && *prompt != ' ')
- {
- wstandout(Hand[DEALER].win);
- waddch(Hand[DEALER].win, *prompt++);
- wstandend(Hand[DEALER].win);
- }
- else
- waddch(Hand[DEALER].win, *prompt++);
- waddch(Hand[DEALER].win, ' ');
-
- get_str(Hand[DEALER].win, input, max, vchrs, flags);
- wmove(Hand[DEALER].win, 5, 1); wclrtoeol(Hand[DEALER].win);
- wrefresh(Hand[DEALER].win);
- }
-
- short
- nextcard()
- {
- return(Cards[Cur_card++]);
- }
-
- short
- bj(hand)
- short hand;
- {
- if (GETCNT(hand) != 21)
- return((short)0);
- if (Hand[hand].cnt == 2)
- return((short)1);
- return((short)0);
- }
- /******************************************************************************
- * get a string through curses...how many times has this been re-written?
- * Returns: key that caused get_str to return.
- * Side Effects: _str_ holds a space padded array of characters entered by user.
- * _win_ will be changed by the contents of string
- * Note: wattron before call to get_str for pretty display of input box...
- * noecho() should be enabled...
- */
- short
- get_str(win, str, max, vchrs, flags)
- WINDOW *win; /* input window */
- char *str; /* changed by side effect */
- short max; /* stop when this is reached */
- char *vchrs; /* valid keystrokes... */
- short flags; /* all kinds of options... */
- {
-
- short sr, sc; /* save row save column -restored on ret*/
- short ofs =0; /* current offset from beginning of str */
- short ret =0; /* return status != when return desired */
- short c; /* each input char is put into this var */
- short first=TRUE; /* first time through the main loop? */
- char save[256]; /* max better be less than 256 chars */
-
- wrefresh(win); /* dump any changes */
- getyx(win, sr, sc); /* get logical cursor location*/
- if (flags & CLR_FLD) /* initialize field from beginning? */
- sprintf(str, "%*.*s", max, max, "");
- strcpy(save, str); /* save in case of an ESC... */
- sprintf(str, "%-*.*s", max, max, save); /* left justified...pad for now... */
- if (~flags & NOECHO) /* if we want to echo string... */
- waddstr(win, str);
- wmove(win, sr, sc+ofs);
- while (!ret)
- {
- if (isprint((c = get_chr(win, vchrs, flags))))
- { /* clear the input string on first */
- if (ofs == max) /* dont write over the terminating */
- ofs--; /* null character... */
- if (first && flags & INIT_ONKEY)/* clear on first printable char... */
- sprintf(str, "%*.*s", max, max, "");
- str[ofs++] = (char) c;
- if (ofs == max) /* if at end of string already... */
- if (flags & AUTO_RET) /* and AUTO_RET flag ON then... */
- ret = CR; /* pretend CR was pressed... */
- }
- else
- switch (c)
- {
- case CR:
- case NL:
- case KEY_UP:
- case KEY_DOWN:
- ret = c;
- break;
- case ESC:
- strcpy(str, save);
- ret = c;
- break;
- case KEY_RIGHT:
- if (ofs < max)
- str[ofs++] = ' ';
- break;
- case KEY_LEFT:
- case BS:
- if (ofs)
- ofs--;
- break;
- default:
- ret = c;
- break;
- }
- if (~flags & NOECHO) /* if NOECHO is OFF then disp str...*/
- mvwaddstr(win, sr, sc, str); /* (display after each character) */
- wmove(win, sr, sc+ofs);
- wrefresh(win);
- first = FALSE; /* we have been around the loop... */
- }
- if (flags & NOPAD)
- for (ofs = 0; ofs < max; ofs++)
- if (str[ofs] == ' ')
- c = ofs;
- return(ret);
- }
-
- short
- get_chr(win, vchrs, flags)
- WINDOW *win;
- char *vchrs;
- short flags;
- {
- short c;
- wrefresh(win);
- while ((c = wgetch(win)) == ERR)
- if (isprint(c) && strchr(vchrs, c))
- break;
- else if (flags & BEEP)
- beep();
- if (flags & MAP_UPPER)
- if (c >= 'a' && c <= 'z')
- c = toupper(c);
- if (flags & MAP_LOWER)
- if (c >= 'A' && c <= 'A')
- c = tolower(c);
- return(c);
-
- }
-
- void
- done()
- {
- mvprintw(19, 20, "Quit with %hd dollars", Hand[1].amt);
- mvprintw(20, 20, "Press any key to exit...");
- refresh();
- getch();
-
- endwin();
- exit(0);
- }
- ---cut here---cut here---cut here---cut here---cut here---cut here---cut here--
-
- --
- .--------------------------. ... |On the border of your mind lies a place
- |uunet!mcnc!unccvax!cs00chs| (") |where dreams and reality are one...I will
- `--------------------------'-w-U-w-|take you there, for I am the subject...
- \%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\|the subject of your imagination. -Aldo Nova
-