[comp.sources.games] v08i071: shuffle - a little curses based game of logic., Part01/01

billr@saab.CNA.TEK.COM (Bill Randle) (11/23/89)

Submitted-by: Stephan Dasia E407 <stephand@maestro.htsa.aha.nl>
Posting-number: Volume 8, Issue 71
Archive-name: shuffle/Part01

#! /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 1 (of 1)."
# Contents:  FILES Makefile README game.c main.c shuffle.6 shuffle.h
#   switch.c visual.c xrand.c
# Wrapped by billr@saab on Wed Nov 22 15:03:49 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'FILES' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'FILES'\"
else
echo shar: Extracting \"'FILES'\" \(434 characters\)
sed "s/^X//" >'FILES' <<'END_OF_FILE'
XYou should have:
X
XMakefile:	this is the makefile, it needs some modification of directory
X		names
X
Xshuffle.6:	this is the unix style manual page formatted in -man macros
X		you can modify the filenames in it.
X
Xshuffle.h	this is the include file for the include files I use.
X		Here are also some modifications necessary.
X
X
XThe rest of the files are the source files, this is a manifest of them:
X
Xgame.c
Xmain.c
Xswitch.c
Xvisual.c
Xxrand.c
END_OF_FILE
if test 434 -ne `wc -c <'FILES'`; then
    echo shar: \"'FILES'\" unpacked with wrong size!
