Initial revision

git-svn-id: file:///srv/svn/joey/bsdgames-trunk@5086 a4a2c43b-8ac3-0310-8836-e0e880c912e2
This commit is contained in:
joey
1999-09-08 23:56:51 +00:00
commit 03272d67da
623 changed files with 243457 additions and 0 deletions

6
snake/Makefile.bsd Normal file
View File

@@ -0,0 +1,6 @@
# $NetBSD: Makefile,v 1.3 1995/04/22 08:34:18 cgd Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
SUBDIR= snake snscore
.include <bsd.subdir.mk>

5
snake/Makefrag Normal file
View File

@@ -0,0 +1,5 @@
# Makefrag - makefile fragment for snake
snake_all:
snake_install:

13
snake/snake/Makefile.bsd Normal file
View File

@@ -0,0 +1,13 @@
# $NetBSD: Makefile,v 1.8 1998/02/04 10:24:13 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= snake
SRCS= snake.c move.c
MAN= snake.6
DPADD= ${LIBM} ${LIBTERMCAP}
LDADD= -lm -ltermcap
HIDEGAME=hidegame
SETGIDGAME=yes
.include "../../Makefile.inc"
.include <bsd.prog.mk>

12
snake/snake/Makefrag Normal file
View File

@@ -0,0 +1,12 @@
# Makefrag - makefile fragment for snake/snake
snake_snake_DIRS := $(GAMESDIR) $(MAN6DIR)
snake_snake_all: snake/snake/snake snake/snake/snake.6
snake_snake_install: snake_snake_all
$(INSTALL_SCORE_GAME) snake/snake/snake $(INSTALL_PREFIX)$(GAMESDIR)/snake
$(HIDE_GAME) snake
$(INSTALL_SCORE_FILE) $(SNAKE_SCOREFILE)
$(INSTALL_SCORE_FILE) $(SNAKE_RAWSCOREFILE)
$(INSTALL_MANUAL) snake/snake/snake.6

717
snake/snake/move.c Normal file
View File

