home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume4
/
bidding
/
bidding.c
next >
Wrap
C/C++ Source or Header
|
1988-05-31
|
9KB
|
378 lines
/* bidding.c */
/*
Bridge bidder
by Nathan Glasser
nathan@xx.lcs.mit.edu (internet)
nathan@mit-eddie.uucp (usenet)
May, 1988
------------------------------------------------------------------------------
Copyright 1988 by Nathan Glasser.
You may feel free to distribute this program in its current form.
Please do not remove this copyright information.
*/
#include "bidding.h"
int num_hands = 10;
char *vuln_relative[] = {"YOUR SIDE","OTHER SIDE"};
char *vuln_absolute[] = {"1ST SIDE","2ND SIDE","NEITHER SIDE","BOTH SIDES"};
char *suit_strings[4] = {"SPADES","HEARTS","DIAMONDS","CLUBS"};
char *vuln_format[2][2] = {
{"DECLARER SIDE","DEFENDER SIDE"},
{"VERTICAL SIDE","HORIZONTAL SIDE"}};
#define PASSED_OUT(pdeal) \
((pdeal)->num_bids == 4 && (pdeal)->bids->bid.suit == PASS)
main(argc,argv)
int argc;
char **argv;
{
deal *deals;
int i,j;
int num_hands_left;
int hand_num;
if (argc > 1)
num_hands = atoi(argv[1]);
printf("Dealing %d hands...\n",num_hands_left = num_hands);
deals = (deal *)malloc(num_hands * sizeof(deal));
srandom((unsigned)time(NULL));
for (i = 0; i < num_hands; i++)
deal_hands(&deals[i]);
/* Accept bids */
while (num_hands_left)
{
hand_num = random() % num_hands;
if (deals[hand_num].bidding_done)
continue;
for (i = 0; i < 24; i++)
putchar('\n');
print_bidding(stdout,&deals[hand_num]);
printf("YOUR HAND (%s VULNERABLE):\n",
(deals[hand_num].vulnerability <= RELATIVE) ?
vuln_relative[(deals[hand_num].num_bids & 1) ^
deals[hand_num].vulnerability] :
vuln_absolute[deals[hand_num].vulnerability]);
print_hand(stdout,deals[hand_num].hands[deals[hand_num].num_bids % 4]);
while(accept_bid(&deals[hand_num]))
printf("Bad bid.\n");
if (deals[hand_num].bidding_done)
{
num_hands_left--;
/* If hand was passed out */
if (PASSED_OUT(&deals[hand_num]))
display_complete_deal(&deals[hand_num],0);
}
}
/* Accept opening leads */
for (hand_num = 0; hand_num < num_hands; hand_num++)
{
/* Make sure hand wasn't passed out */
if (PASSED_OUT(&deals[hand_num]))
continue;
for (i = 0; i < 24; i++)
putchar('\n');
print_bidding(stdout,&deals[hand_num]);
j = figure_out_leader(&deals[hand_num]);
printf("YOUR HAND (%s VULNERABLE):\n",
(deals[hand_num].vulnerability <= RELATIVE) ?
vuln_relative[(j & 1) ^
deals[hand_num].vulnerability] :
vuln_absolute[deals[hand_num].vulnerability]);
print_hand(stdout,deals[hand_num].hands[j]);
while (get_lead(&deals[hand_num],j))
printf("Bad lead.\n");
display_complete_deal(&deals[hand_num],((j + 1) % 4));
}
printf("All bidding complete.\n");
}
display_complete_deal(pdeal,top_hand)
deal *pdeal;
int top_hand;
{
print_complete_deal(stdout,pdeal,top_hand);
more();
log_deal(pdeal,top_hand);
}
print_complete_deal(fp,pdeal,top_hand)
FILE *fp;
deal *pdeal;
int top_hand;
{
int i;
char top_h[4][80],left_h[4][80],right_h[4][80],bottom_h[4][80];
format_hand(top_h,pdeal->hands[top_hand]);
format_hand(right_h,pdeal->hands[(top_hand + 1) % 4]);
format_hand(bottom_h,pdeal->hands[(top_hand + 2) % 4]);
format_hand(left_h,pdeal->hands[(top_hand + 3) % 4]);
fprintf(fp,"\t\t\tCOMPLETE DEAL (%s VULNERABLE):\n",
((pdeal->vulnerability <= RELATIVE) ?
vuln_format[PASSED_OUT(pdeal)][(top_hand & 1) ^ pdeal->vulnerability] :
vuln_absolute[pdeal->vulnerability]));
for (i = 0; i < 4; i++)
fprintf(fp,"\t\t\t%s\n",top_h[i]);
for (i = 0; i < 4; i++)
fprintf(fp,"%-43s%s\n",left_h[i],right_h[i]);
for (i = 0; i < 4; i++)
fprintf(fp,"\t\t\t%s\n",bottom_h[i]);
}
print_bidding(fp,pdeal)
FILE *fp;
deal *pdeal;
{
bid *bids;
static char *bid_suits[] = {"S","H","D","C","N","DB","RD","P"};
int bid_num = 0;
fprintf(fp,"BIDDING:\n");
for (bids = pdeal->bids; bid_num < pdeal->num_bids; bids = bids->next)
{
if (bids->bid.suit <= RANK_USED)
fprintf(fp,"\t%d %s",bids->bid.rank,bid_suits[bids->bid.suit]);
else
fprintf(fp,"\t%s",bid_suits[bids->bid.suit]);
if ((++bid_num % 4) == 0)
putc('\n',fp);
}
if (bid_num % 4)
putc('\n',fp);
}
accept_bid(pdeal)
deal *pdeal;
{
int ch;
int rank = -1,suit;
bid *newbid;
static int suit_cvt[] = {3,2,1,0,4};
bid *tmp;
int i;
printf("\nEnter your bid: ");
/* Get optional rank */
while (isspace(ch = getchar()));
if (isdigit(ch))
{
rank = ch - '0';
while (isspace(ch = getchar()));
}
/* Get suit, notrump, pass, double, or redouble */
if (islower(ch))
ch = toupper(ch);
switch (ch)
{
case 'S':
suit = SPADES;
break;
case 'H':
suit = HEARTS;
break;
case 'D':
suit = (rank >= 0) ? DIAMONDS : DOUBLE;
break;
case 'C':
suit = CLUBS;
break;
case 'N':
suit = NOTRUMP;
break;
case 'P':
suit = PASS;
break;
case 'R':
suit = REDOUBLE;
break;
default:
suit = -1;
break;
}
while (getchar() != '\n');
if (suit < 0)
return(1);
/* Make sure numerical bid is ok */
if (suit <= RANK_USED)
{
if (rank < 1 || rank > 7)
return(1);
if (pdeal->num_bids > 0)
for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i;
tmp = tmp->prev, i--)
if (tmp->bid.suit <= RANK_USED)
{
if (rank < tmp->bid.rank ||
rank == tmp->bid.rank &&
suit_cvt[suit] <= suit_cvt[tmp->bid.suit])
return(1);
break;
}
}
/* Make sure double or redouble is valid */
else if (suit == DOUBLE || suit == REDOUBLE)
{
if (pdeal->num_bids <= 0)
return(1);
for (tmp = pdeal->bids->prev,i = pdeal->num_bids; i;
tmp = tmp->prev, i--)
if (tmp->bid.suit != PASS)
{
/* Double or redouble by wrong side */
/* The person bidding in the num_bids position was
an opponent. The last valid bidder must have had
this parity. */
if (((i ^ pdeal->num_bids) & 1) == 1)
return(1);
/* Double of a double or redouble */
if (suit == DOUBLE && tmp->bid.suit > RANK_USED)
return(1);
/* Redouble of a bid other than double */
if (suit == REDOUBLE && tmp->bid.suit != DOUBLE)
return(1);
break;
}
/* Double or redouble as first non-pass bid */
if (!i)
return(1);
}
newbid = (bid *)malloc(sizeof(bid));
newbid->bid.rank = rank;
newbid->bid.suit = suit;
if (++(pdeal->num_bids) == 1)
newbid->next = newbid->prev = pdeal->bids = newbid;
else
{
(newbid->next = pdeal->bids)->prev =
(newbid->prev = pdeal->bids->prev)->next = newbid;
if (newbid->bid.suit == PASS && newbid->prev->bid.suit == PASS &&
newbid->prev->prev->bid.suit == PASS && pdeal->num_bids >= 4)
pdeal->bidding_done = 1;
}
return(0);
}
more()
{
printf("---Hit return to continue---");
while (getchar() != '\n');
}
log_deal(pdeal,top_hand)
deal *pdeal;
int top_hand;
{
FILE *fp;
int i;
if ((fp = fopen(LOGFILE,"a")) == NULL)
{
perror(LOGFILE);
return;
}
print_bidding(fp,pdeal);
if (pdeal->opening_lead.suit >= 0)
fprintf(fp,"OPENING LEAD: %c of %s\n",pdeal->opening_lead.rank,
suit_strings[pdeal->opening_lead.suit]);
print_complete_deal(fp,pdeal,top_hand);
putc('\n',fp);
putc('\n',fp);
fclose(fp);
}
figure_out_leader(pdeal)
deal *pdeal;
{
int contract_maker;
bid *finalsuit,*tmp;
int suit_bidder;
/* Find out which bid specified the basic contract */
for (contract_maker = pdeal->num_bids - 1, finalsuit = pdeal->bids->prev;
contract_maker >= 0 && finalsuit->bid.suit > RANK_USED;
contract_maker--, finalsuit = finalsuit->prev);
if (contract_maker < 0)
return(-1);
/* Reduce this to a single side */
contract_maker &= 1;
/* Find the first player of this side to bid this suit. */
suit_bidder = contract_maker;
tmp = (suit_bidder) ? pdeal->bids->next : pdeal->bids;
while (tmp->bid.suit != finalsuit->bid.suit)
{
suit_bidder += 2;
tmp = tmp->next->next;
}
return((suit_bidder + 1) % 4);
}
get_lead(pdeal,handnum)
deal *pdeal;
int handnum;
{
int rank,suit,i;
char *tmp;
static char valid_ranks[] = "23456789TJQKA";
static char valid_suits[] = "SHDC";
printf("\nEnter your opening lead: ");
/* Get rank */
while (isspace(rank = getchar()));
/* Get suit */
while (isspace(suit = getchar()));
if (islower(rank))
rank = toupper(rank);
if (index(valid_ranks,rank) == NULL)
{
if (rank == '1' && suit == '0')
{
rank = 'T';
/* Get suit again */
while (isspace(suit = getchar()));
}
else
rank = -1;
}
if (islower(suit))
suit = toupper(suit);
if ((tmp = index(valid_suits,suit)) == NULL)
suit = -1;
while (getchar() != '\n');
if (rank < 0 || suit < 0)
return(1);
pdeal->opening_lead.rank = rank;
pdeal->opening_lead.suit = tmp - valid_suits;
/* Check to see if it's in the hand */
for (i = 0; i < 13; i++)
if (pdeal->hands[handnum][i].suit == pdeal->opening_lead.suit &&
valid_ranks[pdeal->hands[handnum][i].rank - 2] ==
pdeal->opening_lead.rank)
return(0);
return(1);
}