[comp.sources.games] v06i066: cubes2 - a networked dice game

games@tekred.CNA.TEK.COM (04/28/89)

Submitted-by: gmp@rayssdb.RAY.COM (Gregory M. Paris)
Posting-number: Volume 6, Issue 66
Archive-name: cubes2/Part08



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 8 (of 8)."
# Contents:  Makefile avg.c cubeorder.sh cuberank.6 cubes.h
#   cubeserver.6 histconv.sh random.c
# Wrapped by billr@saab on Thu Apr 27 12:13:41 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(4919 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#! /bin/make -f
X# vi:set sw=4 ts=4:
X
XOWNER=		gdaemon
XGROUP=		games
XGAMEDIR=	/usr/games
XGLIBDIR=	$(GAMEDIR)/lib
XPATHNAME=	$(GLIBDIR)/cubeserver
XHISTFILE=	$(GLIBDIR)/cubes.hist
XMONFILE=	$(GLIBDIR)/cubes.monikers
XMANDIR=		/usr/man/man6
XMANPAGES=	$(MANDIR)/cubes.6 $(MANDIR)/cubes.long.6 \
X			$(MANDIR)/cubestat.6 $(MANDIR)/cuberank.6 \
X			$(MANDIR)/cubeserver.6
X
X# If you want the server and client to use a UNIX domain socket
X# for local connections, define UNIXSOCK here.  It must be a pathname
X# to a file in a directory where OWNER has write permission.
X#
X# If you want the server to open an INET domain socket -- allowing
X# players from remote systems -- then define INETSOCK.  The client
X# INET code is compiled in, whether or not INETSOCK is defined.
X#
X# The server will not run if both UNIXSOCK and INETSOCK are left undefined.
X#
XSOCKETS=	-DUNIXSOCK=\"/usr/tmp/cubesocket\" -DINETSOCK
X#SOCKETS=	-DINETSOCK
X#SOCKETS=	-DUNIXSOCK=\"/usr/tmp/cubesocket\"
X
X# GECOS and LIBGECOS are for special password file gecos field decoding.
X# Defining it works only at the author's locale.
X#GECOS=		-DGECOS
X#LIBGECOS=	-lgecos
XGECOS=
XLIBGECOS=
X
X# if graphics won't work, add -DLONGNAMEBUG to CFLAGS
X# I use -OG on our pyramid
X#CFLAGS=	-OG
XCFLAGS=		-O
XLDFLAGS=
X
XSRVFLAGS=	-DPATHNAME=\"$(PATHNAME)\" -DHISTFILE=\"$(HISTFILE)\" $(SOCKETS)
XCLIFLAGS=	$(SOCKETS)
XHANFLAGS=	-DHISTFILE=\"$(HISTFILE)\"
XMONFLAGS=	-DMONFILE=\"$(MONFILE)\"
X
XLIBS=		-lcurses -ltermcap -lm
X
XSRVOBJS=	cubeserv1.o cubeserv2.o announce.o comptbl.o history.o moniker.o \
X			turn.o risk.o tempers.o strategies.o tactics.o dieopts.o random.o
XCLIOBJS=	cubes.o actions.o screen.o random.o fullname.o
XAVGOBJS=	avg.o dieopts.o random.o
XHSTOBJS=	histanal.o comptbl.o history.o tempers.o strategies.o \
X			random.o fullname.o
XSTTOBJS=	cubestat.o
X
XSRVSRCS=	cubeserv1.c cubeserv2.c announce.c comptbl.c history.c moniker.c \
X			turn.c risk.c tempers.c strategies.c tactics.c dieopts.c random.c
XCLISRCS=	cubes.c actions.c screen.c random.c fullname.c
XAVGSRCS=	avg.c dieopts.c random.c
XHSTSRCS=	histanal.c comptbl.c history.c tempers.c strategies.c \
X			random.c fullname.c
XSTTSRCS=	cubestat.c
X
Xall:		source cubeserver cubes cuberank cubestat avg \
X			cubes.6 cubes.long.6 cubestat.6 cuberank.6 cubeserver.6
Xsource:		$(SRVSRCS) $(CLISRCS) $(AVGSRCS) $(HSTSRCS) $(STTSRCS)
Xbins:		$(GLIBDIR)/cubeserver
Xbins:		$(GAMEDIR)/cubes $(GAMEDIR)/cubestat $(GAMEDIR)/cuberank
Xbins:		$(GAMEDIR)/scr
Xfiles:		$(HISTFILE) $(MONFILE) $(MANPAGES)
Xinstall:	source all bins files
X
X$(GLIBDIR)/cubeserver:	cubeserver
X	install -c -m 4100 -o $(OWNER) -g $(GROUP) cubeserver $(GLIBDIR)
X
X$(GAMEDIR)/cubes:		cubes
X	install -c -m  111 -o $(OWNER) -g $(GROUP) cubes      $(GAMEDIR)
X	install -c -m  111 -o $(OWNER) -g $(GROUP) cubes      $(GAMEDIR)
X
X$(GAMEDIR)/cubestat:	cubestat
X	install -c -m  111 -o $(OWNER) -g $(GROUP) cubestat   $(GAMEDIR)
X
X$(GAMEDIR)/cuberank:	cuberank
X	install -c -m 4111 -o $(OWNER) -g $(GROUP) cuberank   $(GAMEDIR)
X
X$(GAMEDIR)/scr:	scr.sh
X	install -c -m  755 -o $(OWNER) -g $(GROUP) scr.sh     $(GAMEDIR)/scr
X
X
Xcubeserver:	$(SRVOBJS)
X	cc $(LDFLAGS) -o cubeserver $(SRVOBJS) $(LIBS)
X
Xcubes:	$(CLIOBJS)
X	cc $(LDFLAGS) -o cubes $(CLIOBJS) $(LIBS) $(LIBGECOS)
X
Xavg:	$(AVGOBJS)
X	cc $(LDFLAGS) -o avg $(AVGOBJS) $(LIBS)
X
Xhistanal cuberank:	$(HSTOBJS)
X	cc $(LDFLAGS) -o histanal $(HSTOBJS) $(LIBS) $(LIBGECOS)
X	rm -f cuberank ; ln histanal cuberank
X
Xcubestat:	$(STTOBJS)
X	cc $(LDFLAGS) -o cubestat $(STTOBJS)
X
X
Xcubeserv1.o:	cubeserv1.c cubes.h Makefile
X	cc $(CFLAGS) $(SRVFLAGS) -c cubeserv1.c
X
Xcubes.o:	cubes.c cubes.h Makefile
X	cc $(CFLAGS) $(CLIFLAGS) -c cubes.c
X
Xhistanal.o:	histanal.c cubes.h Makefile
X	cc $(CFLAGS) $(HANFLAGS) -c histanal.c
X
Xmoniker.o:	moniker.c cubes.h Makefile
X	cc $(CFLAGS) $(MONFLAGS) -c moniker.c
X
Xfullname.o:	fullname.c cubes.h Makefile
X	cc $(CFLAGS) $(GECOS) -c fullname.c
X
X$(SRVOBJS):	cubes.h
X$(CLIOBJS):	cubes.h
X$(AVGOBJS):	cubes.h
X$(HSTOBJS):	cubes.h
X$(STTOBJS):	cubes.h
X
X
X# we must have a history file, but we need build it only once
X$(HISTFILE):	Makefile
X	touch $(HISTFILE)
X	chown $(OWNER) $(HISTFILE)
X	chgrp $(GROUP) $(HISTFILE)
X	chmod 644 $(HISTFILE)
X
X# we must have a monikers file, but we need build it only once
X$(MONFILE):	Makefile
X	touch $(MONFILE)
X	chown $(OWNER) $(MONFILE)
X	chgrp $(GROUP) $(MONFILE)
X	chmod 644 $(MONFILE)
X
X
X$(MANDIR)/cubes.6:		cubes.6
X	install -c -m 644 cubes.6 $(MANDIR)
X
X$(MANDIR)/cubes.long.6:		cubes.long.6
X	install -c -m 644 cubes.long.6 $(MANDIR)
X
X$(MANDIR)/cubestat.6:	cubestat.6
X	install -c -m 644 cubestat.6 $(MANDIR)
X
X$(MANDIR)/cuberank.6:	cuberank.6
X	install -c -m 644 cuberank.6 $(MANDIR)
X
X$(MANDIR)/cubeserver.6:	cubeserver.6
X	install -c -m 644 cubeserver.6 $(MANDIR)
X
X
Xclean:
X	rm -f *.o cubes cubeserver cuberank histanal cubestat avg cubes.shar*
X
Xnewsdist:
X	makekit -p -s50k -ncubes README cube*.6 Makefile *.[ch] *.sh
X
Xmaildist:
X	shar README cube*.6 Makefile *.[ch] *.sh >cubes.shar
X	package cubes.shar 350
END_OF_FILE
if test 4919 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'avg.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'avg.c'\"
else
echo shar: Extracting \"'avg.c'\" \(5359 characters\)
sed "s/^X//" >'avg.c' <<'END_OF_FILE'
X/*	vi:set sw=4 ts=4: */
X#ifndef	lint
Xstatic char	sccsid[] = "@(#)avg.c 5.1 (G.M. Paris) 89/01/22";
X#endif	lint
X
X/*
X**
X**	cubes 5.1  Copyright 1989 Gregory M. Paris
X**		Permission granted to redistribute on a no charge basis.
X**		All other rights are reserved.
X**
X*/
X
X#include	<stdio.h>
X#include	"cubes.h"
X
Xboolean			jokermode	= False;
X
Xextern int		optind;
Xextern int		opterr;
Xextern char	   *optarg;
Xextern long		atol();
X
X#define	ROLLS		1000000L	/* one million trials */
X
Xenum t_c {
X	T_AOK,		/* 5	/* all of a kind */
X	T_STR,		/* 5	/* straight */
X	T_ASMSTR,	/* 5	/* assembled straight */
X	T_4OK1S,	/* 5	/* four of a kind w/ one single */
X	T_SMSTR1S,	/* 5	/* small straight w/ one single */
X	T_3OK2S,	/* 5	/* three of a kind w/ two singles */
X	T_5S,		/* 5	/* five singles */
X	T_4OK,		/* 4	/* four of a kind */
X	T_SMSTR,	/* 4	/* small straight */
X	T_3OK1S,	/* 4	/* three of a kind w/one single */
X	T_4S,		/* 4	/* four singles */
X	T_3OK,		/* 3	/* three of a kind */
X	T_3S,		/* 3	/* three singles */
X	T_2S,		/* 2	/* two singles */
X	T_1S,		/* 1	/* one single */
X	T_ZIP,		/* 0	/* nothing */
X	T_SIZE
X};
X
Xstatic char	   *t_name[]	= {
X	"all of a kind",
X	"straight",
X	"assembled straight",
X	"four of a kind w/ one single",
X	"small straight w/ one single",
X	"three of a kind w/ two singles",
X	"five singles",
X	"four of a kind",
X	"small straight",
X	"three of a kind w/one single",
X	"four singles",
X	"three of a kind",
X	"three singles",
X	"two singles",
X	"one single",
X	"nothing",
X	""
X};
X
Xmain(ac, av)
Xchar   *av[];
X{
X	register diceset   *pd;
X	register enum t_c	t;
X	register int		d, singles, c, r;
X	diceset				dice;
X	long				cnt[(int)T_SIZE];
X	long				pts[(int)T_SIZE];
X	long				tpts;
X	long				rolls			= ROLLS;
X	boolean				aces_are_fives	= False;
X	int					haces			= 0;
X	int					held			= 0;
X
X	opterr = 0;
X	while((c = getopt(ac, av, "jfa:h:r:")) >= 0) {
X		switch(c) {
X		case 'j':	/* toggle jokermode */
X			jokermode = (jokermode == True) ? False : True;
X			break;
X		case 'f':	/* toggle aces_are_fives */
X			aces_are_fives = aces_are_fives == True ? False : True;
X			break;
X		case 'a':	/* number of aces held */
X			if((haces = atoi(optarg)) < 0 || haces >= NDICE) {
X				fprintf(stderr,
X					"avg: aces must be in range 0 to %d\n", NDICE-1);
X				exit(1);
X			}
X			break;
X		case 'h':	/* number of generic dice held */
X			if((held = atoi(optarg)) < 0 || held >= NDICE) {
X				fprintf(stderr,
X					"avg: held must be in range 0 to %d\n", NDICE-1);
X				exit(1);
X			}
X			break;
X		case 'r':	/* number of trials */
X			if((rolls = atol(optarg)) <= 0) {
X				fprintf(stderr, "avg: rolls must be positive\n");
X				exit(1);
X			}
X			break;
X		default:
X			fprintf(stderr,
X				"usage -- avg [-j] [-r rolls] [[-f] -a aces] [-h held]\n");
X			exit(1);
X		}
X	}
X
X	if(haces + held >= NDICE) {
X		fprintf(stderr, "avg: aces plus held must be less than %d\n", NDICE);
X		exit(1);
X	}
X
X	/*
X	**	Initialize.
X	*/
X	irandom();
X	pd = &dice;
X	for(c = 0;c < (int)T_SIZE;++c)
X		cnt[c] = pts[c] = 0;
X
X	/*
X	**	Roll and tally.
X	*/
X	for(r = 0;r < rolls;++r) {
X		initdice(pd);
X		if(aces_are_fives == True) {
X			for(d = 0;d < haces;++d) {
X				pd->d_stat[d] = Held, pd->d_comb[d] = Previous;
X				pd->d_face[d] = FIVE;
X			}
X		} else {
X			for(d = 0;d < haces;++d) {
X				pd->d_stat[d] = Held, pd->d_comb[d] = Previous;
X				pd->d_face[d] = ACE;
X			}
X		}
X		for(;d < haces + held;++d) {
X			pd->d_stat[d] = Held, pd->d_comb[d] = Previous;
X			pd->d_face[d] = BADFACE;
X		}
X
X		rolldice(pd);
X		evaluate(pd);
X
X		/*
X		**	Count singles.
X		*/
X		switch(pd->d_best) {
X		case All_of_a_kind:
X		case Straight:
X		case Asm_straight:
X			singles = 0;
X			break;
X		default:
X			for(singles = d = 0;d < NDICE;++d) {
X				switch(pd->d_comb[d]) {
X				case Ace:
X				case Five:
X				case Joker:
X					++singles;
X					break;
X				default:
X					break;
X				}
X			}
X			break;
X		}
X
X		/*
X		**	Figure out which tallied combination this is.
X		*/
X		switch(pd->d_best) {
X		default:			continue;
X		case Nothing:		t = T_ZIP; break;
X		case All_of_a_kind:	t = T_AOK; break;
X		case Straight:		t = T_STR; break;
X		case Asm_straight:	t = T_ASMSTR; break;
X		case Four_of_a_kind:t = singles ? T_4OK1S : T_4OK; break;
X		case Small_straight:t = singles ? T_SMSTR1S : T_SMSTR; break;
X		case Three_of_a_kind:
X			switch(singles) {
X			case 2: t = T_3OK2S; break;
X			case 1: t = T_3OK1S; break;
X			case 0: t = T_3OK; break;
X			}
X			break;
X		case Ace:
X		case Five:
X		case Joker:
X			switch(singles) {
X			case 5:	t = T_5S; break;
X			case 4:	t = T_4S; break;
X			case 3:	t = T_3S; break;
X			case 2:	t = T_2S; break;
X			case 1:	t = T_1S; break;
X			}
X			break;
X		}
X
X		/*
X		**	The value of d_pts_roll is taken as the expectation value of the roll.
X		**	In the case of All_of_a_kind and Asm_straight, the value must be corrected
X		**	by subtracting the value of previously held dice.
X		*/
X		scoredice(pd);
X		if(t == T_AOK || t == T_ASMSTR)
X			pd->d_pts_roll -= haces * (aces_are_fives==True ? P_FIVE : P_ACE);
X		pts[(int)t] += pd->d_pts_roll;
X		++cnt[(int)t];
X	}
X
X	/*
X	**	Print a summary.
X	*/
X	tpts = 0;
X	printf("%-40s %6s %6s %8s\n",
X		jokermode==True ? "Combination (with Jokers)" : "Combination (no Jokers)",
X		"Ptsper", "Expect", "Count");
X	for(c = 0;c < (int)T_SIZE;++c) {
X		if(cnt[c] != 0) {
X			tpts += pts[c];
X			printf("%-40s %6ld %6ld %8ld\n",
X				t_name[c], pts[c] / cnt[c], pts[c] / rolls, cnt[c]);
X		}
X	}
X	printf("%-40s %6s %6ld %8ld\n", "Total", "", tpts / rolls, rolls);
X
X	exit(0);
X}
END_OF_FILE
if test 5359 -ne `wc -c <'avg.c'`; then
    echo shar: \"'avg.c'\" unpacked with wrong size!
