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