@@ -0,0 +1,717 @@
/* $NetBSD: move.c,v 1.15 1997/10/14 01:02:48 lukem Exp $ */
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)move.c 8.1 (Berkeley) 7/19/93";
#else
__RCSID("$NetBSD: move.c,v 1.15 1997/10/14 01:02:48 lukem Exp $");
#endif
#endif /* not lint */
/*************************************************************************
*
* MOVE LIBRARY
*
* This set of subroutines moves a cursor to a predefined
* location, independent of the terminal type. If the
* terminal has an addressable cursor, it uses it. If
* not, it optimizes for tabs (currently) even if you don't
* have them.
*
* At all times the current address of the cursor must be maintained,
* and that is available as structure cursor.
*
* The following calls are allowed:
* move(sp) move to point sp.
* up() move up one line.
* down() move down one line.
* bs() move left one space (except column 0).
* nd() move right one space(no write).
* clear() clear screen.
* home() home.
* ll() move to lower left corner of screen.
* cr() carriage return (no line feed).
* pr() just like standard printf, but keeps track
* of cursor position. (Uses pstring).
* apr() same as printf, but first argument is &point.
* (Uses pstring).
* pstring(s) output the string of printing characters.
* However, '\r' is interpreted to mean return
* to column of origination AND do linefeed.
* '\n' causes <cr><lf>.
* putpad(str) calls tputs to output character with proper
* padding.
* outch() the output routine for a character used by
* tputs. It just calls putchar.
* pch(ch) output character to screen and update
* cursor address (must be a standard
* printing character). WILL SCROLL.
* pchar(ps,ch) prints one character if it is on the
* screen at the specified location;
* otherwise, dumps it.(no wrap-around).
*
* getcap() initializes strings for later calls.
* cap(string) outputs the string designated in the termcap
* data base. (Should not move the cursor.)
* done() returns the terminal to intial state and exits.
*
* point(&p,x,y) return point set to x,y.
*
* delay(t) causes an approximately constant delay
* independent of baudrate.
* Duration is ~ t/20 seconds.
*
******************************************************************************/
#if __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
#include <unistd.h> /* For _POSIX_VDISABLE */
#include "snake.h"
int CMlength;
int NDlength;
int BSlength;
int delaystr[10];
#ifndef NCURSES_VERSION
speed_t ospeed;
#endif
static char str[80];
void
move(sp)
struct point *sp;
{
int distance;
int tabcol, ct;
struct point z;
if (sp->line < 0 || sp->col < 0 || sp->col > COLUMNS) {
pr("move to [%d,%d]?", sp->line, sp->col);
return;
}
if (sp->line >= LINES) {
move(point(&z, sp->col, LINES - 1));
while (sp->line-- >= LINES)
putchar('\n');
return;
}
if (CM != 0) {
char *cmstr = tgoto(CM, sp->col, sp->line);
CMlength = strlen(cmstr);
if (cursor.line == sp->line) {
distance = sp->col - cursor.col;
if (distance == 0)
return; /* Already there! */
if (distance > 0) { /* Moving to the right */
if (distance * NDlength < CMlength) {
right(sp);
return;
}
if (TA) {
ct = sp->col & 7;
tabcol = (cursor.col | 7) + 1;
do {
ct++;
tabcol = (tabcol | 7) + 1;
}
while (tabcol < sp->col);
if (ct < CMlength) {
right(sp);
return;
}
}
} else {/* Moving to the left */
if (-distance * BSlength < CMlength) {
gto(sp);
return;
}
}
if (sp->col < CMlength) {
cr();
right(sp);
return;
}
/* No more optimizations on same row. */
}
distance = sp->col - cursor.col;
distance = distance > 0 ?
distance * NDlength : -distance * BSlength;
if (distance < 0)
pr("ERROR: distance is negative: %d", distance);
distance += abs(sp->line - cursor.line);
if (distance >= CMlength) {
putpad(cmstr);
cursor.line = sp->line;
cursor.col = sp->col;
return;
}
}
/*
* If we get here we have a terminal that can't cursor
* address but has local motions or one which can cursor
* address but can get there quicker with local motions.
*/
gto(sp);
}
void
gto(sp)
struct point *sp;
{
int distance, f, tfield;
if (cursor.line > LINES || cursor.line < 0 ||
cursor.col < 0 || cursor.col > COLUMNS)
pr("ERROR: cursor is at %d,%d\n",
cursor.line, cursor.col);
if (sp->line > LINES || sp->line < 0 ||
sp->col < 0 || sp->col > COLUMNS)
pr("ERROR: target is %d,%d\n", sp->line, sp->col);
tfield = (sp->col) >> 3;
if (sp->line == cursor.line) {
if (sp->col > cursor.col)
right(sp);
else {
distance = (cursor.col - sp->col) * BSlength;
if (((TA) &&
(distance > tfield + ((sp->col) & 7) * NDlength)
) ||
(((cursor.col) * NDlength) < distance)
) {
cr();
right(sp);
} else {
while (cursor.col > sp->col)
bs();
}
}
return;
}
/* must change row */
if (cursor.col - sp->col > (cursor.col >> 3)) {
if (cursor.col == 0)
f = 0;
else
f = -1;
} else
f = cursor.col >> 3;
if (((sp->line << 1) + 1 < cursor.line - f) && (HO != 0)) {
/*
* home quicker than rlf:
* (sp->line + f > cursor.line - sp->line)
*/
putpad(HO);
cursor.col = cursor.line = 0;
gto(sp);
return;
}
if (((sp->line << 1) > cursor.line + LINES + 1 + f) && (LL != 0)) {
/* home,rlf quicker than lf (LINES+1 - sp->line + f < sp->line
* - cursor.line) */
if (cursor.line > f + 1) {
/* is home faster than wraparound lf? (cursor.line +
* 20 - sp->line > 21 - sp->line + f) */
ll();
gto(sp);
return;
}
}
if ((LL != 0) && (sp->line > cursor.line + (LINES >> 1) - 1))
cursor.line += LINES;
while (sp->line > cursor.line)
down();
while (sp->line < cursor.line)
up();
gto(sp); /* can recurse since cursor.line = sp->line */
}
void
right(sp)
struct point *sp;
{
int field, tfield;
int tabcol, strlength;
if (sp->col < cursor.col)
pr("ERROR:right() can't move left\n");
if (TA) { /* If No Tabs: can't send tabs because
* ttydrive loses count with control
* characters. */
field = cursor.col >> 3;
/*
* This code is useful for a terminal which wraps around on backspaces.
* (Mine does.) Unfortunately, this is not specified in termcap, and
* most terminals don't work that way. (Of course, most terminals
* have addressible cursors, too).
*/
if (BW && (CM == 0) &&
((sp->col << 1) - field > (COLUMNS - 8) << 1)
) {
if (cursor.line == 0) {
outch('\n');
}
outch('\r');
cursor.col = COLUMNS + 1;
while (cursor.col > sp->col)
bs();
if (cursor.line != 0)
outch('\n');
return;
}
tfield = sp->col >> 3;
while (field < tfield) {
putpad(TA);
cursor.col = ++field << 3;
}
tabcol = (cursor.col | 7) + 1;
strlength = (tabcol - sp->col) * BSlength + 1;
/* length of sequence to overshoot */
if (((sp->col - cursor.col) * NDlength > strlength) &&
(tabcol < COLUMNS)
) {
/*
* Tab past and backup
*/
putpad(TA);
cursor.col = (cursor.col | 7) + 1;
while (cursor.col > sp->col)
bs();
}
}
while (sp->col > cursor.col) {
nd();
}
}
void
cr()
{
outch('\r');
cursor.col = 0;
}
void
clear()
{
int i;
if (CL) {
putpad(CL);
cursor.col = cursor.line = 0;
} else {
for (i = 0; i < LINES; i++) {
putchar('\n');
}
cursor.line = LINES - 1;
home();
}
}
void
home()
{
struct point z;
if (HO != 0) {
putpad(HO);
cursor.col = cursor.line = 0;
return;
}
z.col = z.line = 0;
move(&z);
}
void
ll()
{
int l;
struct point z;
l = lcnt + 2;
if (LL != NULL && LINES == l) {
putpad(LL);
cursor.line = LINES - 1;
cursor.col = 0;
return;
}
z.col = 0;
z.line = l - 1;
move(&z);
}
void
up()
{
putpad(UP);
cursor.line--;
}
void
down()
{
putpad(DO);
cursor.line++;
if (cursor.line >= LINES)
cursor.line = LINES - 1;
}
void
bs()
{
if (cursor.col > 0) {
putpad(BS);
cursor.col--;
}
}
void
nd()
{
putpad(ND);
cursor.col++;
if (cursor.col == COLUMNS + 1) {
cursor.line++;
cursor.col = 0;
if (cursor.line >= LINES)
cursor.line = LINES - 1;
}
}
void
pch(c)
int c;
{
outch(c);
if (++cursor.col >= COLUMNS && AM) {
cursor.col = 0;
++cursor.line;
}
}
void
#if __STDC__
apr(struct point * ps, const char *fmt,...)
#else
apr(ps, fmt, va_alist)
struct point *ps;
char *fmt;
va_dcl
#endif
{
struct point p;
va_list ap;
p.line = ps->line + 1;
p.col = ps->col + 1;
move(&p);
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void) vsprintf(str, fmt, ap);
va_end(ap);
pstring(str);
}
void
#if __STDC__
pr(const char *fmt,...)
#else
pr(fmt, va_alist)
char *fmt;
va_dcl
#endif
{
va_list ap;
#if __STDC__
va_start(ap, fmt);
#else
va_start(ap);
#endif
(void) vsprintf(str, fmt, ap);
va_end(ap);
pstring(str);
}
void
pstring(s)
const char *s;
{
struct point z;
int stcol;
stcol = cursor.col;
while (s[0] != '\0') {
switch (s[0]) {
case '\n':
move(point(&z, 0, cursor.line + 1));
break;
case '\r':
move(point(&z, stcol, cursor.line + 1));
break;
case '\t':
z.col = (((cursor.col + 8) >> 3) << 3);
z.line = cursor.line;
move(&z);
break;
case '\b':
bs();
break;
case CTRL('g'):
outch(CTRL('g'));
break;
default:
if (s[0] < ' ')
break;
pch(s[0]);
}
s++;
}
}
void
pchar(ps, ch)
struct point *ps;
char ch;
{
struct point p;
p.col = ps->col + 1;
p.line = ps->line + 1;
if (
(p.col >= 0) &&
(p.line >= 0) &&
(
(
(p.line < LINES) &&
(p.col < COLUMNS)
) ||
(
(p.col == COLUMNS) &&
(p.line < LINES - 1)
)
)
) {
move(&p);
pch(ch);
}
}
int
outch(c)
int c;
{
return putchar(c);
}
void
putpad(str)
char *str;
{
if (str)
tputs(str, 1, outch);
}
void
delay(t)
int t;
{
int k, j;
k = (ospeed * t + 100) / 200;
for (j = 0; j < k; j++) {
putchar(PC);
}
}
void
done()
{
cook();
exit(0);
}
void
cook()
{
delay(1);
putpad(TE);
putpad(KE);
fflush(stdout);
tcsetattr(0, TCSADRAIN, &orig);
}
void
my_raw()
{
tcsetattr(0, TCSADRAIN, &new);
}
struct point *
point(ps, x, y)
struct point *ps;
int x, y;
{
ps->col = x;
ps->line = y;
return (ps);
}
char *ap;
void
getcap()
{
char *term;
char *xPC;
#ifdef TIOCGWINSZ
struct winsize win;
#endif
term = getenv("TERM");
if (term == 0)
errx(1, "No TERM in environment");
switch (tgetent(tbuf, term)) {
case -1:
errx(2, "Cannot open termcap file");
case 0:
errx(3, "unknown terminal `%s'", term);
}
ap = tcapbuf;
#ifdef TIOCGWINSZ
if (ioctl(0, TIOCGWINSZ, (char *) &win) < 0 ||
(LINES = win.ws_row) == 0 || (COLUMNS = win.ws_col) == 0) {
#endif
LINES = tgetnum("li");
COLUMNS = tgetnum("co");
#ifdef TIOCGWINSZ
}
#endif
if (!lcnt)
lcnt = LINES - 2;
if (!ccnt)
ccnt = COLUMNS - 3;
AM = tgetflag("am");
BW = tgetflag("bw");
ND = tgetstr("nd", &ap);
UP = tgetstr("up", &ap);
DO = tgetstr("do", &ap);
if (DO == 0)
DO = "\n";
BS = tgetstr("le", &ap);
if (BS == 0) {
/* try using obsolete capabilities */
BS = tgetstr("bc", &ap);
if (BS == 0 && tgetflag("bs"))
BS = "\b";
}
TA = tgetstr("ta", &ap);
if (TA == 0 && tgetflag("pt"))
TA = "\t";
HO = tgetstr("ho", &ap);
CL = tgetstr("cl", &ap);
CM = tgetstr("cm", &ap);
LL = tgetstr("ll", &ap);
KL = tgetstr("kl", &ap);
KR = tgetstr("kr", &ap);
KU = tgetstr("ku", &ap);
KD = tgetstr("kd", &ap);
if (KL && KR && KU && KD)
Klength = strlen(KL);
else
Klength = 0;
/* NOTE: If KL, KR, KU, and KD are not all the same length, some
* problems may arise, since tests are made on all of them together. */
TI = tgetstr("ti", &ap);
TE = tgetstr("te", &ap);
KS = tgetstr("ks", &ap);
KE = tgetstr("ke", &ap);
xPC = tgetstr("pc", &ap);
if (xPC)
PC = *xPC;
if ((CM == 0) &&
(HO == 0 || UP == 0 || BS == 0 || ND == 0))
errx(5, "Terminal must have addressible cursor or home + 4 local motions");
if (ND == 0)
errx(5, "Terminal must have `nd' capability");
NDlength = strlen(ND);
if (BS == 0)
errx(5, "Terminal must have 'le' or `bs' or `bc' capability");
BSlength = strlen(BS);
if (tgetflag("os"))
errx(5, "Terminal must not overstrike");
if (LINES <= 0 || COLUMNS <= 0)
errx(5, "Must know the screen size");
tcgetattr(0, &orig);
new = orig;
new.c_lflag &= ~(ECHO | ICANON);
new.c_oflag &= ~(ONLCR | OXTABS);
signal(SIGINT, stop);
ospeed = cfgetospeed(&orig);
new.c_cc[VSUSP] = _POSIX_VDISABLE;
#ifdef VDSUSP
new.c_cc[VDSUSP] = _POSIX_VDISABLE;
#endif
my_raw();
if (orig.c_oflag & OXTABS)
TA = 0;
putpad(KS);
putpad(TI);
point(&cursor, 0, LINES - 1);
}