fi
# end of 'avg.c'
fi
if test -f 'cubeorder.sh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cubeorder.sh'\"
else
echo shar: Extracting \"'cubeorder.sh'\" \(1021 characters\)
sed "s/^X//" >'cubeorder.sh' <<'END_OF_FILE'
X: ksh or sh
X# vi:set sw=4 ts=4
X# cubeorder: sort players in temperament/strategy order
X
XPATH=/bin:/usr/games
X
Xumask 066
Xtmp=/tmp/cubeorder.$$
Xtrap "rm -f $tmp;exit 1" 1 2 3 15
X
Xrm -f $tmp
Xecho "BEGIN {" > $tmp
X
Xcuberank -T | awk '
X	BEGIN {
X		n = 1
X	}
X	$1 ~ /[0-9]/ {
X		printf("\ttemp[%d]=\"%s\"\n", n, $2)
X		printf("\tthdr[%d]=\"%s\"\n", n, $0)
X		++n;
X	}
X	END {
X		printf("\ttemps=%d\n", n)
X	}
X' >> $tmp
X
Xcuberank -S | awk '
X	BEGIN {
X		n = 1
X	}
X	$1 ~ /[0-9]/ {
X		printf("\tstrat[%d]=\"%s\"\n", n, $2)
X		++n
X	}
X	END {
X		printf("\tstrats=%d\n", n)
X	}
X' >> $tmp
X
Xcat >> $tmp <<\ENDCAT
X}
X$1 !~ /[0-9]/ {
X	hdr = $0
X	next
X}
X{
X	nam = substr($9, 1, 3) substr($10, 1, 3)
X	if(list[nam] == "")
X		list[nam] = $0
X	else
X		list[nam] = list[nam] "\n" $0
X}
XEND {
X	for(t = 1;t < temps;++t) {
X		print hdr
X		for(s = 1;s < strats;++s) {
X			nam = substr(temp[t], 1, 3) substr(strat[s], 1, 3)
X			if(list[nam] != "")
X				print list[nam]
X		}
X		print thdr[t]
X		print ""
X	}
X}
XENDCAT
X
Xcuberank -sP | awk -f $tmp | sed -e 's/_/ /g'
X
Xrm -f $tmp
Xexit 0
END_OF_FILE
if test 1021 -ne `wc -c <'cubeorder.sh'`; then
    echo shar: \"'cubeorder.sh'\" unpacked with wrong size!
