[net.sources] Modified "chase" game

chris@eneevax.UUCP (01/23/84)

Here is source code for a modified version of the game ``chase''.  While
bored one afternoon I tried it and got annoyed at the various bugs, so I
rewrote it.  I've incorporated a suggestion from Linton Floyd that makes
the game considerably more challenging.

This program requires the Maryland Window Library, and includes a random
number generator written in Vax assembly code (no, I didn't write it; I
got it from someone who got it from someone else).  However, if you have
the C library rand() routine you can write a randint() function easily
enough -- see the comments in the Makefile.

Oh yes, the best part:  the "-r" option lets you use the Rogue motion
keys.

Chris

: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
	all=TRUE
fi
/bin/echo 'Extracting Makefile'
sed 's/^X//' <<'//go.sysin dd *' >Makefile
# Makefile for chase
#
# rand.s is for Vaxen.  The only routines I use from it are srand and randint.
# randint(n) returns an integer in the range [0..n-1], and can be done on a
# 32 bit machine with
#	(int) ((double) n * ((double) rand () / 2147483648.))
# or for 16 bit machines
#	(int) ((double) n * ((double) rand () / 32768.))
# assuming that rand() returns a positive integer.
#
# -- 23 Jan 1983 Chris Torek

OBJS=	chase.o dochase.o gen.o initwin.o key.o move.o rand.o
CFLAGS=	-O

chase: $(OBJS)
	cc -o chase $(OBJS) -lwinlib -ljobs -ltermlib

chase.o: chase.c chase.h
dochase.o: dochase.c chase.h
gen.o: gen.c chase.h
initwin.o: initwin.c chase.h
key.o: key.c chase.h
move.o: move.c chase.h
rand.o: rand.s
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 Makefile
	/bin/echo -n '	'; /bin/ls -ld Makefile
fi
/bin/echo 'Extracting chase.c'
sed 's/^X//' <<'//go.sysin dd *' >chase.c
#ifndef lint
static char rcsid[] = "$Header: /usr/enee/chris/bin/src/chase/RCS/chase.c,v 1.2 84/01/23 04:05:55 chris Rel $";
#endif

X/*
 * $Header: /usr/enee/chris/bin/src/chase/RCS/chase.c,v 1.2 84/01/23 04:05:55 chris Rel $
 *
 * $Log:	chase.c,v $
 * Revision 1.2  84/01/23  04:05:55  chris
 * "fields"->"fences"
 * 
 * Revision 1.1  84/01/23  03:58:01  chris
 * Initial revision
 * 
 */

#include "chase.h"
#include <ctype.h>

main (argc, argv)
register int argc;
register char **argv;
{
    static char askr[] = "How many robots? ";
    static char askef[] = "How many electric fences? ";
    int i;
    printf ("          Welcome to Chase\n");
    while (argc > 1 && argv[1][0] == '-') {
	register char *s;
	argc--;
	argv++;
	s = &argv[0][1];
	while (*s) switch (*s++) {
	    case 'r':
		WantRogueStyle++;
		break;
	    default:
		fprintf (stderr, "Usage: chase [ -r ] [ robots [ fences ]]\n");
		exit (1);
	}
    }
    if (argc > 1)
	GetNum (argv[1], &Robots, 1, MaxRobots, askr);
    else
	GetNum ((char *) 0, &Robots, 1, MaxRobots, askr);
    if (argc > 2)
	GetNum (argv[2], &EFences, 0, MaxEFences, askef);
    else
	GetNum ((char *) 0, &EFences, 0, MaxEFences, askef);
    GetKey = WantRogueStyle ? RogueGetKey : OldGetKey;
    InitWin ();
    srand (time ((long *) 0) + getpid ());
    i = randint ((Robots + 1) >> 1) + (Robots >> 2);
    Gen (i, HRobotChar);
    Gen (Robots - i, RobotChar);
    Gen (EFences, EFenceChar);
    PlaceSelf ();
    DoChase ();
}

