]> git.cameronkatri.com Git - bsdgames-darwin.git/commitdiff
Convert snake to use curses, and generally clean it up somewhat.
authorjsm <jsm@NetBSD.org>
Tue, 14 Sep 1999 18:07:21 +0000 (18:07 +0000)
committerjsm <jsm@NetBSD.org>
Tue, 14 Sep 1999 18:07:21 +0000 (18:07 +0000)
Includes bugfixes from or inspired by OpenBSD.

snake/snake/Makefile
snake/snake/move.c [deleted file]
snake/snake/snake.6
snake/snake/snake.c
snake/snake/snake.h [deleted file]

index a3904e2511e6e38731ca1ffc891bf6e4938eb203..2d6ae90cbff6814206827b4a923de3a82324ced1 100644 (file)
@@ -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
 #      @(#)Makefile    8.1 (Berkeley) 5/31/93
 
 PROG=  snake
-SRCS=  snake.c move.c
+SRCS=  snake.c
 MAN=   snake.6
 MAN=   snake.6
-DPADD= ${LIBM} ${LIBTERMCAP}
-LDADD= -lm -ltermcap
+DPADD= ${LIBM} ${LIBCURSES}
+LDADD= -lm -lcurses
 HIDEGAME=hidegame
 SETGIDGAME=yes
 
 HIDEGAME=hidegame
 SETGIDGAME=yes
 
diff --git a/snake/snake/move.c b/snake/snake/move.c
deleted file mode 100644 (file)
index 2308aeb..0000000
+++ /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);
-}
index 62122b8a7e9b3d931e9b122a4d8971a8fc0076f4..5e5812742fd767ddda4d5bf76b57e0e796dea28e 100644 (file)
@@ -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.
 .\"
 .\" 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
 .Nm
 .Op Fl w Ar width
 .Op Fl l Ar length
+.Op Fl t
 .br
 .Nm snscore
 .Sh DESCRIPTION
 .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.
 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.
 .Pp
 You are represented on the screen by an I.
 The snake is 6 squares long and is represented by S's.
index c3a69681316aecc4c9c3db492537ac5c9d417554..8e47641e70665b8a6e6560e9148e69c71d8e54f9 100644 (file)
@@ -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
 
 /*
  * 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
 #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 */
 
 #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 <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 <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"
 
 #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'
 #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 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;
 
 struct point you;
 struct point money;
@@ -90,30 +110,46 @@ struct point finish;
 struct point snake[6];
 
 int     loot, penalty;
 struct point snake[6];
 
 int     loot, penalty;
-int long tl, tm = 0L;
 int     moves;
 int     moves;
-char    stri[BSIZE];
-char   *p;
-char    ch, savec;
-char   *kl, *kr, *ku, *kd;
 int     fast = 1;
 int     fast = 1;
-int     repeat = 1;
-time_t  tv;
-char   *tn;
 
 int rawscores;
 FILE *logfile;
 
 
 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;
 {
 
 int
 main(argc, argv)
        int     argc;
        char  **argv;
 {
-       extern char *optarg;
-       extern int optind;
        int     ch, i;
        int     ch, i;
+       time_t tv;
 
        /* Open score files then revoke setgid privileges */
        rawscores = open(_PATH_RAWSCORES, O_RDWR|O_CREAT, 0664);
 
        /* 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);
        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) {
                switch ((char) ch) {
-#ifdef notdef
+#if 0
                case 'd':
                        tv = atol(optarg);
                        break;
                case 'd':
                        tv = atol(optarg);
                        break;
@@ -145,20 +180,32 @@ main(argc, argv)
                case 'l':       /* length */
                        lcnt = atoi(optarg);
                        break;
                case 'l':       /* length */
                        lcnt = atoi(optarg);
                        break;
+               case 't':
+                       fast = 0;
                case '?':
                default:
                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);
                }
 
                        exit(1);
                }
 
