/* bridgehands.c by Michael Thorpe 2003-12-12 */ #include #include #include #define RANDOM_FILE "/dev/urandom" #define SUIT(x) ((x)%4) #define CARD(x) ((x)/4) static char buf[17]; static int sprinth(unsigned char hand[13],int suit) { int i,j; buf[0]="CDHS"[suit]; buf[1]=':'; buf[2]=' '; for(i=3,j=0;j<13;j++) if(SUIT(hand[j])==suit) buf[i++]="23456789TJQKA"[CARD(hand[j])]; buf[i]='\0'; return(i); } static unsigned int urandom() { static FILE *rndfile=0; unsigned int n,buf; if(!rndfile) { rndfile=fopen(RANDOM_FILE,"rb"); if(!rndfile) { perror("open"); exit(-1); } setbuffer(rndfile,(void *)&buf,sizeof(buf)); } if(1 != fread((char *)&n,sizeof(n),1,rndfile)) { perror("read"); exit(-1); } return(n); } static int cardcmp(const void *first,const void *second) { char a,b; a=*(char *)first; b=*(char *)second; if(SUIT(a) != SUIT(b)) return(SUIT(b)-SUIT(a)); return(CARD(b)-CARD(a)); } static void calcpoints(unsigned char hand[13],unsigned int *hc,unsigned int *dist) { unsigned int i,distribution[4]; for(i=0;i<4;i++) distribution[i]=0; for(i=0;i<13;i++) distribution[SUIT(hand[i])]++; *hc=0; for(i=0;i<13;i++) if(CARD(hand[i])>8 && CARD(hand[i])+distribution[SUIT(hand[i])]>12) *hc+=CARD(hand[i])-8; *dist=0; for(i=0;i<4;i++) if(distribution[i]<3) *dist+=3-distribution[i]; } int main(int argc,char **argv) { unsigned int i,j,k; unsigned char deck[52]; unsigned char hand[4][13]; unsigned char c,compactform=0,specifiedseed=0,showpoints=0,showseed=0,useprng=0; char *s; while(EOF != (i=getopt(argc,argv,"S:chps"))) { switch(i) { case 'S': k=strtoul(optarg,&s,10); if(*s) goto badarg; srand(k); specifiedseed=1; useprng=1; break; case 'c': compactform=1; break; case 'h': fputs("usage: bridgehands [-S <#>] [-chps]\n",stdout); fputs("\t-S specify game (default is not to use a PRNG)\n",stdout); fputs("\t-c use a compact form to show the hands\n",stdout); fputs("\t-h show this help message and exit\n",stdout); fputs("\t-p show the high card/distribution points in each hand\n",stdout); fputs("\t-s show game number (uses PRNG)\n",stdout); return(0); case 'p': showpoints=1; break; case 's': showseed=1; useprng=1; break; default: goto badarg; } } if(optind] [-chps]\n",stderr); return(1); } if(useprng) { if(!specifiedseed) { k=urandom(); srand(k); } if(showseed) printf("Game: %u\n",k); } for(i=0;i<52;i++) deck[i]=i; for(i=51;i>0;i--) { k=(useprng?rand():urandom())%(i+1); if(i != k) { c=deck[k]; deck[k]=deck[i]; deck[i]=c; } } for(i=0;i<4;i++) for(j=0;j<13;j++) hand[i][j]=deck[13*i+j]; for(i=0;i<4;i++) qsort(hand[i],13,sizeof(char),cardcmp); if(compactform) { for(i=0;i<4;i++) { for(j=0;j<13;j++) { if(j) putchar(' '); putchar("23456789TJQKA"[CARD(hand[i][j])]); putchar("CDHS"[SUIT(hand[i][j])]); } if(showpoints) { calcpoints(hand[i],&j,&k); printf(" %2u+%u=%u",j,k,j+k); } putchar('\n'); } } else { fputs(" North\n",stdout); for(i=0;i<4;i++) { sprinth(hand[1],3-i); fputs(" ",stdout); puts(buf); } fputs("West East\n",stdout); for(i=0;i<4;i++) { j=sprinth(hand[0],3-i); fputs(buf,stdout); fputs(" "+j,stdout); sprinth(hand[2],3-i); puts(buf); } fputs(" South\n",stdout); for(i=0;i<4;i++) { sprinth(hand[3],3-i); fputs(" ",stdout); puts(buf); } if(showpoints) { for(i=0;i<4;i++) { if(i) putchar('\t'); calcpoints(hand[i],&j,&k); printf("%c=%u+%u","WNES"[i],j,k); } putchar('\n'); } } return(0); }