|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T e
Length: 16790 (0x4196) Types: TextFile Names: »eval.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Bidding/eval.c«
/* eval.c */ /* Bridge Bidder Version 3.0 by John Oswalt and Nathan Glasser ..!sun!megatest!jao (usenet) nathan@brokaw.lcs.mit.edu (internet) nathan@mit-eddie.uucp (usenet) June, 1989 ------------------------------------------------------------------------------ Copyright 1988, 1989 by Nathan Glasser and John Oswalt. You may feel free to distribute this program in its current form. Please do not remove this copyright information. */ /* Routines to evaluate hands. John Oswalt (Using structures by Nathan Glasser.) */ #include "bidding.h" /* Is this deal a bad misfit? * These deals are really fun. A bad misfit is a deal in which * you have good fits in two suits with opponents. * * Let F(N) be the number of cards in suit N that you share with the * opponent with the most N. * * We pick two suits X and Y such that F(X) + F(Y) is maximized. * If F(X) + F(Y) >= n, then the deal qualifies. * */ badmisfitq(pdeal, n) deal *pdeal; int n; { int s; int suitmisfit[4]; int fit1, fit2; int s0; int int_compare(); card *h0 = pdeal->hands[0]; card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; for (s=SPADES; s<=CLUBS; s++) { s0 = suitcount(h0, s); fit1 = s0 + suitcount(h1, s); fit2 = s0 + suitcount(h3, s); if (fit2 > fit1) suitmisfit[s] = fit2; else suitmisfit[s] = fit1; } qsort(suitmisfit, 4, sizeof(int), int_compare); if (suitmisfit[0] + suitmisfit[1] >= n) return 1; return 0; } /* Is this deal a misfit? * Critera: * * All fits are 6 or 7 cards. */ misfitq(pdeal, n) deal *pdeal; int n; { int s; int fitcount[4]; card *h0 = pdeal->hands[0]; card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; for (s=SPADES; s<=CLUBS; s++) { fitcount[s] = suitcount(h0, s) + suitcount(h2, s); } for (s=SPADES; s<=CLUBS; s++) { if (!(fitcount[s] == 6 || fitcount[s] == 7)) return 0; } return 1; } /* Does at least one partnership have n cards in two suits? */ doublefitq(pdeal, n) deal *pdeal; int n; { int s; int compn = 26 - n; int count[4]; int fitcount; card *h0 = pdeal->hands[0]; card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; for (s=SPADES; s<=CLUBS; s++) { count[s] = suitcount(h0, s) + suitcount(h2, s); } fitcount = count[SPADES] + count[HEARTS]; if (fitcount == n || fitcount == compn) return 1; fitcount = count[SPADES] + count[DIAMONDS]; if (fitcount == n || fitcount == compn) return 1; fitcount = count[SPADES] + count[CLUBS]; if (fitcount == n || fitcount == compn) return 1; fitcount = count[HEARTS] + count[DIAMONDS]; if (fitcount == n || fitcount == compn) return 1; fitcount = count[HEARTS] + count[CLUBS]; if (fitcount == n || fitcount == compn) return 1; fitcount = count[DIAMONDS] + count[CLUBS]; if (fitcount == n || fitcount == compn) return 1; return 0; } /* Does at least one partnership have an n card fit? */ fitq(pdeal, n) deal *pdeal; int n; { int s; int compn = 13 - n; int count; card *h0 = pdeal->hands[0]; card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; for (s=SPADES; s<=CLUBS; s++) { count = suitcount(h0, s) + suitcount(h2, s); if (count == n) return 1; /* If we have a 13-n card fit, then they have an n card fit*/ if (count == compn) return 1; } return 0; } /* Does this deal contain n hands with voids? */ voidhandsq(pdeal, n) deal *pdeal; int n; { int voids = 0; card *h0 = pdeal->hands[0]; card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; if ((suitcount(h0, SPADES) == 0) || (suitcount(h0, HEARTS) == 0) || (suitcount(h0, DIAMONDS) == 0) || (suitcount(h0, CLUBS) == 0)) voids++; if ((suitcount(h1, SPADES) == 0) || (suitcount(h1, HEARTS) == 0) || (suitcount(h1, DIAMONDS) == 0) || (suitcount(h1, CLUBS) == 0)) voids++; if ((suitcount(h2, SPADES) == 0) || (suitcount(h2, HEARTS) == 0) || (suitcount(h2, DIAMONDS) == 0) || (suitcount(h2, CLUBS) == 0)) voids++; if ((suitcount(h3, SPADES) == 0) || (suitcount(h3, HEARTS) == 0) || (suitcount(h3, DIAMONDS) == 0) || (suitcount(h3, CLUBS) == 0)) voids++; return (voids == n); } /* Does this deal contain n voids? */ totalvoidsq(pdeal, n) deal *pdeal; int n; { int voids = 0; int s; card *h0 = pdeal->hands[0]; card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; for (s=SPADES; s<=CLUBS; s++) { if (suitcount(h0, s) == 0) voids++; if (suitcount(h1, s) == 0) voids++; if (suitcount(h2, s) == 0) voids++; if (suitcount(h3, s) == 0) voids++; } return (voids == n); } /* Does this deal contain any hand who's longest suit is exactly n cards long?*/ longsuitq(pdeal, n) deal *pdeal; int n; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; return (hand_longsuitq(h0, n) || hand_longsuitq(h1, n) || hand_longsuitq(h2, n) || hand_longsuitq(h3, n)); } /* Does this deal contain any hand with exactly n losers?*/ losersq(pdeal, n) deal *pdeal; int n; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; return (hand_losersq(h0, n) || hand_losersq(h1, n) || hand_losersq(h2, n) || hand_losersq(h3, n)); } /* Is any hand in this deal worth opening flannery? */ flanneryq(pdeal) deal *pdeal; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; return (hand_flanneryq(h0) || hand_flanneryq(h1) || hand_flanneryq(h2) || hand_flanneryq(h3)); } /* Is the first hand in this deal worth opening flannery? */ flannery1stq(pdeal) deal *pdeal; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ return (hand_flanneryq(h0)); } /* Is any hand in this deal worth opening 2 notrump? */ twontq(pdeal) deal *pdeal; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; return (hand_twontq(h0) || hand_twontq(h1) || hand_twontq(h2) || hand_twontq(h3)); } /* Is any hand in this deal worth opening 1 notrump? */ onentq(pdeal) deal *pdeal; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; return (hand_onentq(h0) || hand_onentq(h1) || hand_onentq(h2) || hand_onentq(h3)); } /* Is any hand in this deal worth opening 3 notrump? */ threentq(pdeal) deal *pdeal; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; return (hand_threentq(h0) || hand_threentq(h1) || hand_threentq(h2) || hand_threentq(h3)); } /* Is any hand in this deal worth opening 2 clubs? */ twoclubq(pdeal) deal *pdeal; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; return (hand_twoclubq(h0) || hand_twoclubq(h1) || hand_twoclubq(h2) || hand_twoclubq(h3)); } /* * Is this hand's longest suit n cards long? */ hand_longsuitq(h, n) card *h; int n; { return (getlongestlength(h) == n); } /* * Does this hand have exactly n losers? */ hand_losersq(h, n) card *h; int n; { return (countlosers(h) == n); } /* Is this hand worth a flannery opening? * * Critera: * * 11-15 High card points. * Exactly 5 hearts * Exactly 4 spades. * * Yeah, I know that there is more to it than this. */ hand_flanneryq(h) card *h; { int pc = hcp(h); if (pc < 11) return 0; if (pc > 15) return 0; if (suitcount(h, SPADES) != 4) return 0; if (suitcount(h, HEARTS) != 5) return 0; return 1; } /* Is this hand worth a 2 nt opening? * * Critera: * 20 - 21 High card points. * No 5 card major. * No 6 card minor. * No singletons. * No voids. * * XXX: Some 5 and 6 (maybe even 7) card suit hands should qualify. * (Well, what do you open with AQ AQ AQ QJxxxxx ?) */ hand_twontq(h) card *h; { int pc = hcp(h); int s; if (pc != 20 && pc != 21) return 0; for (s=SPADES; s<=CLUBS; s++) { switch (suitcount(h, s)) { case 0: case 1: return 0; case 2: case 3: case 4: break; case 5: if (s == SPADES) return 0; if (s == HEARTS) return 0; break; default: /* 6 - 13 */ return 0; } } return 1; } /* Is this hand worth a 1 nt opening? * * Critera: * 15 - 17 High card points. * No 5 card major. * No 6 card minor. * No singletons. * No voids. * * XXX: Some 5 and 6 (maybe even 7) card suit hands should qualify. * (Well, what do you open with AQ AQ AQ QJxxxxx ?) */ hand_onentq(h) card *h; { int pc = hcp(h); int s; if (pc < 15 || pc > 17) return 0; for (s=SPADES; s<=CLUBS; s++) { switch (suitcount(h, s)) { case 0: case 1: return 0; case 2: case 3: case 4: break; case 5: if (s == SPADES) return 0; if (s == HEARTS) return 0; break; default: /* 6 - 13 */ return 0; } } return 1; } /* Is this hand worth a 2 club opening? * * Critera: * Doesn't qualify for 2NT opener. * If longest suit is major (tie goes to the major), contains * 4 or fewer losers. * If longest suit is minor, contains 3 or fewer losers. * * XXX: what about 2C followed by 2NT? * XXX: what about 4414 hands? * XXX: what about hands which should open high pre-empts? * XXX: what about strong two suiters? */ hand_twoclubq(h) card *h; { int longestsuit, losers; if (hand_twontq(h)) return 0; longestsuit = getlongestsuit(h); losers = countlosers(h); if (longestsuit == SPADES || longestsuit == HEARTS) return (losers <= 4); return (losers <= 3); } /* Is this hand worth a (gambling) 3 nt opening? * * Critera: * Contains a 7 or 8 card minor headed by AKQ * Has no outside A or K. */ hand_threentq(h) card *h; { int clubc = suitcount(h, CLUBS); int diamondc = suitcount(h, DIAMONDS); int thesuit; int s; if (clubc == 7 || clubc == 8) { thesuit = CLUBS; } else if (diamondc == 7 || diamondc == 8) { thesuit = DIAMONDS; } else { return 0; } if (!cardinhandq(h, thesuit, ACE)) return 0; if (!cardinhandq(h, thesuit, KING)) return 0; if (!cardinhandq(h, thesuit, QUEEN)) return 0; for (s=SPADES; s<=CLUBS; s++) { if (s == thesuit) continue; if (cardinhandq(h, s, ACE)) return 0; if (cardinhandq(h, s, KING)) return 0; } return 1; } /* * Return the hand's longest suit. * Ties go to higher ranking suit. */ getlongestsuit(h) card *h; { int suitcount[4]; int i; int longest = 0; int longestsuit; for (i=0; i<4; i++) suitcount[i] = 0; for (i=0; i<13; i++) suitcount[h[i].suit]++; for (i = CLUBS; i>=SPADES; i--) { if (suitcount[i] >= longest) { longest = suitcount[i]; longestsuit = i; } } return (longestsuit); } /* * How long is this hand's longest suit? */ getlongestlength(h) card *h; { int suitcount[4]; int i; int longest = 0; for (i=0; i<4; i++) suitcount[i] = 0; for (i=0; i<13; i++) suitcount[h[i].suit]++; for (i = CLUBS; i>=SPADES; i--) { if (suitcount[i] >= longest) { longest = suitcount[i]; } } return (longest); } /* * How many losers are in this hand? * * We count losers as follows: * * In each suit, count 1 loser for each missing A, K or Q, but * never more losers than you have cards in the suit. * Thus the worst hand you can have has 12 losers. * * Some bridge books suggest refinements to this, where * Qxx counts as 3 losers, QJx counts as 2, and QTx counts * as 2.5. */ countlosers(h) card *h; { int losers = 0; int s; for (s = SPADES; s <= CLUBS; s++) { switch (suitcount(h, s)) { case 0: break; case 1: if (!cardinhandq(h, s, ACE)) losers += 1; break; case 2: if (!cardinhandq(h, s, ACE)) losers += 1; if (!cardinhandq(h, s, KING)) losers += 1; break; default: if (!cardinhandq(h, s, ACE)) losers += 1; if (!cardinhandq(h, s, KING)) losers += 1; if (!cardinhandq(h, s, QUEEN)) losers += 1; break; } } return losers; } /* How many cards of suit s are in hand h? */ suitcount(h, s) card *h; int s; { int i, count = 0; for (i=0; i<13; i++) { if (h[i].suit == s) count++; } return count; } /* Is the r of s in hand h? */ cardinhandq(h, s, r) card *h; int s; int r; { int i; for (i=0; i<13; i++) if (h[i].suit == s && h[i].rank == r) return 1; return 0; } /* Return number of high card points in hand h. */ hcp(h) card *h; { int pc = 0; int i; for (i=0; i<13; i++) switch (h[i].rank) { case ACE: pc += 4; break; case KING: pc += 3; break; case QUEEN: pc += 2; break; case JACK: pc += 1; break; } return pc; } int_compare(a, b) int *a, *b; { return (*a < *b); } #define NUMWILDS 10 int totals[NUMWILDS]; wildq(pdeal, t) deal *pdeal; int t; /* Total number of deals requested. */ { static int firsttime = 1; int i; int eachgets; if (firsttime) { firsttime = 0; eachgets = t/NUMWILDS; for (i=0; i<NUMWILDS; i++) { totals[i] = eachgets; } t = t % NUMWILDS; while (t--) totals[t]++; } t = 1; for (i=0; i<NUMWILDS; i++) { if (totals[i]) { t = 0; break; } } if (t) exit(1); /* shouldn't happen. */ if (totals[0]) { if (twoclubq(pdeal)) { totals[0]--; return 1; } } if (totals[1]) { if (twontq(pdeal)) { totals[1]--; return 1; } } if (totals[2]) { if (flannery1stq(pdeal)) { totals[2]--; return 1; } } if (totals[3]) { if (longsuitq(pdeal, 8)) { totals[3]--; return 1; } } if (totals[4]) { if (losersq(pdeal, 3)) { totals[4]--; return 1; } } if (totals[5]) { if (totalvoidsq(pdeal, 2)) { totals[5]--; return 1; } } if (totals[6]) { if (doublefitq(pdeal, 19)) { totals[6]--; return 1; } } if (totals[7]) { if (badmisfitq(pdeal, 20)) { totals[7]--; return 1; } } if (totals[8]) { if (threentq(pdeal)) { totals[8]--; return 1; } } if (totals[9]) { if (goulash(pdeal)) { totals[9]--; return 1; } } return 0; } goulash(pdeal, filler) deal *pdeal; int filler; { extern int card_compare(); int i, s; card pile[52]; card *h0 = pdeal->hands[0]; card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; s = (random() % 46) + 3; for (i = 0; i<13; i++) { pile[s].suit = h0[i].suit; pile[s].rank = h0[i].rank; if (++s == 52) s = 0; } for (i = 0; i<13; i++) { pile[s].suit = h1[i].suit; pile[s].rank = h1[i].rank; if (++s == 52) s = 0; } for (i = 0; i<13; i++) { pile[s].suit = h2[i].suit; pile[s].rank = h2[i].rank; if (++s == 52) s = 0; } for (i = 0; i<13; i++) { pile[s].suit = h3[i].suit; pile[s].rank = h3[i].rank; if (++s == 52) s = 0; } s = 0; for (i=0; i<=4; i++) { h0[i].suit = pile[s].suit; h0[i].rank = pile[s++].rank; } for (i=0; i<=4; i++) { h1[i].suit = pile[s].suit; h1[i].rank = pile[s++].rank; } for (i=0; i<=4; i++) { h2[i].suit = pile[s].suit; h2[i].rank = pile[s++].rank; } for (i=0; i<=4; i++) { h3[i].suit = pile[s].suit; h3[i].rank = pile[s++].rank; } for (i=5; i<=9; i++) { h0[i].suit = pile[s].suit; h0[i].rank = pile[s++].rank; } for (i=5; i<=9; i++) { h1[i].suit = pile[s].suit; h1[i].rank = pile[s++].rank; } for (i=5; i<=9; i++) { h2[i].suit = pile[s].suit; h2[i].rank = pile[s++].rank; } for (i=5; i<=9; i++) { h3[i].suit = pile[s].suit; h3[i].rank = pile[s++].rank; } for (i=10; i<=12; i++) { h0[i].suit = pile[s].suit; h0[i].rank = pile[s++].rank; } for (i=10; i<=12; i++) { h1[i].suit = pile[s].suit; h1[i].rank = pile[s++].rank; } for (i=10; i<=12; i++) { h2[i].suit = pile[s].suit; h2[i].rank = pile[s++].rank; } for (i=10; i<=12; i++) { h3[i].suit = pile[s].suit; h3[i].rank = pile[s++].rank; } qsort(h0, 13, sizeof(card), card_compare); qsort(h1, 13, sizeof(card), card_compare); qsort(h2, 13, sizeof(card), card_compare); qsort(h3, 13, sizeof(card), card_compare); return 1; } swaphands(a, b) card *a, *b; { int i, t; for (i=0; i<13; i++) { t = a[i].suit; a[i].suit = b[i].suit; b[i].suit = t; t = a[i].rank; a[i].rank = b[i].rank; b[i].rank = t; } } twoclub1stq(pdeal) deal *pdeal; { card *h0 = pdeal->hands[0]; /* Stoopid compiler. */ card *h1 = pdeal->hands[1]; card *h2 = pdeal->hands[2]; card *h3 = pdeal->hands[3]; if (hand_twoclubq(h0)) return 1; if (hand_twoclubq(h1)) { swaphands(h0, h1); return 1; } if (hand_twoclubq(h2)) { swaphands(h0, h2); return 1; } if (hand_twoclubq(h3)) { swaphands(h0, h3); return 1; } return 0; }