X/* Get a number between min and max, from optional string str or keyboard */
GetNum (str, num, min, max, prompt)
char *str;
register int *num;
int min, max;
char *prompt;
{
    static char *remember;
    static char buf[100];

    for (;;) {
	if (str) {
	    *num = atoi (str);
	    str = 0;
	    remember = 0;
	}
	else {
	    register char *s;

	    if (remember)
		s = remember;
	    else {
		printf (prompt);
		fgets (buf, sizeof buf, stdin);
		s = buf;
	    }
	    while (isspace (*s))
		s++;
	    *num = 0;
	    while (isdigit (*s))
		*num = *num * 10 + *s++ - '0';
	    while (isspace (*s))
		s++;
	    remember = *s ? s : 0;
	}
	if (*num >= min && *num <= max)
	    return;
	printf ("Must be at least %d and at most %d\n", min, max);
    }
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 chase.c
	/bin/echo -n '	'; /bin/ls -ld chase.c
fi
/bin/echo 'Extracting chase.h'
sed 's/^X//' <<'//go.sysin dd *' >chase.h
X/*
 * $Header: /usr/enee/chris/bin/src/chase/RCS/chase.h,v 1.1 84/01/23 03:58:11 chris Rel $
 * chase -- robot hunt game
 *
 * $Log:	chase.h,v $
 * Revision 1.1  84/01/23  03:58:11  chris
 * Initial revision
 * 
 */

#include <stdio.h>
#include <local/window.h>

#define	FieldRows	24
#define	FieldCols	60
#define	UsageRows	22
#define	UsageCols	18
#define	MinRows		(FieldRows > UsageRows ? FieldRows : UsageRows)
#define	MinCols		(FieldCols + UsageCols + 1)

#define	FieldX		(FieldCols-2)
#define	FieldY		(FieldRows-2)

#define	MaxRobots	500
#define	MaxEFences	300
#define	MaxTries	4000	/* for placement; see Gen, PlaceSelf */

#define	SelfChar	'I'	/* You */
#define	RobotChar	'='	/* A robot */
#define HRobotChar	'#'	/* Another type of robot */
#define	EFenceChar	'X'	/* An electric fence */
#define	JunkChar	'@'	/* A junk heap */

Win	*Field;			/* The playing field */
Win	*Usage;			/* Description of keys */
int	Rows;			/* Real screen rows */
int	Cols;			/* Real screen cols */
int	Robots;			/* Number of robots on screen */
int	EFences;		/* Number of E-Fences */
Pos	SelfAt;			/* Self's position in field */
int	(*GetKey) ();		/* Keyboard reader */
int	OldGetKey ();		/* Old-chase-style */
int	RogueGetKey ();		/* Rogue style */
int	WantRogueStyle;		/* True => want rogue-style keys */

#define	KUL	0		/* Key: Up & Left */
#define	KU	1		/* Key: Up */
#define	KUR	2		/* Key: Up & Right */
#define	KL	3		/* Key: Left */
#define	KDOT	4		/* Key: stay */
#define	KR	5		/* Key: Right */
#define	KDL	6		/* Key: Down & Left */
#define	KD	7		/* Key: Down */
#define	KDR	8		/* Key: Down & Right */
#define	KTele	9		/* Key: Teleport */
#define	KStand	10		/* Key: Stand */
#define	KQuit	11		/* Key: Quit */
#define	KRedraw	12		/* Key: Redraw */
#define	KBad	13		/* Key: Bad (others) */
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 chase.h
	/bin/echo -n '	'; /bin/ls -ld chase.h
fi
/bin/echo 'Extracting dochase.c'
sed 's/^X//' <<'//go.sysin dd *' >dochase.c
X/*
 * $Header: /usr/enee/chris/bin/src/chase/RCS/dochase.c,v 1.1 84/01/23 03:58:18 chris Rel $
 *
 * $Log:	dochase.c,v $
 * Revision 1.1  84/01/23  03:58:18  chris
 * Initial revision
 * 
 */

#include "chase.h"

DoChase () {
    register int c;

    WSetRealCursor++;
    for (;;) {
	WRCurRow = SelfAt.row + 1;
	WRCurCol = SelfAt.col + 1;
	Wrefresh (0);
	if (Robots == 0)
	    End ("You have defeated all the robots!");
	switch ((*GetKey) ()) {
	    case EOF:
	    case KQuit:
		Wexit (0);
	    case KUL:
		Move (-1, -1);
		break;
	    case KU:
		Move (-1, 0);
		break;
	    case KUR:
		Move (-1, 1);
		break;
	    case KL:
		Move (0, -1);
		break;
	    case KDOT:
		Move (0, 0);
		break;
	    case KR:
		Move (0, 1);
		break;
	    case KDL:
		Move (1, -1);
		break;
	    case KD:
		Move (1, 0);
		break;
	    case KDR:
		Move (1, 1);
		break;
	    case KTele:
		Teleport ();
		break;
	    case KStand:
		for (;;) {
		    Move (0, 0);
		    Wrefresh (0);
		    if (Robots == 0)
			break;
		}
		break;
	    case KRedraw:
		ScreenGarbaged++;
		break;
	    default:
		Ding ();
		break;
	}
    }
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 dochase.c
	/bin/echo -n '	'; /bin/ls -ld dochase.c
fi
/bin/echo 'Extracting gen.c'
sed 's/^X//' <<'//go.sysin dd *' >gen.c
X/*
 * $Header: /usr/enee/chris/bin/src/chase/RCS/gen.c,v 1.1 84/01/23 03:58:32 chris Rel $
 *
 * $Log:	gen.c,v $
 * Revision 1.1  84/01/23  03:58:32  chris
 * Initial revision
 * 
 */

#include "chase.h"

X/* Generate positions for n things displayed with c */
Gen (n, c)
register int n;
int c;
{
    register int    row,
		    col,
		    tries;

    while (--n >= 0) {
	for (tries = MaxTries; --tries >= 0;) {
	    row = randint (FieldY);
	    col = randint (FieldX);
	    WAcursor (Field, row, col);
	    if (Wread (Field, 1, 0) != ' ')
		continue;
	    WAcursor (Field, row, col);
	    Wputc (c, Field);
	    goto ok;
	}
	Wcleanup ();
	printf ("Unable to place %c after %d tries!\n", c, MaxTries);
	exit (1);
ok:;
    }
}

PlaceSelf () {
    register int tries;

    for (tries = MaxTries; --tries >= 0;) {
	SelfAt.row = randint (FieldY - 2) + 1;
	SelfAt.col = randint (FieldX - 2) + 1;
	WAcursor (Field, SelfAt.row - 1, SelfAt.col - 1);
	if (Wread (Field, 1, 0) != ' ' || Wread (Field, 1, 0) != ' '
		|| Wread (Field, 1, 0) != ' ')
	    continue;
	WAcursor (Field, SelfAt.row, SelfAt.col - 1);
	if (Wread (Field, 1, 0) != ' ' || Wread (Field, 1, 0) != ' '
		|| Wread (Field, 1, 0) != ' ')
	    continue;
	WAcursor (Field, SelfAt.row + 1, SelfAt.col - 1);
	if (Wread (Field, 1, 0) != ' ' || Wread (Field, 1, 0) != ' '
		|| Wread (Field, 1, 0) != ' ')
	    continue;
	WAcursor (Field, SelfAt.row, SelfAt.col);
	Wputc (SelfChar, Field);
	WAcursor (Field, SelfAt.row, SelfAt.col);
	return;
    }
    Wcleanup ();
    printf ("Unable to place self after %d tries!\n", MaxTries);
    exit (1);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 gen.c
	/bin/echo -n '	'; /bin/ls -ld gen.c
fi
/bin/echo 'Extracting initwin.c'
sed 's/^X//' <<'//go.sysin dd *' >initwin.c
X/*
 * $Header: /usr/enee/chris/bin/src/chase/RCS/initwin.c,v 1.1 84/01/23 03:58:54 chris Rel $
 *
 * $Log:	initwin.c,v $
 * Revision 1.1  84/01/23  03:58:54  chris
 * Initial revision
 * 
 */

#include "chase.h"

X/* Initialize the window (display) system */
InitWin () {
    if (Winit (0, 0)) {
	printf ("Sorry, but this program won't run on your terminal.\n");
	exit (1);
    }
    Wscreensize (&Rows, &Cols);
    if (Rows < MinRows || Cols < MinCols) {
	Wcleanup ();
	printf ("Sorry, your screen is too small.\n");
	exit (1);
    }
    Field = Wopen (0, 0, 0, FieldCols, FieldRows, 0, 0);
    Usage = Wopen (1, FieldCols+1, 0, UsageCols, UsageRows, 0, 0);
    if (Field == 0 || Usage == 0) {
	Wcleanup ();
	printf ("Something is wrong!  I can't open the window.\n");
	exit (1);
    }
    Woncursor (Field, 0);
    Wframe (Field);
    Wwrap (Field, 0);
    Woncursor (Usage, 0);
    Wnewline (Usage, 1);
    Wwrap (Usage, 0);
    Wputs ("   Move Control:\n", Usage);
    if (WantRogueStyle) {
	Wputs ("      y k u\n", Usage);
        Wputs ("       \\|/\n", Usage);
	Wputs ("      h-.-l\n", Usage);
	Wputs ("       /|\\\n", Usage);
	Wputs ("      b j n\n", Usage);
    }
    else {
	Wputs ("      y u i\n", Usage);
        Wputs ("       \\|/\n", Usage);
	Wputs ("      h-j-k\n", Usage);
	Wputs ("       /|\\\n", Usage);
	Wputs ("      n m ,\n", Usage);
    }
    Wputs ("\n\n\tCommands:\n", Usage);
    Wputs ("  t - Teleport\n", Usage);
    Wputs ("  s - Last stand\n", Usage);
    Wputs ("  q - Quit\n", Usage);
    Wputs (" ^L - Redraw\n", Usage);
    Wputs ("\n\n\tKey\n", Usage);
    Wputs (" I - You\n = - Robot\n # - Robot\n X - Electric\n     Fence\n @ - Junk heap", Usage);
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 initwin.c
	/bin/echo -n '	'; /bin/ls -ld initwin.c
fi
/bin/echo 'Extracting key.c'
sed 's/^X//' <<'//go.sysin dd *' >key.c
X/*
 * $Header: /usr/enee/chris/bin/src/chase/RCS/key.c,v 1.1 84/01/23 03:59:06 chris Rel $
 *
 * $Log:	key.c,v $
 * Revision 1.1  84/01/23  03:59:06  chris
 * Initial revision
 * 
 */

#include "chase.h"

X/* Get a key type, old chase style keyboard */
OldGetKey () {
    switch (getchar ()) {
	case EOF:
	    return EOF;
	case 'y': case 'Y':
	    return KUL;
	case 'u': case 'U':
	    return KU;
	case 'i': case 'I':
	    return KUR;
	case 'h': case 'H':
	    return KL;
	case 'j': case 'J':
	    return KDOT;
	case 'k': case 'K':
	    return KR;
	case 'n': case 'N':
	    return KDL;
	case 'm': case 'M':
	    return KD;
	case ',':
	    return KDR;
	case 't': case 'T':
	    return KTele;
	case 's': case 'S':
	    return KStand;
	case 'q': case 'Q':
	    return KQuit;
	case 014:
	    return KRedraw;
	default:
	    return KBad;
    }
}

X/* Get a key type, new Rogue style */
RogueGetKey () {
    switch (getchar ()) {
	case EOF:
	    return EOF;
	case 'y': case 'Y':
	    return KUL;
	case 'k': case 'K':
	    return KU;
	case 'u': case 'U':
	    return KUR;
	case 'h': case 'H':
	    return KL;
	case '.':
	    return KDOT;
	case 'l': case 'L':
	    return KR;
	case 'b': case 'B':
	    return KDL;
	case 'j': case 'J':
	    return KD;
	case 'n': case 'N':
	    return KDR;
	case 't': case 'T':
	    return KTele;
	case 's': case 'S':
	    return KStand;
	case 'q': case 'Q':
	    return KQuit;
	case 014:
	    return KRedraw;
	default:
	    return KBad;
    }
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 key.c
	/bin/echo -n '	'; /bin/ls -ld key.c
fi
/bin/echo 'Extracting move.c'
sed 's/^X//' <<'//go.sysin dd *' >move.c
X/*
 * $Header: /usr/enee/chris/bin/src/chase/RCS/move.c,v 1.2 84/01/23 04:06:21 chris Rel $
 *
 * $Log:	move.c,v $
 * Revision 1.2  84/01/23  04:06:21  chris
 * "field"->"fence"
 * 
 * Revision 1.1  84/01/23  03:59:13  chris
 * Initial revision
 * 
 */

#include "chase.h"

X/* Bad character found in field window */
BadChar (c, y, x)
int c, y, x;
{
    Wcleanup ();
    printf ("Odd character '%c' found at (%d, %d)\n", c, y, x);
    exit (1);
}

X/* Sign function */
#define sgn(x) ((x) < 0 ? -1 : (x) ? 1 : 0)

X/* Absolute value */
#define abs(x) ((x) < 0 ? -(x) : (x))

X/* Move self, then robots */
Move (DelY, DelX)
int DelY, DelX;
{
    register int c, y, x;
    register char *np;
    int DoMunch;
    static char new[FieldY * FieldX];
    static int beenhere;
    static int minX, minY, maxX, maxY;	/* Field-robot-scan optimization */

    /* Move self */
    if (DelY || DelX) {
	if (SelfAt.row + DelY < 0 || SelfAt.row + DelY >= FieldY
		|| SelfAt.col + DelX < 0 || SelfAt.col + DelX >= FieldX) {
	    Ding ();
	    return;
	}
	WAcursor (Field, SelfAt.row, SelfAt.col);
	Wputc (' ', Field);		/* Blank out self */
	WAcursor (Field, SelfAt.row += DelY, SelfAt.col += DelX);
	switch (c = Wread (Field, 1, 0)) {
	    case HRobotChar:
	    case RobotChar:
		Munch ();
	    case EFenceChar:
		End ("You ran into an electric fence and are now dead.");
	    case JunkChar:
		ForcedStand ();
		return;
	    case ' ':
		break;
	    default:
		BadChar (c, SelfAt.row, SelfAt.col);
	}
	WAcursor (Field, SelfAt.row, SelfAt.col);
	Wputc (SelfChar, Field);
	WAcursor (Field, SelfAt.row, SelfAt.col);
    }
    WRCurRow = SelfAt.row + 1;
    WRCurCol = SelfAt.col + 1;
    Wrefresh (0);

    /* Move robots */
    if (beenhere) {
	for (np = new + sizeof new; np > new;)
	    *--np = 0;
    }
    else
	maxX = FieldX - 1, maxY = FieldY - 1, beenhere++;
    for (y = minY; y <= maxY; y++) {
	WAcursor (Field, y, minX);
	for (x = minX; x <= maxX; x++) {
	    register int ny, nx;
	    int nc;

	    c = Wread (Field, 1, 0);
	    if (c != RobotChar && c != HRobotChar)
		continue;
	    WAcursor (Field, y, x);
	    Wputc (' ', Field);
	    if (c == RobotChar) {
		ny = y + (y < SelfAt.row ? 1 : y == SelfAt.row ? 0 : -1);
		nx = x + (x < SelfAt.col ? 1 : x == SelfAt.col ? 0 : -1);
	    }
	    else {
		ny = SelfAt.row - y;
		nx = SelfAt.col - x;
		if (abs (ny) < abs (nx))
		    nx = x + sgn (nx), ny = y;
		else if (abs (nx) < abs (ny))
		    nx = x,            ny = y + sgn (ny);
		else
		    nx = x + sgn (nx), ny = y + sgn (ny);
	    }
	    WAcursor (Field, ny, nx);
	    if ((nc = Wread (Field, 1, 0)) == EFenceChar || nc == JunkChar)
		Robots--;	/* Destroy one robot */
	    else {
		np = &new[ny * FieldX + nx];
		if (*np == 0)
		    *np = c;
		else if (*np != JunkChar)
		    *np = JunkChar, Robots -= 2;
		else
		    Robots--;
	    }
	    WAcursor (Field, y, x + 1);
	}
    }
    np = new;
    DoMunch = 0;
    minX = FieldX;
    minY = FieldY;
    maxX = 0;
    maxY = 0;
    for (y = 0; y < FieldY; y++) {
	for (x = 0; x < FieldX; x++) {
	    if ((c = *np++) == 0)
		continue;
	    if (y < minY)
		minY = y;
	    if (y > maxY)
		maxY = y;
	    if (x < minX)
		minX = x;
	    if (x > maxX)
		maxX = x;
	    if (y == SelfAt.row && x == SelfAt.col)
		DoMunch++;
	    WAcursor (Field, y, x);
	    Wputc (c, Field);
	}
    }
    if (DoMunch)
	Munch ();
}

X/* End of game routine */
End (message)
char *message;
{
    Wrefresh (1);
    Wcleanup ();
    printf ("%s\n", message);
    exit (0);
}

X/* Get munched by a robot */
Munch () {
    Wauxcursor (Field, SelfAt.row + 1, SelfAt.col + 1);
    Waputs ("*MUNCH*", WINVERSE, Field);
    End ("You have been captured and eaten by robots.");
}

X/* Teleport */
Teleport () {
    register int y, x, tries;

    if (randint ((Robots / 10) + 10) == 0)
	Munch ();
    WAcursor (Field, SelfAt.row, SelfAt.col);
    Wputc (' ', Field);
    for (tries = MaxTries; --tries >= 0;) {
	y = randint (FieldY);
	x = randint (FieldX);
	WAcursor (Field, y, x);
	if (Wread (Field, 1, 0) != ' ')
	    continue;
	WAcursor (Field, SelfAt.row = y, SelfAt.col = x);
	Wputc (SelfChar, Field);
	Move (0, 0);
	return;
    }
    Wcleanup ();
    printf ("Unable to place self after %d tries!\n", MaxTries);
    exit (1);
}

ForcedStand () {
    Win *msg;
    WAcursor (Field, SelfAt.row, SelfAt.col);
    Wputc (SelfChar, Field);
    WAcursor (Field, SelfAt.row, SelfAt.col);
    WRCurRow = SelfAt.row + 1;
    WRCurCol = SelfAt.col + 1;
    msg = Wopen (0, 1, FieldRows - 1, FieldCols - 2, 1, 0, 0);
    if (msg) {
	Woncursor (msg, 0);
	Wsetmode (msg, WBLINK);
	Wputs ("You are trapped in a junk pile!", msg);
    }
    Wrefresh (0);
    for (;;) {
	Move (0, 0);
	Wrefresh (0);
	if (Robots == 0)
	    return;
    }
}
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 move.c
	/bin/echo -n '	'; /bin/ls -ld move.c
fi
/bin/echo 'Extracting rand.s'
sed 's/^X//' <<'//go.sysin dd *' >rand.s
	.data
	.align	2
_randx:
	.long	1

	.text
	.align	2
	.globl	_srand		# set the random seed
_srand:				# srand(seed) int seed;
	.word	0
	movl	_randx,r0
	movl	4(ap),_randx
	ret

	.align	2
	.globl	_rand		# give a 31 bit random positive integer
_rand:				# int rand()
	.word	0
	jsb	rand
	bicl2	$1,r0
	rotl	$-1,r0,r0
	ret

	.align	2
	.globl	_randint	# return a number in [0..n-1]
_randint:			# int randint(n) int n;
	.word	0
	jsb	rand
	emul	4(ap),r0,$0,r2
	tstl	r0
	jgeq	L1
	addl3	4(ap),r3,r0
	ret
L1:	movl	r3,r0
	ret

	.align	2
# compute the next 32 bit random number
rand:	mull3	$505360173,_randx,r0
	addl2	$907633385,r0
	movl	r0,_randx
	rsb

	.align	2
	.globl	_flat		# give a random double in [0.,1.)
_flat:				# double flat()
	.word	0
	jsb	rand
	movl	r0,r2
	movf	$0f1.0,r0
	extzv	$25,$7,r2,r3
	insv	r3,$0,$7,r0
	extzv	$9,$16,r2,r3
	insv	r3,$16,$16,r0
	extzv	$0,$9,r2,r1
	subd2	$0d1.0,r0
	ret
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
	/bin/chmod 644 rand.s
	/bin/echo -n '	'; /bin/ls -ld rand.s
fi
-- 
Chris Torek, Dept of CS, Univeristy of Maryland, College Park, MD
...!umcp-cs!chris   chris%umcp-cs@CSNet-Relay