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