+       srandom((int) tv);
+
        penalty = loot = 0;
        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) {
 
        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 $.
        }
        /*
         * 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);
        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]);
 
 
        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();
        for (i = 1; i < 6; i++)
                chase(&snake[i], &snake[i - 1]);
        setup();
@@ -203,22 +246,34 @@ main(argc, argv)
        return (0);
 }
 
        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()
 {
 /* Main command loop */
 void
 mainloop()
 {
-       int     j, k;
+       int     k;
+       int     repeat = 1;
+       int     lastc = 0;
 
        for (;;) {
 
        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;
                } else {
                        if (c != '.')
                                repeat = 1;
@@ -226,48 +281,6 @@ mainloop()
                if (c == '.') {
                        c = lastc;
                }
                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;
                if (!fast)
                        flushi();
                lastc = c;
@@ -278,10 +291,10 @@ mainloop()
                case EOT:
                case 'x':
                case 0177:      /* del or end of file */
                case EOT:
                case 'x':
                case 0177:      /* del or end of file */
-                       ll();
+                       endwin();
                        length(moves);
                        logit("quit");
                        length(moves);
                        logit("quit");
-                       done();
+                       exit(0);
                case CTRL('l'):
                        setup();
                        winnings(cashvalue);
                case CTRL('l'):
                        setup();
                        winnings(cashvalue);
@@ -335,6 +348,9 @@ mainloop()
                        switch (c) {
                        case 's':
                        case 'h':
                        switch (c) {
                        case 's':
                        case 'h':
+#ifdef KEY_LEFT
+                       case KEY_LEFT:
+#endif
                        case '\b':
                                if (you.col > 0) {
                                        if ((fast) || (k == 1))
                        case '\b':
                                if (you.col > 0) {
                                        if ((fast) || (k == 1))
@@ -347,6 +363,9 @@ mainloop()
                                break;
                        case 'f':
                        case 'l':
                                break;
                        case 'f':
                        case 'l':
+#ifdef KEY_RIGHT
+                       case KEY_RIGHT:
+#endif
                        case ' ':
                                if (you.col < ccnt - 1) {
                                        if ((fast) || (k == 1))
                        case ' ':
                                if (you.col < ccnt - 1) {
                                        if ((fast) || (k == 1))
@@ -360,6 +379,9 @@ mainloop()
                        case CTRL('p'):
                        case 'e':
                        case 'k':
                        case CTRL('p'):
                        case 'e':
                        case 'k':
+#ifdef KEY_UP
+                       case KEY_UP:
+#endif
                        case 'i':
                                if (you.line > 0) {
                                        if ((fast) || (k == 1))
                        case 'i':
                                if (you.line > 0) {
                                        if ((fast) || (k == 1))
@@ -373,6 +395,9 @@ mainloop()
                        case CTRL('n'):
                        case 'c':
                        case 'j':
                        case CTRL('n'):
                        case 'c':
                        case 'j':
+#ifdef KEY_DOWN
+                       case KEY_DOWN:
+#endif
                        case LF:
                        case 'm':
                                if (you.line + 1 < lcnt) {
                        case LF:
                        case 'm':
                                if (you.line + 1 < lcnt) {
@@ -403,19 +428,18 @@ mainloop()
                        }
                        if (same(&you, &finish)) {
                                win(&finish);
                        }
                        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);
                                fflush(stdout);
                                logit("won");
                                post(cashvalue, 1);
                                length(moves);
-                               done();
+                               exit(0);
                        }
                        if (pushsnake())
                                break;
                }
                        }
                        if (pushsnake())
                                break;
                }
-               fflush(stdout);
        }
 }
 
        }
 }
 
@@ -427,7 +451,7 @@ setup()
 {
        int     i;
 
 {
        int     i;
 
-       clear();
+       erase();
        pchar(&you, ME);
        pchar(&finish, GOAL);
        pchar(&money, TREASURE);
        pchar(&you, ME);
        pchar(&finish, GOAL);
        pchar(&money, TREASURE);
@@ -436,34 +460,21 @@ setup()
        }
        pchar(&snake[0], SNAKEHEAD);
        drawbox();
        }
        pchar(&snake[0], SNAKEHEAD);
        drawbox();
-       fflush(stdout);
+       refresh();
 }
 
 void
 drawbox()
 {
        int i;
 }
 
 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;
                        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 (same(&p, &snake[i]))
                                break;
-               if (i < 5)
+               if (i < 6)
                        continue;
                break;
        }
                        continue;
                break;
        }
