summaryrefslogtreecommitdiffstats
path: root/snake
diff options
context:
space:
mode:
authorjsm <jsm@NetBSD.org>1999-09-14 18:07:21 +0000
committerjsm <jsm@NetBSD.org>1999-09-14 18:07:21 +0000
commitd2e32fbfdf35f7c638077852aa6fd4f772e565c8 (patch)
treec045523b5ebd943bfa0749ccd78b6a2dcde5e8a8 /snake
parent30048bed36996889f3fd51086cd36dc9e67a1808 (diff)
downloadbsdgames-darwin-d2e32fbfdf35f7c638077852aa6fd4f772e565c8.tar.gz
bsdgames-darwin-d2e32fbfdf35f7c638077852aa6fd4f772e565c8.tar.zst
bsdgames-darwin-d2e32fbfdf35f7c638077852aa6fd4f772e565c8.zip
Convert snake to use curses, and generally clean it up somewhat.
Includes bugfixes from or inspired by OpenBSD.
Diffstat (limited to 'snake')
-rw-r--r--snake/snake/Makefile8
-rw-r--r--snake/snake/move.c712
-rw-r--r--snake/snake/snake.67
-rw-r--r--snake/snake/snake.c369
-rw-r--r--snake/snake/snake.h126
5 files changed, 213 insertions, 1009 deletions
diff --git a/snake/snake/Makefile b/snake/snake/Makefile
index a3904e25..2d6ae90c 100644
--- a/snake/snake/Makefile
+++ b/snake/snake/Makefile
@@ -1,11 +1,11 @@
-# $NetBSD: Makefile,v 1.8 1998/02/04 10:24:13 christos Exp $
+# $NetBSD: Makefile,v 1.9 1999/09/14 18:07:21 jsm Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= snake
-SRCS= snake.c move.c
+SRCS= snake.c
MAN= snake.6
-DPADD= ${LIBM} ${LIBTERMCAP}
-LDADD= -lm -ltermcap
+DPADD= ${LIBM} ${LIBCURSES}
+LDADD= -lm -lcurses
HIDEGAME=hidegame
SETGIDGAME=yes
diff --git a/snake/snake/move.c b/snake/snake/move.c
deleted file mode 100644
index 2308aeb5..00000000
--- a/snake/snake/move.c
+++ /dev/null
@@ -1,712 +0,0 @@
-/* $NetBSD: move.c,v 1.17 1999/09/08 21:17:59 jsm 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.17 1999/09/08 21:17:59 jsm 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 "snake.h"
-
-int CMlength;
-int NDlength;
-int BSlength;
-int delaystr[10];
-short ospeed;
-
-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)
- const 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)
- const 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(const struct point * ps, const char *fmt,...)
-#else
-apr(ps, fmt, va_alist)
- const 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)
- const 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);
- }
-}
-
-void
-outch(c)
- int c;
-{
- putchar(c);
-}
-
-void
-putpad(str)
- const 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
-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;
- new.c_cc[VDSUSP] = _POSIX_VDISABLE;
- raw();
-
- if (orig.c_oflag & OXTABS)
- TA = 0;
- putpad(KS);
- putpad(TI);
- point(&cursor, 0, LINES - 1);
-}
diff --git a/snake/snake/snake.6 b/snake/snake/snake.6
index 62122b8a..5e581274 100644
--- a/snake/snake/snake.6
+++ b/snake/snake/snake.6
@@ -1,4 +1,4 @@
-.\" $NetBSD: snake.6,v 1.6 1997/10/12 01:49:26 lukem Exp $
+.\" $NetBSD: snake.6,v 1.7 1999/09/14 18:07:21 jsm Exp $
.\"
.\" Copyright (c) 1980, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -44,6 +44,7 @@
.Nm
.Op Fl w Ar width
.Op Fl l Ar length
+.Op Fl t
.br
.Nm snscore
.Sh DESCRIPTION
@@ -55,7 +56,9 @@ getting eaten by the snake. The
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.
+By default the entire screen is used. The
+.Fl t
+option makes the game assume you are on a slow terminal.
.Pp
You are represented on the screen by an I.
The snake is 6 squares long and is represented by S's.
diff --git a/snake/snake/snake.c b/snake/snake/snake.c
index c3a69681..8e47641e 100644
--- a/snake/snake/snake.c
+++ b/snake/snake/snake.c
@@ -1,4 +1,4 @@
-/* $NetBSD: snake.c,v 1.13 1999/09/12 09:02:23 jsm Exp $ */
+/* $NetBSD: snake.c,v 1.14 1999/09/14 18:07:21 jsm Exp $ */
/*
* Copyright (c) 1980, 1993
@@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
#if 0
static char sccsid[] = "@(#)snake.c 8.2 (Berkeley) 1/7/94";
#else
-__RCSID("$NetBSD: snake.c,v 1.13 1999/09/12 09:02:23 jsm Exp $");
+__RCSID("$NetBSD: snake.c,v 1.14 1999/09/14 18:07:21 jsm Exp $");
#endif
#endif /* not lint */
@@ -60,16 +60,31 @@ __RCSID("$NetBSD: snake.c,v 1.13 1999/09/12 09:02:23 jsm Exp $");
#include <sys/param.h>
-#include <errno.h>
+#include <curses.h>
#include <fcntl.h>
#include <pwd.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <err.h>
+#include <math.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
-#include "snake.h"
#include "pathnames.h"
+#define cashvalue chunk*(loot-penalty)/25
+
+struct point {
+ int col, line;
+};
+
+#define same(s1, s2) ((s1)->line == (s2)->line && (s1)->col == (s2)->col)
+
#define PENALTY 10 /* % penalty for invoking spacewarp */
#define EOT '\004'
@@ -82,7 +97,12 @@ __RCSID("$NetBSD: snake.c,v 1.13 1999/09/12 09:02:23 jsm Exp $");
#define TREASURE '$'
#define GOAL '#'
-#define BSIZE 80
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define pchar(point, c) mvaddch((point)->line + 1, (point)->col + 1, (c))
+#define delay(t) usleep(t * 50000);
struct point you;
struct point money;
@@ -90,30 +110,46 @@ 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 lcnt, ccnt; /* user's idea of screen size */
+int chunk; /* amount of money given at a time */
+
+void chase __P((struct point *, struct point *));
+int chk __P((const struct point *));
+void drawbox __P((void));
+void flushi __P((void));
+void home __P((void));
+void length __P((int));
+void logit __P((const char *));
+int main __P((int, char **));
+void mainloop __P((void)) __attribute__((__noreturn__));
+struct point *point __P((struct point *, int, int));
+int post __P((int, int));
+int pushsnake __P((void));
+void right __P((const struct point *));
+void setup __P((void));
+void snap __P((void));
+void snrand __P((struct point *));
+void spacewarp __P((int));
+void stop __P((int)) __attribute__((__noreturn__));
+int stretch __P((const struct point *));
+void surround __P((struct point *));
+void suspend __P((void));
+void win __P((const struct point *));
+void winnings __P((int));
int
main(argc, argv)
int argc;
char **argv;
{
- extern char *optarg;
- extern int optind;
int ch, i;
+ time_t tv;
/* Open score files then revoke setgid privileges */
rawscores = open(_PATH_RAWSCORES, O_RDWR|O_CREAT, 0664);
@@ -130,11 +166,10 @@ main(argc, argv)
setregid(getgid(), getgid());
(void) time(&tv);
- srandom((int) tv);
- while ((ch = getopt(argc, argv, "l:w:")) != -1)
+ while ((ch = getopt(argc, argv, "l:w:t")) != -1)
switch ((char) ch) {
-#ifdef notdef
+#if 0
case 'd':
tv = atol(optarg);
break;
@@ -145,20 +180,32 @@ main(argc, argv)
case 'l': /* length */
lcnt = atoi(optarg);
break;
+ case 't':
+ fast = 0;
case '?':
default:
- fputs("usage: snake [-d seed] [-w width] [-l length]\n", stderr);
+ fputs("usage: snake [-d seed] [-w width] [-l length] [-t]\n", stderr);
exit(1);
}
+ srandom((int) tv);
+
penalty = loot = 0;
- getcap();
+ initscr();
+ cbreak();
+ noecho();
+#ifdef KEY_LEFT
+ keypad(stdscr, TRUE);
+#endif
+ if (!lcnt || lcnt > LINES - 2)
+ lcnt = LINES - 2;
+ if (!ccnt || ccnt > COLS - 2)
+ ccnt = COLS - 2;
i = MIN(lcnt, ccnt);
if (i < 4) {
- cook();
- pr("snake: screen too small for a fair game.\n");
- exit(1);
+ endwin();
+ errx(1, "screen too small for a fair game.");
}
/*
* chunk is the amount of money the user gets for each $.
@@ -185,16 +232,12 @@ main(argc, argv)
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();
@@ -203,22 +246,34 @@ main(argc, argv)
return (0);
}
+struct point *
+point(ps, x, y)
+ struct point *ps;
+ int x, y;
+{
+ ps->col = x;
+ ps->line = y;
+ return (ps);
+}
+
/* Main command loop */
void
mainloop()
{
- int j, k;
+ int k;
+ int repeat = 1;
+ int lastc = 0;
for (;;) {
- int c, lastc, match;
-
- lastc = 0;
- move(&you);
- fflush(stdout);
- if (((c = getchar() & 0177) <= '9') && (c >= '0')) {
- ungetc(c, stdin);
- j = scanf("%d", &repeat);
- c = getchar() & 0177;
+ int c;
+
+ /* Highlight you, not left & above */
+ move(you.line + 1, you.col + 1);
+ refresh();
+ if (((c = getch()) <= '9') && (c >= '0')) {
+ repeat = c - '0';
+ while (((c = getch()) <= '9') && (c >= '0'))
+ repeat = 10 * repeat + (c - '0');
} else {
if (c != '.')
repeat = 1;
@@ -226,48 +281,6 @@ mainloop()
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;
@@ -278,10 +291,10 @@ mainloop()
case EOT:
case 'x':
case 0177: /* del or end of file */
- ll();
+ endwin();
length(moves);
logit("quit");
- done();
+ exit(0);
case CTRL('l'):
setup();
winnings(cashvalue);
@@ -335,6 +348,9 @@ mainloop()
switch (c) {
case 's':
case 'h':
+#ifdef KEY_LEFT
+ case KEY_LEFT:
+#endif
case '\b':
if (you.col > 0) {
if ((fast) || (k == 1))
@@ -347,6 +363,9 @@ mainloop()
break;
case 'f':
case 'l':
+#ifdef KEY_RIGHT
+ case KEY_RIGHT:
+#endif
case ' ':
if (you.col < ccnt - 1) {
if ((fast) || (k == 1))
@@ -360,6 +379,9 @@ mainloop()
case CTRL('p'):
case 'e':
case 'k':
+#ifdef KEY_UP
+ case KEY_UP:
+#endif
case 'i':
if (you.line > 0) {
if ((fast) || (k == 1))
@@ -373,6 +395,9 @@ mainloop()
case CTRL('n'):
case 'c':
case 'j':
+#ifdef KEY_DOWN
+ case KEY_DOWN:
+#endif
case LF:
case 'm':
if (you.line + 1 < lcnt) {
@@ -403,19 +428,18 @@ mainloop()
}
if (same(&you, &finish)) {
win(&finish);
- ll();
- cook();
- pr("You have won with $%d.\n", cashvalue);
+ flushi();
+ endwin();
+ printf("You have won with $%d.\n", cashvalue);
fflush(stdout);
logit("won");
post(cashvalue, 1);
length(moves);
- done();
+ exit(0);
}
if (pushsnake())
break;
}
- fflush(stdout);
}
}
@@ -427,7 +451,7 @@ setup()
{
int i;
- clear();
+ erase();
pchar(&you, ME);
pchar(&finish, GOAL);
pchar(&money, TREASURE);
@@ -436,34 +460,21 @@ setup()
}
pchar(&snake[0], SNAKEHEAD);
drawbox();
- fflush(stdout);
+ refresh();
}
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, '|');
+ for (i = 1; i <= ccnt; i++) {
+ mvaddch(0, i, '-');
+ mvaddch(lcnt + 1, i, '-');
}
- p.line = lcnt;
- for (i = 0; i < ccnt; i++) {
- p.col = i;
- pchar(&p, '-');
+ for (i = 0; i <= lcnt + 1; i++) {
+ mvaddch(i, 0, '|');
+ mvaddch(i, ccnt + 1, '|');
}
}
@@ -487,10 +498,10 @@ snrand(sp)
continue;
if (same(&p, &finish))
continue;
- for (i = 0; i < 5; i++)
+ for (i = 0; i < 6; i++)
if (same(&p, &snake[i]))
break;
- if (i < 5)
+ if (i < 6)
continue;
break;
}
@@ -502,17 +513,22 @@ post(iscore, flag)
int iscore, flag;
{
short score = iscore;
- int rawscores;
short uid;
short oldbest = 0;
short allbwho = 0, allbscore = 0;
struct passwd *p;
+ /* I want to printf() the scores for terms that clear on cook(),
+ * but this routine also gets called with flag == 0 to see if
+ * the snake should wink. If (flag) then we're at game end and
+ * can printf.
+ */
/*
* Neg uid, 0, and 1 cannot have scores recorded.
*/
if ((uid = getuid()) <= 1) {
- pr("No saved scores for uid %d.\n", uid);
+ if (flag)
+ printf("No saved scores for uid %d.\n", uid);
return (1);
}
if (rawscores < 0) {
@@ -531,9 +547,9 @@ post(iscore, flag)
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);
+ printf("You bettered your previous best of $%d\n", oldbest);
} else
- pr("Your best to date is $%d\n", oldbest);
+ printf("Your best to date is $%d\n", oldbest);
/* See if we have a new champ */
p = getpwuid(allbwho);
@@ -542,12 +558,12 @@ post(iscore, flag)
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);
+ printf("You beat %s's old record of $%d!\n",
+ p->pw_name, allbscore);
else
- pr("You set a new record!\n");
+ printf("You set a new record!\n");
} else
- pr("The highest is %s with $%d\n", p->pw_name, allbscore);
+ printf("The highest is %s with $%d\n", p->pw_name, allbscore);
lseek(rawscores, 0, SEEK_SET);
return (1);
}
@@ -620,14 +636,14 @@ chase(np, sp)
}
for (w = i = 0; i < 8; i++)
w += wt[i];
- vp = ((rand() >> 6) & 01777) % w;
+ vp = ((random() >> 6) & 01777) % w;
for (i = 0; i < 8; i++)
if (vp < wt[i])
break;
else
vp -= wt[i];
if (i == 8) {
- pr("failure\n");
+ printw("failure\n");
i = 0;
while (wt[i] == 0)
i++;
@@ -645,7 +661,7 @@ spacewarp(w)
const char *str;
snrand(&you);
- point(&p, COLUMNS / 2 - 8, LINES / 2 - 1);
+ point(&p, COLS / 2 - 8, LINES / 2 - 1);
if (p.col < 0)
p.col = 0;
if (p.line < 0)
@@ -659,9 +675,11 @@ spacewarp(w)
penalty += loot / PENALTY;
}
for (j = 0; j < 3; j++) {
- clear();
+ erase();
+ refresh();
delay(5);
- apr(&p, str);
+ mvaddstr(p.line + 1, p.col + 1, str);
+ refresh();
delay(10);
}
setup();
@@ -671,23 +689,30 @@ spacewarp(w)
void
snap()
{
+#if 0 /* This code doesn't really make sense. */
struct point p;
if (you.line < 3) {
- pchar(point(&p, you.col, 0), '-');
+ mvaddch(1, you.col + 1, '-');
}
if (you.line > lcnt - 4) {
- pchar(point(&p, you.col, lcnt - 1), '_');
+ mvaddch(lcnt, you.col + 1, '_');
}
if (you.col < 10) {
- pchar(point(&p, 0, you.line), '(');
+ mvaddch(you.line + 1, 1, '(');
}
if (you.col > ccnt - 10) {
- pchar(point(&p, ccnt - 1, you.line), ')');
+ mvaddch(you.line + 1, ccnt, ')');
}
+#endif
if (!stretch(&money))
- if (!stretch(&finish))
+ if (!stretch(&finish)) {
+ pchar(&you, '?');
+ refresh();
delay(10);
+ pchar(&you, ME);
+ }
+#if 0
if (you.line < 3) {
point(&p, you.col, 0);
chk(&p);
@@ -704,7 +729,8 @@ snap()
point(&p, ccnt - 1, you.line);
chk(&p);
}
- fflush(stdout);
+#endif
+ refresh();
}
int
@@ -714,37 +740,38 @@ stretch(ps)
struct point p;
point(&p, you.col, you.line);
- if (abs(ps->col - you.col) < 6) {
+ if ((abs(ps->col - you.col) < (ccnt / 12)) && (you.line != ps->line)) {
if (you.line < ps->line) {
- for (p.line = you.line + 1; p.line <= ps->line;
- p.line++)
+ for (p.line = you.line + 1; p.line <= ps->line; p.line++)
pchar(&p, 'v');
+ refresh();
delay(10);
for (; p.line > you.line; p.line--)
chk(&p);
} else {
- for (p.line = you.line - 1; p.line >= ps->line;
- p.line--)
+ for (p.line = you.line - 1; p.line >= ps->line; p.line--)
pchar(&p, '^');
+ refresh();
delay(10);
for (; p.line < you.line; p.line++)
chk(&p);
}
return (1);
} else
- if (abs(ps->line - you.line) < 3) {
+ if ((abs(ps->line - you.line) < (lcnt/7))
+ && (you.col != ps->col)) {
p.line = you.line;
if (you.col < ps->col) {
- for (p.col = you.col + 1; p.col <= ps->col;
- p.col++)
+ for (p.col = you.col + 1; p.col <= ps->col; p.col++)
pchar(&p, '>');
+ refresh();
delay(10);
for (; p.col > you.col; p.col--)
chk(&p);
} else {
- for (p.col = you.col - 1; p.col >= ps->col;
- p.col--)
+ for (p.col = you.col - 1; p.col >= ps->col; p.col--)
pchar(&p, '<');
+ refresh();
delay(10);
for (; p.col < you.col; p.col++)
chk(&p);
@@ -758,7 +785,6 @@ void
surround(ps)
struct point *ps;
{
- struct point x;
int j;
if (ps->col == 0)
@@ -767,22 +793,34 @@ surround(ps)
ps->line++;
if (ps->line == LINES - 1)
ps->line--;
- if (ps->col == COLUMNS - 1)
+ if (ps->col == COLS - 1)
ps->col--;
- apr(point(&x, ps->col - 1, ps->line - 1), "/*\\\r* *\r\\*/");
+ mvaddstr(ps->line, ps->col, "/*\\");
+ mvaddstr(ps->line + 1, ps->col, "* *");
+ mvaddstr(ps->line + 2, ps->col, "\\*/");
for (j = 0; j < 20; j++) {
pchar(ps, '@');
+ refresh();
delay(1);
pchar(ps, ' ');
+ refresh();
delay(1);
}
if (post(cashvalue, 0)) {
- apr(point(&x, ps->col - 1, ps->line - 1), " \ro.o\r\\_/");
+ mvaddstr(ps->line, ps->col, " ");
+ mvaddstr(ps->line + 1, ps->col, "o.o");
+ mvaddstr(ps->line + 2, ps->col, "\\_/");
+ refresh();
delay(6);
- apr(point(&x, ps->col - 1, ps->line - 1), " \ro.-\r\\_/");
+ mvaddstr(ps->line, ps->col, " ");
+ mvaddstr(ps->line + 1, ps->col, "o.-");
+ mvaddstr(ps->line + 2, ps->col, "\\_/");
+ refresh();
delay(6);
}
- apr(point(&x, ps->col - 1, ps->line - 1), " \ro.o\r\\_/");
+ mvaddstr(ps->line, ps->col, " ");
+ mvaddstr(ps->line + 1, ps->col, "o.o");
+ mvaddstr(ps->line + 2, ps->col, "\\_/");
}
void
@@ -813,8 +851,9 @@ win(ps)
pchar(&x, '#');
x.col--;
}
+ refresh();
+ delay(1);
}
- fflush(stdout);
}
int
@@ -822,6 +861,7 @@ pushsnake()
{
int i, bonus;
int issame = 0;
+ struct point tmp;
/*
* My manual says times doesn't return a value. Furthermore, the
@@ -834,18 +874,21 @@ pushsnake()
issame++;
if (!issame)
pchar(&snake[5], ' ');
+ /* Need the following to catch you if you step on the snake's tail */
+ tmp.col = snake[5].col;
+ tmp.line = snake[5].line;
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)) {
+ if (same(&snake[i], &you) || same(&tmp, &you)) {
surround(&you);
i = (cashvalue) % 10;
- bonus = ((rand() >> 8) & 0377) % 10;
- ll();
- pr("%d\n", bonus);
+ bonus = ((random() >> 8) & 0377) % 10;
+ mvprintw(lcnt + 1, 0, "%d\n", bonus);
+ refresh();
delay(30);
if (bonus == i) {
spacewarp(1);
@@ -853,16 +896,18 @@ pushsnake()
flushi();
return (1);
}
+ flushi();
+ endwin();
if (loot >= penalty) {
- pr("You and your $%d have been eaten\n",
+ printf("\nYou and your $%d have been eaten\n",
cashvalue);
} else {
- pr("The snake ate you. You owe $%d.\n",
+ printf("\nThe snake ate you. You owe $%d.\n",
-cashvalue);
}
logit("eaten");
length(moves);
- done();
+ exit(0);
}
}
return (0);
@@ -910,12 +955,8 @@ void
winnings(won)
int won;
{
- struct point p;
-
- p.line = p.col = 1;
if (won > 0) {
- move(&p);
- pr("$%d", won);
+ mvprintw(1, 1, "$%d", won);
}
}
@@ -924,19 +965,17 @@ stop(dummy)
int dummy __attribute__((__unused__));
{
signal(SIGINT, SIG_IGN);
- ll();
+ endwin();
length(moves);
- done();
+ exit(0);
}
void
suspend()
{
- ll();
- cook();
+ endwin();
kill(getpid(), SIGTSTP);
- raw();
- setup();
+ refresh();
winnings(cashvalue);
}
@@ -944,7 +983,7 @@ void
length(num)
int num;
{
- pr("You made %d moves.\n", num);
+ printf("You made %d moves.\n", num);
}
void
diff --git a/snake/snake/snake.h b/snake/snake/snake.h
deleted file mode 100644
index fd414f4d..00000000
--- a/snake/snake/snake.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* $NetBSD: snake.h,v 1.13 1999/09/08 21:45:31 jsm 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 */
-short ospeed;
-#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((const struct point *, const char *, ...));
-void bs __P((void));
-void chase __P((struct point *, struct point *));
-int chk __P((const 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((const struct point *));
-void home __P((void));
-void length __P((int));
-void ll __P((void));
-void logit __P((const char *));
-void mainloop __P((void)) __attribute__((__noreturn__));
-void move __P((struct point *));
-void nd __P((void));
-void outch __P((int));
-void pch __P((int));
-void pchar __P((const 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((const char *));
-void raw __P((void));
-void right __P((const struct point *));
-void setup __P((void));
-void snap __P((void));
-void snrand __P((struct point *));
-void spacewarp __P((int));
-void stop __P((int)) __attribute__((__noreturn__));
-int stretch __P((const struct point *));
-void surround __P((struct point *));
-void suspend __P((void));
-void up __P((void));
-void win __P((const struct point *));
-void winnings __P((int));