home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume11 / ac_bj / part01 / ac_bj.c < prev    next >
C/C++ Source or Header  |  1990-12-11  |  20KB  |  685 lines

  1. #include <curses.h>
  2. #include <ctype.h>
  3. #include <signal.h>
  4. /*****************************************************************************
  5. * You may freely distribute this file as long as the contents of this file
  6. * have not been altered in any way or form. If you decide that you would like
  7. * to re-distribute a change, please send to me for testing first - this keeps
  8. * one current and tested version out there...
  9. *
  10. * Please send suggestions, comments, complaints, ideas, etc...to the author
  11. * at e-mail address: uunet!mcnc!unccvax!cs00chs (cs00chs@unccvax.uncc.edu)
  12. * A small contribution will be appreciated and will ensure future updates
  13. * and hints. Remember, if you practice card counting and basic strategy,
  14. * you have a mathematical advantage over the house (in real life too).
  15. */
  16.  
  17. /*****************************************************************************
  18. * NAME                                                                  Aug 89
  19. *   bj - a blackjack program (version 1.0)
  20. *
  21. * SYNOPSIS
  22. *   bj 
  23. *
  24. * DESCRIPTION
  25. *  This is an eight-deck Atlantic City blackjack game for system V. Splits and
  26. *  double downs are supported. No insurance. Use the Spacebar to Hit and CR to
  27. *  stand if desired. A redeal will occur when half of the all decks are used.
  28. *  bj uses terminfo GRAPHICS capablities - iff they are activated.
  29. *
  30. *  Card-counting: Starting with the beginning of each deck, keep a running
  31. *                 count (initially 0):
  32. *                 ACE,KING,QUEEN,JACK,10 == -1
  33. *                 9, 8, 7                ==  0  (ignore)
  34. *                 6,5,4,3,2              == +1
  35. *                 When count is high (positive) bet high, if low bet minimum.
  36. *  Basic Strategy:    Dealer Showing      Insurance should never be taken
  37. *           Player -2-3-4-5-6-7-8-9-X-A-  unless counting is being used!
  38. *           2-8            H i t
  39. *           09      H D D D D H H H H H
  40. *           10      D D D D D D D D H H
  41. *           11      D D D D D D D D D H
  42. *           12      H H S S S H H H H H
  43. *           13-16   S S S S S H H H H H
  44. *           17            S t a n d
  45. *           A,2|3   H H H D D H H H H H
  46. *           A,4|5   H H D D D H H H H H
  47. *           A,6     H D D D D H H H H H
  48. *           A,7     S D D D D S S H H H
  49. *           A,8|9|X      S t a n d
  50. *
  51. * NOTE
  52. *  The program looks much nicer if you have the smacs=, rmacs= and acsc=
  53. *  capabilities in your terminfo database...but it will still work
  54. *  without them...
  55. *
  56. *  How to add graphics capabilities for vt100, vt101 and vt102 emulators:
  57. *  Type the following commands (re-start here if anything goes wrong):
  58. *  csh> setenv TERM vt100      # vt100 is an example-use TERM name youre that
  59. *  csh> mkdir ~/term           #   emulates a vt10[012] (in terminfo database)
  60. *  csh> infocmp > ~/term/info  # this will create a terminfo source file.
  61. *  csh> setenv TERMINFO ~/term # Tell curses to use the database in ~/term
  62. *  csh> tic ~/term/info        # Ignore warnings (if any)...
  63. *  Edit the ~/term/info file and add the following line to the proper entry:
  64. *    -go to the entry that emulates vt100 (eg. vt100,vt101, vt102)
  65. *    -add the following line to it...
  66. *    smacs=\E(0\E)0, rmacs=\E(B\E)B, acsc=jjkkllmmnnqqssttuuvvww++\,\,,
  67. *    -save it and type the following command:
  68. *  csh> tic ~/term/info
  69. *
  70. *  For non vt100 emulators you must read your terminal reference manual and
  71. *  terminfo(5) to set it up properly. Some old terminals do not have a text
  72. *  graphics mode - i.e. you cannot see the pretty graphics.
  73. *
  74. * BUGS
  75. *  There are a few bugs. These will be fixed on the next version iff there is
  76. *  enough interest. The dealer continues to deal to himself even after the
  77. *  outcome of a score is certain. No insurance. After the first shuffle, the
  78. *  WIN-LOSE is not displayed properly.
  79. *
  80. * AUTHOR
  81. *   clt2!jjr   (can be reached via: uunet!mcnc!unccvax!cs00chs)
  82. *   John J. Ribera, Jr.
  83. *   9505-J University Terrace Drive
  84. *   Charlotte, NC 28262
  85. *
  86. *   A small contribution will be appreciated and will ensure bug fixes and
  87. *   hints. Copyright (C) 1990.
  88. */
  89.  
  90. /* flags for get_str() and get_chr()... */
  91. #define CLR_FLD     0x0001
  92. #define INIT_ONKEY  0x0010
  93. #define MAP_UPPER   0x0002
  94. #define MAP_LOWER   0x0004
  95. #define AUTO_RET    0x0008
  96. #define NOPAD       0x0020
  97. #define NOECHO      0x0040
  98. #define BEEP        0x0080
  99.  
  100. /* keystroke defines for readablity.... */
  101. #define ESC         0x1b
  102. #define CR          '\r'
  103. #define NL          '\n'
  104. #define BS          '\b'
  105.  
  106. #define MAX_HANDS   3
  107. #define DECKS       8
  108. #define DEALER      0
  109. #define DOWN        0
  110. #define UP          1
  111. #define WIN         0x0001
  112. #define LOSE        0x0002
  113. #define PUSH        0x0004
  114. #define BJ          0x0008
  115. #define GETCNT(i)   (short) abs((int) (getcnt(i)))
  116. typedef struct
  117.     {
  118.     short   amt;
  119.     short   bet;
  120.     short   cnt;
  121.     short   cards[13];
  122.     char    name[9+1];
  123.     WINDOW  *win;
  124.     } HAND;
  125.  
  126. HAND    Hand[MAX_HANDS];
  127. short   Hands = 2;
  128. short   *Cards;
  129. short   Cur_card;
  130. short   get_str(), get_chr(), nextcard();
  131. void    getcard(), dispbet(), dispcard();
  132. void    inithand(), disphand();
  133. void    promptfor();
  134. main()
  135. {
  136.     short   i, n, pcnt, dcnt;
  137.     short   decks, cmp;
  138.     short   *shuffle();
  139.     short   getcnt(), bj(), getbet();
  140.     char    *cardtype();
  141.     char    *ptr;
  142.     void    done();
  143.  
  144. signal(SIGINT, done);
  145. initscr();
  146. noecho();
  147. crmode();
  148.  
  149. for (n = 0; n < MAX_HANDS; n++)
  150.     inithand(n);
  151.  
  152. srand(time((long *) 0));
  153. while (TRUE)
  154.     {
  155.     clearok(stdscr, TRUE);
  156.     refresh();
  157.     for (i = 0; i < Hands; i++)
  158.         disphand(i);
  159.     wstandout(Hand[DEALER].win);
  160.     mvwprintw(Hand[DEALER].win, 0, 1, " B L A C K J A C K ");
  161.     wstandend(Hand[DEALER].win);
  162.     wprintw(Hand[DEALER].win, " by clt2!jjr... (press DEL to quit)");
  163.     mvwprintw(Hand[DEALER].win, 5, 1, "Shuffle...");
  164.     wrefresh(Hand[DEALER].win);
  165.     sleep(2);
  166.     Cards = shuffle((decks = DECKS));
  167.     Cur_card = 0;
  168.     while (Cur_card < decks * 52 / 2)
  169.         {
  170.         for (i = 1;Hands > 2; Hands--, i++)
  171.             werase(Hand[i+1].win), wrefresh(Hand[i+1].win);
  172.         Hands = 2;
  173.         for (n = 1; n < Hands; n++)
  174.             {
  175.             if (!getbet(n))
  176.                 done();
  177.             Hand[n].cnt = 0;
  178.             disphand(n);
  179.             }
  180.         Hand[DEALER].cnt = 0;
  181.         disphand(DEALER);
  182.         getcard(1); getcard(DEALER);
  183.         getcard(1); getcard(DEALER);
  184.         getcard(1);
  185.         if (Hands > 2)
  186.             {
  187.             getcard(2);
  188.             getcard(2);
  189.             }
  190.         getcard(DEALER);
  191.         for (dcnt = GETCNT(DEALER), i = 1;  i < Hands; i++)
  192.             {
  193.             if ((pcnt = GETCNT(i)) > 21 || dcnt > 21)
  194.                 cmp = (pcnt > 21) ? LOSE : WIN;
  195.             else if (pcnt == dcnt)
  196.                 cmp = (bj(i)) ? BJ : PUSH;
  197.             else
  198.                 cmp = (pcnt > dcnt) ? (bj(i) ? BJ : WIN) : LOSE;
  199.             switch (cmp)
  200.                 {
  201.             case WIN:
  202.                 Hand[i].amt += Hand[i].bet;
  203.                 Hand[DEALER].amt -= Hand[i].bet;
  204.                 ptr = " WIN ";
  205.                 break;
  206.             case BJ:
  207.                 Hand[i].amt += Hand[i].bet + (Hand[i].bet / 2);
  208.                 Hand[DEALER].amt -= (Hand[i].bet + Hand[i].bet / 2);
  209.                 ptr = " WIN ";
  210.                 break;
  211.             case PUSH:
  212.                 ptr = " PUSH ";
  213.                 break;
  214.             case LOSE:
  215.                 Hand[DEALER].amt += Hand[i].bet;
  216.                 Hand[i].amt -= Hand[i].bet;
  217.                 ptr = " LOSE ";
  218.                 break;
  219.                 }
  220.             dispbet(i);
  221.             dispbet(DEALER);
  222.             wrefresh(Hand[i].win); wrefresh(Hand[0].win);
  223.             wstandout(Hand[i].win); mvwprintw(Hand[i].win, 2, 20, ptr);
  224.             wstandend(Hand[i].win); wrefresh(Hand[i].win);
  225.             }
  226.         }
  227.     promptfor("New deck...press return to continue...", ptr, 1, "", CLR_FLD);
  228.     }
  229. }
  230. void
  231. inithand(n)
  232. short   n;
  233. {
  234.  
  235. Hand[n].win = newwin((n == DEALER) ? 7 : 5,0,(n == DEALER) ? 0 : n * 5 + 2, 0);
  236. Hand[n].amt = (DEALER == n ) ? 0 : 1000;
  237. Hand[n].bet = 0L;
  238. Hand[n].cnt = 0;
  239. strcpy(Hand[n].name, getlogin());
  240. strcpy(Hand[DEALER].name, "Dealer");
  241. }
  242. /*******************************************************************************
  243. * shuffle will return a static pointer to an array of random shorts with a range
  244. * of 0 to 52 * 'decks'. If 'decks' is > 10, then 10 decks will be returned.
  245. * If 'decks' is < 1 then one shuffled deck will be returned.
  246. */
  247. short   *
  248. shuffle(decks)
  249. short   decks;
  250. {
  251. static  short   deck[52 * 10 + 1];
  252.         short   mark[52 * 10 + 1];
  253.         short   card;
  254.         short   cnt = 0;
  255.  
  256. memset(mark, '\0', sizeof(mark));
  257. memset(deck, '\0', sizeof(deck));
  258.  
  259. decks = (decks < 1) ? 1 : ((decks > 10) ? 10 : decks);
  260. while (cnt < 52 * decks)
  261.     if ((card = (short) rand() % (52 * decks)) >= 0 && !mark[card])
  262.         deck[cnt++] = card, mark[card] = 1;
  263. deck[cnt] = -1;
  264. return(deck);
  265. }
  266. /******************************************************************************
  267. * cardtype will return a 3 character string that specifies which card 'card'
  268. * represents. Character [1] of the returned string specifies the cardinality
  269. * of 'card' and character [2] specifies the suit of 'card'.
  270. */
  271. char *
  272. cardtype(card)
  273. short   card;
  274. {
  275. static  char    value[27] = " A 2 3 4 5 6 7 8 910 J Q K";
  276. static  char    suit[5] = "SHCD";
  277. static  char    type[4];
  278.  
  279. strncpy(type, &value[((card % 52) / 4) << 1], 2);
  280. type[2] = suit[card & 3];
  281. type[3] = 0;
  282. return(type);
  283. }
  284.  
  285. int
  286. boxit(win, rows, cols, brow, bcol)
  287. WINDOW  *win;
  288. short   rows;
  289. short   cols;
  290. short   brow;
  291. short   bcol;
  292. {
  293.     short   i;
  294.  
  295. wrefresh(win);
  296. wattron(win, A_ALTCHARSET);
  297. mvwaddch(win, brow, bcol, ACS_ULCORNER);
  298. mvwaddch(win, brow+rows-1, bcol, ACS_LLCORNER);
  299. for (i=bcol+1; i < bcol+cols-1; i++)
  300.     {
  301.     mvwaddch(win, brow, i, ACS_HLINE);
  302.     mvwaddch(win, brow+rows-1, i, ACS_HLINE);
  303.     }
  304. mvwaddch(win, brow, i, ACS_URCORNER);
  305. mvwaddch(win, brow+rows-1, i, ACS_LRCORNER);
  306. for (i=brow+1; i < rows-1; i++)
  307.     {
  308.     mvwaddch(win, i, bcol, ACS_VLINE);
  309.     mvwprintw(win, i, bcol+1, "%*.*s", cols-2, cols-2, "");
  310.     mvwaddch(win, i, bcol+cols-1, ACS_VLINE);
  311.     }
  312. wrefresh(win);
  313. wattroff(win, A_ALTCHARSET);
  314. }
  315.  
  316. void
  317. getcard(hand)
  318. short   hand;
  319. {
  320.     char    c, getact();
  321.     char    *sel, *cardtype();
  322.     char    ctype1[5], ctype2[5];
  323.  
  324. if (Hand[hand].cnt < 2)
  325.     {
  326.     Hand[hand].cards[Hand[hand].cnt++] = nextcard();
  327.     dispcard(hand, Hand[hand].cnt-1, (hand==DEALER&&Hand[0].cnt==2)?DOWN:UP);
  328.     return;
  329.     }
  330. if (hand == DEALER)
  331.     {
  332.     dispcard(DEALER, 1, UP);
  333.     while (GETCNT(DEALER) < 17 || getcnt(DEALER) < 0 && GETCNT(DEALER) == 17)
  334.         {
  335.         Hand[DEALER].cards[Hand[DEALER].cnt++] = nextcard();
  336.         dispcard(DEALER, Hand[DEALER].cnt-1, UP);
  337.         }
  338.     return;
  339.     }
  340. if (GETCNT(hand) == 21)
  341.     return;
  342. strcpy(ctype1, cardtype(Hand[hand].cards[0]));
  343. strcpy(ctype2, cardtype(Hand[hand].cards[1]));
  344. sel = (Hands < MAX_HANDS && ctype1[1]==ctype2[1]) ? "HSDP0123 " : "HSD123 ";
  345. if ((c = getact(hand, sel)) == 'S')
  346.     return;
  347. if (c == 'P')
  348.     {
  349.     Hands++;
  350.     Hand[hand].cnt--;
  351.     Hand[hand+1].bet = Hand[hand].bet;
  352.     Hand[hand+1].cards[0] = Hand[hand].cards[1];
  353.     Hand[hand+1].cnt = 1;
  354.     Hand[hand+1].bet = Hand[hand].bet;
  355.     Hand[hand+1].amt = 0L;
  356.     dispbet(hand);
  357.     disphand(hand + 1);
  358.     dispcard(hand + 1, 0, UP);
  359.     }
  360. Hand[hand].cards[Hand[hand].cnt++] = nextcard();
  361. dispcard(hand, Hand[hand].cnt-1, UP);
  362. /*
  363. if (GETCNT(hand) >= 21)
  364.     return;
  365. */
  366. if (c == 'P')
  367.     {
  368.     if (getact(hand, "^HSD123 ") == 'S')
  369.         return;
  370.     Hand[hand].cards[Hand[hand].cnt++] = nextcard();
  371.     dispcard(hand, Hand[hand].cnt-1, UP);
  372.     }
  373. if (c == 'D')
  374.     {
  375.     Hand[hand].bet *= 2;
  376.     dispbet(hand);
  377.     dispbet(DEALER);
  378.     return;
  379.     }
  380.  
  381. while (GETCNT(hand) < 21)
  382.     {
  383.     if ((c=getact(hand, "^HS12 ")) == 'S')
  384.         return;
  385.     Hand[hand].cards[Hand[hand].cnt++] = nextcard();
  386.     dispcard(hand, Hand[hand].cnt-1, UP);
  387.     }
  388. return;
  389. }
  390.  
  391. short
  392. getcnt(hand)
  393. short   hand;
  394. {
  395.     char    *type;
  396.     char    *strchr();
  397.     short   cnt, acecnt;
  398.     short   i;
  399.  
  400. for (i = 0, cnt = acecnt = 0; i < Hand[hand].cnt; i++)
  401.     {
  402.     type = cardtype(Hand[hand].cards[i]);
  403.     if (strchr("KQJ0", type[1]))
  404.         cnt += 10;
  405.     else if (strchr("23456789", type[1]))
  406.         cnt += type[1] - '0';
  407.     else
  408.         cnt += 11, acecnt++;
  409.     }
  410. while (acecnt--)
  411.     if (cnt > 21)
  412.         cnt -= 10;
  413. return(acecnt>0 ? -cnt : cnt);
  414. }
  415.  
  416. char
  417. getact(hand, valact)
  418. short   hand;
  419. char    *valact;
  420. {
  421.     char    prompt[80];
  422.     char    choice[2];
  423.     char    sel[5];
  424.  
  425. strcpy(sel, "PHSD");
  426. sprintf(prompt, "Enter choice %s (Hit, Stand", Hand[hand].name);
  427. if (strchr(valact, 'D'))
  428.     strcat(prompt, ", Double");
  429. if (strchr(valact, 'P'))
  430.     strcat(prompt, ", sPlit");
  431. strcat(prompt, "): ");
  432. strcpy(choice, "S");
  433. promptfor(prompt, choice, 1, valact, MAP_UPPER|AUTO_RET);
  434. if (strchr("0123", choice[0]))
  435.     choice[0] = sel[choice[0] - '0'];
  436. return(choice[0]);
  437. }
  438.  
  439. short
  440. getbet(hand)
  441. short   hand;
  442. {
  443.     char    prompt[80];
  444.     char    bet[9];
  445.     int     atoi();
  446.  
  447. if (Hand[hand].bet > 500)
  448.     Hand[hand].bet = 500;
  449. sprintf(prompt, "Enter bet %s: ($2 - $500, 0 to quit) ", Hand[hand].name);
  450. do
  451.     {
  452.     sprintf(bet, "%hd", Hand[hand].bet);
  453.     promptfor(prompt, bet, 5, "0123456789", INIT_ONKEY);
  454.     Hand[hand].bet = (long)atoi(bet);
  455.     if (!Hand[hand].bet)
  456.         return((short) 0);
  457.     } while (Hand[hand].bet % 2 || Hand[hand].bet > 500);
  458. dispbet(hand);
  459. return(Hand[hand].bet);
  460. }
  461.  
  462. void
  463. dispbet(hand)
  464. short   hand;
  465. {
  466.     short   i;
  467.  
  468. if (hand == DEALER)
  469.     for (i = 1, Hand[DEALER].bet = 0; i < Hands; i++)
  470.         Hand[DEALER].bet += Hand[i].bet;
  471.  
  472. mvwprintw(Hand[hand].win,2,1,"stakes    : %5hd", Hand[hand].bet);
  473. mvwprintw(Hand[hand].win,3,1,"credit    : %+5hd", Hand[hand].amt);
  474. wrefresh(Hand[hand].win);
  475. }
  476.  
  477. void
  478. dispcard(hand, card, up)
  479. short   hand;
  480. short   card;
  481. short   up;
  482. {
  483.     short   bcol;
  484.     short   bj();
  485.     char    c,type[5];
  486.  
  487. bcol = 40 + (card - 2) * 3;
  488. wstandout(Hand[hand].win);
  489. boxit(Hand[hand].win, (short) 5, (short) 5, (short) 0, (short) bcol);
  490. if (up)
  491.     {
  492.     strcpy(type, cardtype(Hand[hand].cards[card]));
  493.     c = type[2]; type[2] = 0;
  494.     mvwprintw(Hand[hand].win, 1, bcol+1, &type[(type[0] == ' ') ? 1 : 0]);
  495.     mvwprintw(Hand[hand].win, 2, bcol+2, "%c", c);
  496.     mvwprintw(Hand[hand].win, 3, bcol+2, type);
  497.     wrefresh(Hand[hand].win);
  498.     wstandend(Hand[hand].win);
  499.     wrefresh(Hand[hand].win);
  500.     mvwprintw(Hand[hand].win, 1, 13, "%5hd", GETCNT(hand));
  501.     if (GETCNT(hand) > 21)
  502.         mvwprintw(Hand[hand].win, 1, 21, "BUST ");
  503.     if (bj(hand))
  504.         mvwprintw(Hand[hand].win, 1, 21, "BLACKJACK! ");
  505.     }
  506. wstandend(Hand[hand].win);
  507.  
  508. wrefresh(Hand[hand].win);
  509. }
  510.  
  511. void
  512. disphand(hand)
  513. short   hand;
  514. {
  515.     short   i;
  516. for (i = 0; i < 5; i++)
  517.     wmove(Hand[hand].win, i, 1), wclrtoeol(Hand[hand].win);
  518. mvwprintw(Hand[hand].win, 1, 1, "%-10.10s: ", Hand[hand].name);
  519. if (hand < 2)
  520.     dispbet(hand);
  521. wrefresh(Hand[hand].win);
  522. }
  523.  
  524. void
  525. promptfor(prompt, input, max, vchrs, flags)
  526. char    *prompt;
  527. char    *input;
  528. short   max;
  529. long    flags;
  530. {
  531.     char    *strchr();
  532. wmove(Hand[DEALER].win, 5, 1);
  533. while (*prompt)
  534.     if (strchr(vchrs, *prompt) && *prompt != ' ')
  535.         {
  536.         wstandout(Hand[DEALER].win);
  537.         waddch(Hand[DEALER].win, *prompt++);
  538.         wstandend(Hand[DEALER].win);
  539.         }
  540.     else
  541.         waddch(Hand[DEALER].win, *prompt++);
  542. waddch(Hand[DEALER].win, ' ');
  543.  
  544. get_str(Hand[DEALER].win, input, max, vchrs, flags);
  545. wmove(Hand[DEALER].win, 5, 1); wclrtoeol(Hand[DEALER].win);
  546. wrefresh(Hand[DEALER].win);
  547. }
  548.  
  549. short
  550. nextcard()
  551. {
  552. return(Cards[Cur_card++]);
  553. }
  554.  
  555. short
  556. bj(hand)
  557. short   hand;
  558. {
  559. if (GETCNT(hand) != 21)
  560.     return((short)0);
  561. if (Hand[hand].cnt == 2)
  562.     return((short)1);
  563. return((short)0);
  564. }
  565. /******************************************************************************
  566. * get a string through curses...how many times has this been re-written?
  567. * Returns:      key that caused get_str to return.
  568. * Side Effects: _str_ holds a space padded array of characters entered by user.
  569. *               _win_ will be changed by the contents of string
  570. * Note: wattron before call to get_str for pretty display of input box...
  571. *       noecho() should be enabled...
  572. */
  573. short
  574. get_str(win, str, max, vchrs, flags)
  575. WINDOW  *win;           /* input window */
  576. char    *str;           /* changed by side effect   */
  577. short   max;            /* stop when this is reached    */
  578. char    *vchrs;         /* valid keystrokes...  */
  579. short   flags;          /* all kinds of options...  */
  580. {
  581.  
  582.     short   sr, sc;     /* save row save column -restored on ret*/
  583.     short   ofs =0;     /* current offset from beginning of str */
  584.     short   ret =0;     /* return status != when return desired */
  585.     short   c;          /* each input char is put into this var */
  586.     short   first=TRUE; /* first time through the main loop?    */
  587.     char    save[256];  /* max better be less than 256 chars    */
  588.  
  589. wrefresh(win);                          /* dump any changes */
  590. getyx(win, sr, sc);                     /* get logical cursor location*/
  591. if (flags & CLR_FLD)                    /* initialize field from beginning? */
  592.     sprintf(str, "%*.*s", max, max, "");
  593. strcpy(save, str);                      /* save in case of an ESC...    */
  594. sprintf(str, "%-*.*s", max, max, save); /* left justified...pad for now...  */
  595. if (~flags & NOECHO)                    /* if we want to echo string... */
  596.     waddstr(win, str);
  597. wmove(win, sr, sc+ofs);
  598. while (!ret)
  599.     {
  600.     if (isprint((c = get_chr(win, vchrs, flags))))
  601.         {                               /* clear the input string on first  */
  602.         if (ofs == max)                 /* dont write over the terminating  */
  603.             ofs--;                      /* null character...                */
  604.         if (first && flags & INIT_ONKEY)/* clear on first printable char... */
  605.             sprintf(str, "%*.*s", max, max, "");
  606.         str[ofs++] = (char) c;
  607.         if (ofs == max)                 /* if at end of string already...   */
  608.             if (flags & AUTO_RET)       /*   and AUTO_RET flag ON then...   */
  609.                 ret = CR;               /*     pretend CR was pressed...    */
  610.         }
  611.     else
  612.         switch (c)
  613.             {
  614.         case CR:
  615.         case NL:
  616.         case KEY_UP:
  617.         case KEY_DOWN:
  618.             ret = c;
  619.             break;
  620.         case ESC:
  621.             strcpy(str, save);
  622.             ret = c;
  623.             break;
  624.         case KEY_RIGHT:
  625.             if (ofs < max)
  626.                 str[ofs++] = ' ';
  627.             break;
  628.         case KEY_LEFT:
  629.         case BS:
  630.             if (ofs)
  631.                 ofs--;
  632.             break;
  633.         default:
  634.             ret = c;
  635.             }
  636.     if (~flags & NOECHO)                /* if NOECHO is OFF then disp str...*/
  637.         mvwaddstr(win, sr, sc, str);    /* (display after each character)   */
  638.     wmove(win, sr, sc+ofs);
  639.     wrefresh(win);
  640.     first = FALSE;                      /* we have been around the loop...  */
  641.     }
  642. if (flags & NOPAD)
  643.     for (ofs = 0; ofs < max; ofs++)
  644.         if (str[ofs] == ' ')
  645.             c = ofs;
  646. return(ret);
  647. }
  648.  
  649. short
  650. get_chr(win, vchrs, flags)
  651. WINDOW  *win;
  652. char    *vchrs;
  653. short   flags;
  654. {
  655.     short   c;
  656. wrefresh(win);
  657. while ((c = wgetch(win)) == ERR)
  658.     if (isprint(c) && strchr(vchrs, c))
  659.         break;
  660.     else if (flags & BEEP)
  661.         beep();
  662. if (flags & MAP_UPPER)
  663.     if (c >= 'a' && c <= 'z')
  664.         c = toupper(c);
  665. if (flags & MAP_LOWER)
  666.     if (c >= 'A' && c <= 'A')
  667.         c = tolower(c);
  668. return(c);
  669.  
  670. }
  671.  
  672. void
  673. done()
  674. {
  675. mvprintw(19, 20, "Quit with %hd dollars",  Hand[1].amt);
  676. mvprintw(20, 20, "Press any key to exit...");
  677. refresh();
  678. getch();
  679.  
  680. endwin();
  681. exit(0);
  682. }
  683.  
  684.  
  685.