fi
chmod +x 'cubeorder.sh'
# end of 'cubeorder.sh'
fi
if test -f 'cuberank.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cuberank.6'\"
else
echo shar: Extracting \"'cuberank.6'\" \(5375 characters\)
sed "s/^X//" >'cuberank.6' <<'END_OF_FILE'
X.TH CUBERANK 6 "cubes 5.1" GMP "UNIX Gaming Manual"
X.SH NAME
Xcuberank \- cubes player rankings and statistics
X.\"
X.\" sccsid: @(#)cuberank.6 5.1 (G.M. Paris) 89/01/22
X.\"
X.\"
X.\"
X.\"	cubes 5.1  Copyright 1988 Gregory M. Paris
X.\"		Permission granted to redistribute on a no charge basis.
X.\"		All other rights are reserved.
X.\"
X.\"
X.SH SYNOPSIS
X.B cuberank
X[
X.B \-ahlsuCLPRST
X] [
X.B \-n rng
X[
X.B \-p plr
X]] [
X.B \-g gms
X] [
X.B plr ...
X]
X.SH OVERVIEW
XThe
X.I cuberank
Xprogram analyzes the
X.IR cubes (6)
Xscore file and prints statistics about the players.
XThe various command line options allow the user
Xto affect which statistics the program displays
Xand which players the program provides information about.
X.PP
XAlthough useful in and of itself,
Xcombining multiple calls of
X.I cuberank
Xwith pipes to
X.IR sed (1)
Xand/or
X.IR awk (1),
Xcan provide more concise summaries of player ranking information.
XThe shell script /usr/games/scr provides one such summary,
Xwhich can be used as is,
Xor as an example for your own summary script.
X.PP
X.SH OUTPUT
XDepending on the set of command line options specified,
X.I cuberank
Xwill produce from seven to twelve columns of information
Xabout a selected subset of players who have played
X.I cubes
Xon this system.
XThe columns are defined as follows.
X.PP
X.IP Heading 12
XDescription
X.IP Up
Xup next number (displayed using the
X.B \-u
Xoption)
X.IP ##
Xthe player's rank (1 being the top rank)
X.IP Player
Xthe name of the player
X.IP GP
Xthe number of games played
X.IP LG
Xthe last game the player played in
X(displayed using the
X.B \-l
Xoption)
X.IP WinRt
Xwin rate (wins / games played)
X.IP GamPt
Xaverage points per game (total points / games)
X.IP TnPt
Xaverage points per turn (sum of turn averages / games)
X.IP WgtPt
Xweighted points derived from
X.BR WinRt ,
X.BR GamPt ,
Xand
X.BR TnPt
X.IP Pr
Xthe player's game type preference:
X.B \-
Xfor no preference,
X.B S
Xfor Standard,
X.B B
Xfor Blitz,
X.B FS
Xfor Forced Standard,
X.B FB
Xfor Forced Blitz, and
X.B ?
Xfor fickle
X(displayed using the
X.B \-P
Xoption)
X.IP Tmp
Xthe three character abbreviation for the player's temperament,
Xwhich is the roll-or-hold decision function used by this player
X(displayed using the
X.B \-P
Xoption)
X.IP Str
Xthe three character abbreviation for the player's strategy,
Xwhich is the the die-discarding function used by this player
X(displayed using the
X.B \-P
Xoption)
X.PP
XThe ranking order is based on the weighted point value,
Xso that the player with the highest weighted point value is the
Xhighest ranked player (number one).
XThe weighted point value is determined using the following formula.
X.IP
X.B WgtPt
X= 1000 *
X.B WinRt
X+
X.B GamPt
X+
X.B TnPt
X.PP
XThe largest value in each of the
X.BR WinRt ,
X.BR GamPt ,
X.BR TnPt ,
Xand
X.BR WgtPt
Xcolumns is marked with an asterisk.
X.SH "COMMAND LINE OPTIONS"
XSeveral command line options are provided to alter the output produced by
X.IR cuberank .
X.IP Option 12
XDescription
X.IP \-a
XDisplay ``ancient'' records, where ancient records are those
Xcorresponding to players that haven't played a game
Xin as many games as there are players in the score file.
X.IP \-g\ count
XTell only about players that have played in the last
X.B count
Xgames.
X.IP \-h
XProduce information about human players only.
X.IP \-l
XDisplay the game number of the last game each player played.
X.IP \-n\ range
XProduce information only about players ranked within plus or minus
X.B range
Xof your ranking.
X.IP \-p\ plr
XUse
X.B plr
Xas the center for the
X.B \-n range
Xoption.
X.IP \-s
XChange spaces in player names to underscores.
X(Allows easier
X.IR awk ing
Xof
X.I cuberank
Xoutput.)
X.IP \-u
XList computer players only, in order of decreasing likelihood
Xof playing in the next game.
X(Due to the random factors involved,
Xthere's no guarantee that players at the top of the list will be
Xin the next game.)
X.IP \-L
XDisplay
X.RB `` Lifetime ''
Xvalues for
X.BR WinRt ,
X.BR GamPt ,
X.BR TnPt ,
Xand
X.BR WgtPt .
XThese values are representative of the complete history of games
Xplayed by each player.
X.IP \-R
XDisplay
X.RB `` Recent ''
Xvalues for
X.BR WinRt ,
X.BR GamPt ,
X.BR TnPt ,
Xand
X.BR WgtPt .
X.B Recent
Xvalues are computed using a moving average with a window of twenty-five games.
XThus, these values are representative of each player's recent performance.
X.IP \-C
XDisplay
X.RB `` Combined ''
Xvalues for
X.BR WinRt ,
X.BR GamPt ,
X.BR TnPt ,
Xand
X.BR WgtPt .
X.B Combined
Xvalues are derived from the mean of the
X.B Recent
Xand
X.B Lifetime
Xvalues.
X(This is the default.)
X.IP \-P
XDisplay the player's ``personality.''
XThis option causes the
X.BR Pr ,
X.BR Tmp ,
Xand
X.B Str
Xcolumns to be produced.
X.IP \-S
XTabulate and display statistics for the strategies
Xemployed by the players.
XThe tabulated values correspond to the subset of
Xplayers selected by any other command line options.
X.IP \-T
XTabulate and display statistics for the temperaments
Xof the players.
XThe tabulated values correspond to the subset of
Xplayers selected by any other command line options.
X.IP plr\ ...
XRestrict output to that corresponding to the named players.
X.PP
XTwo other commonly desired options,
Xto print the top or bottom of the rankings,
Xare not provided,
Xas they can be had as easily using the
X.IR head (1)
Xand
X.IR tail (1)
Xutilities.
X.SH FILES
X.ta 3.5i
X.nf
X/usr/games/lib/cubes.hist	the score file
X/usr/games/scr	summarize cuberank script
X.fi
X.SH AUTHOR
XGreg Paris <gmp@rayssd.ray.com>
X.SH "SEE ALSO"
Xcubes(6), awk(1), head(1), sed(1), tail(1)
END_OF_FILE
if test 5375 -ne `wc -c <'cuberank.6'`; then
    echo shar: \"'cuberank.6'\" unpacked with wrong size!
