/*
 *	File name:			strategy_bah.c
 *	Purpose:			Defines a robot strategy for playing poker.
 *	Functions:			computer_bet, computer_draw, strategy_init,
 *						strategy_exit, computer_outcome, computer_hear.
 *	Created:			23 Nov 89
 *	Last Modified:		11 Nov 91
 *	Comments:
 *		"Strategy" files must contain six externally visible functions:
 *
 *		strategy_init - called once during startup.
 *		strategy_exit - called once upon orderly exit.
 *		computer_bet - called whenever a bet is needed.
 *		computer_draw - called whenever a draw of cards is needed.
 *		computer_outcome - called at the end of each hand.
 *		computer_hear - called whenever anyone sends a text message.
 *
 *		The interfaces to these six functions are well-defined and should 
 *		remain stable.  You can use this file to entirely alter the playing 
 *		methods of a robot player without being concerned with server 
 *		communication or anything else.
 *
 *	History:
 *		23 Nov 89/JVE	Created.
 *		25 Nov 89/JVE	Added strategy_init().
 *		25 Jul 90/JVE	Converted template to BAH strategy.  Added own
 *						draw strategy.
 *		27 Jul 90/JVE	Sandbags more often, tries to draw straight.
 *		29 Jul 90/JVE	Log tries/results for flushes and straights.
 *						Changed sandbagging to only before draw and only
 *						if amount required to bet is less than 40.
 *		28 Sep 91/JVE	Fine-tuning.
 *		02 Oct 91/JVE	Bet aggressively if close to a flush before draw.
 *		04 Oct 91/JVE	Ditto for a near straight.
 *		07 Oct 91/JVE	Draw three with a pair.  Bluff a little less, and
 *						random amounts.
 *		16 Oct 91/JVE	Choose between GreatStrategy based on experience.
 *		17 Oct 91/JVE	Limits on weighted average so it stays current.
 *		18 Oct 91/JVE	If pair & four_flush & significant betting, go for
 *						the flush.
 *		08 Nov 91/JVE	Little bit of randomness to betting threshhold on
 *						one pair.  BetPair now knows that draw might toss
 *						the pair and go for the flush.
 *		11 Nov 91/JVE	Braver with one pair before the draw.
 *		25 Jul 93/JVE	Prototypes, new standard functions.
 */

# include	<sys/param.h>
# include	"standard.h"
# include	"cards.h"		/* for crandom, suit, card macros */
# include	"whowon.h"		/* for score #defines */
# include	"5draw.h"		/* for raise limit, GAMEINFO struct */
# include	"commands.h"	/* for DISCARD */
# include	"robot.h"
# include	"strategy_protos.h"

# define	MIN_EXPERIENCE			20
# define	MAX_HANDS_FOR_AVERAGE	20

static int	before_draw = FALSE;
static int	first_time_after_draw = FALSE;
static int	try_for_straight = FALSE;
static int	want_suit = -1;
static int	bluffing = FALSE;
static int	started_bluff_at = 0;
static int	I_have_bet = 0;

typedef enum 
	{ 
	UNKNOWN, 
	RAISE_TO_THE_LIMIT, 			/* always raise by RAISE_LIMIT */
	RAISE_SMALL 					/* raise little first, then a lot */
	} GreatStrategy;

static void				AdjustWeights();
static GreatStrategy	ChooseStrategy();

static GreatStrategy strategy = UNKNOWN;

static int		experience = 0;		/* # of great hands */
static float	expect_limit = 0;	/* stake to expect if RAISE_TO_THE_LIMIT */
static float	expect_small = 0;	/* stake to expect if RAISE_SMALL */
static int		hands_limit = 0;	/* # hands played RAISE_TO_THE_LIMIT */
static int		hands_small = 0;	/* # hands played RAISE_SMALL */
static int		mystake = 0;		/* amt I expected from last great hand */

extern int		won_last_hand;		/* did I win the last hand? */

