[net.sources] Another

libes@nbs-amrf.UUCP (Don Libes) (01/31/86)

#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	snake2.6
#	README
#	snake2.c
#	Makefile
#	getkey.c
#	quicksleep.c
#	snake2.h
#	snake2.hlp
#	install.com
#	reinstall.com
# This archive created: Fri Jan 31 14:41:38 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'snake2.6'" '(989 characters)'
if test -f 'snake2.6'
then
	echo shar: over-writing existing file "'snake2.6'"
fi
sed 's/^X//' << \SHAR_EOF > 'snake2.6'
X.TH SNAKE2 6 "University of Rochester"
X.SH NAME
Xsnake2 \- another snake game
X.SH SYNOPSIS
X.B snake2
X.SH DESCRIPTION
XTired of getting eaten by the snake(6) all the time?
XBe a snake!!
XEat other users.
XRun snake2.
X.PP
XYou are the snake.
XYou look like this: ssssssS
X.br
XChange your direction by using the number keypad (i.e. 8 is up,
X2 is down), using the keys around the 'k' key (for righties) or
Xthe 'd' key (for lefties).
XAll 8 directions work.
X.PP
XScore by eating other folks.
XPoint values are based on eatee's size.
XAfter 250 points, all point values are doubled.
XIf you see a capital letter, it means the box has triple point value.
XGo for it!
XBut beware of the root (of all evil).
XIts point value is unknown and sometimes does you more harm than good.
X.PP
XCtrl-L will refresh the screen if necessary (like if somebody writes
Xto you) but won't slow the snake down a mite.
X.SH BUGS
X.PP
XYou can't go to the bathroom in the middle of this game.
X.SH AUTHOR
XDon Libes (seismo!nbs-amrf!libes)
SHAR_EOF
if test 989 -ne "`wc -c 'snake2.6'`"
then
	echo shar: error transmitting "'snake2.6'" '(should have been 989 characters)'
fi
echo shar: extracting "'README'" '(2892 characters)'
if test -f 'README'
then
	echo shar: over-writing existing file "'README'"
fi
sed 's/^X//' << \SHAR_EOF > 'README'
XCopyright (C) 1981 by Don Libes.  This software may be freely copied
Xand distributed for noncommercial purposes provided that this notice
Xremains intact.  Commercial use of this software requires my prior
Xwritten permission.
X
XThese files implement the game of snake2.  snake2 is in no way based
Xon snake(6) from Berkeley except that there is a snake in the picture.
X
Xsnake2 is actually based upon a game I saw for a couple minutes one
Xday at Xerox running on a Data General (c. 1980).  I wrote this
Xwithout access to that one, so it's no longer very similar and
Xcertainly doesn't have any source in common.
X
XThe source for this game is actually useful as an example of how to
Xdo a bunch of not-well-documented things (curses, reading the
Xkeyboard without blocking, <1sec sleeps, updating a file while
Xavoiding the lost-update problem, keeping a setuid log file, etc)
Xwhile still being short.  Additionally, the task of keeping track
Xof the snake and boxes, is cute, and in fact, was used by one
Xprofessor as an assignment for a lower-level programming course.
X
XThis game is known to run under 4.2, Eunice and 4.1 (the latter with
Xthe CMU IPC).  Undoubtedly, it will run under any version of UNIX that
Xcan do the following:
X
X1) Check if the user has hit a key without blocking.  All of 4.2,
X4.1 and Eunice implement the FIONREAD ioctl which returns the number
Xof characters unread in the input buffer.  Additionally, some
Xsystems which claim Berkeley enhancements (eg Unisoft) include this.
XIf that is the case, you don't have to do anything.  Otherwise, just
Xplug your solution into getkey.c and recompile.
X
X2) Sleep for less than a second.  4.2 has select().  Eunice has VMS
Xdo it.  The 4.1 I used had the CMU IPC which had something very
Xsimilar to select.  Some systems (eg Unisoft) implement select in a
Xway that is not useful here.  You must use something else if your
Xselect does not work like the Berkeley select.  For other systems,
Xthere are device drivers available that are designed simply for this
Xpurpose.  Just plug your solution into quicksleep.c and recompile.
X
XNotes, warnings, trust me...
X
XThe actual timeout used is one quarter of a second.  Since the game
Xdoes relatively little processing each move (every .25 seconds), it
Xplaces virtually no load on the system.
X
XIncluded are a man page and (for VMS systems) a help file.  Ignore
Xwhichever one is inappropriate for you.
X
XThe game should be installed setuid with the owner set to "snake" or
X"daemon" or something similarly innocuous, to prevent tampering with
Xthe score file.  Since Eunice does not implement setuid(), Eunice
Xsites must install it with sysprv.  Frightening, isn't it?
X
XIf you have to modify the game to run under your system, please send
Xme back the modifications.  Thanks.
X
XDon Libes
XNational Bureau of Standards
XMet. Bldg, Rm B229
XGaithersburg, MD  20899
X(301) 921-2171
X{seismo,umcp-cs}!nbs-amrf!libes
SHAR_EOF
if test 2892 -ne "`wc -c 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 2892 characters)'
fi
echo shar: extracting "'snake2.c'" '(11780 characters)'
if test -f 'snake2.c'
then
	echo shar: over-writing existing file "'snake2.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'snake2.c'
