DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T e

⟦43160b80f⟧ TextFile

    Length: 16790 (0x4196)
    Types: TextFile
    Names: »eval.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Bidding/eval.c« 

TextFile

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