View File

@@ -0,0 +1,39 @@
/* $NetBSD: pathnames.h,v 1.3 1995/04/22 08:34:33 cgd Exp $ */
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 5/31/93
*/
#define _PATH_RAWSCORES "@snake_rawscorefile@"
#define _PATH_LOGFILE "@snake_scorefile@"

124
snake/snake/snake.6.in Normal file
View File

@@ -0,0 +1,124 @@
.\" $NetBSD: snake.6,v 1.6 1997/10/12 01:49:26 lukem Exp $
.\"
.\" Copyright (c) 1980, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)snake.6 8.1 (Berkeley) 5/31/93
.\"
.Dd May 31, 1993
.Dt SNAKE 6
.Os
.Sh NAME
.Nm snake ,
.Nm snscore
.Nd display chase game
.Sh SYNOPSIS
.Nm
.Op Fl w Ar width
.Op Fl l Ar length
.br
.Nm snscore
.Sh DESCRIPTION
.Nm
is a display-based game which must be played on a CRT terminal.
The object of the game is to make as much money as possible without
getting eaten by the snake. The
.Fl l
and
.Fl w
options allow you to specify the length and width of the field.
By default the entire screen (except for the last column) is used.
.Pp
You are represented on the screen by an I.
The snake is 6 squares long and is represented by S's.
The money is $, and an exit is #.
Your score is posted in the upper left hand corner.
.Pp
You can move around using the same conventions as
.Xr vi 1 ,
the
.Ic h ,
.Ic j ,
.Ic k ,
and
.Ic l
keys work, as do the arrow keys.
Other possibilities include:
.Bl -tag -width indent
.It Ic sefc
These keys are like hjkl but form a directed pad around the d key.
.It Ic HJKL
These keys move you all the way in the indicated direction to the
same row or column as the money. This does
.Em not
let you jump away from the snake, but rather saves you from having
to type a key repeatedly. The snake still gets all his turns.
.It Ic SEFC
Likewise for the upper case versions on the left.
.It Ic ATPB
These keys move you to the four edges of the screen.
Their position on the keyboard is the mnemonic, e.g.
P is at the far right of the keyboard.
.It Ic x
This lets you quit the game at any time.
.It Ic p
Points in a direction you might want to go.
.It Ic w
Space warp to get out of tight squeezes, at a price.
.El
.Pp
To earn money, move to the same square the money is on.
A new $ will appear when you earn the current one.
As you get richer, the snake gets hungrier.
To leave the game, move to the exit (#).
.Pp
A record is kept of the personal best score of each player.
Scores are only counted if you leave at the exit,
getting eaten by the snake is worth nothing.
.Pp
As in pinball, matching the last digit of your score to the number
which appears after the game is worth a bonus.
.Pp
To see who wastes time playing snake, run
.Nm snscore .
.Sh FILES
.Bl -tag -width /var/games/snakerawscores -compact
.It Pa /var/games/snakerawscores
database of personal bests
.It Pa /var/games/snake.log
log of games played
.El
.Sh BUGS
When playing on a small screen,
it's hard to tell when you hit the edge of the screen.
.Pp
The scoring function takes into account the size of the screen.
A perfect function to do this equitably has not been devised.

967
snake/snake/snake.c Normal file
View File

@@ -0,0 +1,967 @@
/* $NetBSD: snake.c,v 1.9 1997/10/12 01:49:28 lukem Exp $ */
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
The Regents of the University of California. All rights reserved.\n");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)snake.c 8.2 (Berkeley) 1/7/94";
#else
__RCSID("$NetBSD: snake.c,v 1.9 1997/10/12 01:49:28 lukem Exp $");
#endif
#endif /* not lint */
/*
* snake - crt hack game.
*
* You move around the screen with arrow keys trying to pick up money
* without getting eaten by the snake. hjkl work as in vi in place of
* arrow keys. You can leave at the exit any time.
*
* compile as follows:
* cc -O snake.c move.c -o snake -lm -ltermlib
*/
#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "snake.h"
#include "pathnames.h"
#define PENALTY 10 /* % penalty for invoking spacewarp */
#define EOT '\004'
#define LF '\n'
#define DEL '\177'
#define ME 'I'
#define SNAKEHEAD 'S'
#define SNAKETAIL 's'
#define TREASURE '$'
#define GOAL '#'
#define BSIZE 80
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif
struct point you;
struct point money;
struct point finish;
struct point snake[6];
int loot, penalty;
int long tl, tm = 0L;
int moves;
char stri[BSIZE];
char *p;
char ch, savec;
char *kl, *kr, *ku, *kd;
int fast = 1;
int repeat = 1;
time_t tv;
char *tn;
int rawscores;
FILE *logfile;
int main __P((int, char **));
int
main(argc, argv)
int argc;
char **argv;
{
extern char *optarg;
extern int optind;
int ch, i;
/* Open score files then revoke setgid privileges */
rawscores = open(_PATH_RAWSCORES, O_RDWR|O_CREAT, 0664);
if (rawscores < 0) {
warn("open %s", _PATH_RAWSCORES);
sleep(2);
}
logfile = fopen(_PATH_LOGFILE, "a");
if (logfile == NULL) {
warn("fopen %s", _PATH_LOGFILE);
sleep(2);
}
setregid(getgid(), getgid());
(void) time(&tv);
srandom((int) tv);
while ((ch = getopt(argc, argv, "l:w:")) != -1)
switch ((char) ch) {
#ifdef notdef
case 'd':
tv = atol(optarg);
break;
#endif
case 'w': /* width */
ccnt = atoi(optarg);
break;
case 'l': /* length */
lcnt = atoi(optarg);
break;
case '?':
default:
fputs("usage: snake [-d seed] [-w width] [-l length]\n", stderr);
exit(1);
}
penalty = loot = 0;
getcap();
i = MIN(lcnt, ccnt);
if (i < 4) {
cook();
pr("snake: screen too small for a fair game.\n");
exit(1);
}
/*
* chunk is the amount of money the user gets for each $.
* The formula below tries to be fair for various screen sizes.
* We only pay attention to the smaller of the 2 edges, since
* that seems to be the bottleneck.
* This formula is a hyperbola which includes the following points:
* (24, $25) (original scoring algorithm)
* (12, $40) (experimentally derived by the "feel")
* (48, $15) (a guess)
* This will give a 4x4 screen $99/shot. We don't allow anything
* smaller than 4x4 because there is a 3x3 game where you can win
* an infinite amount of money.
*/
if (i < 12)
i = 12; /* otherwise it isn't fair */
/*
* Compensate for border. This really changes the game since
* the screen is two squares smaller but we want the default
* to be $25, and the high scores on small screens were a bit
* much anyway.
*/
i += 2;
chunk = (675.0 / (i + 6)) + 2.5; /* min screen edge */
signal(SIGINT, stop);
putpad(TI); /* String to begin programs that use cm */
putpad(KS); /* Put terminal in keypad transmit mode */
snrand(&finish);
snrand(&you);
snrand(&money);
snrand(&snake[0]);
if (ospeed < 9600 || ((!CM) && (!TA)))
fast = 0;
for (i = 1; i < 6; i++)
chase(&snake[i], &snake[i - 1]);
setup();
mainloop();
/* NOTREACHED */
return (0);
}
/* Main command loop */
void
mainloop()
{
int j, k;
for (;;) {
int c, lastc, match;
struct point tmp;
lastc = 0;
tmp.col = you.col + 1;
tmp.line = you.line + 1; /* Highlight you, not left & above */
move(&tmp);
fflush(stdout);
if (((c = getchar() & 0177) <= '9') && (c >= '0')) {
ungetc(c, stdin);
j = scanf("%d", &repeat);
c = getchar() & 0177;
} else {
if (c != '.')
repeat = 1;
}
if (c == '.') {
c = lastc;
}
if ((Klength > 0) &&
(c == *KL || c == *KR || c == *KU || c == *KD)) {
savec = c;
match = 0;
kl = KL;
kr = KR;
ku = KU;
kd = KD;
for (j = Klength; j > 0; j--) {
if (match != 1) {
match = 0;
if (*kl++ == c) {
ch = 'h';
match++;
}
if (*kr++ == c) {
ch = 'l';
match++;
}
if (*ku++ == c) {
ch = 'k';
match++;
}
if (*kd++ == c) {
ch = 'j';
match++;
}
if (match == 0) {
ungetc(c, stdin);
ch = savec;
/* Oops! This works if we
* figure it out on second
* character. */
break;
}
}
savec = c;
if (j != 1)
c = getchar() & 0177;
}
c = ch;
}
if (!fast)
flushi();
lastc = c;
switch (c) {
case CTRL('z'):
suspend();
continue;
case EOT:
case 'x':
case 0177: /* del or end of file */
ll();
length(moves);
logit("quit");
done();
case CTRL('l'):
setup();
winnings(cashvalue);
continue;
case 'p':
case 'd':
snap();
continue;
case 'w':
spacewarp(0);
continue;
case 'A':
repeat = you.col;
c = 'h';
break;
case 'H':
case 'S':
repeat = you.col - money.col;
c = 'h';
break;
case 'T':
repeat = you.line;
c = 'k';
break;
case 'K':
case 'E':
repeat = you.line - money.line;
c = 'k';
break;
case 'P':
repeat = ccnt - 1 - you.col;
c = 'l';
break;
case 'L':
case 'F':
repeat = money.col - you.col;
c = 'l';
break;
case 'B':
repeat = lcnt - 1 - you.line;
c = 'j';
break;
case 'J':
case 'C':
repeat = money.line - you.line;
c = 'j';
break;
}
for (k = 1; k <= repeat; k++) {
moves++;
switch (c) {
case 's':
case 'h':
case '\b':
if (you.col > 0) {
if ((fast) || (k == 1))
pchar(&you, ' ');
you.col--;
if ((fast) || (k == repeat) ||
(you.col == 0))
pchar(&you, ME);
}
break;
case 'f':
case 'l':
case ' ':
if (you.col < ccnt - 1) {
if ((fast) || (k == 1))
pchar(&you, ' ');
you.col++;
if ((fast) || (k == repeat) ||
(you.col == ccnt - 1))
pchar(&you, ME);
}
break;
case CTRL('p'):
case 'e':
case 'k':
case 'i':
if (you.line > 0) {
if ((fast) || (k == 1))
pchar(&you, ' ');
you.line--;
if ((fast) || (k == repeat) ||
(you.line == 0))
pchar(&you, ME);
}
break;
case CTRL('n'):
case 'c':
case 'j':
case LF:
case 'm':
if (you.line + 1 < lcnt) {
if ((fast) || (k == 1))
pchar(&you, ' ');
you.line++;
if ((fast) || (k == repeat) ||
(you.line == lcnt - 1))
pchar(&you, ME);
}
break;
}
if (same(&you, &money)) {
loot += 25;
if (k < repeat)
pchar(&you, ' ');
do {
snrand(&money);
} while ((money.col == finish.col &&
money.line == finish.line) ||
(money.col < 5 && money.line == 0) ||
(money.col == you.col &&
money.line == you.line));
pchar(&money, TREASURE);
winnings(cashvalue);
continue;
}
if (same(&you, &finish)) {
win(&finish);
ll();
cook();
pr("You have won with $%d.\n", cashvalue);
fflush(stdout);
logit("won");
post(cashvalue, 1);
length(moves);
done();
}
if (pushsnake())
break;
}
fflush(stdout);
}
}
/*
* setup the board
*/
void
setup()
{
int i;
clear();
pchar(&you, ME);
pchar(&finish, GOAL);
pchar(&money, TREASURE);
for (i = 1; i < 6; i++) {
pchar(&snake[i], SNAKETAIL);
}
pchar(&snake[0], SNAKEHEAD);
drawbox();
fflush(stdout);
}
void
drawbox()
{
int i;
struct point p;
p.line = -1;
for (i = 0; i < ccnt; i++) {
p.col = i;
pchar(&p, '-');
}
p.col = ccnt;
for (i = -1; i <= lcnt; i++) {
p.line = i;
pchar(&p, '|');
}
p.col = -1;
for (i = -1; i <= lcnt; i++) {
p.line = i;
pchar(&p, '|');
}
p.line = lcnt;
for (i = 0; i < ccnt; i++) {
p.col = i;
pchar(&p, '-');
}
}
void
snrand(sp)
struct point *sp;
{
struct point p;
int i;
for (;;) {
p.col = random() % ccnt;
p.line = random() % lcnt;
/* make sure it's not on top of something else */
if (p.line == 0 && p.col < 5)
continue;
if (same(&p, &you))
continue;
if (same(&p, &money))
continue;
if (same(&p, &finish))
continue;
for (i = 0; i < 5; i++)
if (same(&p, &snake[i]))
break;
if (i < 5)
continue;
break;
}
*sp = p;
}
int
post(iscore, flag)
int iscore, flag;
{
short score = iscore;
short uid;
short oldbest = 0;
short allbwho = 0, allbscore = 0;
struct passwd *p;
/*
* Neg uid, 0, and 1 cannot have scores recorded.
*/
if ((uid = getuid()) <= 1) {
pr("No saved scores for uid %d.\n", uid);
return (1);
}
if (rawscores < 0) {
/* Error reported earlier */
return (1);
}
/* Figure out what happened in the past */
read(rawscores, &allbscore, sizeof(short));
read(rawscores, &allbwho, sizeof(short));
lseek(rawscores, uid * sizeof(short), SEEK_SET);
read(rawscores, &oldbest, sizeof(short));
if (!flag)
return (score > oldbest ? 1 : 0);
/* Update this jokers best */
if (score > oldbest) {
lseek(rawscores, uid * sizeof(short), SEEK_SET);
write(rawscores, &score, sizeof(short));
pr("You bettered your previous best of $%d\n", oldbest);
} else
pr("Your best to date is $%d\n", oldbest);
/* See if we have a new champ */
p = getpwuid(allbwho);
if (p == NULL || score > allbscore) {
lseek(rawscores, 0, SEEK_SET);
write(rawscores, &score, sizeof(short));
write(rawscores, &uid, sizeof(short));
if (allbwho)
pr("You beat %s's old record of $%d!\n",
p->pw_name, allbscore);
else
pr("You set a new record!\n");
} else
pr("The highest is %s with $%d\n", p->pw_name, allbscore);
lseek(rawscores, 0, SEEK_SET);
return (1);
}
/*
* Flush typeahead to keep from buffering a bunch of chars and then
* overshooting. This loses horribly at 9600 baud, but works nicely
* if the terminal gets behind.
*/
void
flushi()
{
tcflush(0, TCIFLUSH);
}
int mx[8] = {
0, 1, 1, 1, 0, -1, -1, -1
};
int my[8] = {
-1, -1, 0, 1, 1, 1, 0, -1
};
float absv[8] = {
1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4
};
int oldw = 0;
void
chase(np, sp)
struct point *sp, *np;
{
/* this algorithm has bugs; otherwise the snake would get too good */
struct point d;
int w, i, wt[8];
double v1, v2, vp, max;
point(&d, you.col - sp->col, you.line - sp->line);
v1 = sqrt((double) (d.col * d.col + d.line * d.line));
w = 0;
max = 0;
for (i = 0; i < 8; i++) {
vp = d.col * mx[i] + d.line * my[i];
v2 = absv[i];
if (v1 > 0)
vp = ((double) vp) / (v1 * v2);
else
vp = 1.0;
if (vp > max) {
max = vp;
w = i;
}
}
for (i = 0; i < 8; i++) {
point(&d, sp->col + mx[i], sp->line + my[i]);
wt[i] = 0;
if (d.col < 0 || d.col >= ccnt || d.line < 0 || d.line >= lcnt)
continue;
/*
* Change to allow snake to eat you if you're on the money,
* otherwise, you can just crouch there until the snake goes
* away. Not positive it's right.
*
* if (d.line == 0 && d.col < 5) continue;
*/
if (same(&d, &money))
continue;
if (same(&d, &finish))
continue;
wt[i] = i == w ? loot / 10 : 1;
if (i == oldw)
wt[i] += loot / 20;
}
for (w = i = 0; i < 8; i++)
w += wt[i];
vp = ((rand() >> 6) & 01777) % w;
for (i = 0; i < 8; i++)
if (vp < wt[i])
break;
else
vp -= wt[i];
if (i == 8) {
pr("failure\n");
i = 0;
while (wt[i] == 0)
i++;
}
oldw = w = i;
point(np, sp->col + mx[w], sp->line + my[w]);
}
void
spacewarp(w)
int w;
{
struct point p;
int j;
char *str;
snrand(&you);
point(&p, COLUMNS / 2 - 8, LINES / 2 - 1);
if (p.col < 0)
p.col = 0;
if (p.line < 0)
p.line = 0;
if (w) {
str = "BONUS!!!";
loot = loot - penalty;
penalty = 0;
} else {
str = "SPACE WARP!!!";
penalty += loot / PENALTY;
}
for (j = 0; j < 3; j++) {
clear();
delay(5);
apr(&p, str);
delay(10);
}
setup();
winnings(cashvalue);
}
void
snap()
{
struct point p;
if (you.line < 3) {
pchar(point(&p, you.col, 0), '-');
}
if (you.line > lcnt - 4) {
pchar(point(&p, you.col, lcnt - 1), '_');
}
if (you.col < 10) {
pchar(point(&p, 0, you.line), '(');
}
if (you.col > ccnt - 10) {
pchar(point(&p, ccnt - 1, you.line), ')');
}
if (!stretch(&money))
if (!stretch(&finish))
delay(10);
if (you.line < 3) {
point(&p, you.col, 0);
chk(&p);
}
if (you.line > lcnt - 4) {
point(&p, you.col, lcnt - 1);
chk(&p);
}
if (you.col < 10) {
point(&p, 0, you.line);
chk(&p);
}
if (you.col > ccnt - 10) {
point(&p, ccnt - 1, you.line);
chk(&p);
}
fflush(stdout);
}
int
stretch(ps)
struct point *ps;
{
struct point p;
point(&p, you.col, you.line);
if (abs(ps->col - you.col) < 6) {
if (you.line < ps->line) {
for (p.line = you.line + 1; p.line <= ps->line;
p.line++)
pchar(&p, 'v');
delay(10);
for (; p.line > you.line; p.line--)
chk(&p);
} else {
for (p.line = you.line - 1; p.line >= ps->line;
p.line--)
pchar(&p, '^');
delay(10);
for (; p.line < you.line; p.line++)
chk(&p);
}
return (1);
} else
if (abs(ps->line - you.line) < 3) {
p.line = you.line;
if (you.col < ps->col) {
for (p.col = you.col + 1; p.col <= ps->col;
p.col++)
pchar(&p, '>');
delay(10);
for (; p.col > you.col; p.col--)
chk(&p);
} else {
for (p.col = you.col - 1; p.col >= ps->col;
p.col--)
pchar(&p, '<');
delay(10);
for (; p.col < you.col; p.col++)
chk(&p);
}
return (1);
}
return (0);
}
void
surround(ps)
struct point *ps;
{
struct point x;
int j;
if (ps->col == 0)
ps->col++;
if (ps->line == 0)
ps->line++;
if (ps->line == LINES - 1)
ps->line--;
if (ps->col == COLUMNS - 1)
ps->col--;
apr(point(&x, ps->col - 1, ps->line - 1), "/*\\\r* *\r\\*/");
for (j = 0; j < 20; j++) {
pchar(ps, '@');
delay(1);
pchar(ps, ' ');
delay(1);
}
if (post(cashvalue, 0)) {
apr(point(&x, ps->col - 1, ps->line - 1), " \ro.o\r\\_/");
delay(6);
apr(point(&x, ps->col - 1, ps->line - 1), " \ro.-\r\\_/");
delay(6);
}
apr(point(&x, ps->col - 1, ps->line - 1), " \ro.o\r\\_/");
}
void
win(ps)
struct point *ps;
{
struct point x;
int j, k;
int boxsize; /* actually diameter of box, not radius */
boxsize = fast ? 10 : 4;
point(&x, ps->col, ps->line);
for (j = 1; j < boxsize; j++) {
for (k = 0; k < j; k++) {
pchar(&x, '#');
x.line--;
}
for (k = 0; k < j; k++) {
pchar(&x, '#');
x.col++;
}
j++;
for (k = 0; k < j; k++) {
pchar(&x, '#');
x.line++;
}
for (k = 0; k < j; k++) {
pchar(&x, '#');
x.col--;
}
}
fflush(stdout);
}
int
pushsnake()
{
int i, bonus;
int issame = 0;
/*
* My manual says times doesn't return a value. Furthermore, the
* snake should get his turn every time no matter if the user is
* on a fast terminal with typematic keys or not.
* So I have taken the call to times out.
*/
for (i = 4; i >= 0; i--)
if (same(&snake[i], &snake[5]))
issame++;
if (!issame)
pchar(&snake[5], ' ');
for (i = 4; i >= 0; i--)
snake[i + 1] = snake[i];
chase(&snake[0], &snake[1]);
pchar(&snake[1], SNAKETAIL);
pchar(&snake[0], SNAKEHEAD);
for (i = 0; i < 6; i++) {
if (same(&snake[i], &you)) {
surround(&you);
i = (cashvalue) % 10;
bonus = ((rand() >> 8) & 0377) % 10;
ll();
pr("%d\n", bonus);
delay(30);
if (bonus == i) {
spacewarp(1);
logit("bonus");
flushi();
return (1);
}
if (loot >= penalty) {
pr("You and your $%d have been eaten\n",
cashvalue);
} else {
pr("The snake ate you. You owe $%d.\n",
-cashvalue);
}
logit("eaten");
length(moves);
done();
}
}
return (0);
}
int
chk(sp)
struct point *sp;
{
int j;
if (same(sp, &money)) {
pchar(sp, TREASURE);
return (2);
}
if (same(sp, &finish)) {
pchar(sp, GOAL);
return (3);
}
if (same(sp, &snake[0])) {
pchar(sp, SNAKEHEAD);
return (4);
}
for (j = 1; j < 6; j++) {
if (same(sp, &snake[j])) {
pchar(sp, SNAKETAIL);
return (4);
}
}
if ((sp->col < 4) && (sp->line == 0)) {
winnings(cashvalue);
if ((you.line == 0) && (you.col < 4))
pchar(&you, ME);
return (5);
}
if (same(sp, &you)) {
pchar(sp, ME);
return (1);
}
pchar(sp, ' ');
return (0);
}
void
winnings(won)
int won;
{
struct point p;
p.line = p.col = 1;
if (won > 0) {
move(&p);
pr("$%d", won);
}
}
void
stop(dummy)
int dummy __attribute__((unused));
{
signal(SIGINT, SIG_IGN);
ll();
length(moves);
done();
}
void
suspend()
{
ll();
cook();
kill(getpid(), SIGTSTP);
my_raw();
setup();
winnings(cashvalue);
}
void
length(num)
int num;
{
pr("You made %d moves.\n", num);
}
void
logit(msg)
const char *msg;
{
time_t t;
if (logfile != NULL) {
time(&t);
fprintf(logfile, "%s $%d %dx%d %s %s",
getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t));
fflush(logfile);
}
}