X/* snake2
X *
X * Copyright (C) 1981 by Don Libes.  This software may be freely copied
X * and distributed for noncommercial purposes provided that this notice
X * remains intact.  Commercial use of this software requires my prior
X * written permission.
X *
X * HISTORY
X * 20-Sep-85  libes at National Bureau of Standards
X *      Modified to support BSD 4.2 and Eunice (BSD 4.1)
X *	Modified to run on any size screen.
X *
X * 07-Aug-81  don at University of Rochester
X *	Fixed lack of rollover bug.  
X *	ioctl(FIONREAD,...) gives # of NEW unread chars added to input
X *	buffer since last call, not just # of unread chars in buffer.
X *
X * 18-Jul-81  don at University of Rochester
X *	Ring structure for snake body was being corrupted.  It seems C's
X *	idea on how to mod negative numbers is backwards.  Hard to tell
X *	if this is a bug, because reference manual is fuzzy on this.
X *
X * 16-Jul-81  don at University of Rochester
X *	Created after playing similar game on DG at Xerox.
X *	Different scoring.  Diagonal moves allowed.  Boxes are people
X *	rather than just points.  Various other hacks.  See man file.
X *	cc snake2.c -lcurses -ltermcap -lipc
X */
X
X#include <sys/types.h>
X#include <curses.h>
X#include <ctype.h>
X#include <pwd.h>
X
X#include "snake2.h"
X
X#define MAXUSERS	255		/* A large number */
X#define MAXLEN		((LINES-2)*(COLS-2))	/* Maximum length of snake */
X#define MAXBOXES	6
X#define SKILL		(12-6)		/* How often we grow */
X#define bell		putchar('\07')	/* Ring my chimes */
X
Xtime_t time();				/* For random factor */
X
Xint *snakex, *snakey;			/* position of snake */
Xint sptr;				/* ptr to snake in its array */
Xint length;				/* length of snake */
Xint turn = 0;				/* number of turns we've had */
Xint points = 0;				/* Points by eating */
Xint diry = 1;				/* direction we are moving */
Xint dirx = 1;				/* initially diagonally and down */
X
X/* Data structures for boxes */
Xstruct {
X	int y;
X	int x;
X	int inuse;
X	char *name;
X	int length;
X	int points;			/* point value of box */
X} boxes[MAXBOXES];
X
Xchar names[MAXUSERS][USERNAME_LENGTH+1];
Xint numnames = 0;			/* number of names in /etc/passwd */
X
X/* Data structures for log */
Xstruct logtype {
X	char name[USERNAME_LENGTH+1];
X	int length;
X	int points;
X	int rows, columns;
X} log[MAXUSERS];
Xlong our_offset;			/* position of our name in log file */
X
X/* scoring algorithm */
X#define score(length,points,rows,columns)	((points)+(length))
X
X/* parameters for lseek */
X#define L_SET	0
X#define L_INCR	1
X#define L_XTND	2
X
Xchar *getlogin(), *whoami;
Xchar *strcpy(), *malloc();
Xint sortlog();
XFILE *fopen();
XFILE *lf;
Xint reluid;				/* uid relative to log file */
Xint usersknown;				/* number of users in log */
Xint userknown = FALSE;				/* if user in log file */
X
XWINDOW *tmpscr;				/* save screen for clear */
XWINDOW *newwin();
X
Xmain()
X{
X	init();
X	while (TRUE) {
X		if (!snake()) break;	/* get user input */
X		quick_sleep(TIMEOUT);
X		ranbox();		/* randomly box */
X		ranbox2();		/* randomly unbox */
X	}
X	quit();
X}
X
Xinit()
X{
X	int i = 0;
X	extern struct passwd *getpwent(), *getpwuid();
X	struct passwd *pwent;
X	long last_offset;	/* keep track of offsets in log file */
X
X#ifdef EUNICE
X	/* if invoked from raw VMS, getlogin() screws up by returning */
X	/* an empty string rather than a null string */
X	if (!((whoami = getlogin()) && whoami[0])) {
X#else
X	if (!(whoami = getlogin())) {
X#endif
X		/* can't just copy ptr from getpwuid since this is */
X		/* static data which will be reused when we read in */
X		/* /etc/passwd! */
X		whoami = malloc(USERNAME_LENGTH+1);
X		strcpy(whoami,getpwuid(getuid())->pw_name);
X	}
X	setuid(geteuid());
X
X	initscr();
X	tmpscr = newwin(LINES,COLS,0,0);
X	box(stdscr,'|','-');
X	noecho();			/* Don't let directions echo! */
X	raw();
X	refresh();
X
X	snakex = (int *)malloc(MAXLEN*sizeof(int));
X	snakey = (int *)malloc(MAXLEN*sizeof(int));
X	snakex[0] = snakey[0] = 2;
X	move(2,2);
X	addch('s');
X	snakey[1] = 3; snakex[1] = 3;
X	move(3,3);
X	addch('s');
X	length = 2;
X	sptr = 1;
X
X	srand((int) time((time_t *)0));
X	/* read in names */
X	while (pwent = getpwent()) {
X		strcpy(names[numnames++],pwent->pw_name);
X	}
X	if (!(lf = fopen(LOG,"r+"))) {
X		cleanup();
X		printf("can't read/update score file (%s)\n",LOG);
X		exit(0);
X	}
X	last_offset = our_offset = 0L;
X	while (5 == fscanf(lf,"%s%d%d%d%d",log[i].name,&log[i].length,
X					&log[i].points,
X					&log[i].rows,
X					&log[i].columns)) {
X		if (!userknown) {
X			if (!strcmp(whoami,log[i].name)) {
X				our_offset = last_offset;
X				reluid = i;
X				userknown = TRUE;
X				/* Give'm something to shoot for */
X				move(LINES-1,50);
X				printw("Personal high score: %d",
X					score(log[i].length,log[i].points,
X						log[i].rows,log[i].columns));
X			} else last_offset = ftell(lf);
X		}
X		i++;
X	}
X
X	if (!userknown) {	/* New entry for this user */
X		our_offset = last_offset;
X		strcpy(log[i].name,whoami);
X		log[i].length = 0;
X		log[i].points = 0;
X		log[i].rows = LINES;
X		log[i].columns = COLS;
X		reluid = i;
X		userknown = TRUE;
X
X		/* make new entry in log file */
X		fseek(lf,0L,L_XTND);	/* EOF */
X		fprintf(lf,"%*s%8d%8d%8d%8d\n",USERNAME_LENGTH,
X					log[i].name,
X					log[i].length,
X					log[i].points,
X					log[i].rows,
X					log[i].columns);
X		i++;
X	}
X	fclose(lf);
X	usersknown = i;
X}
X
Xquit()
X{
X	int i = 0;
X
X	if (score(length,points,LINES,COLS) >
X		score(log[reluid].length,
X			log[reluid].points,
X			log[reluid].rows,
X			log[reluid].columns)) { /* new personal high score! */
X
X		log[reluid].length = length;
X		log[reluid].points = points;
X		log[reluid].rows = LINES;
X		log[reluid].columns = COLS;
X
X		if (!(lf = fopen(LOG,"r+"))) {
X			cleanup();
X			printf("can't update score file (%s)\n",LOG);
X			exit(0);
X		}
X		fseek(lf,our_offset+1,L_SET);
X		fprintf(lf,"%*s%8d%8d%8d%8d\n",USERNAME_LENGTH,
X			whoami,length,points,LINES,COLS);
X		fclose(lf);
X	}
X	/* the 36 here is just the width of the stripe we are painting */
X	/* i.e. it equals the width of the printw */
X	move(1,(COLS-36)/2);
X	printw("%*s%8s%8s%8s",USERNAME_LENGTH,
X		"Who","Length","Points","Score");
X	/* print out top LINES-4 scorers (right on top of game) */
X	qsort(log,usersknown,sizeof(struct logtype),sortlog);
X	for (i=0;i<(LINES-4) && i<usersknown;i++) {
X		move(2+i,(COLS-36)/2);
X		printw("%*s%8d%8d%8d",USERNAME_LENGTH,
X			log[i].name,log[i].length,log[i].points,
X			score(log[i].points,log[i].length,
X				log[i].rows,log[i].columns));
X	}
X	cleanup();
X	/* move UNIX prompt to bottom line (from where?) */
X	mvcur(0,0,LINES-1,0);
X	endwin();
X}
X	
Xsnake()
X{
X	int key;			/* last key struck */
X
X	turn++;
X
X	if (-1 != (key = getkey())) {
X		switch (key) {
X		case 'i': case '8': case 'e':
X			if (diry == 1 && dirx == 0) bell;
X			else {
X				diry = -1;
X				dirx = 0;
X			}
X			break;
X		case 'l': case '6': case 'f':
X			if (diry == 0 && dirx == -1) bell;
X			else {
X				diry = 0;
X				dirx = 1;
X			}
X			break;
X		case ',': case '2': case 'c':
X			if (diry == -1 && dirx == 0) bell;
X			else {
X				diry = 1;
X				dirx = 0;
X			}
X			break;
X		case 'j': case '4': case 's':
X			if (diry == 0 && dirx == 1) bell;
X			else {
X				diry = 0;
X				dirx = -1;
X			}
X			break;
X		case '9': case 'o': case 'r':
X			if (diry == 1 && dirx == -1) bell;
X			else {
X				diry = -1;
X				dirx = 1;
X			}
X			break;
X		case '3': case '.': case 'v':
X			if (diry == -1 && dirx == -1) bell;
X			else {
X				diry = 1;
X				dirx = 1;
X			}
X			break;
X		case '1': case 'm': case 'x':
X			if (diry == -1 && dirx == 1) bell; 
X			else {
X				diry = 1;
X				dirx = -1;
X			}
X			break;
X		case '7': case 'u': case 'w':
X			if (diry == 1 && dirx == 1) bell;
X			else {
X				diry = -1;
X				dirx = -1;
X			}
X			break;
X		case 003:	/* Ctrl-C */
X		case 004:	/* Ctrl-D */
X		case 0177:	/* Rubout */
X		case 034:	/* FS	  */
X			return(0);
X			break;
X		case 014:	/* Ctrl-L */
X			/* Really refresh screen */
X			wclear(tmpscr);
X			overlay(stdscr,tmpscr);
X			clear();
X			refresh();
X			overlay(tmpscr,stdscr);
X			break;
X		}
X	}
X	return movesnake(diry,dirx);
X}
X
Xmovesnake(y,x)    /* check if snake hits money or edge of window, too */
X{
X	int c;
X	int newsptr;	/* temp snake pointer */
X	newsptr = (1+sptr)%MAXLEN;
X
X	/* keep snake at right length */
X	if (turn%SKILL) {
X		move(snakey[(MAXLEN+1+sptr-length)%MAXLEN],
X		     snakex[(MAXLEN+1+sptr-length)%MAXLEN]);
X		addch(' ');
X	} else {
X		length++;
X		move(0,15);
X		printw("Length = %d",length);
X		move(0,33);
X		printw("Points = %d",points);
X		move(0,51);
X		printw("Score = %d",score(length,points,LINES,COLS));
X	}
X
X	/* move head of snake one step further */
X	snakey[newsptr] = snakey[sptr]+y;
X	snakex[newsptr] = snakex[sptr]+x;
X
X	/* check for a hit! */
X	move(snakey[newsptr],snakex[newsptr]);
X	if (snakey[newsptr] == 0 || snakey[newsptr] == LINES-1 ||
X		snakex[newsptr] == 0 || snakex[newsptr] == COLS-1) {
X		move(LINES-2,2);
X		addstr("You hit the edge, you snake!");
X		return(0);
X	}
X	c = inch();
X	if (c != ' ') { /* musta hit sumptin, duh... */
X		int i;
X		for (i=0;i<MAXBOXES;i++) {
X			if (!boxes[i].inuse) continue;
X			if (boxes[i].x <= snakex[newsptr] &&
X			    boxes[i].x + boxes[i].length > snakex[newsptr] &&
X			    boxes[i].y <= snakey[newsptr] &&
X			    boxes[i].y + boxes[i].length > snakey[newsptr]) {
X				/* hit box i */
X				delbox(i);
X				/* double points after 250 */
X				if (points+length>=250)
X					points += 2*boxes[i].points;
X				else points += boxes[i].points;
X				move(0,33);
X				printw("Points = %d",points);
X				move(0,51);
X				printw("Score = %d",points+length);
X				break;
X			}
X		}
X		if (i == MAXBOXES) {
X			move(LINES-2,2);
X			addstr("You hit yourself, you snake!");
X			return(0);
X		}
X	}
X
X	move(snakey[sptr],snakex[sptr]);
X	addch('s');
X	move(snakey[newsptr],snakex[newsptr]);
X	addch('S');
X
X	sptr = newsptr;
X	refresh();
X	return(TRUE);
X}
X
Xranbox() /* randomly draw a box */
X{
X	int i, j, y, x, y2, x2, s;
X	int length;
X
X	i = rand()%MAXBOXES;
X	if (boxes[i].inuse) return;
X	j = rand()%numnames;
X	length = strlen(names[j]);
X	y = 1 + rand()%((LINES-1)-length);
X	x = 1 + rand()%((COLS-1)-length);
X	/* check if area is clear */
X	for(y2=y;y2<y+length;y2++) {
X		for (x2=x;x2<x+length;x2++) {
X			move(y2,x2);
X			if (' ' != inch()) return;
X		}
X	}
X	boxes[i].inuse = TRUE;
X	boxes[i].x = x;
X	boxes[i].y = y;
X	boxes[i].name = names[j];
X	boxes[i].length = length;
X	if (!(s = rand()%9)) boxes[i].points = length*3;
X		else boxes[i].points = length;
X	if (names[j] == names[0] ) { /* root! */
X		boxes[i].points = (rand()%40) - 20;
X	}
X	/* draw box */
X	/* top */
X	move(y,x);
X	addstr(names[j]);
X	/* show triple value by capitalizing first letter */
X	if ((!s) && (islower(names[j][0]))) {
X		move(y,x);
X		addch(names[j][0]-('a'-'A'));
X	}
X	for (y2=y+1;y2<y+length;y2++) {
X		/* left side */
X		move(y2,x);
X		addch(names[j][y2-y]);
X		/* right side */
X		move(y2,x+length-1);
X		addch(names[j][length-(y2-y)-1]);
X	}
X	/* bottom */
X	for (x2=x+1;x2<x+length-1;x2++) {
X		move(y+length-1,x2);
X		addch(names[j][length-(x2-x)-1]);
X	}
X}
X
Xranbox2() /* randomly delete a box */
X{
X	/* about every 10 times try and delete a randomly selected box */
X	if (!(rand()%10)) {
X		delbox(rand()%MAXBOXES);
X	}
X}
X
Xdelbox(i) /* delete a box */
Xint i;
X{
X	int x2, y2, x, y;
X	int length;
X
X	if (!boxes[i].inuse) return;
X	x = boxes[i].x;
X	y = boxes[i].y;
X	length = boxes[i].length;
X	boxes[i].inuse = FALSE;
X	/* delete box (this should probably be written as one loop) */
X	move(y,x);
X	/* delete top of box */
X	for (x2=x;x2<x+length;x2++) {
X		/* to */
X		move(y,x2);
X		addch(' ');
X	}
X	/* sides */
X	for (y2=y+1;y2<y+length;y2++) {
X		move(y2,x);
X		addch(' ');
X		move(y2,x+length-1);
X		addch(' ');
X	}
X	/* bottom */
X	for (x2=x+1;x2<x+length-1;x2++) {
X		move(y+length-1,x2);
X		addch(' ');
X	}
X}
X
Xsortlog(foo,bar)	/* sort function for log */
Xstruct logtype *foo;
Xstruct logtype *bar;
X{
X	int x, y;
X
X	x = score(foo->length,foo->points,foo->rows,foo->columns);
X	y = score(bar->length,bar->points,bar->rows,bar->columns);
X	if (x == y) return(0);
X	else if (x > y) return(-1);
X	else return(1);
X}
X
Xcleanup()
X{
X	echo();
X	noraw();
X	refresh();
X}
SHAR_EOF
if test 11780 -ne "`wc -c 'snake2.c'`"
then
	echo shar: error transmitting "'snake2.c'" '(should have been 11780 characters)'
fi
echo shar: extracting "'Makefile'" '(557 characters)'
if test -f 'Makefile'
then
	echo shar: over-writing existing file "'Makefile'"
fi
sed 's/^X//' << \SHAR_EOF > 'Makefile'
XLOG = /usr/local/lib/snake.scores
X
X# choose system type from one of EUNICE, BSD42, BSD41, SYSIII, SYSV
XUNIX = BSD42
X
X# choose timeout mechanism from one of BSD_SELECT, CMU_IPC, VMS
XTIMER = BSD_SELECT
X
XCFLAGS = -O -D$(UNIX) -D$(TIMER) -DLOG=\"$(LOG)\"
X
XLIBS = -lcurses -ltermcap
X
Xsnake2: snake2.o quicksleep.o getkey.o
X	cc -o snake2 $(CFLAGS) snake2.o quicksleep.o getkey.o -lcurses -ltermcap
X
Xinstall:
X	strip snake2
X	cat /dev/null >> $(LOG)
X	chmod 644 $(LOG)
X	/etc/chown daemon snake2 $(LOG)
X	chmod 4755 snake2
X	mv snake2 /usr/local/bin
X
Xsnake2.o: snake2.h
SHAR_EOF
if test 557 -ne "`wc -c 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 557 characters)'
fi
echo shar: extracting "'getkey.c'" '(559 characters)'
if test -f 'getkey.c'
then
	echo shar: over-writing existing file "'getkey.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'getkey.c'
X/* getkey.c - Don Libes
Xgetkey() - return the last key struck by the user or -1.
XIf user has struct multiple keys, ignore all but the last.
X*/
X
X#include <stdio.h>
X#if BSD42 || BSD41 || EUNICE
X#include <sys/ioctl.h>
X#endif
X#if SYSV || SYSIII
X#include <sys/termio.h>
X#endif
X
X#ifdef FIONREAD
Xint
Xgetkey()
X{
X	long chars = 0;
X
X	if (-1 == ioctl(fileno(stdin),FIONREAD,&chars)) {
X		cleanup();
X		perror("ioctl in getkey");
X		exit(0);
X	}
X	
X	if (chars == 0) return(-1);
X
X	while (chars-- > 1) getchar();
X
X	return(getchar() & 0x7f);		/* strip parity */
X}
X#endif FIONREAD
SHAR_EOF
if test 559 -ne "`wc -c 'getkey.c'`"
then
	echo shar: error transmitting "'getkey.c'" '(should have been 559 characters)'
fi
echo shar: extracting "'quicksleep.c'" '(1134 characters)'
if test -f 'quicksleep.c'
then
	echo shar: over-writing existing file "'quicksleep.c'"
fi
sed 's/^X//' << \SHAR_EOF > 'quicksleep.c'
X/* quicksleep.c - Don Libes
Xquick_sleep() - sleep for less than a second
X*/
X
X#ifdef CMU_IPC
Xquick_sleep(timeout)
Xint timeout;		/* milliseconds */
X{
X	int sop[8];
X	sop[0] = 1;
X
X	ipcmessagewait(sop,timeout);	/* huh, message?  what message? */
X#endif
X
X#ifdef UNISOFT_SELECT
X/* My documentation says that this doesn't work yet, but someday it might */
Xquick_sleep(timeout)
Xint timeout;		/* milliseconds */
X{
X	(void) select(20, 0, 0, timeout);
X}
X#endif
X
X#ifdef BSD_SELECT
X#include <sys/time.h>
Xquick_sleep(timeout)
Xint timeout;		/* microseconds */
X{
X	struct timeval t;
X
X	t.tv_sec = timeout / 1000000;
X	t.tv_usec = timeout % 1000000;
X	(void) select(32, 0, 0, 0, &t);
X}
X#endif
X
X#ifdef VMS
Xquick_sleep(timeout)
Xchar *timeout;
X{
X	int rc;
X	char *vms_timeout[8];
X
X	struct {
X		int length;
X		char *string;
X	} timeout_desc;
X	timeout_desc.string = timeout;
X	timeout_desc.length = strlen(timeout);
X
X	if (1 != (rc = sys$bintim(&timeout_desc,vms_timeout))) {
X		printf("$bintim() = %x\n",rc);
X		cleanup();
X		exit(0);
X	}
X	if (1 != (rc = sys$schdwk(0,0,vms_timeout,0))) {
X		printf("$schdwk() = %x\n",rc);
X		cleanup();
X		exit(0);
X	}
X	sys$hiber(0);
X}
X#endif
SHAR_EOF
if test 1134 -ne "`wc -c 'quicksleep.c'`"
then
	echo shar: error transmitting "'quicksleep.c'" '(should have been 1134 characters)'
fi
echo shar: extracting "'snake2.h'" '(400 characters)'
if test -f 'snake2.h'
then
	echo shar: over-writing existing file "'snake2.h'"
fi
sed 's/^X//' << \SHAR_EOF > 'snake2.h'
X/* TIMEOUT should be one quarter of a second or 250 milliseconds */
X#ifdef VMS
X#define TIMEOUT "000 00:00:00.25"
X#endif
X#ifdef BSD_SELECT
X#define TIMEOUT 250000		/* microseconds */
X#endif
X#ifdef UNISOFT_SELECT
X#define TIMEOUT 250		/* milliseconds */
X#endif
X#ifdef CMU_IPC
X#define TIMEOUT 250		/* milliseconds */
X#endif
X
X#ifdef EUNICE
X#define USERNAME_LENGTH	12
X#else
X#define USERNAME_LENGTH 8
X#endif
SHAR_EOF
if test 400 -ne "`wc -c 'snake2.h'`"
then
	echo shar: error transmitting "'snake2.h'" '(should have been 400 characters)'
fi
echo shar: extracting "'snake2.hlp'" '(1734 characters)'
if test -f 'snake2.hlp'
then
	echo shar: over-writing existing file "'snake2.hlp'"
fi
sed 's/^X//' << \SHAR_EOF > 'snake2.hlp'
X1 SNAKE2
X Be a snake!!  Eat other users.  To run, type: snake2
X
X You are the snake.  You look like this: ssssssS
X
X Change your direction by using the number keypad (i.e.  8 is up, 2 is
X down), using the keys around the 'k' key (for righties) or the 'd' key
X (for lefties).  All 8 directions work.
X
X Score by eating other folks.  Point values are based on eatee's size.
X After 250 points, all point values are doubled.  If you see a capital
X letter, it means the box has triple point value.  Go for it!  But
X beware the root (of all evil).  Its point value is unknown and
X sometimes does you more harm than good.
X
X Ctrl-L will refresh the screen if necessary (like if somebody writes to
X you) but won't slow the snake down a mite.
X2 author
X Don Libes   (seismo!nbs-amrf!libes)
X2 bugs
X You can't go to the bathroom in the middle of this game.
X2 keyboard
X Certain programs (such as EDT) that use the keypad, sometimes leave them
X generating different character sequences than normal (i.e. the '6' key
X generates a <esc>[z rather than a '6').  If you really want to use the
X keypad and the game is ignoring you, try resetting the terminal.
X2 terminal
X If you run snake2 directly from VMS, it will assume you are on a vt100
X compatible terminal.  If you are not on a vt100 lookalike, get into
X Eunice first and set your terminal type.
X
X If you are on a vt100 and the initial box is funny looking (i.e.  the
X left border is missing), the terminal is in "no auto wrap" mode, which
X means that when the cursor gets to column 80, its sits there dropping
X characters rather than doing a crlf and continuing.  Turn off this
X braindamaged feature, by putting your terminal into "auto wrap" mode.
SHAR_EOF
if test 1734 -ne "`wc -c 'snake2.hlp'`"
then
	echo shar: error transmitting "'snake2.hlp'" '(should have been 1734 characters)'
fi
echo shar: extracting "'install.com'" '(196 characters)'
if test -f 'install.com'
then
	echo shar: over-writing existing file "'install.com'"
fi
sed 's/^X//' << \SHAR_EOF > 'install.com'
X$! install snake2 with sysprv
X$! sysprv is necessary to update the score file
X$!
X$ pushp sysprv,cmkrnl,cmexe
X$ mc install
Xeun_usr:[usr.local.bin]snake2./shared/header/priv=sysprv
X$ popp
SHAR_EOF
if test 196 -ne "`wc -c 'install.com'`"
then
	echo shar: error transmitting "'install.com'" '(should have been 196 characters)'
fi
chmod +x 'install.com'
echo shar: extracting "'reinstall.com'" '(306 characters)'
if test -f 'reinstall.com'
then
	echo shar: over-writing existing file "'reinstall.com'"
fi
sed 's/^X//' << \SHAR_EOF > 'reinstall.com'
X$ ! install new version of snake2 - Don Libes
X$
X$! make it /notraceback so it can be installed
X$ trpatch :== $eun_usr:[usr.eun]trpatch trpatch
X$ trpatch snake2.
X$!
X$ pushp sysprv,cmkrnl,cmexe
X$ copy snake2. eun_usr:[usr.local.bin]
X$ mc install
Xeun_usr:[usr.local.bin]snake2./replace
X$ popp
SHAR_EOF
if test 306 -ne "`wc -c 'reinstall.com'`"
then
	echo shar: error transmitting "'reinstall.com'" '(should have been 306 characters)'
fi
chmod +x 'reinstall.com'
#	End of shell archive
exit 0