/*
 ***********************************************************************
 *
 * FUNCTION NAME:	computer_bet
 *
 * DESCRIPTION:		Make a bet.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		knowledge	 I		Everything we know about the current hand.
 *		me			 I		Index in knowledge[] of this robot.
 *		required	 I		Total $$ this hand to bet to stay in.
 *
 * RETURN CODES: 
 *	(int)		Amount of additional cash to bet.
 *	(-1)		Fold.
 *
 * COMMENTS:
 *
 *		1.	23 Nov 89		Created.
 *		2.	25 Jul 90		Created the BAH strategy.
 *		3.	27 Jul 90		Sandbags (only bet 10 with very good hand)
 *							half the time now.
 *		4.	28 Sep 91		Added randomness to cutoff between call/fold
 *							when we have nothing.  Fine-tuned other limits.
 *		5.	02 Oct 91		Bet aggressively if close to a flush.
 *		6.	04 Oct 91		Ditto for near straight.
 *		7.	16 Oct 91		Restructured program.
 *		8.	29 Oct 91		Bust Foobie/Gonzo by always making sure hand
 *							bet is raised above the ANTE.
 *		9.	08 Nov 91		Remove Foobie buster.
 *
 **********************************************************************
 */

int		computer_bet( KNOWLEDGE knowledge[], int me, int required )

{
GAMEINFO	gi;
int			i;
int			add_bet = 0;
int			need = required - knowledge[me].bet;
int			score;
int			dummy;

if ( is_new_hand )
	{
	before_draw = TRUE;
	first_time_after_draw = FALSE;
	bluffing = FALSE;
	if ( strategy != UNKNOWN && won_last_hand )
		AdjustWeights();
	printf( "Starting new hand\n" );
	strategy = UNKNOWN;
	}

score = eval( hand );

if ( first_time_after_draw )
	{
	if ( want_suit != -1 )
		if ( score >= FLUSH )
			printf( "Went for flush and got it!\n" );
		else
			printf( "Went for flush and missed it.\n" );
	else if ( try_for_straight )
		if ( score >= STRAIGHT )
			printf( "Went for straight and got it!\n" );
		else
			printf( "Went for straight and missed it.\n" );
	}

if ( bluffing )
	{
	/*
	 *	We are bluffing.  If someone else is gung-ho on his hand, we must
	 *	drop out of bluff mode and resume normal operation.  If we are
	 *	going to bluff, do it big-time.
	 */
	if ( need < 20 && required < started_bluff_at + RAISE_LIMIT * 2 )
		{
		add_bet = need + RAISE_LIMIT;
		printf( "Continuing bluff\n" );
		}
	else
		{
		bluffing = FALSE;
		printf( "Abandoning bluff\n" );
		add_bet = bet( hand, score, required, need );
		}
	}
else if ( ( is_new_hand || first_time_after_draw ) && crandom( 40 ) > 38 &&
		required < 25 )
	{
	bluffing = TRUE;
	printf( "Deciding to bluff\n" );
	started_bluff_at = required;
	add_bet = need + RAISE_LIMIT;
	}
else
	{
	printf( "Betting normally\n" );
	add_bet = bet( hand, score, required, need );
	}
/*
 *	If we are thinking about folding, but the additional bet needed
 *	to call is small in relation to what we've already bet, then
 *	call instead.
 */
if ( add_bet == -1 && need < knowledge[me].bet / 5 )
	add_bet = need;
printf( "required %d need %d betting %d\n", required, need, add_bet );
first_time_after_draw = FALSE;
I_have_bet = knowledge[me].bet + add_bet;
return add_bet;
}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	bet
 *
 * DESCRIPTION:		Decide how much to bet
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		hand		 I		Our hand.
 *		score		 I		Evaluation of our hand.
 *		required	 I		Total cash required of us during this hand.
 *		need		 I		Amount of cash we need to bet to call.
 *
 * RETURN CODES: 
 *		(int)		How much to bet.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static int	bet( hand, score, required, need )

int			hand[];
int			score;
int			required;
int			need;

{
int			add_bet;

if ( score >= THREE )
	add_bet = BetGreatHand( required, need );
else if ( score == TWOPAIR )
	add_bet = BetTwoPair( required, need );
else if ( score == PAIR )
	add_bet = BetPair( hand, required, need );
else
	add_bet = BetNothing( hand, required, need );
return add_bet;
}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	BetNothing
 *
 * DESCRIPTION:		Bet when we have no useful hand.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		hand		 I		Our hand.
 *		required	 I		Total cash required of us during this hand.
 *		need		 I		Amount of cash we need to bet to call.
 *
 * RETURN CODES: 
 *		Amount to bet.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static int		BetNothing( hand, required, need )