fi
# end of 'cuberank.6'
fi
if test -f 'cubes.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cubes.h'\"
else
echo shar: Extracting \"'cubes.h'\" \(12208 characters\)
sed "s/^X//" >'cubes.h' <<'END_OF_FILE'
X/* vi:set sw=4 ts=4: */
X/*
X**	sccsid: @(#)cubes.h 5.1 (G.M. Paris) 89/01/22
X*/
X
X/*
X**
X**	cubes 5.1  Copyright 1989 Gregory M. Paris
X**		Permission granted to redistribute on a no charge basis.
X**		All other rights are reserved.
X**
X*/
X
X/*
X**	If you don't want Four_of_a_kind or Small_straight, then comment these out.
X**	Unfortunately, you'll have to recalculate the values in risktbl[] if you do.
X**	The existence of Jokers is controlled by a cubeserver command line option.
X*/
X#define	FOUR		4		/* how many in a four of a kind (if defined) */
X#define	SMSTR		4		/* number of dice in small straight (if def) */
X#define	ASMSTR		5		/* number of dice in assembled straight (if def) */
X
X/*
X**	Although you could change any of the following parameters, the nature of
X**	the game would be altered.  Also, some things like 5o'kind are hard coded
X**	in places and would not change automatically.  Best to leave be.
X*/
X#define	SIDES		6		/* six sided dice */
X#define	NDICE		5		/* number of dice in set */
X#define	ONBOARD		500		/* turn score needed to get on scoreboard */
X#define	OFFBOARD	500		/* turn score needed to cross WINSCORE thresh */
X#define	WINSCORE	10000	/* minimum score needed to win in Standard game */
X#define	BLITZSCORE	7500	/* minimum score needed to win in Blitz game */
X#define	WINMARGIN	250		/* winner must best others by this margin */
X
X/*
X**	These values are the basis for scoring.  Again, if you change them, the
X**	play of the game will be altered.  Leave them as they are.
X*/
X#define	P_ACEMULT	10		/* ace is worth disproportionate amount */
X#define	P_AOKMULT	300		/* multiplier for all of a kind */
X#define	P_STRAIGHT	1500	/* points for straight */
X#define	P_ASMSTR	750		/* points for assembled straight */
X#define	P_4OKMULT	200		/* multiplier for three of a kind */
X#define	P_SMSTR		400		/* points for a small straight */
X#define	P_3OKMULT	100		/* multiplier for three of a kind */
X#define	P_ACE		100		/* points for single ace */
X#define	P_FIVE		50		/* points for single five */
X#define	P_JOKER		0		/* value of single Jokers */
X#define	P_JOKERMULT	30		/* <n>o'kind multiplier for Jokers */
X
X/*
X**	The following defines are just symbolic values for numbers.
X*/
X#define	BADFACE		0		/* impossible die face */
X#define	ACE			1		/* an ACE is a one, a scoring die */
X#define	DEUCE		2		/* an DEUCE is a two, the most worthless die */
X#define	THREE		3		/* how many in a Three_of_a_kind or the face name */
X#define	FIVE		5		/* FIVE is five, a scoring die */
X#define	JOKER		9		/* an imphysical die face and scoring die */
X#define	MESGLEN		128		/* length of message buffer */
X#define	NAMELEN		64		/* player name buffer length */
X#define	IDLEN		64		/* player identity buffer length */
X#define	DISPLEN		18		/* field width in client name display */
X#define	COMP		0		/* computer starts as player zero */
X#define	PLAYERS		10		/* max players (client score window limits) */
X#define	MINPLR		4		/* min players at game begining */
X#define	MINCOMP		2		/* min computers at game beginning */
X#define	WRITETIMO	20		/* timeout on socket writes */
X#define	READTIMO	60		/* timeout on socket reads */
X#define	MAXTIMO		3		/* too many timeouts -- goodbye! */
X
X/*
X**	The ANCIENT value is used to prune old records from the history.
X**	The two credit values give additional grace to players as a multiplier
X**	of the number of games played.
X*/
X#define	ANCIENT		((long)(nhist + 1))	/* depends on number of players */
X#define	ANALCREDIT	0					/* games played credit in histanal */
X#define	WRITECREDIT	5					/* games played credit in histwrite */
X
X/*
X**	To mark asynchronous requests, we prepend each with ASYNCMARK.
X**	It should not be a character that would normally be typed.
X*/
X#define	ASYNCMARK	'\1'		/* control-A */
X
X/*
X**	Message numbers.  Defined as enum so that we can keep them
X**	sequential without much trouble.  This allows the dispatching
X**	function in the client to be faster, since we can avoid doing
X**	a linear search of the action table by using a function array.
XXXX	We assume that enums are ints for use in sprintf() calls.
X*/
X#define	M_BASE	100		/* lowest message number */
Xtypedef enum {
X	M_NOOP = M_BASE,	/* no operation (usually heartbeat) */
X	M_INFO,				/* informational or status messages */
X	M_HELP,				/* help messages */
X	M_DICE,				/* complete dice status */
X	M_PARM,				/* game parameters */
X	M_PLAY,				/* play-by-play on other players */
X	M_HELO,				/* hello message */
X	M_DOWN,				/* shutdown message */
X	M_RQID,				/* id request */
X	M_WORP,				/* watch or play? */
X	M_SORP,				/* wait (spider) or play? */
X	M_ACTV,				/* you are an active player */
X	M_AUTO,				/* you are on autopilot */
X	M_WAIT,				/* you are waiting to be added */
X	M_VOYR,				/* you are now a voyeur */
X	M_SPDR,				/* you are now a spider */
X	M_TURN,				/* Player %d, ... up with %d points. */
X	M_NWIN,				/* game over, no winner */
X	M_OVER,				/* Player %d has won the game! */
X	M_RANK,				/* player rank at end of game */
X	M_CPLR,				/* clear all players */
X	M_UARE,				/* you are player %d */
X	M_PNUM,				/* player %d %s */
X	M_FARE,				/* farewell %d %s */
X	M_NOBS,				/* %d observer[s] */
X	M_MSCO,				/* You now have %d points. */
X	M_OSCO,				/* Player %d now has %d points. */
X	M_ANOG,				/* play another game? */
X	M_RFST,				/* Ready to roll? */
X	M_KEEP,				/* %d points: */
X	M_ARGE,				/* argument error */		
X	M_BADM				/* bad message */
X} m_num;
X#define	M_LAST	(int)M_BADM		/* highest message number */
X
X/*
X**	Definitions for status queries.  For now, only one query
X**	type, and only two status responses are supported.
X*/
X#define	STATLEN		512		/* max length of status response */
X#define	Q_ROSTER	'\1'	/* query: current player roster */
X#define	S_IDLE		'\1'	/* status: idle */
X#define	S_ROSTER	'\2'	/* status: current player roster */
X#define	S_UNRECOG	'\177'	/* status: unrecognized query */
X
X/*
X**	Some stuff for converting numbers to names.  Probably should be elsewhere.
X*/
Xextern char	   *numnames[][2];
X#define	NUMBER(n)			(numnames[n][0])
X#ifdef	lint
X#define	FACE(show,ndice)	(numnames[show][ndice])	/* fake to shut up lint */
X#else	lint
X#define	FACE(show,ndice)	(numnames[show][(ndice)!=1])
X#endif	lint
X
X/*
X**	boolean: remind me never to do this again
X*/
Xtypedef enum { False, True } boolean;
X
X/*
X**	diestat: the four states a die can be in
X*/
Xtypedef enum { Free, Held, Rolled, Taken } diestat;
X
X/*
X**	combination: names for all scoring combinations
X*/
Xtypedef enum {
X	Previous = -1, Nothing, Joker, Five, Ace, Three_of_a_kind,
X	Small_straight, Four_of_a_kind, Asm_straight, Straight, All_of_a_kind
X} combination;
X
X/*
X**	Currently, defining DESC does nothing useful.
X*/
X/*#define	DESC	1		/* scoring description (future use) */
X
X#ifdef	DESC
X/*
X**	scoredesc: complete description of a scoring combination
X*/
Xtypedef struct {
X	combination	sc_comb;	/* the type of combination */
X	short		sc_num;		/* how many of this combination */
X	short		sc_face;	/* face value for N_of_a_kind */
X} scoredesc;
X#endif	DESC
X
X/*
X**	diceset: structure for tracking status of all dice
X*/
Xtypedef struct {
X	int			d_face[NDICE];		/* number showing on each die */
X	diestat		d_stat[NDICE];		/* status of each die */
X	combination	d_comb[NDICE];		/* die's scoring combination */
X#ifdef	DESC
X	scoredesc	d_desc[NDICE];		/* list of combinations scored */
X#endif	DESC
X	combination	d_best;				/* best combination scored */
X	boolean		d_again;			/* true if rolling again */
X	int			d_rolling;			/* number of dice rolling */
X	int			d_pts_roll;			/* points due to last roll */
X	int			d_pts_dice;			/* points by this set of NDICE */
X	int			d_pts_turn;			/* points accumulated this turn */
X	int			d_pts_max;			/* max points showing this turn */
X	char		d_mesg[MESGLEN];	/* status message */
X} diceset;
X
X/*
X**	winpref: player game type preference
X*/
Xtypedef enum {
X	Nopref,							/* don't care */
X	Standard,						/* game to WINSCORE */
X	Blitz,							/* game to BLITZSCORE */
X	Fickle,							/* for computer use */
X	Fstand,							/* Standard or quit */
X	Fblitz,							/* Blitz or quit */
X} winpref;
X
X/*
X**	blitzmode: when the server will play Blitz games
X*/
Xtypedef enum {
X	Noblitz,						/* never to be played */
X	Onrequest,						/* only when requested */
X	Workhours,						/* default during working hours */
X	Enforced,						/* enforced during working hours */
X} blitzmode;
X
X/*
X**	cstat: player/connection status
X*/
Xtypedef enum {
X	Inactive,	/* no player */
X	Watching,	/* human voyeur */
X	Waiting,	/* human waiting to get in */
X	Spider,		/* human waiting for another human */
X	Active,		/* active human player */
X	Computer,	/* active computer player */
X} cstat;
X
X/*
X**	strategy: description of a computer player strategy
X*/
Xtypedef struct	{
X	int		  (*s_func)();			/* strategy function */
X	char	   *s_name;				/* name of strategy */
X} strategy;
X
X/*
X**	temper: description of a computer player temperament
X*/
Xtypedef struct	{
X	boolean	  (*t_func)();			/* temperament function */
X	char	   *t_name;				/* name of temperament */
X} temper;
X
X/*
X**	computer: complete description of a computer player
X*/
Xtypedef struct	{
X	char	   *c_name;				/* computer player name */
X	strategy   *c_strategy;			/* pointer into strategy table */
X	temper     *c_temper;			/* pointer into temperament table */
X	winpref		c_pref;				/* gametype preference */
X} computer;
X
X/*
X**	player: player/connection status
X*/
Xtypedef struct {
X	cstat		p_stat;				/* connection status */
X	int			p_fd;				/* communications socket */
X	int			p_timeouts;			/* number of timeouts */
X	int			p_score;			/* player score */
X	int			p_squander;			/* points rolled away */
X	int			p_mood;				/* computer mood value */
X	winpref		p_pref;				/* winscore preference */
X	boolean		p_onboard;			/* True if player on board */
X	computer   *p_computer;			/* pointer into computer table */
X	char		p_name[NAMELEN];	/* player name */
X	char		p_id[IDLEN];		/* "unique" player id */
X} player;
X
X/*
X**	Computer moods have no meaning other than that defined
X**	by each temperament that uses the p_mood value.
X*/
X#define	NOMOOD	0	/* no mood selected */
X#define	MAXMOOD	5	/* moods 1 through MAXMOOD */
X
X/*
X**	graphtype: type of graphics the terminal supports
X*/
Xtypedef enum	{
X	Nographics, Digital, Zenith,
X} graphtype;
X
X/*
X**	history: player scoring history
X*/
X#define	H_MVWINMULT		10000L		/* to avoid floating point stuff */
Xtypedef struct	{
X	long		h_points;			/* lifetime total number of points */
X	long		h_avgturn;			/* lifetime average points per turn */
X	long		h_wins;				/* lifetime number of games won */
X	long		h_games;			/* lifetime number of games played */
X	long		h_mvpoints;			/* moving sum of game points */
X	long		h_mvavgturn;		/* moving sum of avg points per turn */
X	long		h_mvwins;			/* mov sum of games won times H_MVWINMULT */
X	long		h_mvgames;			/* games used to calculate h_mv values */
X	long		h_lastgame;			/* last game played in */
X	long		h_weight;			/* weighted value of record */
X	long		h_rank;				/* ranking based on weight */
X	computer   *h_computer;			/* pointer into computer table */
X	char		h_id[IDLEN];		/* "unique" player id */
X} history;
X
X/*
X**	ptstype: history points type
X*/
Xtypedef enum { Lifetime, Recent, Combined } ptstype;
X
X/*
X**	risk: rolling risks/expectations
X*/
Xtypedef struct	{
X	double	r_p_any;	/* probability of scoring anything (assumes mix) */
X	double	r_p_all;	/* probability of scoring all (assumes mix) */
X	double	r_p_aok;	/* prob. of completing All_of_a_kind in non-scoring */
X	int		r_e_mix;	/* <rolled> with a mix of held dice */
X	int		r_e_aces;	/* <rolled> with held dice all aces (no 3o'kind) */
X	int		r_e_fives;	/* <rolled> with held dice all fives (no 3o'kind) */
X	int		r_e_jokers;	/* <rolled> with held dice all jokers (no 3o'kind) */
X} risk;
X
X/*
X**	enterlate: what to do about a game in progress or about waiting
X*/
Xtypedef enum {
X	Ask, Watch, Play, Wait
X} enterlate;
X
X/*
X**	Definitions for convenient use of select().
X*/
X#ifndef	FD_ZERO
X/*
XXXX:	This system is missing the FD_ macros for select, so it's
XXXX:	probably a 4.2BSDish system.  That means that the fd_set
XXXX:	type is probably just a single int, so just fake it here.
X*/
X#define	FD_ZERO(p)		((p)->fds_bits[0] = 0)
X#define	FD_SET(n,p)		((p)->fds_bits[0] |= 1L << (n))
X#define	FD_ISSET(n,p)	(((p)->fds_bits[0] & (1L << (n))) != 0)
X#endif	FD_ZERO
X#define	NOSEL		((fd_set *)0)
X#define	HANG		((struct timeval *)0)
END_OF_FILE
if test 12208 -ne `wc -c <'cubes.h'`; then
    echo shar: \"'cubes.h'\" unpacked with wrong size!
