jjv3345@ritcv.UUCP (Jeff Van Epps) (11/21/85)
: Run this script with sh, not with csh echo x README sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > README X XInstallation Instructions for Poker: X XSave the shar file in "SHAR". Edit out the mail headers. Xmkdir pokerdir Xmv SHAR pokerdir Xcd pokerdir Xsh SHAR X XThis creates a bunch of source files and a Makefile. XEdit "port.h" and enter the HOST which the daemon will be running on Xand a free Internet PORT number. XThis way a game can span several machines. Edit "scores.c" and enter Xa pathname where the score file can be placed. Xmake pokerd ; make poker Xchmod 711 pokerd ; chmod u+s pokerd X"pokerd" is the daemon, which must be running in order for anyone Xto play. Start it with Xpokerd >log & or pokerd >/dev/null & X"poker" is the user interface, so chmod 711 poker (&tell people Xthe path to it). X XWhat happens when the user types "poker"? XIf the daemon can't be reached, "Connection refused.", else it Xwaits for the hand currently being played (if any) to finish. XThen, if there are <4 people already playing, the new player Xwill be dealt in. If the maximum player limit is already Xreached, the new player is ignored until someone quits ("TABLE FULL"). XIf someone starts "poker", then kills the process, the daemon Xwill become confused and crash. "poker" therefore disables BREAK. X X XScore Info: X XThe player's NAME from his environment and his userid are combined Xwhen searching the stored scores. If POKER is defined, it is used Xinstead of NAME. Scores are kept when a player quits Xand restored when next he plays. If NAME is not set, USER is used. X X XMisc: X XWhen asked for Discard:, enter 134 to throw away the first, third, and Xfourth cards, (i.e. the index of the card in your hand). You may discard Xfrom 0 to 5 cards. X^L will redraw the screen. XSitting out and quitting both do not take effect until AFTER the current Xhand is finished. X X X XBugs: X XIt will wait forever for someone to respond; this can irritate other Xplayers. XSometimes crashes when a client is killed. XComputer is too easy to beat. XA player can get in twice on different terminals; then whichever of him Xquits last is the score that is saved. X X X XDisclaimers: X XWarranty? What warranty? XPlease excuse the low quality of this "documentation". XIt is being written hastily and late at night. X X X XComplaint Department: X Xrochester!ritcv!jjv3345 X X X"A blurry-eyed hacker is a happy hacker!" X PaRtIcUlAtEmAtTeR echo -n ' ' ls -l README echo x Makefile sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > Makefile XSRCS= main.c players.c cards.c util.c showcards.c whowon.c poker.c tellall.c payoff.c betting.c computer.c draw.c scores.c XOBJS= main.o players.o cards.o util.o showcards.o whowon.o tellall.o payoff.o betting.o computer.o draw.o scores.o XOBJS2= poker.o util.o X X# define the type of system programs are being made on X# currently this is only important for MASSCOMP machines because some X# socket routine calls and include files are different than 4.2BSD X#CFLAGS= -DMASSCOMP XCFLAGS= -DVAX X Xpokerd: $(OBJS) X# cc $(OBJS) -lsocket -o pokerd X cc $(OBJS) -o pokerd X Xpoker: $(OBJS2) X# cc $(OBJS2) -lcurses -ltermlib -lsocket -o poker X cc $(OBJS2) -lcurses -ltermlib -o poker X Xlistings: X lpr $(SRCS) X X# This 'target' simply makes a new Makefile (after saving the current one X# in Makefile.old) with added dependencies for header files included X# in the listed source files. Xdepend: X mv Makefile Makefile.old X sed -n '1,/^# DO NOT REMOVE THIS LINE/p' Makefile.old > Makefile X grep '^#[ ]*include[ ]*["]' $(SRCS) | \ X sed -e 's/\.[^:]*:#[ ]*include[ ]*/.o: /' \ X -e 's/"\([^"]*\)".*/\1/' \ X -e 's@<\([^>]*\)>.*@/usr/include/\1@' >> Makefile X X# Lines after this block of comments are replace every time the new dependency X# information is created using 'make depend'. The next line is crucial. X# DO NOT REMOVE THIS LINE Xmain.o: cards.h Xmain.o: players.h Xmain.o: betting.h Xmain.o: draw.h Xmain.o: whowon.h Xmain.o: payoff.h Xmain.o: showcards.h Xmain.o: util.h Xmain.o: tellall.h Xmain.o: limits.h Xplayers.o: players.h Xplayers.o: util.h Xplayers.o: port.h Xplayers.o: scores.h Xcards.o: cards.h Xutil.o: util.h Xshowcards.o: showcards.h Xshowcards.o: players.h Xshowcards.o: cards.h Xshowcards.o: util.h Xwhowon.o: whowon.h Xwhowon.o: players.h Xwhowon.o: cards.h Xwhowon.o: showcards.h Xwhowon.o: tellall.h Xpoker.o: util.h Xpoker.o: port.h Xpoker.o: limits.h Xtellall.o: tellall.h Xtellall.o: util.h Xtellall.o: players.h Xpayoff.o: players.h Xpayoff.o: tellall.h Xbetting.o: betting.h Xbetting.o: players.h Xbetting.o: computer.h Xcomputer.o: computer.h Xcomputer.o: players.h Xcomputer.o: cards.h Xcomputer.o: whowon.h Xcomputer.o: limits.h Xdraw.o: draw.h Xdraw.o: players.h Xdraw.o: showcards.h Xdraw.o: tellall.h Xscores.o: scores.h PaRtIcUlAtEmAtTeR echo -n ' ' ls -l Makefile echo x betting.c sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > betting.c X/* X** Handle all the betting being done. X*/ X X# include <stdio.h> X# include "betting.h" X# include "players.h" X# include "computer.h" X X# define TRUE 1 X# define FALSE 0 X Xint betting( player, n_players, pot, first ) X XPLAYER player[]; /* all player information */ Xint n_players; /* # of players */ Xint *pot; /* current pot */ Xint first; /* player who gets to bet first */ X X{ Xint last_raiser=(-1); /* player who made last raise */ Xint n_active=0; /* # players active in betting (haven't folded) */ Xint n_raises=0; /* # of raises this hand so far */ Xint j=(-1); /* player currently betting */ Xint i; Xint total_bet; /* total amount bet each player this hand */ Xchar temp[80]; Xint done; /* has player entered something valid yet? */ Xint amount; /* how much more is player donating to pot? */ Xint cycle=FALSE; /* has bet been around circle once yet? */ Xint x; Xint rounds=0; X Xi = first; Xwhile ( i != first || !cycle ) X { X if ( player[i].in ) X { X if ( j == -1 ) X { X total_bet = player[i].bet; X j = i; X } X sprintf( temp, "B%d%d", i, player[i].bet ); X tellall( player, n_players, temp ); X sprintf( temp, "$%d%d", i, player[i].cash ); X tellall( player, n_players, temp ); X n_active++; X } X if ( ++i == n_players ) X { X cycle = TRUE; X i = 0; X } X } Xtellall( player, n_players, "U" ); Xwhile( n_active > 1 && j != last_raiser ) X { X sprintf( temp, "T%d", j ); X tellall( player, n_players, temp ); X sprintf( temp, "P%d", *pot ); X tellall( player, n_players, temp ); X sprintf( temp, "B%d%d", j, player[j].bet ); X tellall( player, n_players, temp ); X tellall( player, n_players, "U" ); X sprintf( temp, "$%d%d", j, player[j].cash ); X tellall( player, n_players, temp ); X if ( j > 0 ) /* if not computer */ X { X sprintf( temp, "?%d", total_bet - player[j].bet ); X writeln( player[j].socket, temp ); X } X tellall( player, n_players, "U" ); /* update displays */ X X /* get bet ... */ X X done = FALSE; X while ( !done ) X { X if ( j > 0 ) X readln( player[j].socket, temp ); X else X computer_bet( player, n_players, n_active, n_raises, *pot, total_bet, temp ); X done = TRUE; X switch ( temp[0] ) { X case 'Q' : X player[j].wantsout = TRUE; X done = FALSE; X break; X case 'S' : X player[j].sittingout = TRUE; X done = FALSE; X break; X case 'F' : X player[j].in = FALSE; X sprintf( temp, "H%d--fold--", j ); X tellall( player, n_players, temp ); X n_active--; X break; X case 'C' : X amount = total_bet - player[j].bet; X *pot += amount; X player[j].cash -= amount; X player[j].bet = total_bet; X sprintf( temp, "B%d%d", j, total_bet ); X tellall( player, n_players, temp ); X sprintf( temp, "H%dCall", j ); X tellall( player, n_players, temp ); X break; X case 'R' : X if ( ++n_raises > n_players ) X { X sprintf( temp, "MMax # of raises; Call or fold." ); X writeln( player[j].socket, temp ); X --j; X break; X } X last_raiser = j; X amount = (total_bet += (x = atoi(temp+1))) - player[j].bet; X *pot += amount; X player[j].cash -= amount; X player[j].bet = total_bet; X sprintf( temp, "B%d%d", j, total_bet ); X tellall( player, n_players, temp ); X sprintf( temp, "H%dRaise %d", j, x); X tellall( player, n_players, temp ); X break; X case 'P' : X sprintf( temp, "H%dPass", j ); X tellall( player, n_players, temp ); X break; X } X } X sprintf( temp, "$%d%d", j, player[j].cash ); X tellall( player, n_players, temp ); X X sprintf( temp, "P%d", *pot ); X tellall( player, n_players, temp ); X tellall( player, n_players, "U" ); X if ( ++j >= n_players ) X { X ++rounds; X j = 0; X } X while( !player[j].in ) X if ( ++j >= n_players ) X { X ++rounds; X j = 0; X } X if ( last_raiser == -1 && ( rounds > 1 || ( rounds == 1 && j >= first ) ) ) X break; /* all passed or folded */ X } Xif ( n_active <= 1 ) X return( j ); Xelse X return( -1 ); X} PaRtIcUlAtEmAtTeR echo -n ' ' ls -l betting.c echo x betting.h sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > betting.h X/* X** Handle the intricacies of betting. If all but one player fold, the X** winning player's index is returned. X*/ X Xextern int betting(); PaRtIcUlAtEmAtTeR echo -n ' ' ls -l betting.h echo x cards.c sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > cards.c X X/* X** Basic card playing routines like shuffling, etc. X*/ X X# include "cards.h" X# ifdef MASSCOMP X# define MAXRAND 32767 X# else X# define MAXRAND 2147483648 X# endif X# define ERROR -1 X Xchar ranks[]="23456789TJQKA"; Xchar suits[]="DCHS"; X Xvoid shuffle (deck) X Xint deck[]; /* return deck of shuffled cards here */ X X{ Xint temp[52]; Xint i,x; Xint crandom(); X Xfor(i=0; i<52; i++) X temp[i] = i; Xfor(i=0; i<52; i++) X { X while (temp[x = crandom(52)] == ERROR) ; X deck[i] = temp[x]; X temp[x] = ERROR; X } X} X Xint crandom( limit ) X Xint limit; X X{ X# ifdef MASSCOMP X# define random rand X# endif Xunsigned long random(); Xunsigned long scale; Xint x; X Xscale = (unsigned long) MAXRAND/limit; Xx = random()/scale; Xif ( x < 0 ) x = 0; /* weird things do happen occasionally */ Xreturn(x); X} PaRtIcUlAtEmAtTeR echo -n ' ' ls -l cards.c echo x cards.h sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > cards.h Xextern char ranks[]; /* card ranks 2-A */ Xextern char suits[]; /* card suits D,C,H,S */ X X# define card(x) ((x) % 13) X# define suit(x) ((x) / 13) X# define rank(x) (ranks[card(x)]) X# define color(x) (suits[suit(x)]) X Xextern void shuffle(); /* shuffle a deck of cards */ Xextern int crandom(); /* return random number 0 .. limit-1 */ PaRtIcUlAtEmAtTeR echo -n ' ' ls -l cards.h echo x computer.c sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > computer.c X/* X** Handle betting and drawing for the computer's hand. X*/ X X# include "computer.h" X# include "players.h" X# include "cards.h" X# include "whowon.h" X# include "limits.h" X X# define min(x,y) ((x) > (y) ? (y) : (x)) X X# define TRUE 1 X# define FALSE 0 X Xstatic int bluffing=FALSE; /* bluffing this hand? */ Xstatic int bluffmore=FALSE; /* more bluff bets this hand? */ X Xvoid computer_bet( player, n_players, n_active, n_raises, pot, total, temp ) X XPLAYER player[]; /* player information & hands */ Xint n_players; /* number of players */ Xint n_active; /* number of players still in current hand */ Xint n_raises; /* # raises so far this betting session */ Xint pot; /* size of pot */ Xint total; /* current total bet */ Xchar temp[]; /* return betting command here */ X X{ Xint raise; /* amount to raise by */ Xint chance; /* rating of hand */ Xint x; /* random compared to chance to determine action */ Xint top=(-1); /* highest card hand has most of */ Xint i; Xstatic int lastpot=99999; /* trick to only get random once per hand */ Xstatic int random_factor=0; X Xevaluate( player, 0 ); Xfor( i = 12; i > 0 ; i-- ) X if ( top == -1 || player[0].count[i] > player[0].count[top] ) X top = i; Xif ( pot < lastpot ) /* things to be done once per hand */ X { X random_factor = n_players * crandom( 10 ); X if ( crandom( 20 ) < 1 ) /* bluff sometimes */ X bluffing = TRUE; /* 1 out of 20 chance */ X else X bluffing = FALSE; X bluffmore = bluffing; X } Xlastpot = pot; Xchance = player[0].score * player[0].score * 10 + top + 1 + random_factor ; Xif ( bluffmore ) X chance += n_players * 50; Xif ( ( ( total < chance && crandom(10) < 6 ) || chance > total + 80 ) && n_raises < n_players ) X { X raise = min( RAISE_LIMIT, (player[0].score + crandom(3) - 1) * 10 ); X if ( raise <= 5 ) raise = 5; X if ( bluffing ) X { X raise = RAISE_LIMIT - crandom( 2 ) * 10; X bluffmore = FALSE; X } X sprintf( temp, "R%d", min( RAISE_LIMIT, raise ) ); X } Xelse if ( total <= player[0].bet ) X sprintf( temp, "P" ); Xelse if ( player[0].score >= THREE /* 3 of a kind or better never folds */ X || ( n_active == 2 && player[0].score > NOTHING ) X || total < chance + 80 - 100 / n_players ) /* comparatively good hand */ X { X sprintf( temp, "C" ); X } Xelse X sprintf( temp, "F" ); X} X Xvoid computer_draw( player, temp ) X XPLAYER player[]; /* computer's hand is in here */ Xchar temp[]; /* return command here */ X X{ Xint i,j; X X/* hand has already been evaluated by computer_bet() at least once. */ Xstrcpy( temp, "Dkkkkk" ); Xif ( player[0].score < STRAIGHT ) /* higher hands require no discards */ X for( i=0; i<5; i++ ) X { X for( j=0; j<5; j++ ) X if ( i != j && card(player[0].cards[i]) == card(player[0].cards[j]) ) X break; X if ( j == 5 ) X { X temp[i+1] = 'd'; /* discard it */ X } X } Xbluffmore = bluffing; X} PaRtIcUlAtEmAtTeR echo -n ' ' ls -l computer.c echo x computer.h sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > computer.h X/* X** This handles betting and drawing for the computer's hand. X*/ X Xextern void computer_bet(); Xextern void computer_draw(); PaRtIcUlAtEmAtTeR echo -n ' ' ls -l computer.h echo x draw.c sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > draw.c X/* X** Let each player who is still in draw as many as 5 cards to replace X** those he already has in his hand. This routines expects a command X** of the form Dxxxxx from each player program, where x is either X** 'k' to keep the card in that position, or X** 'd' to discard the card in that position. X*/ X X# include "draw.h" X# include "players.h" X# include "showcards.h" X# include "tellall.h" X X# define TRUE 1 X# define FALSE 0 X Xvoid draw( player, n_players, deck, d, first ) X XPLAYER player[]; /* hands are in here */ Xint n_players; /* # of players */ Xint deck[]; /* shuffled deck of cards */ Xint d; /* next card to take from deck */ Xint first; /* player who gets to draw first */ X X{ Xint i,c; Xchar temp[80]; Xchar temp2[20]; Xint n; Xint cycle=FALSE; X Xi = first; Xwhile ( i != first || !cycle ) X { X if ( player[i].in ) X { X sprintf( temp, "T%d", i ); X tellall( player, n_players, temp ); X tellall( player, n_players, "U" ); X if ( i == 0 ) X computer_draw( player, temp ); X else X { X writeln( player[i].socket, "D" ); X readln( player[i].socket, temp ); X } X if ( temp[0] != 'D' ) /* what else could it be ?? */ X { X --i; /* do this man again ! */ X continue; X } X n = 0; X for( c=0; c<5; c++ ) X if ( temp[c+1] == 'd' ) X { X player[i].cards[c] = deck[d++]; X n++; X } X if ( n == 0 ) X strcpy( temp2, "Draws none" ); X else X sprintf( temp2, "Draws %d", n ); X sprintf( temp, "H%d%s", i, temp2 ); X tellall( player, n_players, temp ); X tellall( player, n_players, "U" ); X if ( i != 0 ) X { X show( player, temp, i, i ); X writeln( player[i].socket, "U" ); X } X } X if ( ++i == n_players ) X { X cycle = TRUE; X i = 0; X } X } X} PaRtIcUlAtEmAtTeR echo -n ' ' ls -l draw.c echo x draw.h sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > draw.h X/* X** Let each player who is still in draw cards to replace those he has. X*/ X Xextern void draw(); PaRtIcUlAtEmAtTeR echo -n ' ' ls -l draw.h echo x limits.h sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > limits.h X/* X** Game limits. X*/ X X# define ANTE 2 X# define RAISE_LIMIT 50 PaRtIcUlAtEmAtTeR echo -n ' ' ls -l limits.h echo x main.c sed -e 's/^X//' << 'PaRtIcUlAtEmAtTeR' > main.c X/* X** This is a program to handle a multi-user poker game. It uses sockets in X** the AF_INET family, so it can handle several players even on different X** machines. The game is 5-card draw poker. X*/ X X# include <signal.h> X# include "cards.h" X# include "players.h" X# include "betting.h" X# include "draw.h" X# include "whowon.h" X# include "payoff.h" X# include "showcards.h" X# include "util.h" X# include "tellall.h" X# include "limits.h" X X# define TRUE 1 X# define FALSE 0 X# define ERROR -1 X Xmain( argc, argv ) X Xint argc; Xchar **argv; X X{ Xint i,c,d; Xint deck[52]; /* the cards */ Xint pot; /* size of current pot */ Xint winner; /* which player won this hand */ Xint first=0; /* first player to bet, draw, etc. */ X# ifdef MASSCOMP Xextern void srand(); X# else Xextern void srandom(); /* starts random number generator */ X# endif Xextern long time(); /* unique parameter to above */ Xextern void crash(); /* if broken pipe, release port (I hope) */ Xextern int strcmp(); Xextern int getpid(); /* more random stuff */ X Xsignal(SIGPIPE,crash); Xsignal(SIGHUP,crash); Xsignal(SIGXCPU,SIG_IGN); X# ifdef MASSCOMP X srand((int) time(0) ^ getpid() ); X# else X srandom((int) time(0) ^ getpid() ); X# endif Xplayer[0].name = strsave( "Computer III" ); Xplayer[0].cash = 200; Xplayer[0].sittingout = FALSE; Xplayer[0].wantsout = FALSE; Xfor(;;) X { X if (n_players < 2) X new_players( player, &n_players, TRUE ); /* wait for someone to play with */ X pot = 0; X for( i=0; i<n_players; i++) X { X if ( player[i].sittingout == FALSE ) X { X player[i].in = TRUE; X player[i].bet = ANTE; /* ante */ X player[i].cash -= ANTE; X pot += ANTE; X } X else X { X player[i].in = FALSE; X player[i].bet = (-1); /* keep tellall() quiet */ X } X if ( n_players == 2 ) X player[i].lonehands += 1; X } X tellall( player, n_players, "X" ); /* clear all screens */ X tellall( player, n_players, "U" ); /* clear all screens */ X shuffle( deck ); X d = 0; /* next card to draw from deck */ X for( c=0; c<5; c++ ) X for( i=0; i<n_players; i++ ) X if ( player[i].in ) X player[i].cards[c] = deck[d++]; X /* show cards to each player ... */ X show_cards( player, n_players, FALSE, FALSE ); X if ( ++first >= n_players ) X first = 0; X if ((winner = betting( player, n_players, &pot, first )) < 0) X { X draw( player, n_players, deck, d, first ); X if ((winner = betting( player, n_players, &pot, first )) < 0) X winner = whowon( player, n_players, argc > 1 && strcmp( argv[1], "-test" ) == 0 ); X else if ( argc > 1 && strcmp( argv[1], "-test" ) == 0 ) X whowon( player, n_players, TRUE ); X } X else if ( argc > 1 && strcmp( argv[1], "-test" ) == 0 ) X whowon( player, n_players, TRUE ); X payoff( player, n_players, winner, pot ); X leave( player, &n_players ); X new_players( player, &n_players, FALSE ); X } X} PaRtIcUlAtEmAtTeR echo -n ' ' ls -l main.c