int				hand[];
int				required;
int				need;

{
GAMEINFO		gi;
int				i;
int				add_bet;
int				dummy;

printf( "NOTHING\n" );
for ( i = 0; i < MAX_CARDS; i++ )
	gi.cards[i] = hand[i];
evaluate( &gi );
if ( before_draw && four_flush( hand ) != -1 )
	if ( required < 50 )
		add_bet = need + 20 + crandom( 2 ) * 10;
	else
		add_bet = need;
else if ( before_draw && possible_straight( gi, &dummy, &dummy ) )
	if ( required < 40 )
		add_bet = need + 10 + crandom( 2 ) * 10;
	else
		add_bet = need;
else if ( before_draw && need < 10 + crandom( 12 ) )
	/*
	 *	It's early yet, and it doesn't take much to stay in.  Call.
	 */
	add_bet = need;
else if ( need == 0 )
	add_bet = 0;
else
	/*
	 *	We have nothing.  Fold.
	 */
	add_bet = -1;
return add_bet;
}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	BetPair
 *
 * DESCRIPTION:		Bet when we have one pair.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		hand		 I		Our hand.
 *		required	 I		Total cash required of us during this hand.
 *		need		 I		Amount of cash we need to bet to call.
 *
 * RETURN CODES: 
 *		Amount to bet.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static int		BetPair( hand, required, need )

int				hand[];
int				required;
int				need;

{
GAMEINFO		gi;
int				i;
int				add_bet;

printf( "PAIR\n" );
/*
 *	We have one pair.
 *
 *	Never raise very much, and set a betting limit based on the
 *	rank of the pair that we have.
 *
 *	If we have four of a suit, we might end up tossing the pair and going
 *	for the flush.  In this case, the betting limit is ignored.
 */
for ( i = 0; i < MAX_CARDS; i++ )
	gi.cards[i] = hand[i];
evaluate( &gi );
if ( before_draw && four_flush( hand ) != -1 )
	{
	/*
	 *	Identical code in BetNothing.  Should be factored.
	 */
	if ( required < 50 )
		add_bet = need + 20 + crandom( 2 ) * 10;
	else
		add_bet = need;
	}
else
	{
	for ( i = 0; i < NUM_CARD_DENOMS; i++ )
		if ( gi.count[i] > 1 )
			break;
# if 0
	if ( before_draw && required > 30 )
		if ( need == 0 )
			add_bet = need;
		else
			add_bet = -1;
	else 
# endif
	if ( ( need == 0 ) || 
		 ( required < ( i/8 + 1 + before_draw ) * ( 27 + crandom( 5 ) ) ) )
		{
		add_bet = need;
		if ( required < 20 && i > 8 )
			add_bet += 10;
		}
	else
		add_bet = -1;
	}
return add_bet;
}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	BetTwoPair
 *
 * DESCRIPTION:		Bet when we have two pair.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		required	 I		Total cash required of us during this hand.
 *		need		 I		Amount of cash we need to bet to call.
 *
 * RETURN CODES: 
 *		Amount to bet.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static int		BetTwoPair( required, need )

int				required;
int				need;

{
int				add_bet;

printf( "TWO PAIR\n" );
/*
 *	If someone else is confident, then just call, otherwise raise.
 */

if ( need >= RAISE_LIMIT + 20 )
	{
	/*
	 *	2 or more other players are very confident.  Fold.
	 */
	add_bet = -1;
	}
else if ( required > 120 || need >= 30 )
	{
	/*
	 *	Getting a little rich.  Call.
	 */
	add_bet = need;
	}
else
	add_bet = need + 10 + crandom( 3 ) * 10;
return add_bet;
}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	BetGreatHand
 *
 * DESCRIPTION:		Bet when we have 3 of a kind or better.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		required	 I		Total cash required of us during this hand.
 *		need		 I		Amount of cash we need to bet to call.
 *
 * RETURN CODES: 
 *		Amount to bet.
 *
 * COMMENTS:
 *		We want to induce the other players to contribute as much cash
 *		as possible to the hand.  Unfortunately, with the present calling
 *		interface, we can't tell how much they contribute.  We can only
 *		tell how much is required of us to stay in the hand.
 *
 *		This implementation tries to adjust to changing conditions of
 *		other players by deciding between the GreatStrategy set declared
 *		at the top of this file.
 *
 **********************************************************************
 */