fi
# end of 'cubes.h'
fi
if test -f 'cubeserver.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cubeserver.6'\"
else
echo shar: Extracting \"'cubeserver.6'\" \(5480 characters\)
sed "s/^X//" >'cubeserver.6' <<'END_OF_FILE'
X.TH CUBESERVER 6 "cubes 5.1" GMP "UNIX Gaming Manual"
X.SH NAME
Xcubeserver \- cubes dice game service
X.\"
X.\" sccsid: @(#)cubeserver.6 5.1 (G.M. Paris) 89/01/22
X.\"
X.\"
X.\"
X.\"	cubes 5.1  Copyright 1988 Gregory M. Paris
X.\"		Permission granted to redistribute on a no charge basis.
X.\"		All other rights are reserved.
X.\"
X.\"
X.SH SYNOPSIS
X.B cubeserver
X[
X.B \-j
X] [
X.BR \-b { nrwe }
X]
X.SH OVERVIEW
XThe
X.I cubeserver
Xis the program that provides the
X.IR cubes
Xgame service.
XThis manual page is intended for games administrators.
XPotential
X.I cubes
Xplayers should see the manual pages for
X.IR cubes ,
X.IR cuberank ,
Xand
X.IR cubestat
Xto find out how to play the game.
X.SH "FILE MODES AND OWNERSHIPS"
XThe
X.I cubeserver
Xis meant to be run setuid to an unprivileged daemon account, often
X.IR gdaemon .
XThe files used by the
X.I cubeserver
Xare assumed to exist, have the same ownership as the executable,
Xand have permissions mode of 644, 640, or 600.
XThe Makefile supplied with the
X.I cubes
Xdistribution should create all needed files with appropriate
Xownership and permissions.
X.SH "UNIX DOMAIN CUBES SERVICE"
XThe
X.I cubeserver
Xcan be configured to provide
X.I cubes
Xservice in the
X.B UNIX
Xdomain.
XThis service can be provided in addition to,
Xor as an alternative to the
X.B INET
Xdomain service (described below).
XAt least one of the services must be provided,
Xor the server will not run.
X.PP
XThe
X.B UNIX
Xdomain service allows connections from clients only on the local system,
Xand could possibly be more efficient than the
X.B INET
Xservice.
XTo configure the server to provide service in this domain,
Xit must be compiled with the
X.B \-DUNIXSOCK=pathname
Xoption, where
X.B pathname
Xis the name of the rendezvous socket.
X(The client program also must be compiled with this option.)
X.SH "INET DOMAIN CUBES SERVICE"
XThe
X.I cubeserver
Xcan be configured to provide
X.I cubes
Xservice in the
X.B INET
Xdomain,
Xallowing the server to be accessed from remote systems.
XTo provide this networked service,
Xthe server must be compiled with the
X.B \-DINETSOCK
Xoption and the
X.I cubes
Xservice must be made a ``well known'' service.
X.PP
XMaking the
X.I cubes
Xservice well known
Xusually means adding an entry to the file /etc/services
X(see
X.IR services (5)).
X(Note that the entry should be added to the services file on every
Xsystem upon which the client program,
X.IR cubes ,
Xis to be run, not just on the system on which the server is to be run.)\ 
XThe entry is for the TCP socket that the server uses to communicate
Xwith its clients during game play.
XThe port number chosen must be greater than 1024
Xso that the server can run as an unprivileged user.
XAlthough not officially registered in any way,
Xthe following entry is suggested.
X.PP
X.DT
X.nf
X.ft B
X	cube		3840/tcp	cubes
X.fi
X.ft P
X.SH "CUBES STATUS SERVICE"
XIf another well known service is defined, namely the
X.I cubestat
Xservice, the server will listen on an
X.B INET
Xdomain UDP socket for status requests generated by the
X.I cubestat
Xprogram.
XSince the TCP and UDP port number spaces are separate,
Xit is reasonable to use the same port number for both sockets.
X(Remember, the port number chosen must be greater than 1024
Xso that the server can run as an unprivileged user.)\ 
XAgain, though not officially registered in any way,
Xthe following entry is suggested.
X.PP
X.DT
X.nf
X.ft B
X	cubestat	3840/udp	cubestatus
X.fi
X.ft P
X.PP
XThe current version of the server does not provide status service in the
X.B UNIX
Xdomain, regardless of compile time options.
X.SH "STARTING THE SERVER"
XNormally, the
X.I cubeserver
Xwill be started automatically on system boot
Xby placing the appropriate line in the file /etc/rc.local,
Xor possibly in another file where similar daemons are started.
XAlternatively, it is possible to start the server via a program like
X.IR cron .
XFor this purpose,
Xwhen the server is started
Xit prints its process id on the standard output.
XThis pid could be saved in a file and be used to turn the daemon
Xoff at a later time,
Xagain using
X.IR cron .
XTo kill the server immediately,
Xsend it a SIGTERM.
XMore politely, killing the server with SIGHUP
Xcauses it to exit when any game in progress finishes.
X.PP
XThere are two command line options for
X.IR cubeserver .
X.PP
XThe
X.B \-j
Xoption allows the server to occasionally play the game of
X.I cubes
Xwith dice that have jokers on them.
XWithout this option,
Xthe game is always played with normal six-sided dice.
X.PP
XThe
X.BR \-b < when >
Xoption allows specifying when the server will play the game of
X.I cubes
Xin Blitz mode (games end at 7500 rather than 10000 points).
XThe values of
X.RB ` n ',
X.RB ` r ',
X.RB ` w ',
Xand
X.RB ` e '
Xtell the server to play in Blitz mode
Xnever, on request, default during working hours,
Xand enforced during working hours respectively.
XThe default is
X.RB ` e '.
X.SH FILES
X.ta 3.2i
X.nf
X/usr/games/lib/cubeserver	the cubeserver executable
X/usr/games/lib/cubes.hist	the cubes score file
X/usr/games/lib/cubes.monikers	names for the chamelion
X.fi
X.PP
XThe cubes.monikers file is a record of names selected by
Xhuman players for use by the chamelion player.
XThis file will grow without bound,
Xso it might be a good idea to check it on occasion.
XA good idea anyway, since
X.I cubeserver
Xdoes not judge the acceptability of names before using them.
XThe program has a short list of names compiled in,
Xso you can avoid problems with this file by linking it to /dev/null.
X.DT
X.SH "SEE ALSO"
Xcubes(6), cuberank(6), cubestat(6), services(5), rc(8), cron(8)
X.SH AUTHOR
XGreg Paris <gmp@rayssd.ray.com>
END_OF_FILE
if test 5480 -ne `wc -c <'cubeserver.6'`; then
    echo shar: \"'cubeserver.6'\" unpacked with wrong size!
fi
# end of 'cubeserver.6'
fi
if test -f 'histconv.sh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'histconv.sh'\"
else
echo shar: Extracting \"'histconv.sh'\" \(774 characters\)
sed "s/^X//" >'histconv.sh' <<'END_OF_FILE'
X#! /bin/sh
X#
X#  This script is for converting cubes4.1 style history file to cubes5.1 style.
X#  You must use this script if you were running cubes4.1 and wish to keep
X#  the players' records intact.
X#
Xawk '
XBEGIN {
X	MVGAMES = 25;
X}
X{
X	split($1, x, ";"); games=x[1]; lastgame=x[2];
X	if(games == 0) next;
X	if(games < MVGAMES) mvgames = games;
X	else mvgames = MVGAMES;
X
X	wins=$2; points=$3; avgturn=$4;
X
X	name=$5;
X	for(n = 6;n <= NF;++n)
X		name = name " " $n;
X
X	mvwins = (10000 * wins * mvgames) / games;
X	mvpoints = (points * mvgames) / games;
X	mvavgturn = (avgturn * mvgames) / games;
X
X	printf("L %5d %5d %10d %10d %6d %s\n", games, wins, points, avgturn, lastgame, name);
X	printf("M %5d %5d %10d %10d %6d %s\n", mvgames, mvwins, mvpoints, mvavgturn, lastgame, name);
X}
X' $1
END_OF_FILE
if test 774 -ne `wc -c <'histconv.sh'`; then
    echo shar: \"'histconv.sh'\" unpacked with wrong size!
fi
chmod +x 'histconv.sh'
# end of 'histconv.sh'
fi
if test -f 'random.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'random.c'\"
else
echo shar: Extracting \"'random.c'\" \(3095 characters\)
sed "s/^X//" >'random.c' <<'END_OF_FILE'
X/*	vi:set sw=4 ts=4: */
X#ifndef	lint
Xstatic char	sccsid[] = "@(#)random.c 5.1 (G.M. Paris) 89/01/22";
X#endif	lint
X
X/*
X**
X**	cubes 5.1  Copyright 1989 Gregory M. Paris
X**		Permission granted to redistribute on a no charge basis.
X**		All other rights are reserved.
X**
X*/
X
X#include	<sys/types.h>
X#include	<sys/time.h>
X#include	"cubes.h"
X
Xextern boolean	jokermode;
Xextern char	   *initstate();
Xextern long		random();
Xextern time_t	time();
X
Xstatic long		diestate[3][256 / sizeof(long)];	/* for die rolls */
Xstatic long		numstate[256 / sizeof(long)];		/* for random numbers */
X
X#define	RANDOM()	(int)((unsigned)random() >> 1)	/* XXX: ensure non-neg? */
X
X/*
X**	irandom: initialize random number generators
X*/
Xirandom()
X{
X	struct timeval		tv;
X	struct timezone		tz;
X	register unsigned	n;
X	int					nstate	= 0;
X
X	/*
X	**	Initialize first die rolling state.
X	*/
X	(void) gettimeofday(&tv, &tz);
X	n = (tv.tv_sec << 8) + ((unsigned)tv.tv_usec >> 8);
X	(void) initstate(n, diestate[nstate++], sizeof diestate[0]);
X	for(n %= 49;n != 0;--n)
X		(void) random();
X	
X	/*
X	**	Initialize random number state and second die rolling state.
X	*/
X	(void) gettimeofday(&tv, &tz);
X	n = ((tv.tv_sec << 16) | ((unsigned)tv.tv_usec >> 16)) + getpid();
X	(void) initstate(n, numstate, sizeof numstate);
X	for(n %= 17;n != 0;--n)
X		(void) random();
X	n = (unsigned)(random() + 1);	/* using numstate */
X	(void) initstate(n, diestate[nstate++], sizeof diestate[0]);
X	for(n %= 13;n != 0;--n)
X		(void) random();
X
X	/*
X	**	Initialize third die rolling state.
X	*/
X	(void) gettimeofday(&tv, &tz);
X	n = (tv.tv_sec << 4) ^ ((unsigned)tv.tv_usec >> 4);
X	(void) initstate(n, diestate[nstate++], sizeof diestate[0]);
X	for(n %= 27;n != 0;--n)
X		(void) random();
X}
X
X/*
X**	dieroll:
X**		if jokermode is true
X**			roll a trick six-sided die which may show a JOKER on
X**			any face every once in thirteen rolls
X**		else
X**			roll a regular six-sided die
X*/
Xdieroll()
X{
X	static which	= 0;
X
X#define	THIRTEEN	(2 * SIDES + 1)
X
X	/*
X	**	We use three random number states for the dice because it turns out
X	**	that the RNG is not good for producing random *strings* of numbers.
X	**	This method does seem to increase randomness for the combinations
X	**	involving three to five dice.  Maybe we should use NDICE states,
X	**	but how do we ensure that our seeds are different enough?
X	*/
X	(void) setstate(diestate[which++ % 3]);
X
X	if(jokermode == True) {
X		int		s;
X
X		if((s = RANDOM() % THIRTEEN) == THIRTEEN - 1)
X			return JOKER;
X		return s % SIDES + 1;
X	}
X
X	return RANDOM() % SIDES + 1;
X
X#undef	THIRTEEN
X}
X
X/*
X**	randint: return a random integer from 1 to n
X*/
Xrandint(n)
X{
X	if(n <= 1)
X		return 1;
X	(void) setstate(numstate);
X	return RANDOM() % n + 1;
X}
X
X/*
X**	hesitate: random hesitation in the range minv to maxv milliseconds
XXXX		No checking of arguments is done.
X*/
Xhesitate(minv, maxv)
Xlong	minv, maxv;
X{
X	long			diff, t;
X	struct timeval	tv;
X
X	if((diff = maxv - minv) <= 1)
X		t = minv;
X	else {
X		(void) setstate(numstate);
X		t = random() % diff + minv;
X	}
X
X	tv.tv_sec = t / 1000;
X	tv.tv_usec = (t % 1000) * 1000;
X	(void) select(32, NOSEL, NOSEL, NOSEL, &tv);
X}
END_OF_FILE
if test 3095 -ne `wc -c <'random.c'`; then
    echo shar: \"'random.c'\" unpacked with wrong size!
fi
# end of 'random.c'
fi
echo shar: End of archive 8 \(of 8\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 8 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0