@@ -502,17 +513,22 @@ post(iscore, flag)
        int     iscore, flag;
 {
        short   score = iscore;
        int     iscore, flag;
 {
        short   score = iscore;
-       int     rawscores;
        short   uid;
        short   oldbest = 0;
        short   allbwho = 0, allbscore = 0;
        struct passwd *p;
 
        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) {
        /*
         * 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) {
                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));
        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
        } 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);
 
        /* 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)
                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
                else
-                       pr("You set a new record!\n");
+                       printf("You set a new record!\n");
        } else
        } 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);
 }
        lseek(rawscores, 0, SEEK_SET);
        return (1);
 }
@@ -620,14 +636,14 @@ chase(np, sp)
        }
        for (w = i = 0; i < 8; i++)
                w += wt[i];
        }
        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) {
        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++;
                i = 0;
                while (wt[i] == 0)
                        i++;
@@ -645,7 +661,7 @@ spacewarp(w)
        const char   *str;
 
        snrand(&you);
        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)
        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++) {
                penalty += loot / PENALTY;
        }
        for (j = 0; j < 3; j++) {
-               clear();
+               erase();
+               refresh();
                delay(5);
                delay(5);
-               apr(&p, str);
+               mvaddstr(p.line + 1, p.col + 1, str);
+               refresh();
                delay(10);
        }
        setup();
                delay(10);
        }
        setup();
@@ -671,23 +689,30 @@ spacewarp(w)
 void
 snap()
 {
 void
 snap()
 {
+#if 0 /* This code doesn't really make sense.  */
        struct point p;
 
        if (you.line < 3) {
        struct point p;
 
        if (you.line < 3) {
-               pchar(point(&p, you.col, 0), '-');
+               mvaddch(1, you.col + 1, '-');
        }
        if (you.line > lcnt - 4) {
        }
        if (you.line > lcnt - 4) {
-               pchar(point(&p, you.col, lcnt - 1), '_');
+               mvaddch(lcnt, you.col + 1, '_');
        }
        if (you.col < 10) {
        }
        if (you.col < 10) {
-               pchar(point(&p, 0, you.line), '(');
+               mvaddch(you.line + 1, 1, '(');
        }
        if (you.col > ccnt - 10) {
        }
        if (you.col > ccnt - 10) {
-               pchar(point(&p, ccnt - 1, you.line), ')');
+               mvaddch(you.line + 1, ccnt, ')');
        }
        }
+#endif
        if (!stretch(&money))
        if (!stretch(&money))
-               if (!stretch(&finish))
+               if (!stretch(&finish)) {
+                       pchar(&you, '?');
+                       refresh();
                        delay(10);
                        delay(10);
+                       pchar(&you, ME);
+               }
+#if 0
        if (you.line < 3) {
                point(&p, you.col, 0);
                chk(&p);
        if (you.line < 3) {
                point(&p, you.col, 0);
                chk(&p);
@@ -704,7 +729,8 @@ snap()
                point(&p, ccnt - 1, you.line);
                chk(&p);
        }
                point(&p, ccnt - 1, you.line);
                chk(&p);
        }
-       fflush(stdout);
+#endif
+       refresh();
 }
 
 int
 }
 
 int
@@ -714,37 +740,38 @@ stretch(ps)
        struct point p;
 
        point(&p, you.col, you.line);
        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) {
                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');
                                pchar(&p, 'v');
+                       refresh();
                        delay(10);
                        for (; p.line > you.line; p.line--)
                                chk(&p);
                } else {
                        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, '^');
                                pchar(&p, '^');
+                       refresh();
                        delay(10);
                        for (; p.line < you.line; p.line++)
                                chk(&p);
                }
                return (1);
        } else
                        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) {
                        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, '>');
                                        pchar(&p, '>');