static int		BetGreatHand( required, need )

int				required;
int				need;

{
int				add_bet;
static int		raise = 0;

printf( "GREAT HAND!\n" );
if ( strategy == UNKNOWN )
	{
	strategy = ChooseStrategy( required, need );
	raise = 5;
	}
switch ( strategy )
	{
	case RAISE_TO_THE_LIMIT:
		add_bet = need + RAISE_LIMIT;
		/*
		 *	Other guy can fold or call and this function won't get called
		 *	again.  Figure on the average he folds 1/2 the time.
		 */
		mystake = required + RAISE_LIMIT / 2;
		break;
	case RAISE_SMALL:
		add_bet = need + ( raise = MIN( raise + 10 + crandom( 5 ), RAISE_LIMIT ) );
		mystake = required + raise / 2;
		break;
	default:
		add_bet = need + 7;		/* something is definitely wrong */
		break;
	}
return add_bet;
}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	AdjustWeights
 *
 * DESCRIPTION:		Keep track of what happened with last GreatStrategy.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *
 * RETURN CODES: 
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static void		AdjustWeights()

{
experience = MIN( ++experience, MIN_EXPERIENCE );
switch ( strategy )
	{
	case RAISE_TO_THE_LIMIT:
		hands_limit = MIN( ++hands_limit, MAX_HANDS_FOR_AVERAGE );
		expect_limit += ( mystake - expect_limit ) / hands_limit;
		printf( "stake = %d adjusting expect_limit to %.2f\n", mystake, 
				expect_limit );
		break;
	case RAISE_SMALL:
		hands_small = MIN( ++hands_small, MAX_HANDS_FOR_AVERAGE );
		expect_small += ( mystake - expect_small ) / hands_small;
		printf( "stake = %d adjusting expect_small to %.2f\n", mystake, 
				expect_small );
		break;
	default:
		printf( "Adjust for unknown strategy!\n" );
		break;
	}
}

/*
 ***********************************************************************
 *
 * FUNCTION NAME:	ChooseStrategy
 *
 * DESCRIPTION:		Choose strategy to use for betting on great hand.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *
 * RETURN CODES: 
 *		(GreatStrategy)
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static GreatStrategy	ChooseStrategy()

{
GreatStrategy			which = UNKNOWN;

/*
 *	Don't try to decide rationally before accumulating enough data.
 */
if ( experience < MIN_EXPERIENCE )
	{
	if ( crandom( 2 ) == 0 )
		{
		printf( "Randomly going to the limit\n" );
		which = RAISE_TO_THE_LIMIT;
		}
	else
		{
		printf( "Randomly raising small\n" );
		which = RAISE_SMALL;
		}
	}
else 
	{
	printf( "expect_limit = %.2f, expect_small = %.2f\n", expect_limit,
			expect_small );
	if ( crandom( (int) ( expect_small + expect_limit ) ) <= (int) expect_limit )
		{
		printf( "Going to the limit\n" );
		which = RAISE_TO_THE_LIMIT;
		}
	else
		{
		printf( "Going to raise small\n" );
		which = RAISE_SMALL;
		}
	}
return which;
}

/*
 ***********************************************************************
 *
 * FUNCTION NAME:	computer_draw
 *
 * DESCRIPTION:		Discard some cards and draw others.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		knowledge	 I		Everything we know about the current hand.
 *		me			 I		Index in knowledge[] of this robot.
 *		cmd			 O		Constructed "discard" command.
 *
 * RETURN CODES: none
 *
 * COMMENTS:
 *
 *		If the hand is nothing and we have three of one suit, try for a
 *		flush.  If we have nothing and no flush chance, toss everything
 *		under Jack.  If we have a pair, keep the high singleton if it is
 *		Ten or better.
 *
 *	HISTORY:
 *		1.	23 Nov 89		Created.
 *		2.	25 Jul 90		Changed from standard_draw().
 *		3.	27 Jul 90		Tries for straight if it has 4 in a row.
 *		4.	29 Jul 90		Only goes for flush if it already has 4.
 *		5.	18 Oct 91		May discard a pair and go for a flush if there
 *							has been any significant betting yet.
 *
 **********************************************************************
 */

