diff options
author | jsm <jsm@NetBSD.org> | 1999-09-14 18:07:21 +0000 |
---|---|---|
committer | jsm <jsm@NetBSD.org> | 1999-09-14 18:07:21 +0000 |
commit | d2e32fbfdf35f7c638077852aa6fd4f772e565c8 (patch) | |
tree | c045523b5ebd943bfa0749ccd78b6a2dcde5e8a8 /snake | |
parent | 30048bed36996889f3fd51086cd36dc9e67a1808 (diff) | |
download | bsdgames-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/Makefile | 8 | ||||
-rw-r--r-- | snake/snake/move.c | 712 | ||||
-rw-r--r-- | snake/snake/snake.6 | 7 | ||||
-rw-r--r-- | snake/snake/snake.c | 369 | ||||
-rw-r--r-- | snake/snake/snake.h | 126 |
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)); |