fi
# end of 'FILES'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(2375 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# Makefile for shuffle V1.0
X#
X# 21/11/89
X#
X# Stephan Dasia   stephand@maestro.htsa.aha.nl
X#                 stephand@htsa.UUCP
X#                 ...!hp4nl!htsa!stephand
X
X
X# Use these lines for BSD.
X#Add library 'lseq' for sequent system.
XLIBS= -lcurses -ltermcap -lm
XCFLAGS = -O
X
X# uncomment these lines for SYSV
X#LIBS= -lcurses -lm
X#CFLAGS = -O -DSYSV
X
X# If you can compile on a sequent system use :
X#PARALLEL= &
X#else
XPARALLEL=
X
XCC = cc
X
X# where the binary will go
XDESTDIR = /usr/local/games
XMANDIR	= /usr/man/man6
X
XINC = 	shuffle.h
X
XSRC =	game.c\
X	main.c\
X	switch.c\
X	visual.c\
X	xrand.c
X
XOBJ = 	game.o\
X	main.o\
X	switch.o\
X	visual.o\
X	xrand.o
X
Xshuffle: $(PARALLEL) $(OBJ) $(INC)
X	 cc -o shuffle $(OBJ) $(LIBS)
X
Xdebug: $(PARALLEL) $(OBJ) $(INC)
X	cc -g -o shuffle $(OBJ) $(LIBS)
X
Xinstall: shuffle
X	install -s -m 711 shuffle $(DESTDIR)
X	install -o -m 400 shuffle.6 $(MANDIR)
X#	install -s -o games -m 711 shuffle $(DESTDIR)
X#	install -o manual -400 shuffle.6 $(MANDIR)
X
Xclean:
X	/bin/rm -rf shuffle *.o core
X
Xshar:
X	@/bin/rm -rf ../shuffle.shar
X	shar -vc README FILES Makefile *.c *.h shuffle.man > ../shuffle.shar
X
Xall: clean shuffle install
X
Xdepend:
X	mkdep $(CFLAGS) $(SRC)
X
X# DO NOT DELETE THIS LINE -- mkdep uses it.
X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
X
Xgame.o: game.c shuffle.h /usr/include/stdio.h /usr/include/math.h
Xgame.o: /usr/include/curses.h /usr/include/stdio.h /usr/include/sgtty.h
Xgame.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
Xgame.o: /usr/include/sys/ttydev.h /usr/include/sgtty.h
Xmain.o: main.c shuffle.h /usr/include/stdio.h /usr/include/math.h
Xmain.o: /usr/include/curses.h /usr/include/stdio.h /usr/include/sgtty.h
Xmain.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
Xmain.o: /usr/include/sys/ttydev.h /usr/include/sgtty.h
Xswitch.o: switch.c shuffle.h /usr/include/stdio.h /usr/include/math.h
Xswitch.o: /usr/include/curses.h /usr/include/stdio.h /usr/include/sgtty.h
Xswitch.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
Xswitch.o: /usr/include/sys/ttydev.h /usr/include/sgtty.h
Xvisual.o: visual.c shuffle.h /usr/include/stdio.h /usr/include/math.h
Xvisual.o: /usr/include/curses.h /usr/include/stdio.h /usr/include/sgtty.h
Xvisual.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h
Xvisual.o: /usr/include/sys/ttydev.h /usr/include/sgtty.h
Xxrand.o: xrand.c
X
X# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
END_OF_FILE
if test 2375 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(440 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XShuffle:
X
X	I wrote this as a way to learn curses.
X
X	I have successfully compiled and run shuffle on a Sequent
X	running under 4.2BSD and a HP9000 running under HP-UX
X
X	When I first wrote this I had a little knowledge of how to
X	make the code portable, so if you patch the code to run on
X	another system I would REALLY appreciate your input and code.
X
X	Stephan Dasia
X	stephand@maestro.htsa.aha.nl
X	stephand@htsa.UUCP
X	...!hp4nl!htsa!stephand
END_OF_FILE
if test 440 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'game.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'game.c'\"
else
echo shar: Extracting \"'game.c'\" \(2364 characters\)
sed "s/^X//" >'game.c' <<'END_OF_FILE'
X/*
X** Written by Stephan Dasia.
X**
X** permission is granted to freely distribute this code provided that you:
X**
X** 1) don't charge for it
X** 2) leave my name and header on it
X** 3) clearly document your changes and place your name on them
X** 4) and please send the changes to me
X**
X*/
X/* Shuffle: game()	This is main game loop				*/
X/*									*/
X/*          end_game()	This procedure is called when a level		*/
X/*			is ended. It quits if you did it in to		*/
X/*			many turns.					*/
X/*									*/
X
X#include "shuffle.h"
X
Xgame(row,level)
Xint *row[],level;
X{
X int nbr ,counter;
X char c;
X
X  do
X  {
X    counter=0;
X    screen();
X    switch_row(row,level);
X    draw_row(row,level,counter);
X    if(counter==0)
X    {
X      move(18,20);
X      printw("Wich switch ? ");
X      mvcur(0,0,18,35);
X    }
X    refresh();
X    do
X    {
X      do
X      {
X        c=getch();
X        c&=0x7f;
X	nbr=0;
X        if(c>='1' && c<='4')
X        {
X          counter++;
X          nbr=1;
X          mvcur(0,0,18,35);
X          printw("%c",c);
X        }
X        if(c=='\022')
X        {
X	  clear();
X          screen();
X          draw_row(row,level,counter);
X          refresh();
X        }
X        if(c=='?' || c=='h' || c=='H')
X        {
X          clear();
X          help();
X          refresh();
X          while((c=getch()) != ' ');
X	  clear();
X          screen();
X          draw_row(row,level,counter);
X          refresh();
X        }
X      }
X      while( nbr!=1 && c!='?' && c!='h' && c!='H' && c!='q' && c!='Q');
X      do_switch(row,c-'0');
X      draw_row(row,level,counter);
X      refresh();
X    }
X    while(test_row(row) ==0 && c!='q' && c!='Q');
X    if(c!='q' && c!='Q')
X      end_game(counter,level);
X    level++;
X  }
X  while(c!='q' && c!='Q' && counter<test_level(level) && level<=MAXLEVEL);
X  if(c=='q' || c=='Q')
X  {
X    clear();
X    refresh();
X  }
X}
X
X
Xend_game(cntr,lvl)	/* gives a next level if you did it ok, and     */
Xint cntr,lvl;		/* stops it if you did it in to many turns	*/
X{
X  char x;
X
X  move(20,2);
X  if(cntr<=test_level(lvl))
X  {
X    printw("You did it in %d switches.",cntr);
X    move(20,42);
X    printw("press <space> to continue");
X    refresh();
X    move(20,2);
X    clrtoeol();
X    while((x=getch()) !=' ');
X  }
X  else
X  {
X    printw("You did it in %d switches and",cntr);
X    printw(" it could be done in %d switches.\n\n",lvl*FAC1);    
X    refresh();
X    exit();
X  }
X}
END_OF_FILE
if test 2364 -ne `wc -c <'game.c'`; then
    echo shar: \"'game.c'\" unpacked with wrong size!
fi
# end of 'game.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(2321 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/*
X** Written by Stephan Dasia.
X**
X** permission is granted to freely distribute this code provided that you:
X**
X** 1) don't charge for it
X** 2) leave my name and header on it
X** 3) clearly document your changes and place your name on them
X** 4) and please send the changes to me
X**
X*/
X/* Shuffle: main()	Gets the options and executes them		*/
X/*									*/
X/*	    test_row()	Test the order of the numbers			*/
X/*									*/
X/*	    draw_row()	Draw the numbers on the screen			*/
X/*									*/
X
X#include "shuffle.h"
X
X
Xmain(argc, argv, optstring)
Xint argc;
Xchar **argv,*optstring;
X{
X int row[9], t, level;
X char c;
Xextern char *optarg;
Xextern int optind,opterr;
X
X  initscr();
X  savetty();		/* start of the actual game */
X#ifdef SYSV
X  cbreak();
X#else
X  crmode();
X#endif
X  nonl(); noecho(); standend();
X
X  for(t=1;t<10;t++) row[t]=t;
X  level=1;
X  if(argv[1] && !strcmp(argv[1], "-"))
X  {
X    fprintf(stderr, "Usage: %s [-] [-L level]\n", argv[0]);
X    fprintf(stderr, "\t- - give this summary of usage\n");
X    fprintf(stderr, "\tL [level] - start at [level] of difficulty\n");
X    exit(0);
X  }
X
X	/* process the arguments to the program */
X
X  while((c = getopt(argc, argv, "L:")) != EOF)
X  {
X    switch(c)
X    {
X    case 'L':
X  	    level = (int)atoi(optarg);
X	    if(level>MAXLEVEL)
X	      level = MAXLEVEL;
X	    break;
X    default:
X     fprintf(stderr, "Unknown flag or improper usage:\n");
X     fprintf(stderr, "\tuse '%s -' for usage\n", argv[0]);
X    exit(1);
X    }
X  }
X
X  game(row,level);
X  resetty();
X  endwin();
X}
X
X
Xtest_level(lvl)
Xint lvl;
X{
X  int temp;
X  temp = lvl*FAC1*FAC2+0.5;
X  temp = temp % (MAXPLAY_L+1) ;
X  return temp;
X}
X
X
Xtest_row(rwt)                        /* test the correct order of the numbers */
Xint rwt[];
X{
X  int bl=0,q,cnt=0;
X
X    for(q=1;q<10;q++)
X     if(rwt[q]==q) cnt++;
X    if(cnt==9) bl=1;
X    return(bl);
X}
X
X
Xdraw_row(rw,lvl,cntr)                /* Draw the numbers on the screen */
Xint *rw[],lvl,cntr;
X{
X  move(11,3);
X  printw("| %d |   | %d |   | %d |   ",rw[1],rw[2],rw[3]);
X  printw("| %d |   | %d |   | %d |   ",rw[4],rw[5],rw[6]);
X  printw("| %d |   | %d |   | %d | \n",rw[7],rw[8],rw[9]);
X  move(18,10);
X  printw("%d",lvl);
X  move(18,42);
X  if(cntr!=0)
X    printw("moves : %d",cntr);
X  else
X    printw("moves : ");
X  move(18,20);
X  printw("Last switch ? ");
X  mvcur(0,0,18,35);
X}
END_OF_FILE
if test 2321 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'shuffle.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shuffle.6'\"
else
echo shar: Extracting \"'shuffle.6'\" \(1344 characters\)
sed "s/^X//" >'shuffle.6' <<'END_OF_FILE'
X.TH SHUFFLE 6 "21 November 1989" "UNIX Programmer's Manual"
X.SH NAME
Xshuffle - shuffle the numbers.
X.SH SYNOPSIS
X.B /usr/games/shuffle
X[-] [-L level]
X.SH DESCRIPTION
X.B Shuffle
Xis a game of logic. A randomly swapped row of numbers is presented
Xon the screen. The object of the game is, to swap the row of numbers
Xin the correct order. If you succeed to do this in less turns, then the
Xcomputer needed to make the row, you advance a level. Otherwise the game
Xends.
X.br
X.SH ARGUMENTS
X
XThe command line arguments are as follows:
X
X.B
X-
X- give summary of usage
X.br
X.B
X-
XL
X.I [level]
X- start at [level] of difficulty
X.br
X
X.SH COMMANDS
X
X.B 1
X- switch the boxes one to four.
X.br
X.B 2
X- switch the boxes two to five.
X.br
X.B 3
X- switch the boxes five to eight.
X.br
X.B 4
X- switch the boxes six to nine.
X.br
X.B ?,h
X- online help 
X.br
X.B q
X- quit game 
X.br
X.B ^R
X- redraw screen.
X.br
X.SH DIAGNOSTICS
X.I Your terminal must have cursor movement capabilities: 
X.br
XThis is message from the cursor movement package informing you that
Xyour terminal is not sophisticated enough for shuffle. In some cases, your
Xtermcap entry might be to blame.
X
X.br
X
X.SH AUTHOR
Xstephand@maestro.htsa.aha.nl
X.br
X{...}!hp4nl!htsa!stephand
X.br
X.SH NOTES
XShuffle is meant for free distribution. It is not to be licensed or sold
Xfor profit.
X
X.br
XAnyone who wishes a copy may have one.
END_OF_FILE
if test 1344 -ne `wc -c <'shuffle.6'`; then
    echo shar: \"'shuffle.6'\" unpacked with wrong size!