void	computer_draw( KNOWLEDGE knowledge[], int me, char *cmd )

{
GAMEINFO		gi;
int				i, j;
int				high_singleton = -1;
int				ace_low = FALSE;		/* using ace low in a straight? */
int				discards, highcard, highindex;

before_draw = FALSE;
first_time_after_draw = TRUE;
try_for_straight = FALSE;
strcpy( cmd, DISCARD );
for ( i = 0; i < MAX_CARDS; i++ )
	gi.cards[i] = knowledge[me].cards[i];
evaluate( &gi );
want_suit = four_flush( knowledge[me].cards );
if ( gi.score == NOTHING || ( gi.score == PAIR && want_suit != -1 && I_have_bet > 25 ) )
	{
	/*
	 *	If we are trying for a flush, toss out cards of wrong suit.
	 */
	if ( want_suit != -1 )
		{
		for ( i = 0; i < MAX_CARDS; i++ )
			if ( suit(knowledge[me].cards[i]) != want_suit )
				sprintf( cmd, "%s:%d", cmd, i );
		}
	else
		{
		/*
		 *	Check for possible straight.  Only try if we have 4 in a row.
		 */
		
		if ( try_for_straight = possible_straight( gi, &j, &ace_low ) )
			{
			if ( ace_low )
				{
				for ( i = 0; i < MAX_CARDS; i++ )
					if ( card(knowledge[me].cards[i]) < j && card(knowledge[me].cards[i]) > 2 )
						sprintf( cmd, "%s:%d", cmd, i );
				}
			else
				{
				for ( i = 0; i < MAX_CARDS; i++ )
					if ( card(knowledge[me].cards[i]) < j || card(knowledge[me].cards[i]) > j + 3 )
						sprintf( cmd, "%s:%d", cmd, i );
				}
			}
		else
			{
			/*
			 *	Otherwise, keep highest card Jack or above.
			 */
			discards = 0;
			for ( i = 0; i < MAX_CARDS; i++ )
				if ( card(knowledge[me].cards[i]) < 9 )
					{
					sprintf( cmd, "%s:%d", cmd, i );
					knowledge[me].cards[i] = -1;
					++discards;
					}
			highcard = 0;
			if ( discards < 4 )
				for ( i = 0; i < MAX_CARDS; i++ )
					if ( knowledge[me].cards[i] != -1 && card(knowledge[me].cards[i]) > highcard )
						{
						highcard = card(knowledge[me].cards[i]);
						highindex = i;
						}
			if ( highcard != 0 )
				{
				sprintf( cmd, "%s:%d", cmd, highindex );
				}
			}
		}
	}
else if ( gi.score == PAIR )
	{
	/*
	 *	If I haven't bet much, then try to keep a high singleton and hope
	 *	for two pair.  If I have bet much, then someone else probably has
	 *	a good hand and I should go for three of a kind, so don't keep any
	 *	singletons.
	 */
	if ( I_have_bet < 30 || bluffing )
		/*
		 *	Find highest singleton, Ten or higher.
		 */
		for ( i = NUM_CARD_DENOMS - 1; high_singleton == -1 && i > 7; i-- )
			if ( gi.count[i] == 1 )
				high_singleton = i;
	/*
	 *	Toss all singletons which are not the high singleton (if any)
	 *	found above.
	 */
	for ( i = 0; i < MAX_CARDS; i++ )
		if ( gi.count[ card( knowledge[me].cards[i] ) ] == 1 && card( knowledge[me].cards[i] ) != high_singleton )
			sprintf( cmd, "%s:%d", cmd, i );
	}
else if ( gi.score < STRAIGHT )
	{
	/*
	 *	We have Two Pair or 3 of a Kind.  Toss all singletons.
	 */
	for ( i = 0; i < MAX_CARDS; i++ )
		if ( gi.count[ card( knowledge[me].cards[i] ) ] == 1 )
			sprintf( cmd, "%s:%d", cmd, i );
	}
}



