[net.sources.games] Poker Part 2

jjv3345@ritcv.UUCP (Jeff Van Epps) (11/21/85)

: Run this script with sh, not with csh
echo x payoff.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > payoff.c
X/*
X** Add current pot to winners available cash. Tell everyone who won.
X*/
X
X# include	"players.h"
X# include	"tellall.h"
X
Xvoid	payoff( player, n_players, winner, pot )
X
XPLAYER	player[];		/* player information */
Xint	n_players;		/* number of players */
Xint	winner;			/* which player won */
Xint	pot;			/* how much $ was won */
X
X{
Xchar	temp[80];
X
Xplayer[winner].cash += pot;
Xsprintf( temp, "W%s", player[winner].name );
Xtellall( player, n_players, temp );
X}
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l payoff.c
echo x payoff.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > payoff.h
X/*
X** Pay the pot to the winner.
X*/
X
Xextern	void	payoff();
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l payoff.h
echo x players.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > players.c
X/*
X** Routines to handle players joining game and quitting.
X*/
X
X# include	"players.h"
X# include	"util.h"
X# include	"port.h"
X# include	"scores.h"
X# include	<errno.h>
X# include	<sys/types.h>
X# include	<sys/socket.h>
X# ifdef MASSCOMP
X#	include		<net/in.h>
X	typedef	unsigned long	u_long;
X# 	include		<net/misc.h>
X# else
X# 	include		<netinet/in.h>
X#	include		<sys/time.h>
X# endif
X# include	<stdio.h>
X# include	<netdb.h>
X# ifdef MASSCOMP
X	extern	char	*index();
X# else
X# 	include		<strings.h>
X# endif
X
X# define	TRUE		1
X# define	FALSE		0
X# define	ERROR		-1
X
X# define	START_CASH	200	/* amount new player starts with */
X# define	MAX_PLAYERS	5	/* max # concurrent players 	*/
X
XPLAYER	player[MAX_PLAYERS];		/* player information	*/
Xint		n_players=1;		/* computer is playing	*/
Xstatic	int	main_socket=ERROR;	/* socket to accept connections on */
X
Xvoid	new_players( player, n_players, block )
X
XPLAYER	player[];	/* array of player info structures	*/
Xint	*n_players;	/* number of players (incl comp) 	*/
Xint	block;		/* if nobody wants to join, wait on socket
X			   until somebody does. */
X
X{
Xint	readfds;		/* for select() call 	*/
Xchar	temp[80];		/* to read player's name*/
Xint	s;			/* temp holder for new socket	*/
Xint	rc;			/* # ready selected sockets */
Xint	open_sock();		/* to open main socket */
X# ifdef MASSCOMP
Xint	free_socket();		/* gets a free socket */
Xint	new_socket;		/* file descriptor of socket gotten */
X# endif
Xstruct	sockaddr_in	from;	/* connection acceptor */
Xint	fromlen = sizeof(from);
X# ifndef MASSCOMP
Xstruct	timeval	t;		/* don't let select() run forever */
X# endif
Xint	i;
X
Xif (main_socket == ERROR)
X	main_socket = open_sock();
X/* set up 1 second timeout for use on all select() calls */
X# ifndef MASSCOMP
Xt.tv_sec = 1L;
Xt.tv_usec = 0L;
X# endif
X/* see if people who were sitting out want to rejoin yet */
Xfor( i=1; i<*n_players; i++ )
X	{
X	if ( player[i].sittingout )
X		{
X		readfds = 1 << player[i].socket;
X# ifdef MASSCOMP
X		if ( select( 32, &readfds, 0, 1000 ) > 0 )	/* 1000 ms */
X# else
X		if ( select( 32, &readfds, 0, 0, &t ) > 0 )
X# endif
X			{
X			readln( player[i].socket, temp );
X			if ( temp[0] == 'S' )
X				player[i].sittingout = FALSE;
X			}
X		}
X	}
Xfor (;;)
X	{
X	readfds = 1 << main_socket;
X# ifdef MASSCOMP
X	rc = select( 32, &readfds, 0, 1000 );
X# else
X	rc = select( 32, &readfds, 0, 0, &t );
X# endif
X	if (rc > 0 || block)
X		{
X# ifdef MASSCOMP
X		if ((s = accept( main_socket, &from )) < 0 )
X# else
X		if ((s = accept( main_socket, &from, &fromlen)) < 0)
X# endif
X			{
X			perror("accept");
Xfflush(stdout);
X			break;
X			}
X		if ( *n_players >= MAX_PLAYERS )
X			{
X			writeln( s, "TOOMANY" );
X			close( s );
X			}
X		else
X			{
X			block = FALSE;
X			printf("accepted connection from ");
X# ifdef MASSCOMP
X			new_socket = free_socket();
X			socketaddr( new_socket, &from );
X			sprintf( temp, "%d", ntohs( from.sin_port ) );
X			writeln( main_socket, temp );
X			accept( new_socket, &from );
X			read( main_socket, temp, 1 );	/* eat the EOF ????? */
X			close( main_socket );
X			sleep(5);
X			main_socket = open_sock();
X			s = new_socket;
X# else
X			writeln( s, "OK" );
X# endif
X			player[*n_players].socket = s;
X			player[*n_players].cash = START_CASH;
X			player[*n_players].in = FALSE;
X			player[*n_players].wantsout = FALSE;
X			player[*n_players].sittingout = FALSE;
X			player[*n_players].lonehands = 0;
X			readln( s, temp );
X			temp[strlen( temp ) - 1] = NULL;
X			/* don't allow colons in name because of format of score file */
X			if ( index( temp, ':' ) != NULL )	
X				*index( temp, ':' ) = NULL;
X			if ( strlen( temp ) > 25 )
X				temp[25] = NULL;
X			player[*n_players].name = strsave( temp );
X			printf("%s\n",temp);
X			fflush(stdout);
X			readln( s, temp );
X			player[*n_players].userid = atoi( temp );
X			if ( played_before( player[*n_players].name, player[*n_players].userid ) )
X				player[*n_players].cash = get_cash();
X			(*n_players)++;
X			break;
X			}
X		}
X	else
X		break;
X	}
X}
X
Xvoid	leave( player, n_players )
X
XPLAYER	player[];
Xint	*n_players;
X
X{
Xregister int	i;
X
Xfor( i=1; i<*n_players; i++)
X	if (player[i].wantsout)
X		{
X		writeln( player[i].socket, "Q" );
X		put_cash( player[i].name, player[i].userid, player[i].cash );
X		high_score_list( player[i].socket );
X		close( player[i].socket );
X		free( player[i].name );
X		player[i] = player[*n_players - 1];
X		(*n_players)--;
X		--i;		/* since this entry is new, test again */
X		}
X}
X/* Open the main socket. */
X
Xint	open_sock()
X
X{
Xint	s;
Xstruct	sockaddr_in	sockaddr;
Xstruct	hostent		*host;
X
X# ifdef MASSCOMP
X	sockaddr.sin_family = AF_INET;
X	sockaddr.sin_port = htons( PORT );
X	if ((host = gethostbyname( HOST )) == NULL)
X		{
X		perror( "gethostbyname" );
X		exit(1);
X		}
X	sockaddr.sin_addr.s_addr = *(u_long *) host->h_addr;
X	s = socket( SOCK_STREAM, 0, &sockaddr, SO_ACCEPTCONN );
X# else
X	s = socket( AF_INET, SOCK_STREAM, 0 );
X# endif
Xif (s < 0)
X	{
X	perror("open_sock");
X	exit(1);
X	}
X# ifndef MASSCOMP
Xsockaddr.sin_family = AF_INET;
Xsockaddr.sin_port = htons( PORT );
Xif (bind( s, &sockaddr, sizeof(sockaddr)) < 0)
X	{
X	perror("bind");
X	exit(1);
X	}
Xif (listen( s, 0 ) < 0)
X	{
X	perror("listen");
X	exit(1);
X	}
X# endif
Xreturn( s );
X}
X
Xvoid	crash()
X
X{
Xint	i;
X
Xfor(i=0; i<32; i++)
X	close(i);
Xexit(9);
X}
X
X# ifdef MASSCOMP
X
X/* accept() does not allocate a new socket on the Masscomps. Therefore we
X** have to grab our own new socket and tell the client where it is.
X*/
X
Xfree_socket()
X
X{
Xint	s;
X
Xif ( ( s = socket( SOCK_STREAM, 0, 0, SO_ACCEPTCONN ) ) < 0 )
X	{
X	perror( "free_socket" );
X	crash();
X	}
Xreturn( s );
X}
X
X# endif
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l players.c
echo x players.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > players.h
X/*
X** A structure is maintained with information on each player.
X*/
X
Xtypedef struct _player {
X	char	*name;		/* Player's name 	*/
X	int	userid;		/* player's user id number	*/
X	int	cash;		/* Amount of money player currently has */
X	int	cards[5];	/* Player's current hand (indexes into deck[]) */
X	int	score;		/* PAIR, THREE, FLUSH, etc.	*/
X	int	count[13];	/* counters used to determine score */
X	int	in;		/* Still in current hand?	*/
X	int	wantsout;	/* Quit after this hand?	*/
X	int	sittingout;	/* Sit out after this hand?	*/
X	int	bet;		/* How much bet into current pot*/
X	int	lonehands;	/* # hands played against only computer */
X	int	socket;		/* To communicate with player on*/
X	} PLAYER;
X
Xextern	PLAYER	player[];
X
Xextern	int	n_players;	/* current number of players (including computer) */
X
Xextern	void	new_players(),leave(),crash();
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l players.h
echo x poker.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > poker.c
X# include	"util.h"
X# include	"port.h"
X# include	"limits.h"
X# include	<sys/types.h>
X# include	<sys/socket.h>
X# ifdef MASSCOMP
X# 	include		<net/in.h>
X	typedef	unsigned long	u_long;
X#	include		<net/misc.h>
X# else
X# 	include		<netinet/in.h>
X# endif
X# include	<netdb.h>
X# include	<stdio.h>
X# include	<curses.h>
X# include	<ctype.h>
X# include	<signal.h>
X
Xint	s;	/* the socket */
X
Xmain( argc, argv, envp )
X
Xint	argc;
Xchar	**argv;
Xchar	**envp;
X
X{
Xstruct	sockaddr_in	sockaddr;
Xstruct	hostent		*host;
Xchar	*getenv();
Xchar	*name;
Xchar	temp[80];
Xextern	int	getuid();
Xvoid	closem();
X
X# ifdef MASSCOMP
X	s = socket( SOCK_STREAM, 0, 0, 0 );
X# else
X	s = socket( AF_INET, SOCK_STREAM, 0 );
X# endif
Xif (s < 0) 
X	{
X	perror( "socket" );
X	exit(1);
X	}
Xif ((host = gethostbyname( (argc > 1) ? argv[1] : HOST )) == NULL)
X	{
X	perror( "gethostbyname" );
X	exit(1);
X	}
Xsockaddr.sin_family = AF_INET;
Xsockaddr.sin_port = htons( PORT );
Xsockaddr.sin_addr.s_addr = *(u_long *) host->h_addr;
Xprintf( "Waiting for last hand to finish ... " );
Xfflush(stdout);
Xsignal( SIGINT, closem );
Xsignal( SIGQUIT, closem );
X# ifdef MASSCOMP
Xif ( connect( s, &sockaddr ) < 0 )
X# else
Xif ( connect( s, &sockaddr, sizeof(sockaddr) ) < 0)
X# endif
X	{
X	perror( "connect" );
X	exit(1);
X	}
Xreadln( s, temp );
Xif ( strcmp( temp, "TOOMANY\n" ) == 0 )
X	printf( "Table Full!\n" );
Xelse
X	{
X	if ( strcmp( temp, "OK\n" ) != 0 )	/* must go to another socket */
X		{
X		close( s );
X		sockaddr.sin_port = htons( atoi( temp ) );
X# ifdef MASSCOMP
X		s = socket( SOCK_STREAM, 0, 0, 0 );
X		if ( s < 0 )
X			perror("damn socket");
X		if ( connect( s, &sockaddr ) < 0 )
X# else
X		s = socket( AF_INET, SOCK_STREAM, 0 );
X		if ( connect( s, &sockaddr, sizeof(sockaddr) ) < 0 )
X# endif
X			{
X			perror( "second connect" );
X			exit( 1 );
X			}
X		}
X	signal( SIGINT, SIG_IGN );
X	signal( SIGQUIT, SIG_IGN );
X	if ( ( name = getenv( "POKER" ) ) == NULL )
X		if ( ( name = getenv( "NAME" ) ) == NULL )
X			name = getenv( "USER" );
X	writeln( s, name );
X	sprintf( temp, "%d", getuid() );
X	writeln( s, temp );
X	play( s );
X	readln( s, temp );
X	while( temp[0] != ':' )
X		{
X		printf( "%s", temp );
X		readln( s, temp ); 
X		}
X	}
Xclose(s);
Xexit(0);
X}
X
X
X/* 
X** Listen to poker daemon and update the screen as it says. These are the
X** commands from the daemon to this program:
X**
X**	Nn	name of player n
X**	Cn	cards for player n
X**	P	pot value
X**	U	update screen
X**	X	clear screen
X**	Hn	action for player n (fold, raise, call, etc.)
X**	Rn	result for player n (straight, two pair, --fold--, etc.)
X**	Bn	total amount bet by player n this hand
X**	$n	amount of cash player n has
X**	D	get discards from this player
X**	?	get bet from this player - amount to call follows
X** 	Q	player has quit; cleanup & terminate
X**	W	player name following has won this hand
X**	T	tells which player's turn it is; cursor is put next to his name
X**	M	message to print on bottom of screen
X**
X**
X** These are the commands from this program to the daemon:
X**
X**	Q	quit after this hand is finished
X**	F	fold
X**	Dxxxxx	discard these cards (k=keep,d=discard)
X**	C	call
X**	Rxx	raise by this amount
X**	P	pass - not allowed if player has to call someone else's raise
X**	S	toggles sitting out switch
X**
X*/
X
Xplay( s )
X
Xint	s;		/* socket we communicate upon */
X
X{
Xchar	temp[80];	/* buffer to read command into */
Xchar	temp2[80];	/* outgoing commands are sometimes built here */
Xint	n;		/* determine which player we're talking about */
Xint	minimum;	/* minimum bet to stay in */
Xchar	c;		/* player's command */
Xint	done;		/* get commands until something valid */
Xint	quit=FALSE;	/* has player quit yet? */
Xint	out=FALSE;	/* is player sitting out? */
Xchar	cards[20];	/* hold player's current hand */
Xvoid	mygetstr();	/* because curses getstr() doesn't work */
Xint	i,x;
Xint	oldx=0,oldy=0;	/* markers for current player cursor */
X
Xinitscr();
Xnoecho(); crmode();
Xleaveok( stdscr, FALSE );
Xwhile ( !quit )
X	{
X	readln( s, temp );
X	n = temp[1] - '0';	/* which player? */
X	switch ( temp[0] ) {
X		case 'M' :
X				mvaddstr( 15, 40, temp+1 );
X				refresh();
X				break;
X		case 'N' :
X				mvaddstr( n*2, 4, temp+2 );
X				break;
X		case 'T' :
X				mvaddstr( oldy, oldx, "    " );
X				mvaddstr( n*2, 0, "--> " );
X				oldy = n * 2;
X				oldx = 0;
X				refresh();
X				break;
X		case 'C' :
X				mvaddstr( n*2, 35, temp+2 );
X				strcpy( cards, temp+2 );
X				break;
X		case 'U' :
X				move( 0, 0 );
X				refresh();
X				break;
X		case 'X' :
X				clear();
X				mvaddstr( 14, 4, "C) Call last raise" );
X				mvaddstr( 15, 4, "F) Fold this hand" );
X				mvaddstr( 16, 4, "P) Pass (Check)" );
X				mvaddstr( 17, 4, "Q) Quit after this hand" );
X				mvaddstr( 18, 4, "R) Raise last bet" );
X				mvaddstr( 19, 4, "S) Sit out for a while" );
X				break;
X		case 'P' :
X				move( LINES-1, 4 );
X				printw( "Pot: %-6d ", atoi( temp + 1 ) );
X				break;
X		case 'B' :
X				move( n*2+1, 6 );
X				printw( "Bet: %-6d ", atoi( temp + 2 ) );
X				break;
X		case 'H' :
X				mvaddstr( n*2+1, 35, temp+2 );
X				break;
X		case 'R' :
X				mvaddstr( n*2, 60, temp+2 );
X				break;
X		case '$' :
X				move( n*2+1, 18 );
X				printw( "Cash: %-6d ", atoi( temp + 2 ) );
X				break;
X		case 'Q' :
X				endwin();
X				quit = TRUE;
X				break;
X		case 'W' :
X				move( LINES-2, 20 );
X				temp[strlen( temp ) - 1] = NULL;	/* strip newline */
X				printw( "%s wins this hand! --more-- ", temp+1 );
X				refresh();
X				while( getch() != ' ' ) ;
X				if ( out )
X					{
X					move( LINES-2, 20 );
X					clrtoeol();
X					printw( "Hit space to come back--" );
X					refresh();
X					while( getch() != ' ' ) ;
X					printw( "waiting..." );
X					refresh();
X					writeln( s, "S" );
X					out = FALSE;
X					}
X				break;
X		case 'D' :
X				/* find out what player wants to discard */
X				move( 14, 25 );
X				clrtoeol();
X				mvaddstr( 14, 40, "Discard: " );
X				refresh();
X				mygetstr( temp );
X				i = 0;
X				strcpy( temp2, "Dkkkkk" );
X				while( temp[i] != NULL )
X					{
X					if ( isdigit( temp[i] ) )
X						{
X						x = temp[i] - '0';
X						if ( x > 0 && x < 6 )
X							temp2[x] = 'd';
X						}
X					i++;
X					}
X				writeln( s, temp2 );
X				break;
X		case '?' :
X				/* time to let player bet on this hand */
X				minimum = atoi( temp + 1 );
X				done = FALSE;
X				move( 14, 25 );
X				clrtoeol();
X				while ( !done )
X					{
X					mvaddstr( 14, 25, "Bet: " );
X					refresh();
X					while( (c = getch()) == '\014' )
X						wrefresh( curscr );
X					if ( islower( c ) )
X						c = toupper( c );
X					done = TRUE;
X					switch (c)  {
X						case 'Q' :
X							done = FALSE;
X							mvaddstr( LINES-1, 50, "Quitting." );
X						case 'C' :
X							if ( c == 'C' && minimum == 0 )
X								{
X								mvaddstr( 14, 35, "No raise to call; pass or raise." );
X								refresh();
X								done = FALSE;
X								break;
X								}
X						case 'F' :
X							sprintf( temp, "%c", c );
X							writeln( s, temp );
X							break;
X						case 'S' :
X							done = FALSE;
X							out = TRUE;
X							writeln( s, "S" );
X							mvaddstr( LINES-1, 30, "Sitting out." );
X							break;
X						case 'P' :
X							if ( minimum > 0 )
X								{
X								mvaddstr( 14, 35, "Can't pass; meet last raise or fold." );
X								refresh();
X								done = FALSE;
X								}
X							else
X								writeln( s, "P" );
X							break;
X						case 'R' :
X							strcpy( temp, "0" );
X							while ( atoi( temp ) <= 0 )
X								{
X								move( 15, 25 );
X								printw( "%15.15s", " " );
X								mvaddstr( 15, 25, "Raise: " );
X								refresh();
X								mygetstr( temp );
X								if ( atoi( temp ) > RAISE_LIMIT )
X									{
X									move( 15, 40 );
X									printw( "Raise limit = %d.", RAISE_LIMIT );
X									strcpy( temp, "0" );
X									}
X								}
X							minimum = atoi( temp );
X							sprintf( temp, "R%d", minimum );
X							writeln( s, temp );
X							break;
X						default:
X							done = FALSE;
X							/* try again */
X							break;
X						}
X					}
X				break;
X		default:
X			/* ignore unknown commands */
X				break;
X		}
X	}
Xprintf("\n\n\n");
X}
X
Xvoid	mygetstr( str )
X
Xchar	*str;
X
X{
Xint	i=0,x,y;
Xchar	c;
X
Xgetyx( stdscr, y, x );
Xwhile ( ( c = getch() ) != '\n' )
X	if ( c == '\b' && i > 0 )
X		{
X		move( y, --x );
X		refresh();
X		--i;
X		}
X	else if ( c == '\014' )
X		wrefresh( curscr );
X	else 
X		{
X		str[i++] = c;
X		addch( c );
X		refresh();
X		x++;
X		}
Xstr[i] = NULL;
X}
X
Xvoid	closem()
X
X{
Xclose( s );
Xexit( 1 );
X}
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l poker.c
echo x port.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > port.h
X/*
X** Port for POKER.
X*/
X
X# define	PORT		55142
X# define	HOST		"ritcv"
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l port.h
echo x scores.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > scores.c
X/*
X**	Maintain players' cash from one play to the next.
X**	Money is stored according to NAME. Thus if a player plays on different
X**	systems, he's still playing with the same cash. Also note that if a
X**	player changes his name, he starts anew with START_CASH.
X**	Userid is also now included, so that someone can not "steal" another
X**	player's cash by usurping his name temporarily.
X*/
X
X# include	"scores.h"
X# include	<stdio.h>
X# ifdef MASSCOMP
X#	include		<sys/types.h>
X	char		*index();
X# else
X# 	include		<strings.h>
X# endif
X# ifdef MASSCOMP
X#	include		<fcntl.h>
X# else
X# 	include		<sys/file.h>
X# endif
X
X# define	SCORE_FILE	"/a2/s11/jjv3345/POKERSCORES"
X# define	TRUE		1
X# define	FALSE		0
X
Xstatic	int	scores=(-1);	/* file channel for scores	*/
Xstatic	char	temp[81];
X
Xplayed_before( name, id )
X
Xchar	*name;		/* player's name to search for	*/
Xint	id;
X
X{
Xint	found=FALSE;
Xchar	*p;
X
Xif ( scores == -1 )
X	if ( ( scores = open( SCORE_FILE, O_RDWR, 0 ) ) == -1 )
X		{
X		perror( SCORE_FILE );
X		return( FALSE );
X		}
Xlseek( scores, 0, 0 );
Xwhile( read( scores, temp, 80 ) == 80 )
X	if ( strncmp( temp, name, (p = index( temp, ':' )) - temp ) == 0 && atoi( p + 1 ) == id )
X		{
X		found = TRUE;
X		break;
X		}
Xreturn( found );
X}
X
X
Xget_cash()
X
X{
Xreturn( atoi( index( index( temp, ':' ) + 1, ':' ) + 1 ) );
X}
X
X
Xvoid	put_cash( name, id, cash )
X
Xchar	*name;		/* player's name	*/
Xint	id;		/* player's userid	*/
Xint	cash;		/* how much dough he had*/
X
X{
Xint	found=FALSE;
Xchar	*p;
Xchar	idstr[10];
X
Xlseek( scores, 0, 0 );
Xwhile( read( scores, temp, 80 ) == 80 )
X	if ( strncmp( temp, name, (p = index( temp, ':' )) - temp ) == 0 && atoi( p + 1 ) == id )
X		{
X		found = TRUE;
X		break;
X		}
Xif ( found )
X	lseek( scores, -80, 1 );
Xsprintf( idstr, "%d", id );
Xsprintf( temp, "%s:%s:%-*d\n", name, idstr, 77 - strlen( name ) - strlen( idstr) , cash );
Xwrite( scores, temp, 80 );
X}
X
Xvoid	high_score_list( s )
X
Xint	s;		/* player's socket	*/
X
X{
Xstruct	stuff	{
X	char	name[30];
X	int	score;
X	struct	stuff	*next;
X	} *head, *ptr, *tempptr, *last;
Xint	l;
Xint	num;
Xint	score;
Xchar	name[30];
Xchar	output[80];
X
Xhead = NULL;
Xlseek( scores, 0, 0 );
Xwriteln( s, "HIGH SCORE LIST" );
Xwriteln( s, "=====================================" );
Xwhile( read( scores, temp, 80 ) == 80 )
X	{
X	strncpy( name, temp, l = ( index( temp, ':' ) - temp ) );
X	name[l] = NULL;
X	score = get_cash();
X	ptr = head;
X	last = NULL;
X	while( ptr != NULL && ptr->score > score )
X		{
X		last = ptr;
X		ptr = ptr->next;
X		}
X	if ( head == NULL )
X		{
X		head = (struct stuff *) malloc( sizeof(struct stuff) );
X		ptr = head;
X		ptr->next = NULL;
X		}
X	else if ( ptr == head )
X		{
X		head = (struct stuff *) malloc( sizeof(struct stuff) );
X		head->next = ptr;
X		ptr = head;
X		}
X	else
X		{
X		tempptr = ptr;
X		ptr = last;
X		ptr->next = (struct stuff *) malloc( sizeof(struct stuff) );
X		ptr->next->next = tempptr;
X		ptr = ptr->next;
X		}
X	strcpy( ptr->name, name );
X	ptr->score = score;
X	}
Xnum = 0;
Xptr = head;
Xwhile( num++ < 10 && ptr != NULL )
X	{
X	sprintf( output, "%6d %-30s", ptr->score, ptr->name );
X	writeln( s, output );
X	ptr = ptr->next;
X	}
Xwriteln( s, ":" );	/* tell client that we are truly finished */
Xptr = head;
Xwhile( ptr != NULL )
X	{
X	tempptr = ptr->next;
X	free( ptr );
X	ptr = tempptr;
X	}
X}
X
X# ifdef MASSCOMP	/* should be in library somewhere, but where? */
X
Xchar	*index( str, ch )
X
Xchar	*str;		/* string to search in */
Xchar	ch;		/* character to look for */
X
X{
Xwhile( *str != NULL && *str != ch )
X	str++;
Xreturn( (*str == NULL) ? NULL : str );
X}
X
X# endif
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l scores.c
echo x scores.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > scores.h
X/*
X**	Maintain players' cash from one play to the next.
X*/
X
Xextern	int	played_before(), get_cash();
Xextern	void	put_cash(), high_score_list();
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l scores.h
echo x showcards.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > showcards.c
X/*
X** Tell each player everybody's name. Show each player only his own cards.
X*/
X
X# include	"showcards.h"
X# include	"players.h"
X# include	"cards.h"
X# include	"util.h"
X
Xvoid	show_cards( player, n_players, all, test )
X
XPLAYER	player[];		/* all player info */
Xint	n_players;		/* # active players */
Xint	all;			/* TRUE=show everybody's cards who is still in
X				   FALSE=show only player's cards to himself */
Xint	test;			/* show all cards whether in or out */
X				/* only used if 'all' is TRUE */
X
X{
Xint	i,j,k;
Xchar	temp[10];
Xvoid	show();
X
Xfor(i=1; i<n_players; i++)	/* don't show cards to computer */
X	if ( player[i].bet >= 0 )	/* if sitting out, be quiet */
X		{
X		for( j=0; j<n_players; j++ )	/* tell player everyone's name */
X			{
X			sprintf( temp, "N%d", j );
X			write( player[i].socket, temp, 2 );
X			writeln( player[i].socket, player[j].name );
X			}
X		if ( all )
X			{
X			for( k=0; k<n_players; k++ )
X				if ( test || player[k].in )
X					show( player, temp, k, i );
X			}
X		else
X			show( player, temp, i, i );
X		writeln( player[i].socket, "U" );	/* update screen command */
X		}
X}
X
Xvoid show( player, temp, i, j )
X
XPLAYER	player[];
Xchar	temp[];
Xint	i;		/* whose cards to show */
Xint	j;		/* who to show them to */
X
X{
Xint	c;
X
Xsprintf( temp, "C%d", i );		/* cards for player i */
Xwrite( player[j].socket, temp, 2 );
Xfor(c=0; c<5; c++)
X	{
X	sprintf( temp, "%c%c ", rank(player[i].cards[c]), color(player[i].cards[c]));
X	write( player[j].socket, temp, 3 );
X	}
Xwrite( player[j].socket, "\n", 1 );
X}
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l showcards.c
echo x showcards.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > showcards.h
X/*
X** Routine which shows each player his or everybody's cards. 
X*/
X
Xextern	void	show_cards();
Xextern	void	show();
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l showcards.h
echo x tellall.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > tellall.c
X/*
X** Send everyone a message.
X*/
X
X# include	"tellall.h"
X# include	"util.h"
X# include	"players.h"
X
Xvoid	tellall( player, n_players, msg )
X
XPLAYER	player[];		/* all player info */
Xint	n_players;		/* # of players */
Xchar	*msg;			/* message to send */
X
X{
Xint	i;
X
Xfor( i=1; i<n_players; i++ )	/* don't send any messages to the computer */
X	if ( player[i].bet != -1 )	/* no messages to anyone sitting out */
X		writeln( player[i].socket, msg );
X}
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l tellall.c
echo x tellall.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > tellall.h
X/*
X** Send everyone a message.
X*/
X
Xextern	void	tellall();
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l tellall.h
echo x util.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > util.c
X/*
X** Various utility routines. 
X*/
X
X# include	<stdio.h>
X# include	"util.h"
X
Xchar	*strsave( temp )
X
Xchar	*temp;
X
X{
Xchar	*p;
Xextern	char	*malloc();
X
Xp = malloc( strlen(temp) + 1 );
Xstrcpy( p, temp );
Xreturn( p );
X}
X
Xint	readln( s, temp )
X
Xint	s;		/* fd to read from	*/
Xchar	*temp;		/* area to read into	*/
X
X{
Xdo {
X	if (read( s, temp, 1) < 1)
X		return(0);
X   }
Xwhile( *temp++ != '\n');
X*temp = NULL;
X}
X
Xwriteln( s, temp )
X
Xint	s;		/* channel to write on	*/
Xchar	*temp;		/* what to write	*/
X
X{
Xwrite( s, temp, strlen( temp ) );
Xwrite( s, "\n", 1 );
X}
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l util.c
echo x util.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > util.h
X/*
X** Various utility routines.
X*/
X
Xextern	char	*strsave();
Xextern	int	readln();
Xextern	int	writeln();
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l util.h
echo x whowon.c
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > whowon.c
X/*
X** Figure out who wins.
X*/
X
X# include	<stdio.h>
X# include	"whowon.h"
X# include	"players.h"
X# include	"cards.h"
X# include	"showcards.h"
X# include	"tellall.h"
X
X# define	TRUE		1
X# define	FALSE		0
X
Xstatic	char	*scores[] = {
X	"Nothing", "Pair", "Two Pair", "Three of a kind", "Straight", "Flush", 
X	"Full House", "Four of a kind", "Straight Flush", "Royal Flush" };
X
Xint	whowon( player, n_players, test )
X
XPLAYER	player[];		/* all player information */
Xint	n_players;		/* number of players */
Xint	test;			/* show all cards regardless */
X
X{
Xint	i;
Xint	max=(-1);		/* highest score */
Xint	winner=0;		/* which player won */
Xchar	temp[80];		/* tell everybody what everybody has */
Xvoid	evaluate(),tie();
X
Xshow_cards( player, n_players, TRUE, test );	/* show all hands everywhere */
Xfor( i=0; i<n_players; i++ )
X	if ( test || player[i].in )
X		{
X		evaluate( player, i );
X		sprintf( temp, "R%d%s", i, scores[player[i].score] );
X		tellall( player, n_players, temp );
X		if ( player[i].in && player[i].score > max )
X			{
X			max = player[i].score;
X			winner = i;
X			}
X		else if ( player[i].in && player[i].score == max )
X			{
X			tie( player, &winner, i );
X			}
X		}
Xreturn( winner );
X}
X
Xstatic	void	tie( player, winner, which )
X
XPLAYER	player[];		/* all hands on deck */
Xint	*winner;		/* may have to set new winner */
Xint	which;			/* which player is challenging the winner */
X
X{
Xint	top1,top2;
Xint	i;
Xint	done=FALSE;
Xint	oldwinner;
X
Xoldwinner = *winner;
Xwhile( !done )
X	{
X	top1 = top2 = -1;
X	for( i=12; i>=0; i-- )
X		{
X		if ( top1 == -1 || player[which].count[i] > player[which].count[top1] )
X			top1 = i;
X		if ( top2 == -1 || player[*winner].count[i] > player[*winner].count[top2] )
X			top2 = i;
X		}
X	if ( top1 != top2 )
X		{
X		if ( top1 > top2 )
X			*winner = which;
X		done = TRUE;
X		}
X	else if ( player[which].count[top1] == 0 )	/* OH, NO! */
X		{
X		printf( "tie() failed to resolve - details follow\n" );
X		for( i=0; i<5; i++ )
X			printf( "%c%c ", rank(player[which].cards[i]), color(player[which].cards[i]) );
X		for( i=0; i<5; i++ )
X			printf( "%c%c ", rank(player[*winner].cards[i]), color(player[*winner].cards[i]) );
X		fflush( stdout );
X		done = TRUE;
X		}
X	else
X		{
X		player[which].count[top1] = 0;
X		player[*winner].count[top2] = 0;
X		}
X	}
X/* re-evaluate hands because counts have been messed ... */
Xevaluate( player, oldwinner );
Xevaluate( player, which );
X}
X
Xvoid	evaluate( player, which )
X
XPLAYER	player[];
Xint	which;			/* which player's hand to evaluate */
X
X{
Xint	kind[6];
Xint	i,j;
X
Xfor( i=0; i<13; i++ )
X	player[which].count[i] = 0;
Xfor( i=0; i<5; i++ )
X	player[which].count[card(player[which].cards[i])] ++ ;
Xfor( i=0; i<6; i++ )
X	kind[i] = 0;
Xfor( i=0; i<13; i++ )
X	kind[player[which].count[i]] ++ ;
Xif ( kind[4] )
X	player[which].score = FOUR;
Xelse if ( kind[3] && kind[2] )
X	player[which].score = FULL;
Xelse if ( kind[3] )
X	player[which].score = THREE;
Xelse if ( kind[2] == 2 )
X	player[which].score = TWOPAIR;
Xelse if ( kind[2] )
X	player[which].score = PAIR;
Xelse 
X	player[which].score = NOTHING;
Xif ( player[which].score == NOTHING )
X	{
X	for( i=1; i<5; i++ )
X		if ( suit(player[which].cards[i]) != suit(player[which].cards[0] ) )
X			break;
X	if ( i == 5 )
X		player[which].score = FLUSH;
X	i = -1;
X	while( player[which].count[++i] == 0 ) ;
X	j = i;
X	while( ++i < 13 && player[which].count[i] == 1 ) ;
X	/* trash below is for A-5 straights */
X	if ( i - j == 5 || ((i == 4) && (j == 0) && (player[which].count[12] == 1)) )
X		if ( player[which].score == FLUSH )
X			player[which].score = STRAIGHT_FLUSH;
X		else
X			player[which].score = STRAIGHT;
X	if ( player[which].score == STRAIGHT_FLUSH && i == 13 )
X		player[which].score = ROYAL_FLUSH;
X	}
X}
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l whowon.c
echo x whowon.h
sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > whowon.h
X/*
X** Evaluate the hands of everyone who is still in, then return winner.
X*/
X
Xextern	int	whowon();
Xextern	void	evaluate();
X
X# define	NOTHING		0
X# define	PAIR		1
X# define	TWOPAIR		2
X# define	THREE		3
X# define	STRAIGHT	4
X# define	FLUSH		5
X# define	FULL		6
X# define	FOUR		7
X# define	STRAIGHT_FLUSH	8
X# define	ROYAL_FLUSH	9
X
PaRtIcUlAtEmAtTeR
echo -n '	'
ls -l whowon.h