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