130
snake/snake/snake.h Normal file
View File

@@ -0,0 +1,130 @@
/* $NetBSD: snake.h,v 1.10 1998/09/13 15:27:30 hubertf Exp $ */
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)snake.h 8.1 (Berkeley) 5/31/93
*/
# include <sys/types.h>
# include <sys/ioctl.h>
# include <assert.h>
# include <err.h>
# include <math.h>
# include <signal.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <termcap.h>
# include <termios.h>
#define ESC '\033'
struct tbuffer {
long t[4];
} tbuffer;
char *CL, *UP, *DO, *ND, *BS,
*HO, *CM,
*TA, *LL,
*KL, *KR, *KU, *KD,
*TI, *TE, *KS, *KE;
int LINES, COLUMNS; /* physical screen size. */
int lcnt, ccnt; /* user's idea of screen size */
char PC;
int AM, BW;
char tbuf[1024], tcapbuf[128];
int Klength; /* length of KX strings */
int chunk; /* amount of money given at a time */
#ifndef NCURSES_VERSION
speed_t ospeed;
#endif
#ifdef debug
#define cashvalue (loot-penalty)/25
#else
#define cashvalue chunk*(loot-penalty)/25
#endif
struct point {
int col, line;
};
struct point cursor;
struct termios orig, new;
#define same(s1, s2) ((s1)->line == (s2)->line && (s1)->col == (s2)->col)
void apr __P((struct point *, const char *, ...));
void bs __P((void));
void chase __P((struct point *, struct point *));
int chk __P((struct point *));
void clear __P((void));
void cook __P((void));
void cr __P((void));
void delay __P((int));
void done __P((void)) __attribute__((__noreturn__));
void down __P((void));
void drawbox __P((void));
void flushi __P((void));
void getcap __P((void));
void gto __P((struct point *));
void home __P((void));
void length __P((int));
void ll __P((void));
void logit __P((const char *));
void mainloop __P((void));
void move __P((struct point *));
void nd __P((void));
int outch __P((int));
void pch __P((int));
void pchar __P((struct point *, char));
struct point *point __P((struct point *, int, int));
int post __P((int, int));
void pr __P((const char *, ...));
void pstring __P((const char *));
int pushsnake __P((void));
void putpad __P((char *));
void my_raw __P((void));
void right __P((struct point *));
void setup __P((void));
void snap __P((void));
void snap __P((void));
void snrand __P((struct point *));
void spacewarp __P((int));
void stop __P((int)) __attribute__((__noreturn__));
int stretch __P((struct point *));
int stretch __P((struct point *));
void surround __P((struct point *));
void suspend __P((void));
void up __P((void));
void win __P((struct point *));
void winnings __P((int));