/****************************************************************************/
/*	FUNCTION:	strategy_init												*/
/*																			*/
/*	PURPOSE:	Any initialization this strategy requires.					*/
/*																			*/
/*	INPUT PARAMETERS:														*/
/*		NAME		I/O		DESCRIPTION										*/
/*		----		---		-----------										*/
/*																			*/
/*	RETURNS: none															*/
/*																			*/
/*	COMMENTS:																*/
/*		Since computer_bet uses random numbers in its strategy, we must		*/
/*		here initialize the random number generator.						*/
/*																			*/
/*	HISTORY:																*/
/*		1.	25 Nov 89		Created.										*/
/*																			*/
/****************************************************************************/

void strategy_init()

{
srandom( (int) time( 0 ) ^ getpid() );
}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	four_flush
 *
 * DESCRIPTION:		Find if we have at least four of the same suit.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		hand		 I		The robot's hand.
 *
 * RETURN CODES: 
 *		(int)		Suit we want, or -1 if we're not close to a flush.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static int		four_flush( hand )

int				hand[];

	{
	int			i;
	int			want_suit = -1;
	int			have_suits[4];

	for ( i = 0; i < 4; i++ )
		have_suits[i] = 0;
	for ( i = 0; i < MAX_CARDS; i++ )
		have_suits[suit(hand[i])]++;
	for ( i = 0; i < 4; i++ )
		if ( have_suits[i] > 3 )
			break;
	if ( i < 4 )
		want_suit = i;
	return want_suit;
	}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	possible_straight
 *
 * DESCRIPTION:		Check for 4 cards in sequence.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		gi			 I		Info on the hand.
 *		start		 O		Returns starting denomination of possible straight.
 *		ace_low		 O		Returns whether or not ace must be used as low.
 *
 * RETURN CODES: 
 *		TRUE		Have four in a row.
 *		FALSE		Don't have four in a row.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

static int		possible_straight( gi, start, ace_low )

GAMEINFO		gi;
int				*start;
int				*ace_low;

	{
	int			i, j;
	int			go_for_it = FALSE;

	for ( i = 0; i < NUM_CARD_DENOMS - 3 && !go_for_it; i++ )
		if ( gi.count[i] )
			{
			for ( j = 1; j < 4 && gi.count[i+j]; j++ ) ;
			if ( j == 4 )
				{
				go_for_it = TRUE;
				j = i;
				break;
				}
			else if ( j == 3 && i == 0 && gi.count[NUM_CARD_DENOMS-1] )
				{
				go_for_it = TRUE;
				j = NUM_CARD_DENOMS-1;
				*ace_low = TRUE;
				break;
				}
			}
	*start = j;
	return go_for_it;
	}

/*
 ****************************************************************************
 *	FUNCTION:	strategy_exit
 *
 *	PURPOSE:	Called as this program exits.
 *
 *	INPUT PARAMETERS:
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *
 *	RETURNS: none
 *
 *	COMMENTS:
 *
 *	HISTORY:
 *		1.	13 Mar 93/JVE		Created.
 *
 ****************************************************************************
 */

void strategy_exit(void)

{
}

/*
 ****************************************************************************
 *	FUNCTION:	computer_hear
 *
 *	PURPOSE:	Called when someone at the table speaks.
 *
 *	INPUT PARAMETERS:
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *
 *	RETURNS: none
 *
 *	COMMENTS:
 *
 *	HISTORY:
 *		1.	13 Mar 93/JVE		Created.
 *
 ****************************************************************************
 */

void computer_hear(KNOWLEDGE knowledge[], char *from, char *text)

{
}

/*
 ****************************************************************************
 *	FUNCTION:	computer_outcome
 *
 *	PURPOSE:	Tells us the result of the hand.
 *
 *	INPUT PARAMETERS:
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *
 *	RETURNS: none
 *
 *	COMMENTS:
 *
 *	HISTORY:
 *		1.	13 Mar 93/JVE		Created.
 *
 ****************************************************************************
 */

void computer_outcome(KNOWLEDGE knowledge[], int me, int winner)

{
}
