/*
 *	File name:			strategy_observer.c
 *	Purpose:			Find patterns in the actions of the other players.
 *	Functions:			computer_bet, computer_draw, strategy_init,
 *						strategy_exit, computer_outcome, computer_hear.
 *	Created:			17 Dec 91
 *	Last Modified:		14 Sep 92
 *	Comments:
 *	History:
 *		17 Dec 91/JVE	Created.
 *		14 Sep 92/JVE	Count folds.
 */

# include	<stdio.h>
# include	<string.h>
# include	"standard.h"
# include	"cards.h"		/* for crandom, suit, card macros */
# include	"5draw.h"		/* for MAX_PLAYERS */
# include	"knowledge.h"
# include	"scores.h"
# include	"whowon.h"
# include	"robot.h"
# include	"robot_main_protos.h"
# include	"strategy_protos.h"

# define	MAX_HISTORY		1000

typedef struct
	{
	char			*name;		/* name of player */
	int				bet;		/* amount player bet in hand */
	int				score;		/* score rating of player's hand */
	int				done;		/* this record been interrogated yet? */
	} HISTORY;

static HISTORY		history[MAX_HISTORY];

static int			entries = 0;				/* # entries recorded */

int		Pot(KNOWLEDGE k[]);

extern char		*myname;

/*
 ***********************************************************************
 *
 * FUNCTION NAME:	strategy_init
 *
 * DESCRIPTION:		Any initialization needed.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *
 * RETURN CODES: 
 *		TRUE		I am ready to play.
 *		FALSE		I'm not playing, just watching.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

int		strategy_init()

	{
	/*
	 *	Initialize random number generator, initialize knowledge base,
	 *	whatever.
	 */
	return FALSE;
	}

/*
 ***********************************************************************
 *
 * FUNCTION NAME:	strategy_exit
 *
 * DESCRIPTION:		Actions to be performed on shutdown.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *
 * RETURN CODES: none
 *
 * COMMENTS:
 *
 **********************************************************************
 */

void	strategy_exit()

	{
	talk( "It's been a pleasure ... NOT!" );
	}


/*
 ***********************************************************************
 *
 * 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:
 *
 **********************************************************************
 */

int		computer_bet( knowledge, me, required )

KNOWLEDGE		knowledge[];
int				me;
int				required;

	{
	/*
	 *	Call: return required - knowledge[me].bet
	 *	Pass: return 0
	 *	Fold: return -1
	 *
	 *	If Pass/Call/Raise and you don't meet 'required' as the total for
	 *	the hand, the robot interface will force a Call.  This is because
	 *	the usual cause of the server rejecting a bet is due to raising
	 *	too many $$ or too many times during the betting session.
	 */
	return 0;
	}


/*
 ***********************************************************************
 *
 * 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:
 *
 **********************************************************************
 */

void	computer_draw( knowledge, me, cmd )

KNOWLEDGE		knowledge[];
int				me;
char			*cmd;

	{
	standard_draw( knowledge[me].cards, cmd );
	}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	computer_outcome
 *
 * DESCRIPTION:		Is informed of the outcome of each hand.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		knowledge	 I		Everything we know about the current hand.
 *		me			 I		Index in knowledge[] of this robot.
 *		winner		 I		Index in knowledge[] winning player.
 *
 * RETURN CODES: none
 *
 * COMMENTS:
 *
 **********************************************************************
 */

void	computer_outcome( knowledge, me, winner )

KNOWLEDGE		knowledge[];
int				me;
int				winner;

	{
	int			i;

	if ( entries < MAX_HISTORY )
		for ( i = 0; i < MAX_PLAYERS; i++ )
			if ( knowledge[i].valid )
				{
				history[entries].name = strdup( knowledge[i].name );
				history[entries].bet = knowledge[i].bet;
				history[entries].score = knowledge[i].score;
				history[entries].done = FALSE;
				entries++;
				}
	}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	computer_hear
 *
 * DESCRIPTION:		Listen to incoming text message.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		knowledge	 I		Everything we know about the current hand.
 *		from		 I		Who is message from?
 *		text		 I		Text of message.
 *
 * RETURN CODES: none
 *
 * COMMENTS:
 *
 **********************************************************************
 */

void	computer_hear( knowledge, from, text )

KNOWLEDGE		knowledge[];
char			*from;
char			*text;

	{
	char		*name;
	int			i, j, start, score;
	int			total[NUM_SCORES], hands[NUM_SCORES], average[NUM_SCORES];
	char		temp[MAXLINE];
	int			numfolds;

	/*
	 *	This causes the robot to exit if a message is addressed to him
	 *	containing the string "EXIT" anywhere in it.
	 *
	 *	A "dump" message causes him to tell everyone what he has observed.
	 *	You'd better run client_curses on a screen with *many* lines so
	 *	you can see everything :-)
	 */
	if ( strstr( text, myname ) != NULL )
		if ( strstr( text, "EXIT" ) != NULL )
			{
			strategy_exit();
			robot_exit();
			/*NOTREACHED*/
			}
		else if ( strstr( text, "dump" ) != NULL )
			{
			sprintf( temp, "%d entries", entries );
			talk( temp );
			talk( "" );
			for ( start = 0; start < entries; )
				{
				name = history[start].name;
				numfolds = 0;
				for ( j = NOTHING; j < NUM_SCORES; j++ )
					{
					total[j] = hands[j] = 0;
					}
				for ( i = start; i < entries; i++ )
					if ( !history[i].done && strcmp( history[i].name, name ) == 0 )
						{
						score = history[i].score;
						if ( score > FOLDED )
							{
							total[score] += history[i].bet;
							hands[score] += 1;
							average[score] = total[score] / hands[score];
							}
						else if ( score == FOLDED )
							numfolds++;
						history[i].done = TRUE;
						}
				sprintf( temp, "[%s]", name );
				talk( temp );
				for ( j = NOTHING; j < NUM_SCORES; j++ )
					{
					if ( hands[j] > 0 )
						{
						sprintf( temp, "Average bet %d for %s", average[j], scores[j] );
						talk( temp );
						}
					}
				sprintf( temp, "Folded %d times", numfolds );
				talk( temp );
				for ( ; start < entries && history[start].done; start++ ) ;
				}
			talk( "END" );
			}
	}


/*
 ***********************************************************************
 *
 * FUNCTION NAME:	Pot
 *
 * DESCRIPTION:		Compute total pot for hand.
 *
 * PARAMETERS: 
 *		NAME		I/O		DESCRIPTION
 *		----		---		-----------
 *		k			 I		knowledge of this hand.
 *
 * RETURN CODES: 
 *		(int)		The total pot.
 *
 * COMMENTS:
 *
 **********************************************************************
 */

int			Pot( KNOWLEDGE k[] )

	{
	int		i;
	int		pot = 0;

	for ( i = 0; i < MAX_PLAYERS; i++ )
		{
		if ( k[i].valid )
			{
			pot += k[i].bet;
			}
		}
	return pot;
	}
