#include "Card.h" // Given the index of a card, return its name. string cardName(int index, bool lowerCase) { static char rslt[4]; if (index < 0 || index >= 52) { printf("Error, cardName index out of range %d\n", index); exit(1); } rslt[0] = cardValue[index % 13]; rslt[1] = cardSuit[index / 13]; if (lowerCase) { rslt[0] = tolower(rslt[0]); rslt[1] = tolower(rslt[1]); } rslt[2] = 0; return string(rslt); } // Given the card's name, return its index. Names are always two chars, [Value][Suit] int Card2Index(char* name) { int index; char v = toupper(name[0]); // value char for (index = 0; index < 13; index++) if (cardValue[index] == v) break; assert(index < 13); v = toupper(name[1]); // Suit char int i; for (i = 0; i < 4; i++) if (cardSuit[i] == v) break; assert(i < 4); return index + 13 * i; } /* Read a file in PBN format. Only the "[Deal ... ] tag is processed. * Return the 52 card deck, with each card's index filled with the player * who receives the card index. * N = 0, E = 1, S = 2, W = 3. * unsigned char hands[52] */ int readDeal(const char* fileName, uchar* hands) { FILE* file; char buff[132]; const char dealerC[] = { 'N', 'E', 'S', 'W', 0 }; // first dealer ordinal 0,1,2,3... file = fopen(fileName, "r"); if (file == 0) { printf("Error opening file %s\n", fileName); return 0; } int nCards = 1; // will be set to 0 if [DEAL is there int dealer = 0; // assume north = 0. char* p; // Scan lines until we get the "[Deal" while (1) { char* p = fgets(buff, sizeof(buff) - 1, file); // scan for "[Deal" if (!p || feof(file)) { printf("File didn't contain a deal: %s\n", fileName); return 0; } for (p = buff; *p; p++) *p = toupper(*p); if ((nCards = strncmp(buff, "[DEAL ", 6)) == 0) break; // look for header "[DEAL " } if (nCards != 0) { printf("File doesn't contain \"[DEAL \"\n"); return 0; } for (p = buff + 5; *p && !isalpha(*p); p++); // find first alpha char if (!*p) { syntax_error: printf("Deal tag syntax is illegal: %s\n", buff); return 0; } for (dealer = 0; dealerC[dealer]; dealer++) // read who's the dealer if (dealerC[dealer] == *p) break; if (*p++ == 0) goto syntax_error; for (; *p != ':' && *p; p++); // skip & find find ':' if (!*p++) goto syntax_error; for (int i = 0; i < 52; i++) hands[i] = 99; // error indicator for (int iPlayer = 0; iPlayer < 4; iPlayer++) { // get each player's hand int iSuit = 3; // spades are the first suit. Order is S-H-D-C. for (; *p; p++) { // each char if (*p == ' ') { // space indicates next player dealer = (dealer + 1) & 3; // space separates players. iSuit = 3; } else if (*p == '.') iSuit = (iSuit - 1) & 3; // '.' = next suit else if (*p == '\"') break; else { int k; for (k = 0; cardValue[k]; k++) // find the card value if (*p == cardValue[k]) break; if (!cardValue[k]) goto syntax_error; int j = k + 13 * iSuit; // printf("Dealt %d - %s, ", dealer, cardName(j, false).c_str()); if (hands[j] != 99) { printf("Card %s was dealt twice\n", cardName(j, false).c_str()); return 0; } hands[j] = dealer; nCards++; } } // each char if (!*p) { printf("Hand not complete, line ended prematurely\n--%s\n", buff); } } // iPlayer if (nCards != 52) { printf("Don't have 52 cards: %s", buff); return 0; } fclose(file); return 1; } void printDeal(uchar* hands) { const char* players[] = { "North", "East ", "South", "West " }; for (int iPlayer = 0; iPlayer < 4; iPlayer++) { printf("%s: ", players[iPlayer]); for (int i = 0; i < 52; i++) if (hands[i] == iPlayer) printf("%s ", cardName(i, false).c_str()); printf("\n"); } } // compare function for sorting random numbers *********** static char init=0; int cmpfunc(const void *a, const void *b) { static int rval[52]; time_t t; if (!init) { /* Intializes random number generator */ srand((unsigned) time(&t)); // initialize from current time. init++; } if (a == NULL) { // if null, init arrays for (int i=0; i < 52; i++) rval[i] = rand(); return 0; } return (rval[(int) *(char *)a] - rval[(int)*(char *)b]); // return comparison result } void randomDeal(uchar *hands) { uchar index[52]; for (int i=0; i < 52; i++) index[i] = i; (void) cmpfunc(NULL, NULL); // init w/ random qsort(index, 52, sizeof(char), cmpfunc); // index is now random, 0-51. // first 13 random cards go to N, 2nd 13 to E, etc. for (int i=0; i < 52; i++) hands[index[i]] = i/13; } // Return the # of high card points in the hand held by the indicated player. int handPoints(uchar *hands, int player) { int r=0; for (int i=0; i < 52; i++) if (hands[i] == player) r += cardPoints[VALUE(i)]; return r; } // Deal a random hand, then if NS has less points than EW, swap the hands. void nsIsBetter(uchar *hands) { int points[4] = { 0, 0, 0, 0}; randomDeal(hands); for (int i=0; i < 52; i++) // count points points[hands[i]] += cardPoints[VALUE(i)]; if (points[0] + points[2] > points[1] + points[3]) // NS already better? return; // swap NS & EW for (int i=0; i < 52; i++) // swap hands[i] = (hands[i]+1) & 3; return; } // Pretty print the hands on the console. void printHands(uchar *hands) { #define NCOLS 44 const int xoff[4] = { 15, 28, 15, 2}; // horiz offset for hand const int yoff[4] = { 0, 4, 8, 4}; const int nxoff[4] = { 15, 28, 15, 2}; // offsets of notes const int nyoff[4] = { 4, 3, 7, 3}; char buff[12][NCOLS]; for (int iline=0; iline < 12; iline++) { for (int j=0; j < NCOLS; j++) buff[iline][j] = ' '; buff[iline][NCOLS-1] = 0; // terminating null } for (int i=0; i < 52; i++) // each card { int ip = hands[i]; // player int s = SUIT(i); int c = printOrder[VALUE(i)]; // in order buff[(3-s)+yoff[ip]][xoff[ip]+c] = cardValue[VALUE(i)]; // suits go S H D C } for (int ihand=0; ihand < 4; ihand++) { // add annotation + point counts char note[10]; sprintf(note, "(%c %d)", handName[ihand], handPoints(hands, ihand)); char *p1 = note; for (char *p = buff[nyoff[ihand]] + nxoff[ihand]; *p1; ) *p++ = *p1++; for (int isuit=0; isuit < 4; isuit++) { buff[yoff[ihand]+isuit][xoff[ihand]-2] = cardSuit[3-isuit]; } for (int is=0; is < 4; is++) { // remove extraneous blanks char *p0 = buff[yoff[ihand]+is] + xoff[ihand]; for (int i = 0; i < 13; i++) { char *p = buff[yoff[ihand]+is] + xoff[ihand]+i; if (*p != ' ') { char t = *p; *p = ' '; *p0++ = t; } } } } for (int iline=0; iline < 12; iline++) { printf("%s\n", buff[iline]); } }