home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume4 / bidding / bidding.c next >
C/C++ Source or Header  |  1988-05-31  |  9KB  |  378 lines

  1. /* bidding.c */
  2. /*
  3.             Bridge bidder
  4.             by Nathan Glasser
  5.             nathan@xx.lcs.mit.edu (internet)
  6.             nathan@mit-eddie.uucp (usenet)
  7.  
  8.             May, 1988
  9. ------------------------------------------------------------------------------
  10. Copyright 1988 by Nathan Glasser.
  11. You may feel free to distribute this program in its current form.
  12. Please do not remove this copyright information.
  13. */
  14.  
  15. #include "bidding.h"
  16.  
  17. int num_hands = 10;
  18.  
  19. char *vuln_relative[] = {"YOUR SIDE","OTHER SIDE"};
  20. char *vuln_absolute[] = {"1ST SIDE","2ND SIDE","NEITHER SIDE","BOTH SIDES"};
  21. char *suit_strings[4] = {"SPADES","HEARTS","DIAMONDS","CLUBS"};
  22. char *vuln_format[2][2] = {
  23.   {"DECLARER SIDE","DEFENDER SIDE"},
  24.   {"VERTICAL SIDE","HORIZONTAL SIDE"}};
  25.  
  26. #define PASSED_OUT(pdeal) \
  27.     ((pdeal)->num_bids == 4 && (pdeal)->bids->bid.suit == PASS)
  28.  
  29. main(argc,argv)
  30. int argc;
  31. char **argv;
  32. {
  33.     deal *deals;
  34.     int i,j;
  35.     int num_hands_left;
  36.     int hand_num;
  37.  
  38.     if (argc > 1)
  39.     num_hands = atoi(argv[1]);
  40.     printf("Dealing %d hands...\n",num_hands_left = num_hands);
  41.  
  42.     deals = (deal *)malloc(num_hands * sizeof(deal));
  43.  
  44.     srandom((unsigned)time(NULL));
  45.  
  46.     for (i = 0; i < num_hands; i++)
  47.     deal_hands(&deals[i]);
  48.  
  49.     /* Accept bids */
  50.     while (num_hands_left)
  51.     {
  52.     hand_num = random() % num_hands;
  53.  
  54.     if (deals[hand_num].bidding_done)
  55.         continue;
  56.     for (i = 0; i < 24; i++)
  57.         putchar('\n');
  58.     print_bidding(stdout,&deals[hand_num]);
  59.     printf("YOUR HAND (%s VULNERABLE):\n",
  60.       (deals[hand_num].vulnerability <= RELATIVE) ?
  61.       vuln_relative[(deals[hand_num].num_bids & 1) ^ 
  62.       deals[hand_num].vulnerability] :
  63.       vuln_absolute[deals[hand_num].vulnerability]);
  64.     print_hand(stdout,deals[hand_num].hands[deals[hand_num].num_bids % 4]);
  65.     while(accept_bid(&deals[hand_num]))
  66.         printf("Bad bid.\n");
  67.     if (deals[hand_num].bidding_done)
  68.     {
  69.         num_hands_left--;
  70.         /* If hand was passed out */
  71.         if (PASSED_OUT(&deals[hand_num]))
  72.             display_complete_deal(&deals[hand_num],0);
  73.     }
  74.     }
  75.  
  76.     /* Accept opening leads */
  77.     for (hand_num = 0; hand_num < num_hands; hand_num++)
  78.     {
  79.         /* Make sure hand wasn't passed out */
  80.     if (PASSED_OUT(&deals[hand_num]))
  81.         continue;
  82.     for (i = 0; i < 24; i++)
  83.         putchar('\n');
  84.     print_bidding(stdout,&deals[hand_num]);
  85.     j = figure_out_leader(&deals[hand_num]);
  86.     printf("YOUR HAND (%s VULNERABLE):\n",
  87.       (deals[hand_num].vulnerability <= RELATIVE) ?
  88.       vuln_relative[(j & 1) ^ 
  89.       deals[hand_num].vulnerability] :
  90.       vuln_absolute[deals[hand_num].vulnerability]);
  91.     print_hand(stdout,deals[hand_num].hands[j]);
  92.     while (get_lead(&deals[hand_num],j))
  93.         printf("Bad lead.\n");
  94.     display_complete_deal(&deals[hand_num],((j + 1) % 4));
  95.     }
  96.  
  97.     printf("All bidding complete.\n");
  98. }
  99.  
  100. display_complete_deal(pdeal,top_hand)
  101. deal *pdeal;
  102. int top_hand;
  103. {
  104.     print_complete_deal(stdout,pdeal,top_hand);
  105.     more();
  106.     log_deal(pdeal,top_hand);
  107. }
  108.  
  109. print_complete_deal(fp,pdeal,top_hand)
  110. FILE *fp;
  111. deal *pdeal;
  112. int top_hand;
  113. {
  114.     int i;
  115.     char top_h[4][80],left_h[4][80],right_h[4][80],bottom_h[4][80];
  116.  
  117.     format_hand(top_h,pdeal->hands[top_hand]);
  118.     format_hand(right_h,pdeal->hands[(top_hand + 1) % 4]);
  119.     format_hand(bottom_h,pdeal->hands[(top_hand + 2) % 4]);
  120.     format_hand(left_h,pdeal->hands[(top_hand + 3) % 4]);
  121.     fprintf(fp,"\t\t\tCOMPLETE DEAL (%s VULNERABLE):\n",
  122.       ((pdeal->vulnerability <= RELATIVE) ?
  123.       vuln_format[PASSED_OUT(pdeal)][(top_hand & 1) ^ pdeal->vulnerability] :
  124.       vuln_absolute[pdeal->vulnerability]));
  125.  
  126.     for (i = 0; i < 4; i++)
  127.         fprintf(fp,"\t\t\t%s\n",top_h[i]);
  128.     for (i = 0; i < 4; i++)
  129.         fprintf(fp,"%-43s%s\n",left_h[i],right_h[i]);
  130.     for (i = 0; i < 4; i++)
  131.         fprintf(fp,"\t\t\t%s\n",bottom_h[i]);
  132. }
  133.  
  134. print_bidding(fp,pdeal)
  135. FILE *fp;
  136. deal *pdeal;
  137. {
  138.     bid *bids;
  139.     static char *bid_suits[] = {"S","H","D","C","N","DB","RD","P"};
  140.     int bid_num = 0;
  141.  
  142.     fprintf(fp,"BIDDING:\n");
  143.     for (bids = pdeal->bids; bid_num < pdeal->num_bids; bids = bids->next)
  144.     {
  145.     if (bids->bid.suit <= RANK_USED)
  146.         fprintf(fp,"\t%d %s",bids->bid.rank,bid_suits[bids->bid.suit]);
  147.     else
  148.         fprintf(fp,"\t%s",bid_suits[bids->bid.suit]);
  149.     if ((++bid_num % 4) == 0)
  150.         putc('\n',fp);
  151.     }
  152.     if (bid_num % 4)
  153.     putc('\n',fp);
  154. }
  155.  
  156. accept_bid(pdeal)
  157. deal *pdeal;
  158. {
  159.     int ch;
  160.     int rank = -1,suit;
  161.     bid *newbid;
  162.     static int suit_cvt[] = {3,2,1,0,4};
  163.     bid *tmp;
  164.     int i;
  165.     
  166.     printf("\nEnter your bid: ");
  167.  
  168.     /* Get optional rank */
  169.     while (isspace(ch = getchar()));
  170.  
  171.     if (isdigit(ch))
  172.     {
  173.     rank = ch - '0';
  174.     while (isspace(ch = getchar()));
  175.     }
  176.  
  177.     /* Get suit, notrump, pass, double, or redouble */
  178.     if (islower(ch))
  179.     ch = toupper(ch);
  180.  
  181.     switch (ch)
  182.     {
  183.     case 'S':
  184.         suit = SPADES;
  185.         break;
  186.     case 'H':
  187.         suit = HEARTS;
  188.         break;
  189.     case 'D':
  190.         suit = (rank >= 0) ? DIAMONDS : DOUBLE;
  191.         break;
  192.     case 'C':
  193.         suit = CLUBS;
  194.         break;
  195.     case 'N':
  196.         suit = NOTRUMP;
  197.         break;
  198.     case 'P':
  199.         suit = PASS;
  200.         break;
  201.     case 'R':
  202.         suit = REDOUBLE;
  203.         break;
  204.     default:
  205.         suit = -1;
  206.         break;
  207.     }
  208.  
  209.     while (getchar() != '\n');
  210.     if (suit < 0)
  211.     return(1);
  212.  
  213.     /* Make sure numerical bid is ok */
  214.     if (suit <= RANK_USED)
  215.     {
  216.         if (rank < 1 || rank > 7)
  217.         return(1);
  218.     if (pdeal->num_bids > 0)
  219.         for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i;
  220.           tmp = tmp->prev, i--)
  221.         if (tmp->bid.suit <= RANK_USED)
  222.         {
  223.             if (rank < tmp->bid.rank || 
  224.               rank == tmp->bid.rank &&
  225.               suit_cvt[suit] <= suit_cvt[tmp->bid.suit])
  226.             return(1);
  227.             break;
  228.         }
  229.     }
  230.     /* Make sure double or redouble is valid */
  231.     else if (suit == DOUBLE || suit == REDOUBLE)
  232.     {
  233.     if (pdeal->num_bids <= 0)
  234.         return(1);
  235.         for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i;
  236.       tmp = tmp->prev, i--)
  237.         if (tmp->bid.suit != PASS)
  238.         {
  239.             /* Double or redouble by wrong side */
  240.         /* The person bidding in the num_bids position was
  241.            an opponent. The last valid bidder must have had
  242.            this parity. */
  243.         if (((i ^ pdeal->num_bids) & 1) == 1)
  244.             return(1);
  245.         /* Double of a double or redouble */
  246.         if (suit == DOUBLE && tmp->bid.suit > RANK_USED)
  247.             return(1);
  248.         /* Redouble of a bid other than double */
  249.         if (suit == REDOUBLE && tmp->bid.suit != DOUBLE)
  250.             return(1);
  251.         break;
  252.         }
  253.     /* Double or redouble as first non-pass bid */
  254.     if (!i)
  255.         return(1);
  256.     }
  257.  
  258.     newbid = (bid *)malloc(sizeof(bid));
  259.     newbid->bid.rank = rank;
  260.     newbid->bid.suit = suit;
  261.  
  262.     if (++(pdeal->num_bids) == 1)
  263.     newbid->next = newbid->prev = pdeal->bids = newbid;
  264.     else
  265.     {
  266.     (newbid->next = pdeal->bids)->prev = 
  267.       (newbid->prev = pdeal->bids->prev)->next = newbid;
  268.     if (newbid->bid.suit == PASS && newbid->prev->bid.suit == PASS &&
  269.       newbid->prev->prev->bid.suit == PASS && pdeal->num_bids >= 4)
  270.         pdeal->bidding_done = 1;
  271.     }
  272.     return(0);
  273. }
  274.  
  275. more()
  276. {
  277.     printf("---Hit return to continue---");
  278.     while (getchar() != '\n');
  279. }
  280.  
  281. log_deal(pdeal,top_hand)
  282. deal *pdeal;
  283. int top_hand;
  284. {
  285.     FILE *fp;
  286.     int i;
  287.  
  288.     if ((fp = fopen(LOGFILE,"a")) == NULL)
  289.     {
  290.     perror(LOGFILE);
  291.     return;
  292.     }
  293.     print_bidding(fp,pdeal);
  294.     if (pdeal->opening_lead.suit >= 0)
  295.         fprintf(fp,"OPENING LEAD: %c of %s\n",pdeal->opening_lead.rank,
  296.           suit_strings[pdeal->opening_lead.suit]);
  297.     print_complete_deal(fp,pdeal,top_hand);
  298.     putc('\n',fp);
  299.     putc('\n',fp);
  300.     fclose(fp);
  301. }
  302.  
  303. figure_out_leader(pdeal)
  304. deal *pdeal;
  305. {
  306.     int contract_maker;
  307.     bid *finalsuit,*tmp;
  308.     int suit_bidder;
  309.  
  310.     /* Find out which bid specified the basic contract */
  311.     for (contract_maker = pdeal->num_bids - 1, finalsuit = pdeal->bids->prev;
  312.       contract_maker >= 0 && finalsuit->bid.suit > RANK_USED;
  313.       contract_maker--, finalsuit = finalsuit->prev);
  314.     if (contract_maker < 0)
  315.         return(-1);
  316.     /* Reduce this to a single side */
  317.     contract_maker &= 1;
  318.     /* Find the first player of this side to bid this suit. */
  319.     suit_bidder = contract_maker;
  320.     tmp = (suit_bidder) ? pdeal->bids->next : pdeal->bids;
  321.     while (tmp->bid.suit != finalsuit->bid.suit)
  322.     {
  323.         suit_bidder += 2;
  324.     tmp = tmp->next->next;
  325.     }
  326.     return((suit_bidder + 1) % 4);
  327. }
  328.  
  329. get_lead(pdeal,handnum)
  330. deal *pdeal;
  331. int handnum;
  332. {
  333.     int rank,suit,i;
  334.     char *tmp;
  335.     static char valid_ranks[] = "23456789TJQKA";
  336.     static char valid_suits[] = "SHDC";
  337.     
  338.     printf("\nEnter your opening lead: ");
  339.  
  340.     /* Get rank */
  341.     while (isspace(rank = getchar()));
  342.  
  343.     /* Get suit */
  344.     while (isspace(suit = getchar()));
  345.  
  346.     if (islower(rank))
  347.         rank = toupper(rank);
  348.     if (index(valid_ranks,rank) == NULL)
  349.     {
  350.         if (rank == '1' && suit == '0')
  351.     {
  352.         rank = 'T';
  353.         /* Get suit again */
  354.         while (isspace(suit = getchar()));
  355.     }
  356.     else
  357.         rank = -1;
  358.     }
  359.     if (islower(suit))
  360.         suit = toupper(suit);
  361.     if ((tmp = index(valid_suits,suit)) == NULL)
  362.         suit = -1;
  363.     while (getchar() != '\n');
  364.     if (rank < 0 || suit < 0)
  365.         return(1);
  366.  
  367.     pdeal->opening_lead.rank = rank;
  368.     pdeal->opening_lead.suit = tmp - valid_suits;
  369.  
  370.     /* Check to see if it's in the hand */
  371.     for (i = 0; i < 13; i++)
  372.         if (pdeal->hands[handnum][i].suit == pdeal->opening_lead.suit &&
  373.       valid_ranks[pdeal->hands[handnum][i].rank - 2] ==
  374.       pdeal->opening_lead.rank)
  375.         return(0);
  376.     return(1);
  377. }
  378.