+                               refresh();
                                delay(10);
                                for (; p.col > you.col; p.col--)
                                        chk(&p);
                        } else {
                                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, '<');
                                        pchar(&p, '<');
+                               refresh();
                                delay(10);
                                for (; p.col < you.col; p.col++)
                                        chk(&p);
                                delay(10);
                                for (; p.col < you.col; p.col++)
                                        chk(&p);
@@ -758,7 +785,6 @@ void
 surround(ps)
        struct point *ps;
 {
 surround(ps)
        struct point *ps;
 {
-       struct point x;
        int     j;
 
        if (ps->col == 0)
        int     j;
 
        if (ps->col == 0)
@@ -767,22 +793,34 @@ surround(ps)
                ps->line++;
        if (ps->line == LINES - 1)
                ps->line--;
                ps->line++;
        if (ps->line == LINES - 1)
                ps->line--;
-       if (ps->col == COLUMNS - 1)
+       if (ps->col == COLS - 1)
                ps->col--;
                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, '@');
        for (j = 0; j < 20; j++) {
                pchar(ps, '@');
+               refresh();
                delay(1);
                pchar(ps, ' ');
                delay(1);
                pchar(ps, ' ');
+               refresh();
                delay(1);
        }
        if (post(cashvalue, 0)) {
                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);
                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);
        }
                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
 }
 
 void
@@ -813,8 +851,9 @@ win(ps)
                        pchar(&x, '#');
                        x.col--;
                }
                        pchar(&x, '#');
                        x.col--;
                }
+               refresh();
+               delay(1);
        }
        }
-       fflush(stdout);
 }
 
 int
 }
 
 int
@@ -822,6 +861,7 @@ pushsnake()
 {
        int     i, bonus;
        int     issame = 0;
 {
        int     i, bonus;
        int     issame = 0;
+       struct point tmp;
 
        /*
         * My manual says times doesn't return a value.  Furthermore, the
 
        /*
         * My manual says times doesn't return a value.  Furthermore, the
@@ -834,18 +874,21 @@ pushsnake()
                        issame++;
        if (!issame)
                pchar(&snake[5], ' ');
                        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++) {
        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;
                        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);
                        delay(30);
                        if (bonus == i) {
                                spacewarp(1);
@@ -853,16 +896,18 @@ pushsnake()
                                flushi();
                                return (1);
                        }
                                flushi();
                                return (1);
                        }
+                       flushi();
+                       endwin();
                        if (loot >= penalty) {
                        if (loot >= penalty) {
-                               pr("You and your $%d have been eaten\n",
+                               printf("\nYou and your $%d have been eaten\n",
                                    cashvalue);
                        } else {
                                    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);
                                    -cashvalue);
                        }
                        logit("eaten");
                        length(moves);
-                       done();
+                       exit(0);
                }
        }
        return (0);
                }
        }
        return (0);
@@ -910,12 +955,8 @@ void
 winnings(won)
        int     won;
 {
 winnings(won)
        int     won;
 {
-       struct point p;
-
-       p.line = p.col = 1;
        if (won > 0) {
        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);
        int dummy __attribute__((__unused__));
 {
        signal(SIGINT, SIG_IGN);
-       ll();
+       endwin();
        length(moves);
        length(moves);
-       done();
+       exit(0);
 }
 
 void
 suspend()
 {
 }
 
 void
 suspend()
 {
-       ll();
-       cook();
+       endwin();
        kill(getpid(), SIGTSTP);
        kill(getpid(), SIGTSTP);
-       raw();
-       setup();
+       refresh();
        winnings(cashvalue);
 }
 
        winnings(cashvalue);
 }
 
@@ -944,7 +983,7 @@ void
 length(num)
        int     num;
 {
 length(num)
        int     num;
 {
-       pr("You made %d moves.\n", num);
+       printf("You made %d moves.\n", num);
 }
 
 void
 }
 
 void
diff --git a/snake/snake/snake.h b/snake/snake/snake.h
deleted file mode 100644 (file)
index fd414f4..0000000
+++ /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));