|
|
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.