fi
# end of 'shuffle.6'
fi
if test -f 'shuffle.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shuffle.h'\"
else
echo shar: Extracting \"'shuffle.h'\" \(898 characters\)
sed "s/^X//" >'shuffle.h' <<'END_OF_FILE'
X/*
X** Written by Stephan Dasia.
X**
X** permission is granted to freely distribute this code provided that you:
X**
X** 1) don't charge for it
X** 2) leave my name and header on it
X** 3) clearly document your changes and place your name on them
X** 4) and please send the changes to me
X**
X*/
X/* Shuffle: shuffle.h							*/
X/*									*/
X/* this is the header file, it does all the necessary includes.		*/
X
X
X#include <stdio.h>
X#include <math.h>
X#include <curses.h>
X
X/* Here start the definitions of the random generator. I've used an	*/
X/* other random generator which is declared in xrand.c.			*/  
X
X#define RANDOM1		rnd_i
X#define RANDOM2		rnd_init
X
X/* Here are the definitions of MAXLEVEL, be sure that the last number	*/
X/* of MAXLEVEL is a 0.							*/
X
X#define FAC1		5
X#define FAC2		1.1
X#define MAXLEVEL 	1000
X#define MAXCOMP_L	5000	/* MAXLEVEL*FAC1			*/
X#define MAXPLAY_L	5500	/* MAXCOMP_L*FAC2			*/
END_OF_FILE
if test 898 -ne `wc -c <'shuffle.h'`; then
    echo shar: \"'shuffle.h'\" unpacked with wrong size!
