|
|
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;
}