games@tekred.TEK.COM (05/31/88)
Submitted by: nathan@eddie.mit.edu (Nathan Glasser) Comp.sources.games: Volume 4, Issue 18 Archive-name: bidding [This program lets you practice your bridge bidding by working with and against yourself. -br] #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: README MANIFEST bidding.c bidding.doc bidding.h deal.c # makefile # Wrapped by billr@saab on Tue May 31 08:57:45 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f README -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"README\" else echo shar: Extracting \"README\" \(1388 characters\) sed "s/^X//" >README <<'END_OF_README' Xfrom the "bidding.doc" file: X X Bridge Bidder Version 1.0 X------------------------------------------------------------------------------ XCopyright 1988 by Nathan Glasser. XYou may feel free to distribute this program in its current form. XPlease do not remove this copyright information. X============================================================================== XThis program lets you practice your bidding and opening leads. X XAny conventions you want to use are allowed because you're your own Xpartner, as well as your own opponents. The idea behind this program Xis that if you're involved with a large enough number of boards, you Xhopefully won't remember all the hands of a given board, and so you Xcan bid each of the four hands at different times. What the program Xdoes is let you make all the bids in all the hands, one bid at a Xtime, choosing which board to use at any point randomly and letting Xyou enter the next bid in its bidding sequence. X XIn this way, you get to practice bidding with 3 other players whose Xbidding you understand completely and a partner whom you trust Ximplicitly. If you find this not to be the case, then you'll probably Xhave discovered ways in which you need to better understand your Xbidding system or in which bidding can otherwise be improved. X X by Nathan Glasser X nathan@xx.lcs.mit.edu (internet) X nathan@mit-eddie.uucp (usenet) X X May, 1988 END_OF_README if test 1388 -ne `wc -c <README`; then echo shar: \"README\" unpacked with wrong size! fi # end of overwriting check fi if test -f MANIFEST -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"MANIFEST\" else echo shar: Extracting \"MANIFEST\" \(324 characters\) sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST' X File Name Archive # Description X----------------------------------------------------------- X MANIFEST 1 This shipping list X README 1 X bidding.c 1 X bidding.doc 1 X bidding.h 1 X deal.c 1 X makefile 1 END_OF_MANIFEST if test 324 -ne `wc -c <MANIFEST`; then echo shar: \"MANIFEST\" unpacked with wrong size! fi # end of overwriting check fi if test -f bidding.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"bidding.c\" else echo shar: Extracting \"bidding.c\" \(9272 characters\) sed "s/^X//" >bidding.c <<'END_OF_bidding.c' X/* bidding.c */ X/* X Bridge bidder X by Nathan Glasser X nathan@xx.lcs.mit.edu (internet) X nathan@mit-eddie.uucp (usenet) X X May, 1988 X------------------------------------------------------------------------------ XCopyright 1988 by Nathan Glasser. XYou may feel free to distribute this program in its current form. XPlease do not remove this copyright information. X*/ X X#include "bidding.h" X Xint num_hands = 10; X Xchar *vuln_relative[] = {"YOUR SIDE","OTHER SIDE"}; Xchar *vuln_absolute[] = {"1ST SIDE","2ND SIDE","NEITHER SIDE","BOTH SIDES"}; Xchar *suit_strings[4] = {"SPADES","HEARTS","DIAMONDS","CLUBS"}; Xchar *vuln_format[2][2] = { X {"DECLARER SIDE","DEFENDER SIDE"}, X {"VERTICAL SIDE","HORIZONTAL SIDE"}}; X X#define PASSED_OUT(pdeal) \ X ((pdeal)->num_bids == 4 && (pdeal)->bids->bid.suit == PASS) X Xmain(argc,argv) Xint argc; Xchar **argv; X{ X deal *deals; X int i,j; X int num_hands_left; X int hand_num; X X if (argc > 1) X num_hands = atoi(argv[1]); X printf("Dealing %d hands...\n",num_hands_left = num_hands); X X deals = (deal *)malloc(num_hands * sizeof(deal)); X X srandom((unsigned)time(NULL)); X X for (i = 0; i < num_hands; i++) X deal_hands(&deals[i]); X X /* Accept bids */ X while (num_hands_left) X { X hand_num = random() % num_hands; X X if (deals[hand_num].bidding_done) X continue; X for (i = 0; i < 24; i++) X putchar('\n'); X print_bidding(stdout,&deals[hand_num]); X printf("YOUR HAND (%s VULNERABLE):\n", X (deals[hand_num].vulnerability <= RELATIVE) ? X vuln_relative[(deals[hand_num].num_bids & 1) ^ X deals[hand_num].vulnerability] : X vuln_absolute[deals[hand_num].vulnerability]); X print_hand(stdout,deals[hand_num].hands[deals[hand_num].num_bids % 4]); X while(accept_bid(&deals[hand_num])) X printf("Bad bid.\n"); X if (deals[hand_num].bidding_done) X { X num_hands_left--; X /* If hand was passed out */ X if (PASSED_OUT(&deals[hand_num])) X display_complete_deal(&deals[hand_num],0); X } X } X X /* Accept opening leads */ X for (hand_num = 0; hand_num < num_hands; hand_num++) X { X /* Make sure hand wasn't passed out */ X if (PASSED_OUT(&deals[hand_num])) X continue; X for (i = 0; i < 24; i++) X putchar('\n'); X print_bidding(stdout,&deals[hand_num]); X j = figure_out_leader(&deals[hand_num]); X printf("YOUR HAND (%s VULNERABLE):\n", X (deals[hand_num].vulnerability <= RELATIVE) ? X vuln_relative[(j & 1) ^ X deals[hand_num].vulnerability] : X vuln_absolute[deals[hand_num].vulnerability]); X print_hand(stdout,deals[hand_num].hands[j]); X while (get_lead(&deals[hand_num],j)) X printf("Bad lead.\n"); X display_complete_deal(&deals[hand_num],((j + 1) % 4)); X } X X printf("All bidding complete.\n"); X} X Xdisplay_complete_deal(pdeal,top_hand) Xdeal *pdeal; Xint top_hand; X{ X print_complete_deal(stdout,pdeal,top_hand); X more(); X log_deal(pdeal,top_hand); X} X Xprint_complete_deal(fp,pdeal,top_hand) XFILE *fp; Xdeal *pdeal; Xint top_hand; X{ X int i; X char top_h[4][80],left_h[4][80],right_h[4][80],bottom_h[4][80]; X X format_hand(top_h,pdeal->hands[top_hand]); X format_hand(right_h,pdeal->hands[(top_hand + 1) % 4]); X format_hand(bottom_h,pdeal->hands[(top_hand + 2) % 4]); X format_hand(left_h,pdeal->hands[(top_hand + 3) % 4]); X fprintf(fp,"\t\t\tCOMPLETE DEAL (%s VULNERABLE):\n", X ((pdeal->vulnerability <= RELATIVE) ? X vuln_format[PASSED_OUT(pdeal)][(top_hand & 1) ^ pdeal->vulnerability] : X vuln_absolute[pdeal->vulnerability])); X X for (i = 0; i < 4; i++) X fprintf(fp,"\t\t\t%s\n",top_h[i]); X for (i = 0; i < 4; i++) X fprintf(fp,"%-43s%s\n",left_h[i],right_h[i]); X for (i = 0; i < 4; i++) X fprintf(fp,"\t\t\t%s\n",bottom_h[i]); X} X Xprint_bidding(fp,pdeal) XFILE *fp; Xdeal *pdeal; X{ X bid *bids; X static char *bid_suits[] = {"S","H","D","C","N","DB","RD","P"}; X int bid_num = 0; X X fprintf(fp,"BIDDING:\n"); X for (bids = pdeal->bids; bid_num < pdeal->num_bids; bids = bids->next) X { X if (bids->bid.suit <= RANK_USED) X fprintf(fp,"\t%d %s",bids->bid.rank,bid_suits[bids->bid.suit]); X else X fprintf(fp,"\t%s",bid_suits[bids->bid.suit]); X if ((++bid_num % 4) == 0) X putc('\n',fp); X } X if (bid_num % 4) X putc('\n',fp); X} X Xaccept_bid(pdeal) Xdeal *pdeal; X{ X int ch; X int rank = -1,suit; X bid *newbid; X static int suit_cvt[] = {3,2,1,0,4}; X bid *tmp; X int i; X X printf("\nEnter your bid: "); X X /* Get optional rank */ X while (isspace(ch = getchar())); X X if (isdigit(ch)) X { X rank = ch - '0'; X while (isspace(ch = getchar())); X } X X /* Get suit, notrump, pass, double, or redouble */ X if (islower(ch)) X ch = toupper(ch); X X switch (ch) X { X case 'S': X suit = SPADES; X break; X case 'H': X suit = HEARTS; X break; X case 'D': X suit = (rank >= 0) ? DIAMONDS : DOUBLE; X break; X case 'C': X suit = CLUBS; X break; X case 'N': X suit = NOTRUMP; X break; X case 'P': X suit = PASS; X break; X case 'R': X suit = REDOUBLE; X break; X default: X suit = -1; X break; X } X X while (getchar() != '\n'); X if (suit < 0) X return(1); X X /* Make sure numerical bid is ok */ X if (suit <= RANK_USED) X { X if (rank < 1 || rank > 7) X return(1); X if (pdeal->num_bids > 0) X for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i; X tmp = tmp->prev, i--) X if (tmp->bid.suit <= RANK_USED) X { X if (rank < tmp->bid.rank || X rank == tmp->bid.rank && X suit_cvt[suit] <= suit_cvt[tmp->bid.suit]) X return(1); X break; X } X } X /* Make sure double or redouble is valid */ X else if (suit == DOUBLE || suit == REDOUBLE) X { X if (pdeal->num_bids <= 0) X return(1); X for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i; X tmp = tmp->prev, i--) X if (tmp->bid.suit != PASS) X { X /* Double or redouble by wrong side */ X /* The person bidding in the num_bids position was X an opponent. The last valid bidder must have had X this parity. */ X if (((i ^ pdeal->num_bids) & 1) == 1) X return(1); X /* Double of a double or redouble */ X if (suit == DOUBLE && tmp->bid.suit > RANK_USED) X return(1); X /* Redouble of a bid other than double */ X if (suit == REDOUBLE && tmp->bid.suit != DOUBLE) X return(1); X break; X } X /* Double or redouble as first non-pass bid */ X if (!i) X return(1); X } X X newbid = (bid *)malloc(sizeof(bid)); X newbid->bid.rank = rank; X newbid->bid.suit = suit; X X if (++(pdeal->num_bids) == 1) X newbid->next = newbid->prev = pdeal->bids = newbid; X else X { X (newbid->next = pdeal->bids)->prev = X (newbid->prev = pdeal->bids->prev)->next = newbid; X if (newbid->bid.suit == PASS && newbid->prev->bid.suit == PASS && X newbid->prev->prev->bid.suit == PASS && pdeal->num_bids >= 4) X pdeal->bidding_done = 1; X } X return(0); X} X Xmore() X{ X printf("---Hit return to continue---"); X while (getchar() != '\n'); X} X Xlog_deal(pdeal,top_hand) Xdeal *pdeal; Xint top_hand; X{ X FILE *fp; X int i; X X if ((fp = fopen(LOGFILE,"a")) == NULL) X { X perror(LOGFILE); X return; X } X print_bidding(fp,pdeal); X if (pdeal->opening_lead.suit >= 0) X fprintf(fp,"OPENING LEAD: %c of %s\n",pdeal->opening_lead.rank, X suit_strings[pdeal->opening_lead.suit]); X print_complete_deal(fp,pdeal,top_hand); X putc('\n',fp); X putc('\n',fp); X fclose(fp); X} X Xfigure_out_leader(pdeal) Xdeal *pdeal; X{ X int contract_maker; X bid *finalsuit,*tmp; X int suit_bidder; X X /* Find out which bid specified the basic contract */ X for (contract_maker = pdeal->num_bids - 1, finalsuit = pdeal->bids->prev; X contract_maker >= 0 && finalsuit->bid.suit > RANK_USED; X contract_maker--, finalsuit = finalsuit->prev); X if (contract_maker < 0) X return(-1); X /* Reduce this to a single side */ X contract_maker &= 1; X /* Find the first player of this side to bid this suit. */ X suit_bidder = contract_maker; X tmp = (suit_bidder) ? pdeal->bids->next : pdeal->bids; X while (tmp->bid.suit != finalsuit->bid.suit) X { X suit_bidder += 2; X tmp = tmp->next->next; X } X return((suit_bidder + 1) % 4); X} X Xget_lead(pdeal,handnum) Xdeal *pdeal; Xint handnum; X{ X int rank,suit,i; X char *tmp; X static char valid_ranks[] = "23456789TJQKA"; X static char valid_suits[] = "SHDC"; X X printf("\nEnter your opening lead: "); X X /* Get rank */ X while (isspace(rank = getchar())); X X /* Get suit */ X while (isspace(suit = getchar())); X X if (islower(rank)) X rank = toupper(rank); X if (index(valid_ranks,rank) == NULL) X { X if (rank == '1' && suit == '0') X { X rank = 'T'; X /* Get suit again */ X while (isspace(suit = getchar())); X } X else X rank = -1; X } X if (islower(suit)) X suit = toupper(suit); X if ((tmp = index(valid_suits,suit)) == NULL) X suit = -1; X while (getchar() != '\n'); X if (rank < 0 || suit < 0) X return(1); X X pdeal->opening_lead.rank = rank; X pdeal->opening_lead.suit = tmp - valid_suits; X X /* Check to see if it's in the hand */ X for (i = 0; i < 13; i++) X if (pdeal->hands[handnum][i].suit == pdeal->opening_lead.suit && X valid_ranks[pdeal->hands[handnum][i].rank - 2] == X pdeal->opening_lead.rank) X return(0); X return(1); X} END_OF_bidding.c if test 9272 -ne `wc -c <bidding.c`; then echo shar: \"bidding.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f bidding.doc -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"bidding.doc\" else echo shar: Extracting \"bidding.doc\" \(2818 characters\) sed "s/^X//" >bidding.doc <<'END_OF_bidding.doc' X Bridge Bidder Version 1.0 X by Nathan Glasser X nathan@xx.lcs.mit.edu (internet) X nathan@mit-eddie.uucp (usenet) X X May, 1988 X------------------------------------------------------------------------------ XCopyright 1988 by Nathan Glasser. XYou may feel free to distribute this program in its current form. XPlease do not remove this copyright information. X============================================================================== XThis program lets you practice your bidding and opening leads. X XAny conventions you want to use are allowed because you're your own Xpartner, as well as your own opponents. The idea behind this program Xis that if you're involved with a large enough number of boards, you Xhopefully won't remember all the hands of a given board, and so you Xcan bid each of the four hands at different times. What the program Xdoes is let you make all the bids in all the hands, one bid at a Xtime, choosing which board to use at any point randomly and letting Xyou enter the next bid in its bidding sequence. X XIn this way, you get to practice bidding with 3 other players whose Xbidding you understand completely and a partner whom you trust Ximplicitly. If you find this not to be the case, then you'll probably Xhave discovered ways in which you need to better understand your Xbidding system or in which bidding can otherwise be improved. X X(By the way, randomly dealt hands tend to have more unusual Xdistribution than cards which are shuffled and dealt. Thus you may Xfind that you're pushing your knowledge of your bidding system to its Xlimits with some of the hands you'll get.) X------------------------------------------------------------------------------ XThe operation of the program is as follows: X XUsage: bidding [number of boards] X XThe number of boards to deal can be specified on the command line; the Xdefault is 10. X XThe appropriate number of boards are dealt. X XYou are shown a single hand, and the bidding of the current board so Xfar (if there's been any), and you get to enter the next bid. X XYou continue in this fashion until the bidding is completed on every hand. X XThen you are presented with the hand of the player to make the Xopening lead on a board, and the bidding of the hand, and get to Xenter the opening lead. X XThe complete hand is then presented to you for your analysis. X XYou continue in this fashion until all the hands have been bid and led to. X XA complete log of each board is automatically written to the file X"bidding.log" after the board's completion. X------------------------------------------------------------------------------ XBids are specified in the obvious way, e.g. 1s = 1 spade, 2n = 2 notrump, Xp = pass, d = double, r = redouble. X XSimilarly, opening leads are specified in the obvious way, e.g. X2c = 2 of clubs, js = jack of spades, th or 10h = ten of hearts. END_OF_bidding.doc if test 2818 -ne `wc -c <bidding.doc`; then echo shar: \"bidding.doc\" unpacked with wrong size! fi # end of overwriting check fi if test -f bidding.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"bidding.h\" else echo shar: Extracting \"bidding.h\" \(1261 characters\) sed "s/^X//" >bidding.h <<'END_OF_bidding.h' X/* bidding.h */ X/* X Bridge bidder X by Nathan Glasser X nathan@xx.lcs.mit.edu (internet) X nathan@mit-eddie.uucp (usenet) X X May, 1988 X------------------------------------------------------------------------------ XCopyright 1988 by Nathan Glasser. XYou may feel free to distribute this program in its current form. XPlease do not remove this copyright information. X*/ X X#include <stdio.h> X#include <ctype.h> X#ifdef MSDOS X#include <string.h> X#include <stdlib.h> X#define random rand X#define srandom srand X#define index strchr X#else X#include <strings.h> X#endif X X#define LOGFILE "bidding.log" X X#define JACK 11 X#define QUEEN 12 X#define KING 13 X#define ACE 14 X X#define SPADES 0 X#define HEARTS 1 X#define DIAMONDS 2 X#define CLUBS 3 X X#define NOTRUMP 4 X#define RANK_USED 4 X X#define DOUBLE 5 X#define REDOUBLE 6 X#define PASS 7 X X X#define FIRSTPAIR 0 X#define SECONDPAIR 1 X#define RELATIVE 1 X#define NEITHER 2 X#define BOTH 3 X X Xstruct card_or_bid { X int rank; X int suit; X}; X Xtypedef struct card_or_bid card; X Xtypedef struct bid { X struct card_or_bid bid; X struct bid *next,*prev; X} bid; X Xtypedef card hand[13]; X Xtypedef struct deal { X hand hands[4]; X int vulnerability; X bid *bids; X int num_bids; X int bidding_done; X card opening_lead; X} deal; END_OF_bidding.h if test 1261 -ne `wc -c <bidding.h`; then echo shar: \"bidding.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f deal.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"deal.c\" else echo shar: Extracting \"deal.c\" \(2224 characters\) sed "s/^X//" >deal.c <<'END_OF_deal.c' X/* deal.c */ X/* X Bridge bidder X by Nathan Glasser X nathan@xx.lcs.mit.edu (internet) X nathan@mit-eddie.uucp (usenet) X X May, 1988 X------------------------------------------------------------------------------ XCopyright 1988 by Nathan Glasser. XYou may feel free to distribute this program in its current form. XPlease do not remove this copyright information. X*/ X X#include "bidding.h" X X Xcard_compare(pcard1,pcard2) Xcard *pcard1,*pcard2; X{ X return((pcard1->suit != pcard2->suit) ? (pcard1->suit - pcard2->suit) : X (pcard2->rank - pcard1->rank)); X} X Xdeal_hands(pdeal) Xdeal *pdeal; X{ X card *thehand; X int cards[52]; X int player,cardsinhand; X int cardnum; X int nextcard; X int cardsleft = 52; X static vulnerability = 0; X X pdeal->num_bids = 0; X pdeal->bidding_done = 0; X vulnerability = ((pdeal->vulnerability = vulnerability) + 1) % 4; X pdeal->opening_lead.rank = pdeal->opening_lead.suit = -1; X X for (cardnum = 0; cardnum < 52; cardnum++) X cards[cardnum] = 0; X X for (player = 0; player < 4; player++) X { X thehand = pdeal->hands[player]; X for (cardsinhand = 0; cardsinhand < 13; cardsinhand++) X { X nextcard = random() % (cardsleft--); X for (cardnum = 0 ; cards[cardnum] || --nextcard >= 0; cardnum++); X cards[cardnum] = 1; X thehand[cardsinhand].suit = cardnum / 13; X thehand[cardsinhand].rank = 2 + (cardnum % 13); X } X qsort(thehand,13,sizeof(card),card_compare); X } X} X X Xprint_hand(fp,thehand) XFILE *fp; Xcard *thehand; X{ X int i; X char bufs[4][80]; X X format_hand(bufs,thehand); X for (i = 0; i < 4; i++) X { X fputs(bufs[i],fp); X putc('\n',fp); X } X} X X/* Accepts an array of size four of strings, and formats into it */ Xformat_hand(bufs,thehand) Xchar (*bufs)[80]; Xcard *thehand; X{ X extern char *suit_strings[]; X static char card_chars[] = "xx23456789TJQKA"; X int suit_num = -1; X int i; X static char card_str[3] = " A"; X X bufs--; X for (i = 0; i < 13; i++) X { X while (thehand[i].suit != suit_num) X sprintf(*++bufs,"%8s: ",suit_strings[++suit_num]); X card_str[1] = card_chars[thehand[i].rank]; X strcat(*bufs,card_str); X } X while (suit_num < 3) X sprintf(*++bufs,"%8s: ",suit_strings[++suit_num]); X} END_OF_deal.c if test 2224 -ne `wc -c <deal.c`; then echo shar: \"deal.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f makefile -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"makefile\" else echo shar: Extracting \"makefile\" \(122 characters\) sed "s/^X//" >makefile <<'END_OF_makefile' X#Unix makefile for bridge bidder X XOBJS = bidding.o deal.o X Xbidding: $(OBJS) X $(CC) $(OBJS) -o bidding X X$(OBJS): bidding.h END_OF_makefile if test 122 -ne `wc -c <makefile`; then echo shar: \"makefile\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 1 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0