fi
# end of 'shuffle.h'
fi
if test -f 'switch.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'switch.c'\"
else
echo shar: Extracting \"'switch.c'\" \(2169 characters\)
sed "s/^X//" >'switch.c' <<'END_OF_FILE'
X/*
X** Written by Stephan Dasia.
X**
X** permission is granted to freely distribute this code provided that you:
X**
X** 1) don't charge for it
X** 2) leave my name and header on it
X** 3) clearly document your changes and place your name on them
X** 4) and please send the changes to me
X**
X*/
X/* Shuffle: switch_row		switch the numbers for the computer	*/
X/*									*/
X/*	    do_switch()		switch the numbers for the player	*/
X/*									*/
X/*	    switch_number()	switch the numbers			*/
X/*									*/
X
X#include "shuffle.h"
X
X
Xswitch_row(rw,lvl)	/* switch the numbers for the computer */
Xint *rw[] , lvl;
X{
X  int r[MAXPLAY_L],cnt,df,x;
X
X  RANDOM2(time(0));
X  do
X  {
X    x=2;
X    r[x-2]=RANDOM1()%4+1;
X    do
X    {
X      r[x-1]=RANDOM1()%4+1;
X    }
X    while(r[x-2]==r[x-1]);
X    for(cnt=1;cnt<=lvl*FAC1;cnt++)
X    {
X      do
X      {
X        r[x]=RANDOM1()%4+1;
X      }
X      while(r[x-1]==r[x]);
X      df=abs(r[x-2]-r[x-1]);
X      switch(df)
X      {
X        case(2): if(r[x-2] ==1 || r[x-1] ==1)
X                 {
X                     r[x]=RANDOM1()%2;
X                     if(r[x]==0)
X                       r[x]=2;
X                     else
X                       r[x]=4;
X                 }
X                 else
X                 {
X                     r[x]=RANDOM1()%2;
X                     if(r[x]==0)
X                       r[x]=1;
X                     else
X                       r[x]=3;
X                 }
X                 break;
X        case(3): r[x]=RANDOM1()%2+2;
X                 break;
X      }
X      do_switch(rw,r[x]);
X      x++;
X    }
X  }
X  while(test_row(rw) == 1);
X}
X
X
Xdo_switch(rw,mv)	/* switch the numbers for the player */
Xint *rw[];
Xint mv;
X{
X   switch(mv)
X   {
X     case(1): switch_number(rw,1,2,3,4);
X                break;
X     case(2): switch_number(rw,2,3,4,5);
X                break;
X     case(3): switch_number(rw,5,6,7,8);
X                break;
X     case(4): switch_number(rw,6,7,8,9);
X                break;
X   }
X}
X
X
Xswitch_number(rwx,n1,n2,n3,n4)	/* switch the numbers */
Xint *rwx[],n1,n2,n3,n4;
X{
X  int *temp;
X    temp    = rwx[n1];
X    rwx[n1] = rwx[n4];
X    rwx[n4] = temp;
X    temp    = rwx[n2];
X    rwx[n2] = rwx[n3];
X    rwx[n3] = temp;
X}
END_OF_FILE
if test 2169 -ne `wc -c <'switch.c'`; then
    echo shar: \"'switch.c'\" unpacked with wrong size!
