home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / BBS / SBBS1B00.ZIP / XTRN.EXE / XTRN / SBJ / SBJ.C < prev    next >
C/C++ Source or Header  |  1992-08-11  |  44KB  |  1,630 lines

  1. /* SBJ.C */
  2.  
  3. /* Synchronet Blackjack */
  4.  
  5. /* Multiuser Blackjack game for Synchronet BBS systems */
  6.  
  7. /* Uses Xtrn SDK functions for convenience */
  8.  
  9. /* This source code is completely Public Domain and can be modified and     */
  10. /* distributed freely (as long as changes are documented).                    */
  11.  
  12. /***********/
  13. /* History */
  14. /****************************************************************************\
  15.  
  16. 1.0     Many bugs. Especially multiplayer.
  17. 1.01    Many bugs fixed. Timing problems still exist.
  18. 1.02    Fixed yet more bugs. No more timing problems. Appears bullet-proof.
  19. 1.03    Fixed dealer card up always showing card symbol (even when symbols off).
  20.         Added ctrl-e answer detection and user notification.
  21.         Fixed three 7's bug.
  22.         Raised maximum number of decks to 100 for large multinode systems.
  23.         Fixed /<CR> bug.
  24.         Fixed multiple split bug.
  25.         Fixed non-symbols being sent to other nodes bug.
  26.         Changed this node's hands to say "You" instead of the user name.
  27. v1.04    Changed the warning and timeout times
  28. v1.05    Fixed symbols being displayed on dealer's hand even when disabled.
  29.         Made different inactivity warning and timeout values for the main
  30.         menu and when in play.
  31. v1.06    Fixed invalid (usually negative) card bug. THELP random() doc error.
  32.         Card now actually contains all the cards minus one.
  33.         Fixed multinode play join and hang bug.
  34. v1.07    If player gets blackjack and dealer gets 21, player wins. Used to push.
  35. v1.08    Fixed split, then double bug.
  36. v2.00    Replaced bioskey(1) calls with inkey() and used XSDK v2.0 with node
  37.         intercommunication with users on BBS or in other external programs.
  38. v2.01    Fixed problem with loosing first character of chat lines
  39.         Added DESQview awareness
  40.         Replaced all calls to delay() with fdelay()
  41. v2.02    Listing users now displays what external program they're running.
  42.         Fixed problem with max bet being too small when users have over
  43.         65mb of credit.
  44.  
  45. \****************************************************************************/
  46.  
  47. #include <stdio.h>
  48. #include <stdlib.h>
  49. #include <ctype.h>
  50.  
  51. #include "xsdk.h"
  52.  
  53. #define MAX_DECKS    100
  54. #define MAX_CARDS    10        /* maximum number of cards per hand */
  55. #define MAX_HANDS    4        /* maximum number of hands per player */
  56.  
  57. #define DEBUG 0
  58.  
  59. #define J 11    /* jack */
  60. #define Q 12    /* queen */
  61. #define K 13    /* king */
  62. #define A 14    /* ace */
  63.  
  64. #define H 0        /* heart */
  65. #define D 1     /* diamond */
  66. #define C 2        /* club */
  67. #define S 3        /* spade */
  68.                                     /* bits used in misc variable */
  69. #define INPLAY        (1<<0)            /* hand in play */
  70.  
  71. enum {                                /* values for status bytes */
  72.      BET                            /* betting */
  73.     ,WAIT                            /* waiting for turn */
  74.     ,PLAY                            /* playing his hand */
  75.     ,SYNC_P                         /* In sync area - player */
  76.     ,SYNC_D                         /* In sync area - dealer */
  77.     };
  78.  
  79. typedef struct { char value, suit; } card_t;
  80.  
  81. card_t newdeck[52]={
  82.      2,H, 2,D, 2,C, 2,S,
  83.      3,H, 3,D, 3,C, 3,S,
  84.      4,H, 4,D, 4,C, 4,S,
  85.      5,H, 5,D, 5,C, 5,S,
  86.      6,H, 6,D, 6,C, 6,S,
  87.      7,H, 7,D, 7,C, 7,S,
  88.      8,H, 8,D, 8,C, 8,S,
  89.      9,H, 9,D, 9,C, 9,S,
  90.     10,H,10,D,10,C,10,S,
  91.      J,H, J,D, J,C, J,S,
  92.      Q,H, Q,D, Q,C, Q,S,
  93.      K,H, K,D, K,C, K,S,
  94.      A,H, A,D, A,C, A,S };
  95.  
  96. uchar    misc;
  97. uchar    curplayer;
  98. uchar    total_decks,sys_decks;
  99. uchar    total_nodes;
  100. int     cur_card;
  101. uchar    dc;
  102. card_t    dealer[MAX_CARDS];
  103. int     gamedab;                     /* file handle for data file */
  104. card_t    card[MAX_DECKS*52];
  105. card_t    player[MAX_HANDS][MAX_CARDS];
  106. char    hands,pc[MAX_HANDS];
  107. uchar    total_players;
  108. uchar    symbols=1;
  109. char    autoplay=0;
  110. char    logit=0;
  111. uint    node[MAX_NODES];   /* the usernumber in each node */
  112. char    status[MAX_NODES];
  113. ulong    credits;
  114. uint    bet[MAX_HANDS],ibet,min_bet,max_bet;
  115. char    tmp[81];
  116. char    *UserSays="\1n\1m\1h%s \1n\1msays \"\1c\1h%s\1n\1m\"\r\n";
  117. char    *UserWhispers="\1n\1m\1h%s \1n\1mwhispers \"\1c\1h%s\1n\1m\"\r\n";
  118. char    *ShoeStatus="\r\n\1_\1w\1hShoe: %u/%u\r\n";
  119.  
  120. #ifndef SBJCLEAN
  121.  
  122. void play(void);
  123. char *cardstr(card_t card);
  124. char hand(card_t card[MAX_CARDS], char count);
  125. void getgamedat(char lockit);
  126. void putgamedat(void);
  127. void getcarddat(void);
  128. void putcarddat(void);
  129. void shuffle(void);
  130. void waitturn(void);
  131. void nextplayer(void);
  132. char lastplayer(void);
  133. char firstplayer(void);
  134. void getnodemsg(void);
  135. void putnodemsg(char *msg,char nodenumber);
  136. void putallnodemsg(char *msg);
  137. void syncplayer(void);
  138. void syncdealer(void);
  139. void moduserdat(void);
  140. char *hit(void);
  141. char *stand(void);
  142. char *doubit(void);
  143. char *split(void);
  144. void open_gamedab(void);
  145. void create_gamedab(void);
  146. char *activity(char status_type);
  147. void chat(void);
  148. void listplayers(void);
  149. char *joined(void);
  150. char *left(void);
  151. void strip_symbols(char *str);
  152. void debug(void);
  153.  
  154. /****************************************************************************/
  155. /* Entry point                                                                */
  156. /****************************************************************************/
  157. int main(int argc, char **argv)
  158. {
  159.     char str[81],ch;
  160.     int i,file;
  161.     FILE *stream;
  162.  
  163. if(argc<2) {    /* node directory not specified */
  164.     bputs("usage: sbj <node directory> [/options]\r\n");
  165.     bputs("\r\noptions: L = log wins/losses for each day\r\n");
  166.     getch();
  167.     return(1); }
  168. strcpy(node_dir,argv[1]);
  169. if(node_dir[strlen(node_dir)-1]!='\\')  /* make sure node_dir ends in '\' */
  170.     strcat(node_dir,"\\");
  171. if(argc>2 && !stricmp(argv[2],"/L"))
  172.     logit=1;
  173.  
  174. initdata();                                 /* read XTRN.DAT and more */
  175. credits=user_cdt;
  176. total_nodes=sys_nodes;
  177.  
  178.  
  179. if((file=nopen("SBJ.CFG",O_RDONLY))==-1) {  /* open config file */
  180.     bputs("Error opening SBJ.CFG\r\n");
  181.     pause();
  182.     return(1); }
  183. if((stream=fdopen(file,"rb"))==NULL) {      /* convert to stream */
  184.     bputs("Error converting SBJ.CFG handle to stream\r\n");
  185.     pause();
  186.     return(1); }
  187. fgets(str,81,stream);                        /* number of decks in shoe */
  188. total_decks=sys_decks=atoi(str);
  189. fgets(str,81,stream);                        /* min bet (in k) */
  190. min_bet=atoi(str);
  191. fgets(str,81,stream);                        /* max bet (in k) */
  192. max_bet=atoi(str);
  193. fgets(str,81,stream);                        /* default bet (in k) */
  194. ibet=atoi(str);
  195. fclose(stream);
  196. if(!total_decks || total_decks>MAX_DECKS) {
  197.     bputs("Invalid number of decks in SBJ.CFG\r\n");
  198.     pause();
  199.     return(1); }
  200. if(!max_bet) {
  201.     bputs("Invalid max bet in SBJ.CFG\r\n");
  202.     pause();
  203.     return(1); }
  204. if(min_bet>max_bet) {
  205.     bputs("Invalid min bet in SBJ.CFG\r\n");
  206.     pause();
  207.     return(1); }
  208. if(ibet>max_bet || ibet<min_bet) {
  209.     bputs("Invalid default bet in SBJ.CFG\r\n");
  210.     pause();
  211.     return(1); }
  212.  
  213. if(!fexist("CARD.DAB")) {
  214.     cur_card=0;
  215.     dc=0;
  216.     memset(dealer,0,sizeof(dealer));
  217.     memset(card,0,sizeof(card));
  218.     putcarddat(); }
  219. else {
  220.     getcarddat();
  221.     if(total_decks!=sys_decks) {
  222.         remove("CARD.DAB");
  223.         total_decks=sys_decks;
  224.         putcarddat(); } }
  225.  
  226. if(!fexist("GAME.DAB"))         /* File's not there */
  227.     create_gamedab();
  228.  
  229. open_gamedab();
  230.  
  231. getgamedat(0);
  232. if(total_nodes!=sys_nodes) {  /* total nodes changed */
  233.     close(gamedab);
  234.     total_nodes=sys_nodes;
  235.     create_gamedab();
  236.     open_gamedab(); }
  237.  
  238. randomize();
  239.  
  240. while(bioskey(1))    /* clear input buffer */
  241.     bioskey(0);
  242. putchar(5); /* ctrl-e */
  243. fdelay(500);
  244. if(bioskey(1)) {
  245.     while(bioskey(1))
  246.         bioskey(0);
  247.     bputs("\r\n\1r\1h\1i*** ATTENTION ***\1n\1h\r\n");
  248.     bputs("\r\nSynchronet Blackjack uses Ctrl-E (ENQ) for the 'club' card "
  249.         "symbol.");
  250.     bputs("\r\nYour terminal responded to this control character with an "
  251.         "answerback string.");
  252.     bputs("\r\nYou will need to either disable all Ctrl-E (ENQ) answerback "
  253.         "strings (Including \r\nCompuserve Quick B transfers) or toggle card "
  254.         "symbols off.\r\n\r\n");
  255.     pause(); }
  256.  
  257. cls();
  258. bputs("\1n \1h\1cSynchronet\r\n");
  259. bputs("\1n\0011\1k Blackjack! \r\n");
  260. bputs("\1n\1r   v2.02\r\n");
  261.  
  262. getgamedat(1);
  263. node[node_num-1]=0;
  264. putgamedat();
  265.  
  266. sec_warn=120;    /* Override default inactivity timeout values */
  267. sec_timeout=180;
  268.  
  269. while(1) {
  270.     mnemonics("\r\n~Instructions\r\n");
  271.     mnemonics("~Join Game\r\n");
  272.     mnemonics("~List Players\r\n");
  273.     mnemonics("~Rules of the Game\r\n");
  274.     mnemonics("~Toggle Card Symbols\r\n");
  275.     sprintf(str,"~Quit to %s\r\n",sys_name);
  276.     mnemonics(str);
  277.     nodesync();
  278.     bprintf("\1_\r\n\1y\1hWhich: \1n");
  279.     switch(getkeys("IJLRTQ|!",0)) {
  280.         #if DEBUG
  281.         case '!':
  282.             if(user_ml>=90)
  283.                 autoplay=1;
  284.             break;
  285.         case '|':
  286.             debug();
  287.             break;
  288.         #endif
  289.         case 'I':
  290.             printfile("SBJ.MSG");
  291.             break;
  292.         case 'L':
  293.             listplayers();
  294.             bprintf(ShoeStatus,cur_card,total_decks*52);
  295.             break;
  296.         case 'R':
  297.             bprintf("\1n\1c\r\nMinimum bet: \1h%uk",min_bet);
  298.             bprintf("\1n\1c\r\nMaximum bet: \1h%uk\r\n",max_bet);
  299.             bprintf("\1w\1h\r\nCard decks in shoe: \1h%u\r\n",sys_decks);
  300.             break;
  301.         case 'T':
  302.             symbols=!symbols;
  303.             bprintf("\1_\1w\r\nCard symbols now: %s\r\n",symbols ? "ON":"OFF");
  304.             break;
  305.         case 'Q':
  306.             exit(0);
  307.         case 'J':
  308.             sec_warn=60;    /* Override default inactivity timeout values */
  309.             sec_timeout=90;
  310.             play();
  311.             sec_warn=120;
  312.             sec_timeout=180;
  313.             break; } }
  314. }
  315.  
  316. #if DEBUG
  317. void debug()
  318. {
  319.     int i;
  320.  
  321. if(user_ml<90)
  322.     return;
  323. getgamedat(0);
  324. getcarddat();
  325.  
  326. bprintf("\r\nDeck (%d) Current: %d\r\n\r\n",total_decks,cur_card);
  327. for(i=0;i<total_decks*52;i++) {
  328.     if(!(i%11))
  329.         bputs("\r\n");
  330.     bprintf("%3d:%-11s",i,cardstr(card[i])); }
  331.  
  332. pause();
  333. bprintf("\1n\r\nDealer (%d)\r\n\r\n",dc);
  334. for(i=0;i<dc;i++)
  335.     bprintf("%s ",cardstr(dealer[i]));
  336. bprintf("\1n\r\nNodes (%d) Current: %d\r\n\r\n"
  337.     ,total_nodes,curplayer);
  338. for(i=0;i<total_nodes;i++)
  339.     bprintf("%d: node=%d status=%d %s\r\n",i+1,node[i]
  340.         ,status[i],activity(status[i]));
  341. }
  342.  
  343. #endif
  344.  
  345. /****************************************************************************/
  346. /* This function is the actual game playing loop.                            */
  347. /****************************************************************************/
  348. void play()
  349. {
  350.     char str[256],str2[256],log[81],done,doub,dh
  351.         ,*YouWereDealt="\1n\1k\0015 You \1n\1m were dealt: %s\r\n"
  352.         ,*UserWasDealt="\1n\1m\1h%s\1n\1m was dealt: %s\r\n"
  353.         ,*YourHand="\1n\1k\0015 You \1n\1m                     (%2d) %s"
  354.         ,*UserHand="\1n\1m\1h%-25s \1n\1m(%2d) %s"
  355.         ,*DealerHand="\1n\1hDealer                    \1n\1m(%2d) "
  356.         ,*Bust="\1n\1r\1hBust\1n\r\n"
  357.         ,*Natural="\1g\1h\1iNatural "
  358.         ,*Three7s="\1r\1h\1iThree 7's "
  359.         ,*Blackjack="\1n\0011\1k Blackjack! \1n\r\n"
  360.         ,*TwentyOne="\1n\0012\1k Twenty-one \1n\r\n";
  361.     int h,i,j,file;
  362.     uint max;
  363.     long val;
  364.     time_t start,now;
  365.     struct date date;
  366.  
  367. sprintf(str,"MESSAGE.%d",node_num);         /* remove message if waiting */
  368. if(fexist(str))
  369.     remove(str);
  370.  
  371. getgamedat(0);
  372. if(node[node_num-1]) {
  373.     getgamedat(1);
  374.     node[node_num-1]=0;
  375.     putgamedat();
  376.     getgamedat(0); }
  377.  
  378. if(total_players && misc&INPLAY) {
  379.     bputs("\r\n\1hWaiting for end of hand (^A to abort)...\1n");
  380.     start=now=time(NULL);
  381.     getgamedat(0);
  382.     while(total_players && misc&INPLAY) {
  383.         if((i=inkey())!=0) {    /* if key was hit */
  384.             if(i==1) {         /* if ctrl-a */
  385.                 bputs("\r\n");
  386.                 return; } }  /* return */
  387.         fdelay(100);
  388.         getgamedat(0);
  389.         now=time(NULL);
  390.         if(now-start>300) { /* only wait up to 5 minutes */
  391.             bputs("\r\ntimeout\r\n");
  392.             return; } }
  393.     bputs("\r\n"); }
  394.  
  395. getgamedat(1);
  396. node[node_num-1]=user_number;
  397. putgamedat();
  398.  
  399. if(!total_players)
  400.     shuffle();
  401. else
  402.     listplayers();
  403.  
  404. sprintf(str,"\1n\1m\1h%s \1n\1m%s\r\n",user_name,joined());
  405. putallnodemsg(str);
  406.  
  407. while(1) {
  408.     bprintf(ShoeStatus,cur_card,total_decks*52);
  409.     if(cur_card>(total_decks*52)-(total_players*10)-10 && lastplayer())
  410.         shuffle();
  411.     getgamedat(1);
  412.     misc&=~INPLAY;
  413.     status[node_num-1]=BET;
  414.     node[node_num-1]=user_number;
  415.     putgamedat();
  416.  
  417.     bprintf("\r\n\1n\1cYou have \1h%s\1n\1ck credits\r\n"
  418.         ,ultoac(credits/1024L,str));
  419.     if(credits<min_bet/1024) {
  420.         bprintf("\1n\1cMinimum bet: \1h%uk\r\n",min_bet);
  421.         bputs("\1n\1r\1hCome back when you have more credits.\r\n");
  422.         break; }
  423.     if(credits/1024L>(ulong)max_bet)
  424.         max=max_bet;
  425.     else
  426.         max=credits/1024L;
  427.     sprintf(str,"\r\nBet amount (in kilobytes) or ~Quit [%u]: "
  428.         ,ibet<credits/1024L ? ibet : credits/1024L);
  429.     chat();
  430.     mnemonics(str);
  431.     if(autoplay && bioskey(1))
  432.         autoplay=0;
  433.     if(autoplay)
  434.         i=ibet;
  435.     else
  436.         i=getnum(max);
  437.     if(i==-1)    /* if user hit ^C or 'Q' */
  438.         break;
  439.     bputs("\r\n");
  440.     if(i)        /* if user entered a value */
  441.         bet[0]=i;
  442.     else        /* if user hit enter */
  443.         bet[0]=ibet<credits/1024L ? ibet : credits/1024L;
  444.     if(bet[0]<min_bet) {
  445.         bprintf("\1n\1cMinimum bet: \1h%uk\r\n",min_bet);
  446.         bputs("\1n\1r\1hCome back when you're ready to bet more.\r\n");
  447.         break; }
  448.     ibet=bet[0];
  449.     getgamedat(0);    /* to get all new arrivals */
  450.     sprintf(str,"\1m\1h%s\1n\1m bet \1n\1h%u\1n\1mk\r\n",user_name,bet[0]);
  451.     putallnodemsg(str);
  452.  
  453.     pc[0]=2;                        /* init player's 1st hand to 2 cards */
  454.     for(i=1;i<MAX_HANDS;i++)        /* init player's other hands to 0 cards */
  455.         pc[i]=0;
  456.     hands=1;                        /* init total player's hands to 1 */
  457.  
  458.     getgamedat(1);                    /* first come first serve to be the */
  459.     for(i=0;i<total_nodes;i++)        /* dealer in control of sync */
  460.         if(node[i] && status[i]==SYNC_D)
  461.             break;
  462.     if(i==total_nodes)
  463.         syncdealer();                /* all players meet here */
  464.     else                            /* first player is current after here */
  465.         syncplayer();                /* game is closed (INPLAY) at this point */
  466.     
  467.     waitturn();
  468.     getnodemsg();
  469.                                         /* Initial deal card #1 */
  470.     getcarddat();
  471.     player[0][0]=card[cur_card++];
  472.     putcarddat();
  473.     sprintf(str,YouWereDealt,cardstr(card[cur_card-1]));
  474.     if(!symbols)
  475.         strip_symbols(str);
  476.     bputs(str);
  477.     sprintf(str,UserWasDealt,user_name,cardstr(card[cur_card-1]));
  478.     putallnodemsg(str);
  479.     
  480.     if(lastplayer()) {
  481.         getcarddat();
  482.         dealer[0]=card[cur_card++];
  483.         dc=1;
  484.         putcarddat(); }
  485.     nextplayer();
  486.     waitturn();
  487.     getnodemsg();
  488.  
  489.     getcarddat();                       /* Initial deal card #2 */
  490.     player[0][1]=card[cur_card++];
  491.     putcarddat();
  492.     sprintf(str,YouWereDealt,cardstr(card[cur_card-1]));
  493.     if(!symbols)
  494.         strip_symbols(str);
  495.     bputs(str);
  496.     sprintf(str,UserWasDealt,user_name,cardstr(card[cur_card-1]));
  497.     putallnodemsg(str);
  498.     
  499.     if(lastplayer()) {
  500.         getcarddat();
  501.         dealer[1]=card[cur_card++];
  502.         dc=2;
  503.         putcarddat(); }
  504.     nextplayer();
  505.     waitturn();
  506.     getnodemsg();
  507.     getcarddat();
  508.  
  509.     for(i=0;i<hands;i++) {
  510.         done=doub=0;
  511.         while(!done && pc[i]<MAX_CARDS && cur_card<total_decks*52) {
  512.             h=hand(player[i],pc[i]);
  513.             str[0]=0;
  514.             for(j=0;j<pc[i];j++) {
  515.                 strcat(str,cardstr(player[i][j]));
  516.                 strcat(str," "); }
  517.             j=bstrlen(str);
  518.             while(j++<19)
  519.                 strcat(str," ");
  520.             if(h>21) {
  521.                 strcat(str,Bust);
  522.                 sprintf(str2,YourHand,h,str);
  523.                 if(!symbols)
  524.                     strip_symbols(str2);
  525.                 bputs(str2);
  526.                 sprintf(str2,UserHand,user_name,h,str);
  527.                 putallnodemsg(str2);
  528.                 break; }
  529.             if(h==21) {
  530.                 if(pc[i]==2) {    /* blackjack */
  531.                     if(player[i][0].suit==player[i][1].suit)
  532.                         strcat(str,Natural);
  533.                     strcat(str,Blackjack); }
  534.                 else {
  535.                     if(player[i][0].value==7
  536.                         && player[i][1].value==7
  537.                         && player[i][2].value==7)
  538.                         strcat(str,Three7s);
  539.                     strcat(str,TwentyOne); }
  540.                 sprintf(str2,YourHand,h,str);
  541.                 if(!symbols)
  542.                     strip_symbols(str2);
  543.                 bputs(str2);
  544.                 sprintf(str2,UserHand,user_name,h,str);
  545.                 putallnodemsg(str2);
  546.                 fdelay(500);
  547.                 break; }
  548.             strcat(str,"\r\n");
  549.             sprintf(str2,YourHand,h,str);
  550.             if(!symbols)
  551.                 strip_symbols(str2);
  552.             bputs(str2);
  553.             sprintf(str2,UserHand,user_name,h,str);
  554.             putallnodemsg(str2);
  555.             if(doub)
  556.                 break;
  557.             sprintf(str,"\1n\1hDealer\1n\1m card up: %s\r\n"
  558.                 ,cardstr(dealer[1]));
  559.             if(!symbols)
  560.                 strip_symbols(str);
  561.             bputs(str);
  562.             strcpy(str,"\r\n~Hit");
  563.             strcpy(tmp,"H\r");
  564.             if(bet[i]+ibet<=credits/1024L && pc[i]==2) {
  565.                 strcat(str,", ~Double");
  566.                 strcat(tmp,"D"); }
  567.             if(bet[i]+ibet<=credits/1024L && pc[i]==2 && hands<MAX_HANDS
  568.                 && player[i][0].value==player[i][1].value) {
  569.                 strcat(str,", ~Split");
  570.                 strcat(tmp,"S"); }
  571.             strcat(str,", or [Stand]: ");
  572.             chat();
  573.             mnemonics(str);
  574.             if(autoplay && bioskey(1))
  575.                 autoplay=0;
  576.             if(autoplay) {
  577.                 bputs("\r\n");
  578.                 strcpy(str,stand());
  579.                 bputs(str);
  580.                 putallnodemsg(str);
  581.                 done=1; }
  582.             else
  583.             switch(getkeys(tmp,0)) {
  584.                 case 'H':     /* hit */
  585.                     strcpy(str,hit());
  586.                     bputs(str);
  587.                     putallnodemsg(str);
  588.                     getcarddat();
  589.                     player[i][pc[i]++]=card[cur_card++];
  590.                     putcarddat();
  591.                     break;
  592.                 case 'D':   /* double down */
  593.                     strcpy(str,doubit());
  594.                     bputs(str);
  595.                     putallnodemsg(str);
  596.                     getcarddat();
  597.                     player[i][pc[i]++]=card[cur_card++];
  598.                     putcarddat();
  599.                     doub=1;
  600.                     bet[i]+=ibet;
  601.                     break;
  602.                 case 'S':   /* split */
  603.                     strcpy(str,split());
  604.                     bputs(str);
  605.                     putallnodemsg(str);
  606.                     player[hands][0]=player[i][1];
  607.                     getcarddat();
  608.                     player[i][1]=card[cur_card++];
  609.                     player[hands][1]=card[cur_card++];
  610.                     putcarddat();
  611.                     pc[hands]=2;
  612.                     bet[hands]=ibet;
  613.                     hands++;
  614.                     break;
  615.                 case CR:
  616.                     strcpy(str,stand());
  617.                     bputs(str);
  618.                     putallnodemsg(str);
  619.                     done=1;
  620.                     break; } } }
  621.  
  622.     if(lastplayer()) {    /* last player plays the dealer's hand */
  623.         getcarddat();
  624.         while(hand(dealer,dc)<17 && dc<MAX_CARDS && cur_card<total_decks*52)
  625.             dealer[dc++]=card[cur_card++];
  626.         putcarddat(); }
  627.  
  628.     nextplayer();
  629.     waitturn();
  630.     getnodemsg();
  631.  
  632.     if(firstplayer()==node_num) {
  633.         strcpy(str,"\1n\0014\1h Final \1n\r\n");
  634.         bputs(str);
  635.         putallnodemsg(str); }
  636.     getcarddat();
  637.     dh=hand(dealer,dc);                     /* display dealer's hand */
  638.     sprintf(str,DealerHand,dh);
  639.     for(i=0;i<dc;i++) {
  640.         strcat(str,cardstr(dealer[i]));
  641.         strcat(str," "); }
  642.     i=bstrlen(str);
  643.     while(i++<50)
  644.         strcat(str," ");
  645.     if(dh>21) {
  646.         strcat(str,Bust);
  647.         if(!symbols)
  648.             strip_symbols(str);
  649.         bputs(str); }
  650.     else if(dh==21) {
  651.         if(dc==2) {     /* blackjack */
  652.             if(dealer[0].suit==dealer[1].suit)
  653.                 strcat(str,Natural);
  654.             strcat(str,Blackjack); }
  655.         else {            /* twenty-one */
  656.             if(dc==3 && dealer[0].value==7 && dealer[1].value==7
  657.                 && dealer[2].value==7)
  658.                 strcat(str,Three7s);
  659.             strcat(str,TwentyOne); }
  660.         if(!symbols)
  661.             strip_symbols(str);
  662.         bputs(str); }
  663.     else {
  664.         if(!symbols)
  665.             strip_symbols(str);
  666.         bprintf("%s\r\n",str); }
  667.  
  668.     for(i=0;i<hands;i++) {                        /* display player's hand(s) */
  669.         h=hand(player[i],pc[i]);
  670.         str[0]=0;
  671.         for(j=0;j<pc[i];j++) {
  672.             strcat(str,cardstr(player[i][j]));
  673.             strcat(str," "); }
  674.         j=bstrlen(str);
  675.         while(j++<19)
  676.             strcat(str," ");
  677.         if(logit) {
  678.             getdate(&date);
  679.             sprintf(log,"%02d%02d%02d.LOG"                  /* log winnings */
  680.                 ,date.da_mon,date.da_day,date.da_year-1900);
  681.             if((file=nopen(log,O_RDONLY))!=-1) {
  682.                 read(file,tmp,filelength(file));
  683.                 tmp[filelength(file)]=0;
  684.                 val=atol(tmp);
  685.                 close(file); }
  686.             else
  687.                 val=0L;
  688.             if((file=nopen(log,O_WRONLY|O_CREAT|O_TRUNC))==-1) {
  689.                 bprintf("modeuserdat: error opening %s\r\n",log);
  690.                 return; } }
  691.         if(h<22 && (h>dh || dh>21    /* player won */
  692.             || (h==21 && pc[i]==2 && dh==21 && dh>2))) {    /* blackjack */
  693.             j=bet[i];                                  /* and dealer got 21 */
  694.             if(h==21 &&     /* natural blackjack or three 7's */
  695.                 ((player[i][0].value==7 && player[i][1].value==7
  696.                 && player[i][2].value==7)
  697.                 || (pc[i]==2 && player[i][0].suit==player[i][1].suit)))
  698.                 j*=2;
  699.             else if(h==21 && pc[i]==2)    /* regular blackjack */
  700.                 j*=1.5; /* blackjack pays 1½ to 1 */
  701.             sprintf(tmp,"\1n\1h\1m\1iWon!\1n\1h %u\1n\1mk",j);
  702.             strcat(str,tmp);
  703.             credits+=j*1024L;
  704.             val-=j*1024L;
  705.             moduserdat(); }
  706.         else if(h<22 && h==dh)
  707.             strcat(str,"\1n\1hPush");
  708.         else {
  709.             strcat(str,"\1nLost");
  710.             credits-=bet[i]*1024L;
  711.             val+=bet[i]*1024L;
  712.             moduserdat(); }
  713.         if(logit) {
  714.             sprintf(tmp,"%ld",val);
  715.             write(file,tmp,strlen(tmp));
  716.             close(file); }                    /* close winning log */
  717.         strcat(str,"\1n\r\n");
  718.         sprintf(str2,YourHand,h,str);
  719.         if(!symbols)
  720.             strip_symbols(str2);
  721.         bputs(str2);
  722.         sprintf(str2,UserHand,user_name,h,str);
  723.         putallnodemsg(str2); }
  724.  
  725.     nextplayer();
  726.     if(!lastplayer()) {
  727.         waitturn();
  728.         nextplayer(); }
  729.     getnodemsg(); }
  730.  
  731. getgamedat(1);
  732. node[node_num-1]=0;
  733. putgamedat();
  734. sprintf(str,"\1n\1m\1h%s \1n\1m%s\r\n",user_name,left());
  735. putallnodemsg(str);
  736. }
  737.  
  738. /****************************************************************************/
  739. /* This function returns a static string that describes the status byte     */
  740. /****************************************************************************/
  741. char *activity(char status_type)
  742. {
  743.     static char str[50];
  744.  
  745. switch(status_type) {
  746.     case BET:
  747.         strcpy(str,"betting");
  748.         break;
  749.     case WAIT:
  750.         strcpy(str,"waiting for turn");
  751.         break;
  752.     case PLAY:
  753.         strcpy(str,"playing");
  754.         break;
  755.     case SYNC_P:
  756.         strcpy(str,"synchronizing");
  757.         break;
  758.     case SYNC_D:
  759.         strcpy(str,"synchronizing (dealer)");
  760.         break;
  761.     default:
  762.         strcat(str,"UNKNOWN");
  763.         break; }
  764. return(str);
  765. }
  766.  
  767. /****************************************************************************/
  768. /* This function returns the string that represents a playing card.         */
  769. /****************************************************************************/
  770. char *cardstr(card_t card)
  771. {
  772.     static char str[20];
  773.     char tmp[20];
  774.  
  775. strcpy(str,"\1n\0017"); /* card color - background always white */
  776. if(card.suit==H || card.suit==D)
  777.     strcat(str,"\1r");  /* hearts and diamonds - foreground red */
  778. else
  779.     strcat(str,"\1k");  /* spades and clubs - foreground black */
  780. if(card.value>10)    /* face card */
  781.     switch(card.value) {
  782.         case J:
  783.             strcat(str,"J");
  784.             break;
  785.         case Q:
  786.             strcat(str,"Q");
  787.             break;
  788.         case K:
  789.             strcat(str,"K");
  790.             break;
  791.         case A:
  792.             strcat(str,"A");
  793.             break; }
  794. else {
  795.     sprintf(tmp,"%d",card.value);
  796.     strcat(str,tmp); }
  797. switch(card.suit) {  /* suit */
  798.     case H:
  799.         strcat(str,"\3");
  800.         break;
  801.     case D:
  802.         strcat(str,"\4");
  803.         break;
  804.     case C:
  805.         strcat(str,"\5");
  806.         break;
  807.     case S:
  808.         strcat(str,"\6");
  809.         break; }
  810. strcat(str,"\1n");
  811. return(str);
  812. }
  813.  
  814.  
  815. /****************************************************************************/
  816. /* This function returns the best value of a given hand.                    */
  817. /****************************************************************************/
  818. char hand(card_t card[MAX_CARDS],char count)
  819. {
  820.     char c,total=0,ace=0;
  821.  
  822. for(c=0;c<count;c++) {
  823.     if(card[c].value==A) {        /* Ace */
  824.         if(total+11>21)
  825.             total++;
  826.         else {
  827.             ace=1;
  828.             total+=11; } }
  829.     else if(card[c].value>=J)    /* Jack, Queen, King */
  830.         total+=10;
  831.     else                        /* Number cards */
  832.         total+=card[c].value; }
  833. if(total>21 && ace)    /* ace is low if bust */
  834.     total-=10;
  835. return(total);
  836. }
  837.  
  838.  
  839. /****************************************************************************/
  840. /* This function shuffles the deck.                                         */
  841. /****************************************************************************/
  842. void shuffle()
  843. {
  844.     char str[81];
  845.     uint i,j;
  846.     card_t shufdeck[52*MAX_DECKS];
  847.  
  848.  
  849. getcarddat();
  850.  
  851. sprintf(str,"\1_\1w\1h\r\nShuffling %d Deck Shoe...",total_decks);
  852. bputs(str);
  853. strcat(str,"\r\n");     /* add crlf for other nodes */
  854. putallnodemsg(str);
  855.  
  856. for(i=0;i<total_decks;i++)
  857.     memcpy(shufdeck+(i*52),newdeck,sizeof(newdeck));      /* fresh decks */
  858.  
  859. i=0;
  860. while(i<(total_decks*52)-1) {
  861.     j=random((total_decks*52)-1);
  862.     if(!shufdeck[j].value)    /* card already used */
  863.         continue;
  864.     card[i]=shufdeck[j];
  865.     shufdeck[j].value=0;    /* mark card as used */
  866.     i++; }
  867.  
  868. cur_card=0;
  869. for(i=0;i<MAX_HANDS;i++)
  870.     pc[i]=0;
  871. hands=0;
  872. dc=0;
  873. putcarddat();
  874. bputs("\r\n");
  875. }
  876.  
  877. /****************************************************************************/
  878. /* This function reads and displays a message waiting for this node, if     */
  879. /* there is one.                                                            */
  880. /****************************************************************************/
  881. void getnodemsg()
  882. {
  883.     char str[81], *buf;
  884.     int file;
  885.     ulong length;
  886.  
  887. nodesync();
  888. sprintf(str,"MESSAGE.%d",node_num);
  889. if(flength(str)<1L)                     /* v1.02 fix */
  890.     return;
  891. if((file=nopen(str,O_RDONLY))==-1) {
  892.     bprintf("Couldn't open %s\r\n",str);
  893.     return; }
  894. length=filelength(file);
  895. if((buf=malloc(length+1L))==NULL) {
  896.     close(file);
  897.     bprintf("\7\r\ngetnodemsg: Error allocating %lu bytes of memory for %\r\n"
  898.         ,length+1L,str);
  899.     return; }
  900. buf[read(file,buf,length)]=0;
  901. close(file);
  902. if((file=nopen(str,O_WRONLY|O_TRUNC))==-1) {
  903.     bprintf("Couldn't truncate %s\r\n",str);
  904.     return; }
  905. close(file);
  906. if(!symbols)
  907.     strip_symbols(buf);
  908. bputs(buf);
  909. free(buf);
  910. }
  911.  
  912. /****************************************************************************/
  913. /* This function creates a message for a certain node.                        */
  914. /****************************************************************************/
  915. void putnodemsg(char *msg, char nodenumber)
  916. {
  917.     char str[81];
  918.     int file;
  919.  
  920. sprintf(str,"MESSAGE.%d",nodenumber);
  921. if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
  922.     bprintf("\r\n\7putnodemsg: error opening/creating %s\r\n",str);
  923.     return; }
  924. write(file,msg,strlen(msg));
  925. close(file);
  926. }
  927.  
  928. /****************************************************************************/
  929. /* This function creates a message for all nodes in the game.                */
  930. /****************************************************************************/
  931. void putallnodemsg(char *msg)
  932. {
  933.     int i;
  934.  
  935. for(i=0;i<total_nodes;i++)
  936.     if(node[i] && i+1!=node_num)
  937.         putnodemsg(msg,i+1);
  938. }
  939.  
  940. /****************************************************************************/
  941. /* This function waits until it is the current player.                        */
  942. /****************************************************************************/
  943. void waitturn()
  944. {
  945.     time_t start,now;
  946.  
  947. start=now=time(NULL);
  948. getgamedat(1);
  949. status[node_num-1]=WAIT;
  950. putgamedat();
  951. while(curplayer!=node_num) {
  952.     chat();
  953.     fdelay(100);
  954.     getgamedat(0);
  955.     if(curplayer && !node[curplayer-1] /*  || status[curplayer-1]==BET */ )
  956.         nextplayer();        /* current player is not playing? */
  957.  
  958.     if(!node[node_num-1]) { /* current node not in game? */
  959.         getgamedat(1);
  960.         node[node_num-1]=user_number;    /* fix it */
  961.         putgamedat(); }
  962.  
  963.     now=time(NULL);
  964.     if(now-start>300) { /* only wait upto 5 minutes */
  965.         bputs("\r\nwaitturn: timeout\r\n");
  966.         break; } }
  967. getgamedat(1);
  968. status[node_num-1]=PLAY;
  969. putgamedat();
  970. }
  971.  
  972. /****************************************************************************/
  973. /* This is the function that is called to see if the user has hit a key,    */
  974. /* and if so, read in a line of chars and send them to the other nodes.     */
  975. /****************************************************************************/
  976. void chat()
  977. {
  978.     char str1[150],str2[256],ch;
  979.     int i;
  980.  
  981. if((ch=inkey())!=0 || wordwrap[0]) {
  982.     if(ch=='/') {
  983.         bputs("\1n\1y\1hCommand: \1n");
  984.         ch=getkeys("?LS|\r",0);
  985.         switch(ch) {
  986.             case CR:
  987.                 return;
  988.             #if DEBUG
  989.             case '|':
  990.                 debug();
  991.                 return;
  992.             #endif
  993.             case '?':
  994.                 mnemonics("\r\n~List Players");
  995.                 mnemonics("\r\n~Send Private Message to Player");
  996.                 bputs("\r\n");
  997.                 return;
  998.             case 'L':
  999.                 listplayers();
  1000.                 bprintf(ShoeStatus,cur_card,total_decks*52);
  1001.                 return;
  1002.             case 'S':
  1003.                 listplayers();
  1004.                 bputs("\1n\r\n\1y\1hWhich node: \1n");
  1005.                 i=getnum(sys_nodes);
  1006.                 getgamedat(0);
  1007.                 if(i>0 && i!=node_num && node[i-1]) {
  1008.                     bputs("\r\n\1n\1y\1hMessage: ");
  1009.                     if(getstr(str1,50,K_LINE)) {
  1010.                         sprintf(str2,UserWhispers,user_name
  1011.                             ,str1);
  1012.                         putnodemsg(str2,i); } }
  1013.                 else
  1014.                     bputs("\1n\r\n\1r\1hInvalid node.\1n\r\n");
  1015.                 return; } }
  1016.     ungetkey(ch);
  1017.     if(!getstr(str1,50,K_CHAT|K_WRAP))
  1018.         return;
  1019.     sprintf(str2,UserSays,user_name,str1);
  1020.     putallnodemsg(str2); }
  1021. getnodemsg();
  1022. }
  1023.  
  1024. /****************************************************************************/
  1025. /* This function returns 1 if the current node is the highest (or last)     */
  1026. /* node in the game, or 0 if there is another node with a higher number     */
  1027. /* in the game. Used to determine if this node is to perform the dealer   */
  1028. /* function                                                               */
  1029. /****************************************************************************/
  1030. char lastplayer()
  1031. {
  1032.     int i;
  1033.  
  1034. getgamedat(0);
  1035. if(total_players==1 && node[node_num-1])    /* if only player, definetly */
  1036.     return(1);                                /* the last */
  1037.  
  1038. for(i=node_num;i<total_nodes;i++)              /* look for a higher number */
  1039.     if(node[i])
  1040.         break;
  1041. if(i<total_nodes)                              /* if one found, return 0 */
  1042.     return(0);
  1043. return(1);                                    /* else return 1 */
  1044. }
  1045.  
  1046. /****************************************************************************/
  1047. /* Returns the node number of the lower player in the game                    */
  1048. /****************************************************************************/
  1049. char firstplayer()
  1050. {
  1051.     int i;
  1052.  
  1053. for(i=0;i<total_nodes;i++)
  1054.     if(node[i])
  1055.         break;
  1056. if(i==total_nodes)
  1057.     return(0);
  1058. return(i+1);
  1059. }
  1060.  
  1061. /****************************************************************************/
  1062. /* This function is only run on the highest node number in the game. It     */
  1063. /* waits until all other nodes are waiting in their sync routines, and then */
  1064. /* releases them by changing the status byte from SYNC_P to PLAY            */
  1065. /* it is assumed that getgamedat(1) is called immediately prior.            */
  1066. /****************************************************************************/
  1067. void syncdealer()
  1068. {
  1069.     char *Dealing="\1n\1hDealing...\r\n\1n";
  1070.     int i;
  1071.     time_t start,now;
  1072.  
  1073. status[node_num-1]=SYNC_D;
  1074. putgamedat();
  1075. start=now=time(NULL);
  1076. fdelay(1000);                  /* wait for stragglers to join game v1.02 */
  1077. getgamedat(0);
  1078. while(total_players) {
  1079.     for(i=0;i<total_nodes;i++)
  1080.         if(i!=node_num-1 && node[i] && status[i]!=SYNC_P)
  1081.             break;
  1082.     if(i==total_nodes)          /* all player nodes are waiting */
  1083.         break;
  1084.     chat();
  1085.     fdelay(100);
  1086.     getgamedat(0);
  1087.     if(!node[node_num-1]) { /* current node not in game? */
  1088.         getgamedat(1);
  1089.         node[node_num-1]=user_number;    /* fix it */
  1090.         putgamedat(); }
  1091.     now=time(NULL);
  1092.     if(now-start>300) { /* only wait upto 5 minutes */
  1093.         bputs("\r\nsyncdealer: timeout\r\n");
  1094.         break; } }
  1095.  
  1096. getgamedat(1);
  1097. misc|=INPLAY;
  1098. curplayer=firstplayer();
  1099. putgamedat();
  1100.  
  1101. getnodemsg();
  1102. bputs(Dealing);
  1103. putallnodemsg(Dealing);
  1104.  
  1105. getgamedat(1);
  1106. for(i=0;i<total_nodes;i++)          /* release player nodes */
  1107.     if(node[i])
  1108.         status[i]=PLAY;
  1109. putgamedat();
  1110. }
  1111.  
  1112.  
  1113. /****************************************************************************/
  1114. /* This function halts this node until the dealer releases it by changing    */
  1115. /* the status byte from SYNC_P to PLAY                                        */
  1116. /* it is assumed that getgamedat(1) is called immediately prior.            */
  1117. /****************************************************************************/
  1118. void syncplayer()
  1119. {
  1120.     time_t start,now;
  1121.  
  1122. status[node_num-1]=SYNC_P;
  1123. putgamedat();
  1124. start=now=time(NULL);
  1125. while(node[node_num-1] && status[node_num-1]==SYNC_P) {
  1126.     chat();
  1127.     fdelay(100);
  1128.     getgamedat(0);
  1129.     if(!node[node_num-1]) { /* current node not in game? */
  1130.         getgamedat(1);
  1131.         node[node_num-1]=user_number;    /* fix it */
  1132.         putgamedat(); }
  1133.     now=time(NULL);
  1134.     if(now-start>300) { /* only wait upto 5 minutes */
  1135.         bputs("\r\nsyncplayer: timeout\r\n");
  1136.         break; } }
  1137. }
  1138.  
  1139. /****************************************************************************/
  1140. /* Updates the MODUSER.DAT file that SBBS reads to ajust the user's credits */
  1141. /* This function is called whenever the user's credits are adjust so that   */
  1142. /* the file will be current in any event.                                    */
  1143. /****************************************************************************/
  1144. void moduserdat()
  1145. {
  1146.     char str[128];
  1147.     FILE *stream;
  1148.  
  1149. sprintf(str,"%sMODUSER.DAT",node_dir);
  1150. if((stream=fopen(str,"wt"))==NULL) {
  1151.     bprintf("Error opening %s for write\r\n",str);
  1152.     return; }
  1153. fprintf(stream,"%ld",credits-user_cdt);
  1154. fclose(stream);
  1155.  
  1156. }
  1157.  
  1158. /****************************************************************************/
  1159. /* This function reads the entire shoe of cards and the dealer's hand from  */
  1160. /* the card database file (CARD.DAB)                                        */
  1161. /****************************************************************************/
  1162. void getcarddat()
  1163. {
  1164.     int file;
  1165.  
  1166. if((file=nopen("CARD.DAB",O_RDONLY))==-1) {
  1167.     bputs("getcarddat: Error opening CARD.DAB\r\n");
  1168.     return; }
  1169. read(file,&dc,1);
  1170. read(file,dealer,sizeof(dealer));
  1171. read(file,&total_decks,1);
  1172. read(file,&cur_card,2);
  1173. read(file,card,total_decks*52*sizeof(card_t));
  1174. close(file);
  1175. }
  1176.  
  1177. /****************************************************************************/
  1178. /* This function writes the entire shoe of cards and the dealer's hand to   */
  1179. /* the card database file (CARD.DAB)                                        */
  1180. /****************************************************************************/
  1181. void putcarddat()
  1182. {
  1183.     int file;
  1184.  
  1185. if((file=nopen("CARD.DAB",O_WRONLY|O_CREAT))==-1) {
  1186.     bputs("putcarddat: Error opening CARD.DAB\r\n");
  1187.     return; }
  1188. write(file,&dc,1);
  1189. write(file,dealer,sizeof(dealer));
  1190. write(file,&total_decks,1);
  1191. write(file,&cur_card,2);
  1192. write(file,card,total_decks*52*sizeof(card_t));
  1193. close(file);
  1194. }
  1195.  
  1196. /****************************************************************************/
  1197. /* This function creates random ways to say "hit"                           */
  1198. /****************************************************************************/
  1199. char *hit()
  1200. {
  1201.     static char str[81];
  1202.  
  1203. strcpy(str,"\1n\1r\1h");
  1204. switch(rand()%10) {
  1205.     case 1:
  1206.         strcat(str,"Hit it.");
  1207.         break;
  1208.     case 2:
  1209.         strcat(str,"Hit me, Baby!");
  1210.         break;
  1211.     case 3:
  1212.         strcat(str,"Give me an ace.");
  1213.         break;
  1214.     case 4:
  1215.         strcat(str,"One more.");
  1216.         break;
  1217.     case 5:
  1218.         strcat(str,"Just one more.");
  1219.         break;
  1220.     case 6:
  1221.         strcat(str,"Give me a baby card.");
  1222.         break;
  1223.     case 7:
  1224.         strcat(str,"Hit it, Dude.");
  1225.         break;
  1226.     case 8:
  1227.         strcat(str,"Hit.");
  1228.         break;
  1229.     case 9:
  1230.         strcat(str,"Um... Hit.");
  1231.         break;
  1232.     case 10:
  1233.         strcat(str,"Thank you Sir, may I have another.");
  1234.         break;
  1235.     default:
  1236.         strcat(str,"Face card, please.");
  1237.         break; }
  1238. strcat(str,"\1n\r\n");
  1239. return(str);
  1240. }
  1241.  
  1242. /****************************************************************************/
  1243. /* This function creates random ways to say "double"                        */
  1244. /****************************************************************************/
  1245. char *doubit()
  1246. {
  1247.     static char str[81];
  1248.  
  1249. strcpy(str,"\1n\1b\1h");
  1250. switch(rand()%10) {
  1251.     case 1:
  1252.         strcat(str,"Double.");
  1253.         break;
  1254.     case 2:
  1255.         strcat(str,"Double Down, Man.");
  1256.         break;
  1257.     case 3:
  1258.         strcat(str,"Double it, Dude.");
  1259.         break;
  1260.     case 4:
  1261.         strcat(str,"One more card for double the dough.");
  1262.         break;
  1263.     case 5:
  1264.         strcat(str,"Double me.");
  1265.         break;
  1266.     case 6:
  1267.         strcat(str,"Oh yeah... Double!");
  1268.         break;
  1269.     case 7:
  1270.         strcat(str,"I shouldn't do it, but... Double!");
  1271.         break;
  1272.     case 8:
  1273.         strcat(str,"Double my bet and give me one more card.");
  1274.         break;
  1275.     case 9:
  1276.         strcat(str,"Um... Double.");
  1277.         break;
  1278.     case 10:
  1279.         strcat(str,"Thank you Sir, may I Double?");
  1280.         break;
  1281.     default:
  1282.         strcat(str,"Double - face card, please.");
  1283.         break; }
  1284. strcat(str,"\1n\r\n");
  1285. return(str);
  1286. }
  1287.  
  1288. /****************************************************************************/
  1289. /* This function creates random ways to say "stand"                         */
  1290. /****************************************************************************/
  1291. char *stand()
  1292. {
  1293.     static char str[81];
  1294.  
  1295. strcpy(str,"\1n\1c\1h");
  1296. switch(rand()%10) {
  1297.     case 1:
  1298.         strcat(str,"Stand.");
  1299.         break;
  1300.     case 2:
  1301.         strcat(str,"Stay.");
  1302.         break;
  1303.     case 3:
  1304.         strcat(str,"No more.");
  1305.         break;
  1306.     case 4:
  1307.         strcat(str,"Just right.");
  1308.         break;
  1309.     case 5:
  1310.         strcat(str,"I should hit, but I'm not gonna.");
  1311.         break;
  1312.     case 6:
  1313.         strcat(str,"Whoa!");
  1314.         break;
  1315.     case 7:
  1316.         strcat(str,"Hold it.");
  1317.         break;
  1318.     case 8:
  1319.         strcat(str,"No way, Jose!");
  1320.         break;
  1321.     case 9:
  1322.         strcat(str,"Um... Stand.");
  1323.         break;
  1324.     case 10:
  1325.         strcat(str,"Thanks, but no thanks.");
  1326.         break;
  1327.     default:
  1328.         strcat(str,"No card, no bust.");
  1329.         break; }
  1330. strcat(str,"\1n\r\n");
  1331. return(str);
  1332. }
  1333.  
  1334. /****************************************************************************/
  1335. /* This function creates random ways to say "split"                         */
  1336. /****************************************************************************/
  1337. char *split()
  1338. {
  1339.     static char str[81];
  1340.  
  1341. strcpy(str,"\1n\1y\1h");
  1342. switch(rand()%10) {
  1343.     case 1:
  1344.         strcat(str,"Split.");
  1345.         break;
  1346.     case 2:
  1347.         strcat(str,"Split 'em.");
  1348.         break;
  1349.     case 3:
  1350.         strcat(str,"Split it.");
  1351.         break;
  1352.     case 4:
  1353.         strcat(str,"Split, please.");
  1354.         break;
  1355.     case 5:
  1356.         strcat(str,"I should hit, but I'm gonna split instead.");
  1357.         break;
  1358.     case 6:
  1359.         strcat(str,"Whoa! Split them puppies...");
  1360.         break;
  1361.     case 7:
  1362.         strcat(str,"Split 'em, Dude.");
  1363.         break;
  1364.     case 8:
  1365.         strcat(str,"Double the cards, for double the money.");
  1366.         break;
  1367.     case 9:
  1368.         strcat(str,"Um... Split.");
  1369.         break;
  1370.     case 10:
  1371.         strcat(str,"Thank you Sir, I think I'll split 'em.");
  1372.         break;
  1373.     default:
  1374.         strcat(str,"Banana Split.");
  1375.         break; }
  1376. strcat(str,"\1n\r\n");
  1377. return(str);
  1378. }
  1379.  
  1380. /****************************************************************************/
  1381. /* This function creates random ways to say "joined"                        */
  1382. /****************************************************************************/
  1383. char *joined()
  1384. {
  1385.     static char str[81];
  1386.  
  1387. switch(rand()%10) {
  1388.     case 1:
  1389.         strcpy(str,"joined.");
  1390.         break;
  1391.     case 2:
  1392.         strcpy(str,"sat down to play.");
  1393.         break;
  1394.     case 3:
  1395.         strcpy(str,"plopped on the chair next to you.");
  1396.         break;
  1397.     case 4:
  1398.         strcpy(str,"belched loudly to announce his entrance.");
  1399.         break;
  1400.     case 5:
  1401.         strcpy(str,"dropped in.");
  1402.         break;
  1403.     case 6:
  1404.         strcpy(str,"joined our game.");
  1405.         break;
  1406.     case 7:
  1407.         strcpy(str,"fell on his face entering the casino!");
  1408.         break;
  1409.     case 8:
  1410.         strcpy(str,"slams a roll of credits on the table.");
  1411.         break;
  1412.     case 9:
  1413.         strcpy(str,"rolled in to join the game.");
  1414.         break;
  1415.     case 10:
  1416.         strcpy(str,"smiles widely as he takes your wife's seat.");
  1417.         break;
  1418.     default:
  1419.         strcpy(str,"spills a drink on your pants while sitting down.");
  1420.         break; }
  1421. return(str);
  1422. }
  1423.  
  1424. /****************************************************************************/
  1425. /* This function creates random ways to say "left"                          */
  1426. /****************************************************************************/
  1427. char *left()
  1428. {
  1429.     static char str[81];
  1430.  
  1431. switch(rand()%10) {
  1432.     case 1:
  1433.         strcpy(str,"left abruptly.");
  1434.         break;
  1435.     case 2:
  1436.         strcpy(str,"sneaked away.");
  1437.         break;
  1438.     case 3:
  1439.         strcpy(str,"took the credits and ran.");
  1440.         break;
  1441.     case 4:
  1442.         strcpy(str,"fell out of the chair.");
  1443.         break;
  1444.     case 5:
  1445.         strcpy(str,"left the game.");
  1446.         break;
  1447.     case 6:
  1448.         strcpy(str,"slipped out the door.");
  1449.         break;
  1450.     case 7:
  1451.         strcpy(str,"giggled as he left the table.");
  1452.         break;
  1453.     case 8:
  1454.         strcpy(str,"left clenching empty pockets.");
  1455.         break;
  1456.     case 9:
  1457.         strcpy(str,"went to the pawn shop to hawk a watch.");
  1458.         break;
  1459.     case 10:
  1460.         strcpy(str,"bailed out the back door.");
  1461.         break;
  1462.     default:
  1463.         strcpy(str,"made like a train and left.");
  1464.         break; }
  1465. return(str);
  1466. }
  1467.  
  1468. /****************************************************************************/
  1469. /* This function creates the file "GAME.DAB" in the current directory.      */
  1470. /****************************************************************************/
  1471. void create_gamedab()
  1472. {
  1473.  
  1474. if((gamedab=open("GAME.DAB"
  1475.     ,O_WRONLY|O_CREAT|O_DENYNONE|O_BINARY,S_IWRITE|S_IREAD))==-1) {
  1476.     bputs("Error creating GAME.DAB\r\n");
  1477.     pause();
  1478.     exit(1); }
  1479. misc=0;
  1480. curplayer=0;
  1481. memset(node,0,sizeof(node));
  1482. memset(status,0,sizeof(status));
  1483. write(gamedab,&misc,1);
  1484. write(gamedab,&curplayer,1);
  1485. write(gamedab,&total_nodes,1);
  1486. write(gamedab,node,total_nodes*2);
  1487. write(gamedab,status,total_nodes);
  1488. close(gamedab);
  1489. }
  1490.  
  1491. /****************************************************************************/
  1492. /* This function opens the file "GAME.DAB" in the current directory and     */
  1493. /* leaves it open with deny none access. This file uses record locking        */
  1494. /* for shared access.                                                        */
  1495. /****************************************************************************/
  1496. void open_gamedab()
  1497. {
  1498. if((gamedab=open("GAME.DAB",O_RDWR|O_DENYNONE|O_BINARY))==-1) {
  1499.     bputs("Error opening GAME.DAB\r\n");                /* open deny none */
  1500.     pause();
  1501.     exit(1); }
  1502. }
  1503.  
  1504. /****************************************************************************/
  1505. /* Lists the players currently in the game and the status of the shoe.        */
  1506. /****************************************************************************/
  1507. void listplayers()
  1508. {
  1509.     int i;
  1510.  
  1511. getgamedat(0);
  1512. bputs("\r\n");
  1513. if(!total_players) {
  1514.     bputs("\1_\1w\1hNo game in progres\r\n");
  1515.     return; }
  1516. for(i=0;i<total_nodes;i++)
  1517.     if(node[i])
  1518.         bprintf("\1-\1mNode %2d: \1h%s \1n\1m%s\r\n"
  1519.             ,i+1,username(node[i]),activity(status[i]));
  1520. getcarddat();
  1521. /***
  1522. bprintf("\r\nCurrent player=Node %d user #%d\r\n",curplayer,node[curplayer-1]);
  1523. ***/
  1524. }
  1525.  
  1526. /****************************************************************************/
  1527. /* This function replaces the card symbols in 'str' with letters to         */
  1528. /* represent the different suits.                                            */
  1529. /****************************************************************************/
  1530. void strip_symbols(char *str)
  1531. {
  1532.     int i,j;
  1533.  
  1534. j=strlen(str);
  1535. for(i=0;i<j;i++)
  1536.     if(str[i]>=3 && str[i]<=6)
  1537.         switch(str[i]) {
  1538.             case 3:
  1539.                 str[i]='H';
  1540.                 break;
  1541.             case 4:
  1542.                 str[i]='D';
  1543.                 break;
  1544.             case 5:
  1545.                 str[i]='C';
  1546.                 break;
  1547.             case 6:
  1548.                 str[i]='S';
  1549.                 break; }
  1550. }
  1551.  
  1552. #endif    /* end of function not needed for SBJCLEAN.C */
  1553.  
  1554. /****************************************************************************/
  1555. /* Reads information from GAME.DAB file. If 'lockit' is 1, the file is      */
  1556. /* and putgamedat must be called to unlock it. If your updating the info    */
  1557. /* in GAME.DAB, you must first call getgamedat(1), then putgamedat().        */
  1558. /****************************************************************************/
  1559. void getgamedat(char lockit)
  1560. {
  1561.     int i=0;
  1562.  
  1563. if(lockit) {    /* retry 100 times taking at least 3 seconds */
  1564.     while(lock(gamedab,0L,filelength(gamedab))==-1 && i++<100)
  1565.         fdelay(30);  /* lock the whole thing */
  1566.     if(i>=100) {
  1567.         printf("gamedab=%d %04X:%p %04X\r\n",gamedab,_psp,&gamedab,_DS);
  1568.         printf("\7getgamedat: error locking GAME.DAB\r\n"); } }
  1569.  
  1570. lseek(gamedab,0L,SEEK_SET);
  1571. read(gamedab,&misc,1);
  1572. read(gamedab,&curplayer,1);
  1573. read(gamedab,&total_nodes,1);
  1574. read(gamedab,node,total_nodes*2);       /* user number playing for each node */
  1575. read(gamedab,status,total_nodes);       /* the status of the player */
  1576. total_players=0;
  1577. for(i=0;i<total_nodes;i++)
  1578.     if(node[i])
  1579.         total_players++;
  1580. }
  1581.  
  1582. /****************************************************************************/
  1583. /* Writes information to GAME.DAB file. getgamedat(1) MUST be called before  */
  1584. /* this function is called.                                                 */
  1585. /****************************************************************************/
  1586. void putgamedat()
  1587. {
  1588.  
  1589. lseek(gamedab,0L,SEEK_SET);
  1590. write(gamedab,&misc,1);
  1591. write(gamedab,&curplayer,1);
  1592. write(gamedab,&total_nodes,1);
  1593. write(gamedab,node,total_nodes*2);
  1594. write(gamedab,status,total_nodes);
  1595. unlock(gamedab,0L,filelength(gamedab));
  1596. }
  1597.  
  1598. /***************************************************************/
  1599. /* This function makes the next active node the current player */
  1600. /***************************************************************/
  1601. void nextplayer()
  1602. {
  1603.     int i;
  1604.  
  1605. getgamedat(1);                      /* get current info and lock */
  1606. if((!curplayer                        /* if no current player */
  1607.     || total_players==1)            /* or only one player in game */
  1608.     && node[node_num-1]) {          /* and this node is in the game */
  1609.     curplayer=node_num;             /* make this node current player */
  1610.     putgamedat();                   /* write data and unlock */
  1611.     return; }                       /* and return */
  1612.  
  1613. for(i=curplayer;i<total_nodes;i++)    /* search for the next highest node */
  1614.     if(node[i])                     /* that is active */
  1615.         break;
  1616. if(i>=total_nodes) {                /* if no higher active nodes, */
  1617.     for(i=0;i<curplayer-1;i++)        /* start at bottom and go up  */
  1618.         if(node[i])
  1619.             break;
  1620.     if(i==curplayer-1)                /* if no active nodes found */
  1621.         curplayer=0;                /* make current player 0 */
  1622.     else
  1623.         curplayer=i+1; }
  1624. else
  1625.     curplayer=i+1;                    /* else active node current player */
  1626.  
  1627. putgamedat();                       /* write info and unlock */
  1628. }
  1629.  
  1630.