View File

@@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.4 1997/10/22 05:26:25 lukem Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= snscore
CPPFLAGS+=-I${.CURDIR}/../snake
NOMAN= noman
HIDEGAME=hidegame
.include "../../Makefile.inc"
.include <bsd.prog.mk>

11
snake/snscore/Makefrag Normal file
View File

@@ -0,0 +1,11 @@
# Makefrag - makefile fragment for snake/snscore
snake_snscore_DIRS := $(GAMESDIR) $(MAN6DIR)
snake_snscore_INCS := -Isnake/snake
snake_snscore_all: snake/snscore/snscore
snake_snscore_install: snake_snscore_all
$(INSTALL_BINARY) snake/snscore/snscore $(INSTALL_PREFIX)$(GAMESDIR)/snscore
$(HIDE_GAME) snscore
$(INSTALL_MANUAL) snake.6 snscore.6

133
snake/snscore/snscore.c Normal file
View File

@@ -0,0 +1,133 @@
/* $NetBSD: snscore.c,v 1.8 1998/09/11 14:25:22 hubertf Exp $ */
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
The Regents of the University of California. All rights reserved.\n");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)snscore.c 8.1 (Berkeley) 7/19/93";
#else
__RCSID("$NetBSD: snscore.c,v 1.8 1998/09/11 14:25:22 hubertf Exp $");
#endif
#endif /* not lint */
#include <sys/types.h>
#include <err.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pathnames.h"
char *recfile = _PATH_RAWSCORES;
#define MAXPLAYERS 65534
struct player {
short uids;
short scores;
char *name;
} players[MAXPLAYERS], temp;
int main __P((void));
int
main()
{
short uid, score;
FILE *fd;
int noplayers;
int i, j, notsorted;
short whoallbest, allbest;
const char *q;
struct passwd *p;
/* Revoke setgid privileges */
setregid(getgid(), getgid());
fd = fopen(recfile, "r");
if (fd == NULL)
err(1, "opening `%s'", recfile);
printf("Snake players scores to date\n");
if (fread(&whoallbest, sizeof(short), 1, fd) == 0) {
printf("No scores recorded yet!\n");
exit(0);
}
fread(&allbest, sizeof(short), 1, fd);
noplayers = 0;
for (uid = 2; ;uid++) {
if(fread(&score, sizeof(short), 1, fd) == 0)
break;
if (score > 0) {
if (noplayers > MAXPLAYERS) {
printf("too many players: %d\n", noplayers);
exit(2);
}
players[noplayers].uids = uid;
players[noplayers].scores = score;
p = getpwuid(uid);
if (p == NULL)
continue;
q = p -> pw_name;
players[noplayers].name = malloc(strlen(q) + 1);
strcpy(players[noplayers].name, q);
noplayers++;
}
}
/* bubble sort scores */
for (notsorted = 1; notsorted; ) {
notsorted = 0;
for (i = 0; i < noplayers - 1; i++)
if (players[i].scores < players[i + 1].scores) {
temp = players[i];
players[i] = players[i + 1];
players[i + 1] = temp;
notsorted++;
}
}
j = 1;
for (i = 0; i < noplayers; i++) {
printf("%d:\t$%d\t%s\n", j, players[i].scores, players[i].name);
if (players[i].scores > players[i + 1].scores)
j = i + 2;
}
exit(0);
}