fi
# end of 'switch.c'
fi
if test -f 'visual.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'visual.c'\"
else
echo shar: Extracting \"'visual.c'\" \(2241 characters\)
sed "s/^X//" >'visual.c' <<'END_OF_FILE'
X/*
X** Written by Stephan Dasia.
X**
X** permission is granted to freely distribute this code provided that you:
X**
X** 1) don't charge for it
X** 2) leave my name and header on it
X** 3) clearly document your changes and place your name on them
X** 4) and please send the changes to me
X**
X*/
X/* Shuffle: screen()	The game screen					*/
X/*									*/
X/*          help()	This procedure is the online help		*/
X/*									*/
X
X#include "shuffle.h"
X
X
Xscreen()                             /* game screen */
X{
X  move(8,13);
X  printw("+-----------2-----------+ ");
X  printw("      +-----------4-----------+\n");
X  printw("             |       +---2---+       |  ");
X  printw("     |       +---4---+       |\n");
X  printw("   +---+   +---+   +---+   +---+   +---+");
X  printw("   +---+   +---+   +---+   +---+\n");
X  printw("   |   |   |   |   |   |   |   |   |   |");
X  printw("   |   |   |   |   |   |   |   |\n");
X  printw("   +---+   +---+   +---+   +---+   +---+");
X  printw("   +---+   +---+   +---+   +---+\n");
X  printw("     |       +---1---+       |  ");
X  printw("     |       +---3---+       |\n");
X  printw("     +-----------1-----------+");
X  printw("       +-----------3-----------+\n");
X  move(17,0);
X  printw("+-----------------+---------------------+-------------------");
X  printw("-------------+\n");
X  printw("| LEVEL:          |                     |");
X  printw("                                |\n");
X  printw("+-----------------+---------------------+-------------------");
X  printw("-------------+\n");
X}
X
X
Xhelp()			/* help screen */
X{
X  move(0,30);
X  printw("S H U F F L E\n");
X  move(1,30);
X  printw("-------------");
X  move(3,1);
X  printw("\tThe problem in this game is to get the");
X  printw(" numbers from 1 to 9\n");
X  printw("\tin the correct order using keys ");
X  printw("1 to 4.\n");
X  printw("\tAvailable commands are :\n");
X  printw("\t1   : to switch the boxes one to four.\n");
X  printw("\t2   : to switch the boxes two to five.\n");
X  printw("\t3   : to switch the boxes five to eight.\n");
X  printw("\t4   : to switch the boxes six to nine.\n");
X  printw("\tq   : to end the game.\n");
X  printw("\t?,h : to get this screen.\n");
X  printw("\t^R  : to redraw screen\n");
X  move(16,34);
X  printw("press <space>\n");
X}
END_OF_FILE
if test 2241 -ne `wc -c <'visual.c'`; then
    echo shar: \"'visual.c'\" unpacked with wrong size!
fi
# end of 'visual.c'
fi
if test -f 'xrand.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'xrand.c'\"
else
echo shar: Extracting \"'xrand.c'\" \(8061 characters\)
sed "s/^X//" >'xrand.c' <<'END_OF_FILE'
X/* Random number generators:
X *
X *  rnd_init (unsigned seed) 
X *			: initializes the generator
X *
X *  rnd_i ()		: returns positive integers [0,0x7fffffff]
X *  rnd_u ()		: returns unsigned's        [0,0xffffffff]
X *  rnd_ri (long n)	: returns positive integers [0,n-1]
X *  rnd_01d ()		: returns doubles	    [0.0,1.0)
X *			  Note: ")" is no typo - rnd_01d will not return a 1.0,
X *                              but can return the next smaller FP number.
X *  rnd_ned (double lam): returns neg. exponential distributed doubles [0.0,+inf)
X *  rnd_nedi (double rt): same with lam = 1/rt - used to save divides
X *
X *  Algorithm M as describes in Knuth's "Art of Computer Programming", Vol 2. 1969
X *  is used with a linear congruential generator (to get a good uniform
X *  distribution) that is permuted with a Fibonacci additive congruential
X *  generator to get good independence.
X *
X *  Bit, byte, and word distributions were extensively tested and pass
X *  Chi-squared test near perfect scores (>7E8 numbers tested, Uniformity
X *  assumption holds with probability > 0.999)
X *
X *  Run-up tests for on 7E8 numbers confirm independence with
X *  probability > 0.97.
X *
X *  Plotting random points in 2d reveals no apparent structure.
X *
X *  Autocorrelation on sequences of 5E5 numbers (A(i) = SUM X(n)*X(n-i), i=1..512)
X *  results in no obvious structure (A(i) ~ const).
X *
X *  On a SUN 3/60, rnd_u() takes about 19.4 usec per call, which is about 44%
X *  slower than Berkeley's random() (13.5 usec/call).
X *
X *  Except for speed and memory requirements, this generator outperforms
X *  random() for all tests. (random() scored rather low on uniformity tests,
X *  while independence test differences were less dramatic).
X *
X *  Thanks to M.Mauldin, H.Walker, J.Saxe and M.Molloy for inspiration & help.
X *
X *  (c) Copyright 1988 by A. Nowatzyk
X *
X */
X
X/* LC-parameter selection follows recommendations in 
X * "Handbook of Mathematical Functions" by Abramowitz & Stegun 10th, edi.
X */
X#define LC_A 66049		    /* = 251^2, ~= sqrt(2^32)			*/
X#define LC_C 3907864577		    /* result of a long trial & error series    */
X
X#define Xrnd(x) (x * LC_A + LC_C)   /* the LC polynomial			*/
X			
Xstatic unsigned long Fib[55];	    /* will use X(n) = X(n-55) - X(n-24)	*/
Xstatic int Fib_ind;		    /* current index in circular buffer		*/
Xstatic unsigned long Xrnd_var;	    /* LCA - recurrence variable		*/
Xstatic unsigned long auxtab[256];   /* temporal permutation table		*/
Xstatic unsigned long prmtab[64] = { /* spatial permutation table		*/
X    0xffffffff, 0x00000000,  0x00000000,  0x00000000,  /* 3210 */
X    0x0000ffff, 0x00ff0000,  0x00000000,  0xff000000,  /* 2310 */
X    0xff0000ff, 0x0000ff00,  0x00000000,  0x00ff0000,  /* 3120 */
X    0x00ff00ff, 0x00000000,  0xff00ff00,  0x00000000,  /* 1230 */
X
X    0xffff0000, 0x000000ff,  0x00000000,  0x0000ff00,  /* 3201 */
X    0x00000000, 0x00ff00ff,  0x00000000,  0xff00ff00,  /* 2301 */
X    0xff000000, 0x00000000,  0x000000ff,  0x00ffff00,  /* 3102 */
X    0x00000000, 0x00000000,  0x00000000,  0xffffffff,  /* 2103 */
X
X    0xff00ff00, 0x00000000,  0x00ff00ff,  0x00000000,  /* 3012 */
X    0x0000ff00, 0x00000000,  0x00ff0000,  0xff0000ff,  /* 2013 */
X    0x00000000, 0x00000000,  0xffffffff,  0x00000000,  /* 1032 */
X    0x00000000, 0x0000ff00,  0xffff0000,  0x000000ff,  /* 1023 */
X
X    0x00000000, 0xffffffff,  0x00000000,  0x00000000,  /* 0321 */
X    0x00ffff00, 0xff000000,  0x00000000,  0x000000ff,  /* 0213 */
X    0x00000000, 0xff000000,  0x0000ffff,  0x00ff0000,  /* 0132 */
X    0x00000000, 0xff00ff00,  0x00000000,  0x00ff00ff   /* 0123 */
X};
X
Xunion hack {			    /* used to access doubles as unsigneds	*/
X    double d;
X    unsigned long u[2];
X};
X
Xstatic union hack man;		    /* mantissa bit vector			*/
X
Xrnd_init (seed)			    /* modified: seed 0-31 use precomputed stuff */
X    unsigned seed;
X{
X    register unsigned long u;
X    register int i;
X    double x, y;
X    union hack t;
X
X    static unsigned seed_tab[32] = {
X		0xbdcc47e5, 0x54aea45d, 0xec0df859, 0xda84637b,
X		0xc8c6cb4f, 0x35574b01, 0x28260b7d, 0x0d07fdbf,
X		0x9faaeeb0, 0x613dd169, 0x5ce2d818, 0x85b9e706,
X		0xab2469db, 0xda02b0dc, 0x45c60d6e, 0xffe49d10,
X		0x7224fea3, 0xf9684fc9, 0xfc7ee074, 0x326ce92a,
X		0x366d13b5, 0x17aaa731, 0xeb83a675, 0x7781cb32,
X		0x4ec7c92d, 0x7f187521, 0x2cf346b4, 0xad13310f,
X		0xb89cff2b, 0x12164de1, 0xa865168d, 0x32b56cdf  };
X
X    if (seed < 32)
X	u = seed_tab[seed];
X    else
X	u = seed ^ seed_tab[seed & 31];
X
X    for (i = 55; i--;)		    /* set up Fibonacci additive congruential	*/
X	Fib[i] = u = Xrnd(u);
X
X    for (i = 256; i--;)
X	auxtab[i] = u = Xrnd(u);
X
X    Fib_ind = u % 55;		    /* select a starting point			*/
X
X    Xrnd_var = u;
X
X    if (sizeof(x) != 2 * sizeof(unsigned long)) {
X	x = 0.0;
X	y = 1.0;
X	y /= x;			    /*** intentional divide by 0: rnd_01d will
X					 not work because a double doesn't fit
X					 in 2 unsigned longs on your machine! ***/
X    };
X
X    x = 1.0;
X    y = 0.5;
X    do {			    /* find largest fp-number < 2.0		*/
X	t.d = x;
X	x += y;
X	y *= 0.5;
X    } while (x != t.d && x < 2.0);
X
X    man.d = 1.0;
X    man.u[0] ^= t.u[0];
X    man.u[1] ^= t.u[1];		    /* man is now 1 for each mantissa bit	*/
X}
X
Xlong rnd_i ()
X/*
X * returns a positive, uniformly distributed random number in [0,0x7fffffff]
X */
X{ 
X    register unsigned long i, j, *t = Fib;
X
X    i = Fib_ind;
X    j = t[i];				    /* = X(n-55) */
X    j -= (i >= 24) ? t[i - 24] : t[i + 21]; /* = X(n-24) */
X    t[i] = j;
X    if (++i >= 55) i = 0;
X    Fib_ind = i;
X
X    t = &auxtab[(j >> 24) & 0xff];
X    i = *t;
X    Xrnd_var = *t = Xrnd(Xrnd_var);
X    t = &prmtab[j & 0x3c];
X
X    j =  *t++ & i;
X    j |= *t++ & ((i << 24) | ((i >>  8) & 0x00ffffff));
X    j |= *t++ & ((i << 16) | ((i >> 16) & 0x0000ffff));
X    j |= *t   & ((i <<  8) | ((i >> 24) & 0x000000ff));
X    
X    return j & 0x7fffffff;
X}
X
Xunsigned long rnd_u ()
X/*
X * same as rnd_i, but gives full 32 bit range
X */
X{ 
X    register unsigned long i, j, *t = Fib;
X
X    i = Fib_ind;
X    j = t[i];				    /* = X(n-55) */
X    j -= (i >= 24) ? t[i - 24] : t[i + 21]; /* = X(n-24) */
X    t[i] = j;
X    if (++i >= 55) i = 0;
X    Fib_ind = i;
X
X    t = &auxtab[(j >> 24) & 0xff];
X    i = *t;
X    Xrnd_var = *t = Xrnd(Xrnd_var);
X    t = &prmtab[j & 0x3c];
X
X    j =  *t++ & i;
X    j |= *t++ & ((i << 24) | ((i >>  8) & 0x00ffffff));
X    j |= *t++ & ((i << 16) | ((i >> 16) & 0x0000ffff));
X    j |= *t   & ((i <<  8) | ((i >> 24) & 0x000000ff));
X    
X    return j;
X}
X
Xlong rnd_ri (rng)
X    long rng;
X/*
X * randint: Return a random integer in a given Range [0..rng-1]
X *          Note:  0 < rng
X */
X{
X    register unsigned long  r, a;
X
X    do {
X	r = rnd_i();
X	a = (r / rng) + 1;
X	a *= rng;
X    } while (a >= 0x7fffffff);
X    
X    a--;
X    return a - r;
X}
X
Xdouble rnd_01d ()
X/*
X * returns a uniformly distributed double in the range of [0..1)
X *         or  0.0 <= rnd_01d() < 1.0 to be precise
X *
X * Note: this code assumes that 2 'unsigned long's can hold a 'double'
X *       (works on SUN-3's, SUN-4's, MIPS, VAXen, IBM RT's)
X */
X{
X    union hack t;
X
X    t.d = 1.0;
X
X    t.u[0] |= rnd_u() & man.u[0];	      /* munch in 1st part   */
X    t.u[1] |= rnd_u() & man.u[1];	      /* munch in 2nd part   */
X
X    return t.d - 1.0;
X}
X
Xdouble rnd_ned (lam)
X    double lam;
X/*
X * returns a neg. exponential distributed double in the range of [0..+infinity)
X *         or  0.0 <= rnd_neg() < +infinity to be precise
X *
X * Note: this code assumes that 2 'unsigned long's can hold a 'double'
X *       it also assumes that 'log()' behaves as advertised.
X *
X */
X{
X    union hack t;
X
X    t.d = 1.0;
X
X    t.u[0] |= rnd_u() & man.u[0];	      /* munch in 1st part   */
X    t.u[1] |= rnd_u() & man.u[1];	      /* munch in 2nd part   */
X
X    return -log(2.0 - t.d) / lam;
X}
X
Xdouble rnd_nedi (lam)
X    double lam;
X/*
X * same as 'rnd_ned' called with 1/lam
X *
X * This is used to save a divide operation in some places
X *
X */
X{
X    union hack t;
X
X    t.d = 1.0;
X
X    t.u[0] |= rnd_u() & man.u[0];	      /* munch in 1st part   */
X    t.u[1] |= rnd_u() & man.u[1];	      /* munch in 2nd part   */
X
X    return -log(2.0 - t.d) * lam;
X}
END_OF_FILE
if test 8061 -ne `wc -c <'xrand.c'`; then
    echo shar: \"'xrand.c'\" unpacked with wrong size!
fi
# end of 'xrand.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    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