386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Tue, 9 Apr 1991 01:09:36 +0000 (17:09 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Tue, 9 Apr 1991 01:09:36 +0000 (17:09 -0800)
Work on file usr/othersrc/games/snake/snake/move.c
Work on file usr/othersrc/games/snake/snake/snake.6
Work on file usr/othersrc/games/snake/snake/pathnames.h
Work on file usr/othersrc/games/snake/snake/snake.c
Work on file usr/othersrc/games/snake/snake/snake.h
Work on file usr/othersrc/games/snake/snscore/snscore.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/othersrc/games/snake/snake/move.c [new file with mode: 0644]
usr/othersrc/games/snake/snake/pathnames.h [new file with mode: 0644]
usr/othersrc/games/snake/snake/snake.6 [new file with mode: 0644]
usr/othersrc/games/snake/snake/snake.c [new file with mode: 0644]
usr/othersrc/games/snake/snake/snake.h [new file with mode: 0644]
usr/othersrc/games/snake/snscore/snscore.c [new file with mode: 0644]

diff --git a/usr/othersrc/games/snake/snake/move.c b/usr/othersrc/games/snake/snake/move.c
new file mode 100644 (file)
index 0000000..decddf6
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * Copyright (c) 1980 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.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)move.c     5.8 (Berkeley) 2/28/91";
+#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.
+ *
+ *             baudrate(x)     returns the baudrate of the terminal.
+ *             delay(t)        causes an approximately constant delay
+ *                                     independent of baudrate.
+ *                                     Duration is ~ t/20 seconds.
+ *
+ ******************************************************************************/
+
+#include <stdarg.h>
+#include "snake.h"
+
+int CMlength;
+int NDlength;
+int BSlength;
+int delaystr[10];
+short ospeed;
+
+static char str[80];
+
+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);
+}
+gto(sp)
+struct point *sp;
+{
+
+       int distance,f,tfield,j;
+
+       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 */
+}
+
+right(sp)
+struct point *sp;
+{
+       int field,tfield;
+       int tabcol,strlength;
+
+       if (sp->col < cursor.col)
+               pr("ERROR:right() can't move left\n");
+       if(TA){         /* If No Tabs: can't send tabs because ttydrive
+                        * loses count with control characters.
+                        */
+               field = cursor.col >> 3;
+/*
+ *     This code is useful for a terminal which wraps around on backspaces.
+ *     (Mine does.)  Unfortunately, this is not specified in termcap, and
+ *     most terminals don't work that way.  (Of course, most terminals
+ *     have addressible cursors, too).
+ */
+               if (BW && (CM == 0) &&
+                   ((sp->col << 1) - field > (COLUMNS - 8) << 1 )
+                  ){
+                       if (cursor.line == 0){  
+                               outch('\n');
+                       }
+                       outch('\r');
+                       cursor.col = COLUMNS + 1;
+                       while(cursor.col > sp->col)bs();
+                       if (cursor.line != 0) outch('\n');
+                       return;
+               }
+
+               tfield = sp->col >> 3;
+
+               while (field < tfield){
+                       putpad(TA);
+                       cursor.col = ++field << 3;
+               }
+               tabcol = (cursor.col|7) + 1;
+               strlength = (tabcol - sp->col)*BSlength + 1;
+               /* length of sequence to overshoot */
+               if (((sp->col - cursor.col)*NDlength > strlength) &&
+                   (tabcol < COLUMNS)
+                  ){
+                       /*
+                        * Tab past and backup
+                        */
+                       putpad(TA);
+                       cursor.col = (cursor.col | 7) + 1;
+                       while(cursor.col > sp->col)bs();
+               }
+       }
+       while (sp->col > cursor.col){
+               nd();
+       }
+}
+
+cr(){
+       outch('\r');
+       cursor.col = 0;
+}
+
+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();
+       }
+}
+
+home(){
+       struct point z;
+
+       if(HO != 0){
+               putpad(HO);
+               cursor.col = cursor.line = 0;
+               return;
+       }
+       z.col = z.line = 0;
+       move(&z);
+}
+
+ll(){
+       int j,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);
+}
+
+up(){
+       putpad(UP);
+       cursor.line--;
+}
+
+down(){
+       putpad(DO);
+       cursor.line++;
+       if (cursor.line >= LINES)cursor.line=LINES-1;
+}
+bs(){
+       if (cursor.col > 0){
+               putpad(BS);
+               cursor.col--;
+       }
+}
+
+nd(){
+       putpad(ND);
+       cursor.col++;
+       if (cursor.col == COLUMNS+1){
+               cursor.line++;
+               cursor.col = 0;
+               if (cursor.line >= LINES)cursor.line=LINES-1;
+       }
+}
+
+pch(c)
+{
+       outch(c);
+       if(++cursor.col >= COLUMNS && AM) {
+               cursor.col = 0;
+               ++cursor.line;
+       }
+}
+
+apr(ps, fmt)
+       struct point *ps;
+       char *fmt;
+{
+       struct point p;
+       va_list ap;
+
+       p.line = ps->line+1; p.col = ps->col+1;
+       move(&p);
+       va_start(ap, fmt);
+       (void)vsprintf(str, fmt, ap);
+       va_end(ap);
+       pstring(str);
+}
+
+pr(fmt)
+       char *fmt;
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       (void)vsprintf(str, fmt, ap);
+       va_end(ap);
+       pstring(str);
+}
+
+pstring(s)
+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++;
+       }
+}
+
+pchar(ps,ch)
+struct point *ps;
+char ch;{
+       struct point p;
+       p.col = ps->col + 1; p.line = ps->line + 1;
+       if (
+               (p.col >= 0) &&
+               (p.line >= 0) &&
+               (
+                       (
+                               (p.line < LINES) &&
+                               (p.col < COLUMNS)
+                       ) ||
+                       (
+                               (p.col == COLUMNS) &&
+                               (p.line < LINES-1)
+                       )
+               )
+       ){
+               move(&p);
+               pch(ch);
+       }
+}
+
+                       
+outch(c)
+{
+       putchar(c);
+}
+
+putpad(str)
+char *str;
+{
+       if (str)
+               tputs(str, 1, outch);
+}
+baudrate()
+{
+
+       switch (orig.sg_ospeed){
+       case B300:
+               return(300);
+       case B1200:
+               return(1200);
+       case B4800:
+               return(4800);
+       case B9600:
+               return(9600);
+       default:
+               return(0);
+       }
+}
+delay(t)
+int t;
+{
+       int k,j;
+
+       k = baudrate() * t / 300;
+       for(j=0;j<k;j++){
+               putchar(PC);
+       }
+}
+
+done()
+{
+       cook();
+       exit(0);
+}
+
+cook()
+{
+       delay(1);
+       putpad(TE);
+       putpad(KE);
+       fflush(stdout);
+       stty(0, &orig);
+#ifdef TIOCSLTC
+       ioctl(0, TIOCSLTC, &olttyc);
+#endif
+}
+
+raw()
+{
+       stty(0, &new);
+#ifdef TIOCSLTC
+       ioctl(0, TIOCSLTC, &nlttyc);
+#endif
+}
+
+struct point *point(ps,x,y)
+struct point *ps;
+int x,y;
+{
+       ps->col=x;
+       ps->line=y;
+       return(ps);
+}
+
+char *ap;
+
+getcap()
+{
+       char *getenv();
+       char *term;
+       char *xPC;
+       struct point z;
+       void stop();
+
+       term = getenv("TERM");
+       if (term==0) {
+               fprintf(stderr, "No TERM in environment\n");
+               exit(1);
+       }
+
+       switch (tgetent(tbuf, term)) {
+       case -1:
+               fprintf(stderr, "Cannot open termcap file\n");
+               exit(2);
+       case 0:
+               fprintf(stderr, "%s: unknown terminal", term);
+               exit(3);
+       }
+
+       ap = tcapbuf;
+
+       LINES = tgetnum("li");
+       COLUMNS = tgetnum("co");
+       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("bc", &ap);
+       if (BS == 0 && tgetflag("bs"))
+               BS = "\b";
+       if (BS)
+               xBC = *BS;
+
+       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);
+       Klength = strlen(KL);
+               /*      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;
+
+       NDlength = strlen(ND);
+       BSlength = strlen(BS);
+       if ((CM == 0) &&
+               (HO == 0 | UP==0 || BS==0 || ND==0)) {
+               fprintf(stderr, "Terminal must have addressible ");
+               fprintf(stderr, "cursor or home + 4 local motions\n");
+               exit(5);
+       }
+       if (tgetflag("os")) {
+               fprintf(stderr, "Terminal must not overstrike\n");
+               exit(5);
+       }
+       if (LINES <= 0 || COLUMNS <= 0) {
+               fprintf(stderr, "Must know the screen size\n");
+               exit(5);
+       }
+
+       gtty(0, &orig);
+       new=orig;
+       new.sg_flags &= ~(ECHO|CRMOD|ALLDELAY|XTABS);
+       new.sg_flags |= CBREAK;
+       signal(SIGINT,stop);
+       ospeed = orig.sg_ospeed;
+#ifdef TIOCGLTC
+       ioctl(0, TIOCGLTC, &olttyc);
+       nlttyc = olttyc;
+       nlttyc.t_suspc = '\377';
+       nlttyc.t_dsuspc = '\377';
+#endif
+       raw();
+
+       if ((orig.sg_flags & XTABS) == XTABS) TA=0;
+       putpad(KS);
+       putpad(TI);
+       point(&cursor,0,LINES-1);
+}
diff --git a/usr/othersrc/games/snake/snake/pathnames.h b/usr/othersrc/games/snake/snake/pathnames.h
new file mode 100644 (file)
index 0000000..bf3d5d5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pathnames.h 5.3 (Berkeley) 6/1/90
+ */
+
+#define        _PATH_RAWSCORES "/var/games/snakerawscores"
+#define        _PATH_LOGFILE   "/var/games/snake.log"
diff --git a/usr/othersrc/games/snake/snake/snake.6 b/usr/othersrc/games/snake/snake/snake.6
new file mode 100644 (file)
index 0000000..5251f1a
--- /dev/null
@@ -0,0 +1,113 @@
+.\" Copyright (c) 1980 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by the University of
+.\"    California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\"    may be used to endorse or promote products derived from this software
+.\"    without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"    @(#)snake.6     6.4 (Berkeley) 6/23/90
+.\"
+.TH SNAKE 6 "June 23, 1990"
+.UC 4
+.SH NAME
+snake, snscore \- display chase game
+.SH SYNOPSIS
+.B snake
+[
+.B -w width
+] [
+.B -l length
+]
+.br
+.B snscore
+.SH DESCRIPTION
+Snake is a display-based game which must be played on a CRT terminal.
+The object of the game is to make as much money as possible without
+getting eaten by the snake.  The
+.B \-l
+and
+.B \-w
+options allow you to specify the length and width of the field.
+By default the entire screen (except for the last column) is used.
+.PP
+You are represented on the screen by an I.
+The snake is 6 squares long and is represented by S's.
+The money is $, and an exit is #.
+Your score is posted in the upper left hand corner.
+.PP
+You can move around using the same conventions as vi(1),
+the h, j, k, and l keys work, as do the arrow keys.
+Other possibilities include:
+.IP sefc
+These keys are like hjkl but form a directed pad around the d key.
+.IP HJKL
+These keys move you all the way in the indicated direction to the
+same row or column as the money.  This does
+.I not
+let you jump away from the snake, but rather saves you from having
+to type a key repeatedly.  The snake still gets all his turns.
+.IP SEFC
+Likewise for the upper case versions on the left.
+.IP ATPB
+These keys move you to the four edges of the screen.
+Their position on the keyboard is the mnemonic, e.g.
+P is at the far right of the keyboard.
+.IP x
+This lets you quit the game at any time.
+.IP p
+Points in a direction you might want to go.
+.IP w
+Space warp to get out of tight squeezes, at a price.
+.PP
+To earn money, move to the same square the money is on.
+A new $ will appear when you earn the current one.
+As you get richer, the snake gets hungrier.
+To leave the game, move to the exit (#).
+.PP
+A record is kept of the personal best score of each player.
+Scores are only counted if you leave at the exit,
+getting eaten by the snake is worth nothing.
+.PP
+As in pinball, matching the last digit of your score to the number
+which appears after the game is worth a bonus.
+.PP
+To see who wastes time playing snake, run
+.I snscore .
+.SH FILES
+.nf
+.ta \w'/usr/games/lib/snakerawscores 'u
+/usr/games/lib/snakerawscores  database of personal bests
+/usr/games/lib/snake.log       log of games played
+.DT
+.fi
+.SH BUGS
+.PP
+When playing on a small screen,
+it's hard to tell when you hit the edge of the screen.
+.PP
+The scoring function takes into account the size of the screen.
+A perfect function to do this equitably has not been devised.
diff --git a/usr/othersrc/games/snake/snake/snake.c b/usr/othersrc/games/snake/snake/snake.c
new file mode 100644 (file)
index 0000000..686465e
--- /dev/null
@@ -0,0 +1,890 @@
+/*
+ * Copyright (c) 1980 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.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)snake.c    5.10 (Berkeley) 2/28/91";
+#endif /* not lint */
+
+/*
+ * snake - crt hack game.
+ *
+ * You move around the screen with arrow keys trying to pick up money
+ * without getting eaten by the snake.  hjkl work as in vi in place of
+ * arrow keys.  You can leave at the exit any time.
+ *
+ * compile as follows:
+ *     cc -O snake.c move.c -o snake -lm -ltermlib
+ */
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <errno.h>
+#include "snake.h"
+#include "pathnames.h"
+
+#define PENALTY  10    /* % penalty for invoking spacewarp     */
+
+#define EOT    '\004'
+#define LF     '\n'
+#define DEL    '\177'
+
+#define ME             'I'
+#define SNAKEHEAD      'S'
+#define SNAKETAIL      's'
+#define TREASURE       '$'
+#define GOAL           '#'
+
+#define BSIZE  80
+
+struct point you;
+struct point money;
+struct point finish;
+struct point snake[6];
+
+int loot, penalty;
+int long tl, tm=0L;
+int moves;
+char stri[BSIZE];
+char *p;
+char ch, savec;
+char *kl, *kr, *ku, *kd;
+int fast=1;
+int repeat=1;
+long tv;
+char *tn;
+
+main(argc,argv)
+int argc;
+char **argv;
+{
+       extern char *optarg;
+       extern int optind;
+       int ch, i, j, k;
+       time_t time();
+       long atol();
+       void stop();
+
+       (void)time(&tv);
+       srandom((int)tv);
+
+       while ((ch = getopt(argc, argv, "l:w:")) != EOF)
+               switch((char)ch) {
+#ifdef notdef
+               case 'd':
+                       tv = atol(optarg);
+                       break;
+#endif
+               case 'w':       /* width */
+                       ccnt = atoi(optarg);
+                       break;
+               case 'l':       /* length */
+                       lcnt = atoi(optarg);
+                       break;
+               case '?':
+               default:
+                       fputs("usage: snake [-d seed] [-w width] [-l length]\n", stderr);
+                       exit(1);
+               }
+
+       penalty = loot = 0;
+       getcap();
+
+       i = MIN(lcnt, ccnt);
+       if (i < 4) {
+               cook();
+               pr("snake: screen too small for a fair game.\n");
+               exit(1);
+       }
+
+       /*
+        * chunk is the amount of money the user gets for each $.
+        * The formula below tries to be fair for various screen sizes.
+        * We only pay attention to the smaller of the 2 edges, since
+        * that seems to be the bottleneck.
+        * This formula is a hyperbola which includes the following points:
+        *      (24, $25)       (original scoring algorithm)
+        *      (12, $40)       (experimentally derived by the "feel")
+        *      (48, $15)       (a guess)
+        * This will give a 4x4 screen $99/shot.  We don't allow anything
+        * smaller than 4x4 because there is a 3x3 game where you can win
+        * an infinite amount of money.
+        */
+       if (i < 12) i = 12;     /* otherwise it isn't fair */
+       /*
+        * Compensate for border.  This really changes the game since
+        * the screen is two squares smaller but we want the default
+        * to be $25, and the high scores on small screens were a bit
+        * much anyway.
+        */
+       i += 2;
+       chunk = (675.0 / (i+6)) + 2.5;  /* min screen edge */
+
+       signal (SIGINT, stop);
+       putpad(TI); /*  String to begin programs that use cm */
+       putpad(KS); /*  Put terminal in keypad transmit mode */
+
+       snrand(&finish);
+       snrand(&you);
+       snrand(&money);
+       snrand(&snake[0]);
+
+       if ((orig.sg_ospeed < B9600) ||
+           ((! CM) && (! TA))) fast=0;
+       for(i=1;i<6;i++)
+               chase (&snake[i], &snake[i-1]);
+       setup();
+       mainloop();
+}
+
+/* Main command loop */
+mainloop()
+{
+       int j, k;
+
+       for (;;) {
+               int c,lastc,match;
+
+               move(&you);
+               fflush(stdout);
+               if (((c = getchar() & 0177) <= '9') && (c >= '0')) {
+                       ungetc(c,stdin);
+                       j = scanf("%d",&repeat);
+                       c = getchar() & 0177;
+               } else {
+                       if (c != '.') repeat = 1;
+               }
+               if (c == '.') {
+                       c = lastc;
+               }
+               if ((Klength > 0) && 
+                   (c == *KL || c == *KR || c == *KU || c == *KD)) {
+                       savec = c;
+                       match = 0;
+                       kl = KL;
+                       kr = KR;
+                       ku = KU;
+                       kd = KD;
+                       for (j=Klength;j>0;j--){
+                               if (match != 1) {
+                               match = 0;
+                                       if (*kl++ == c) {
+                                               ch = 'h';
+                                               match++;
+                                       }
+                                       if (*kr++ == c) {
+                                               ch = 'l';
+                                               match++;
+                                       }
+                                       if (*ku++ == c) {
+                                               ch = 'k';
+                                               match++;
+                                       }
+                                       if (*kd++ == c) {
+                                               ch = 'j';
+                                               match++;
+                                       }
+                                       if (match == 0) {
+                                               ungetc(c,stdin);
+                                               ch = savec;
+               /* Oops! 
+                * This works if we figure it out on second character.
+                */
+                                               break;
+                                       }
+                               }
+                               savec = c;
+                               if(j != 1) c = getchar() & 0177;
+                       }
+                       c = ch;
+               }
+               if (!fast) flushi();
+               lastc = c;
+               switch (c){
+               case CTRL('z'):
+                       suspend();
+                       continue;
+               case EOT:
+               case 'x':
+               case 0177:      /* del or end of file */
+                       ll();
+                       length(moves);
+                       logit("quit");
+                       done();
+               case CTRL('l'):
+                       setup();
+                       winnings(cashvalue);
+                       continue;
+               case 'p':
+               case 'd':
+                       snap();
+                       continue;
+               case 'w':
+                       spacewarp(0);
+                       continue;
+               case 'A':
+                       repeat = you.col;
+                       c = 'h';
+                       break;
+               case 'H':
+               case 'S':
+                       repeat = you.col - money.col;
+                       c = 'h';
+                       break;
+               case 'T':
+                       repeat = you.line;
+                       c = 'k';
+                       break;
+               case 'K':
+               case 'E':
+                       repeat = you.line - money.line;
+                       c = 'k';
+                       break;
+               case 'P':
+                       repeat = ccnt - 1 - you.col;
+                       c = 'l';
+                       break;
+               case 'L':
+               case 'F':
+                       repeat = money.col - you.col;
+                       c = 'l';
+                       break;
+               case 'B':
+                       repeat = lcnt - 1 - you.line;
+                       c = 'j';
+                       break;
+               case 'J':
+               case 'C':
+                       repeat = money.line - you.line;
+                       c = 'j';
+                       break;
+               }
+               for(k=1;k<=repeat;k++){
+                       moves++;
+                       switch(c) {
+                       case 's':
+                       case 'h':
+                       case '\b':
+                               if (you.col >0) {
+                                       if((fast)||(k == 1))
+                                               pchar(&you,' ');
+                                       you.col--;
+                                       if((fast) || (k == repeat) ||
+                                          (you.col == 0))
+                                               pchar(&you,ME);
+                               }
+                               break;
+                       case 'f':
+                       case 'l':
+                       case ' ':
+                               if (you.col < ccnt-1) {
+                                       if((fast)||(k == 1))
+                                               pchar(&you,' ');
+                                       you.col++;
+                                       if((fast) || (k == repeat) ||
+                                          (you.col == ccnt-1))
+                                               pchar(&you,ME);
+                               }
+                               break;
+                       case CTRL('p'):
+                       case 'e':
+                       case 'k':
+                       case 'i':
+                               if (you.line > 0) {
+                                       if((fast)||(k == 1))
+                                               pchar(&you,' ');
+                                       you.line--;
+                                       if((fast) || (k == repeat) ||
+                                         (you.line == 0))
+                                               pchar(&you,ME);
+                               }
+                               break;
+                       case CTRL('n'):
+                       case 'c':
+                       case 'j':
+                       case LF:
+                       case 'm':
+                               if (you.line+1 < lcnt) {
+                                       if((fast)||(k == 1))
+                                               pchar(&you,' ');
+                                       you.line++;
+                                       if((fast) || (k == repeat) ||
+                                         (you.line == lcnt-1))
+                                               pchar(&you,ME);
+                               }
+                               break;
+                       }
+
+                       if (same(&you,&money))
+                       {
+                               char xp[20]; 
+                               struct point z;
+                               loot += 25;
+                               if(k < repeat)
+                                       pchar(&you,' ');
+                               do {
+                                       snrand(&money);
+                               } while (money.col == finish.col && money.line == finish.line ||
+                                        money.col < 5 && money.line == 0 ||
+                                        money.col == you.col && money.line == you.line);
+                               pchar(&money,TREASURE);
+                               winnings(cashvalue);
+                               continue;
+                       }
+                       if (same(&you,&finish))
+                       {
+                               win(&finish);
+                               ll();
+                               cook();
+                               pr("You have won with $%d.\n",cashvalue);
+                               fflush(stdout);
+                               logit("won");
+                               post(cashvalue,1);
+                               length(moves);
+                               done();
+                       }
+                       if (pushsnake())break;
+               }
+               fflush(stdout);
+       }
+}
+
+setup(){       /*
+                * setup the board
+                */
+       int i;
+
+       clear();
+       pchar(&you,ME);
+       pchar(&finish,GOAL);
+       pchar(&money,TREASURE);
+       for(i=1; i<6; i++) {
+               pchar(&snake[i],SNAKETAIL);
+       }
+       pchar(&snake[0], SNAKEHEAD);
+       drawbox();
+       fflush(stdout);
+}
+
+drawbox()
+{
+       register int i;
+       struct point p;
+
+       p.line = -1;
+       for (i= 0; i<ccnt; i++) {
+               p.col = i;
+               pchar(&p, '-');
+       }
+       p.col = ccnt;
+       for (i= -1; i<=lcnt; i++) {
+               p.line = i;
+               pchar(&p, '|');
+       }
+       p.col = -1;
+       for (i= -1; i<=lcnt; i++) {
+               p.line = i;
+               pchar(&p, '|');
+       }
+       p.line = lcnt;
+       for (i= 0; i<ccnt; i++) {
+               p.col = i;
+               pchar(&p, '-');
+       }
+}
+
+snrand(sp)
+struct point *sp;
+{
+       struct point p;
+       register int i;
+
+       for (;;) {
+               p.col = random() % ccnt;
+               p.line = random() % lcnt;
+
+               /* make sure it's not on top of something else */
+               if (p.line == 0 && p.col < 5)
+                       continue;
+               if (same(&p, &you))
+                       continue;
+               if (same(&p, &money))
+                       continue;
+               if (same(&p, &finish))
+                       continue;
+               for (i = 0; i < 5; i++)
+                       if (same(&p, &snake[i]))
+                               break;
+               if (i < 5)
+                       continue;
+               break;
+       }
+       *sp = p;
+}
+
+post(iscore, flag)
+int    iscore, flag;
+{
+       short   score = iscore;
+       int     rawscores;
+       short   uid;
+       short   oldbest=0;
+       short   allbwho=0, allbscore=0;
+       struct  passwd *p;
+
+       /*
+        * Neg uid, 0, and 1 cannot have scores recorded.
+        */
+       if ((uid = getuid()) <= 1) {
+               pr("No saved scores for uid %d.\n", uid);
+               return(1);
+       }
+       if ((rawscores = open(_PATH_RAWSCORES, O_RDWR|O_CREAT, 0644)) < 0) {
+               pr("No score file %s: %s.\n", _PATH_RAWSCORES,
+                   strerror(errno));
+               return(1);
+       }
+       /* Figure out what happened in the past */
+       read(rawscores, &allbscore, sizeof(short));
+       read(rawscores, &allbwho, sizeof(short));
+       lseek(rawscores, ((long)uid)*sizeof(short), 0);
+       read(rawscores, &oldbest, sizeof(short));
+       if (!flag)
+               return (score > oldbest ? 1 : 0);
+
+       /* Update this jokers best */
+       if (score > oldbest) {
+               lseek(rawscores, ((long)uid)*sizeof(short), 0);
+               write(rawscores, &score, sizeof(short));
+               pr("You bettered your previous best of $%d\n", oldbest);
+       } else
+               pr("Your best to date is $%d\n", oldbest);
+
+       /* See if we have a new champ */
+       p = getpwuid(allbwho);
+       if (p == NULL || score > allbscore) {
+               lseek(rawscores, (long)0, 0);
+               write(rawscores, &score, sizeof(short));
+               write(rawscores, &uid, sizeof(short));
+               if (allbwho)
+                       pr("You beat %s's old record of $%d!\n",
+                           p->pw_name, allbscore);
+               else
+                       pr("You set a new record!\n");
+       } else
+               pr("The highest is %s with $%d\n", p->pw_name, allbscore);
+       close(rawscores);
+       return (1);
+}
+
+/*
+ * Flush typeahead to keep from buffering a bunch of chars and then
+ * overshooting.  This loses horribly at 9600 baud, but works nicely
+ * if the terminal gets behind.
+ */
+flushi()
+{
+       stty(0, &new);
+}
+int mx [8] = { 
+       0, 1, 1, 1, 0,-1,-1,-1};
+int my [8] = {
+       -1,-1, 0, 1, 1, 1, 0,-1};
+float absv[8]= { 
+       1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4
+};
+int oldw=0;
+chase (np, sp)
+struct point *sp, *np;
+{
+       /* this algorithm has bugs; otherwise the
+          snake would get too good */
+       struct point d;
+       int w, i, wt[8];
+       double sqrt(), v1, v2, vp, max;
+       point(&d,you.col-sp->col,you.line-sp->line);
+       v1 = sqrt( (double) (d.col*d.col + d.line*d.line) );
+       w=0; 
+       max=0;
+       for(i=0; i<8; i++)
+       {
+               vp = d.col*mx[i] + d.line*my[i];
+               v2 = absv[i];
+               if (v1>0)
+                       vp = ((double)vp)/(v1*v2);
+               else vp=1.0;
+               if (vp>max)
+               {
+                       max=vp;
+                       w=i;
+               }
+       }
+       for(i=0; i<8; i++)
+       {
+               point(&d,sp->col+mx[i],sp->line+my[i]);
+               wt[i]=0;
+               if (d.col<0 || d.col>=ccnt || d.line<0 || d.line>=lcnt)
+                       continue;
+               /*
+                * Change to allow snake to eat you if you're on the money,
+                * otherwise, you can just crouch there until the snake goes
+                * away.  Not positive it's right.
+                *
+                * if (d.line == 0 && d.col < 5) continue;
+                */
+               if (same(&d,&money)) continue;
+               if (same(&d,&finish)) continue;
+               wt[i]= i==w ? loot/10 : 1;
+               if (i==oldw) wt [i] += loot/20;
+       }
+       for(w=i=0; i<8; i++)
+               w+= wt[i];
+       vp = (( rand() >> 6 ) & 01777) %w;
+       for(i=0; i<8; i++)
+               if (vp <wt[i])
+                       break;
+               else
+                       vp -= wt[i];
+       if (i==8) {
+               pr("failure\n"); 
+               i=0;
+               while (wt[i]==0) i++;
+       }
+       oldw=w=i;
+       point(np,sp->col+mx[w],sp->line+my[w]);
+}
+
+spacewarp(w)
+int w;{
+       struct point p;
+       int j;
+       char *str;
+
+       snrand(&you);
+       point(&p,COLUMNS/2 - 8,LINES/2 - 1);
+       if (p.col < 0)
+               p.col = 0;
+       if (p.line < 0)
+               p.line = 0;
+       if (w) {
+               str = "BONUS!!!";
+               loot = loot - penalty;
+               penalty = 0;
+       } else {
+               str = "SPACE WARP!!!";
+               penalty += loot/PENALTY;
+       }
+       for(j=0;j<3;j++){
+               clear();
+               delay(5);
+               apr(&p,str);
+               delay(10);
+       }
+       setup();
+       winnings(cashvalue);
+}
+snap()
+{
+       struct point p;
+       int i;
+
+       if(you.line < 3){
+               pchar(point(&p,you.col,0),'-');
+       }
+       if(you.line > lcnt-4){
+               pchar(point(&p,you.col,lcnt-1),'_');
+       }
+       if(you.col < 10){
+               pchar(point(&p,0,you.line),'(');
+       }
+       if(you.col > ccnt-10){
+               pchar(point(&p,ccnt-1,you.line),')');
+       }
+       if (! stretch(&money)) if (! stretch(&finish)) delay(10);
+       if(you.line < 3){
+               point(&p,you.col,0);
+               chk(&p);
+       }
+       if(you.line > lcnt-4){
+               point(&p,you.col,lcnt-1);
+               chk(&p);
+       }
+       if(you.col < 10){
+               point(&p,0,you.line);
+               chk(&p);
+       }
+       if(you.col > ccnt-10){
+               point(&p,ccnt-1,you.line);
+               chk(&p);
+       }
+       fflush(stdout);
+}
+stretch(ps)
+struct point *ps;{
+       struct point p;
+
+       point(&p,you.col,you.line);
+       if(abs(ps->col-you.col) < 6){
+               if(you.line < ps->line){
+                       for (p.line = you.line+1;p.line <= ps->line;p.line++)
+                               pchar(&p,'v');
+                       delay(10);
+                       for (;p.line > you.line;p.line--)
+                               chk(&p);
+               } else {
+                       for (p.line = you.line-1;p.line >= ps->line;p.line--)
+                               pchar(&p,'^');
+                       delay(10);
+                       for (;p.line < you.line;p.line++)
+                               chk(&p);
+               }
+               return(1);
+       } else if(abs(ps->line-you.line) < 3){
+               p.line = you.line;
+               if(you.col < ps->col){
+                       for (p.col = you.col+1;p.col <= ps->col;p.col++)
+                               pchar(&p,'>');
+                       delay(10);
+                       for (;p.col > you.col;p.col--)
+                               chk(&p);
+               } else {
+                       for (p.col = you.col-1;p.col >= ps->col;p.col--)
+                               pchar(&p,'<');
+                       delay(10);
+                       for (;p.col < you.col;p.col++)
+                               chk(&p);
+               }
+               return(1);
+       }
+       return(0);
+}
+
+surround(ps)
+struct point *ps;{
+       struct point x;
+       int i,j;
+
+       if(ps->col == 0)ps->col++;
+       if(ps->line == 0)ps->line++;
+       if(ps->line == LINES -1)ps->line--;
+       if(ps->col == COLUMNS -1)ps->col--;
+       apr(point(&x,ps->col-1,ps->line-1),"/*\\\r* *\r\\*/");
+       for (j=0;j<20;j++){
+               pchar(ps,'@');
+               delay(1);
+               pchar(ps,' ');
+               delay(1);
+       }
+       if (post(cashvalue,0)) {
+               apr(point(&x,ps->col-1,ps->line-1),"   \ro.o\r\\_/");
+               delay(6);
+               apr(point(&x,ps->col-1,ps->line-1),"   \ro.-\r\\_/");
+               delay(6);
+       }
+       apr(point(&x,ps->col-1,ps->line-1),"   \ro.o\r\\_/");
+}
+win(ps)
+struct point *ps;
+{
+       struct point x;
+       int j,k;
+       int boxsize;    /* actually diameter of box, not radius */
+
+       boxsize = fast ? 10 : 4;
+       point(&x,ps->col,ps->line);
+       for(j=1;j<boxsize;j++){
+               for(k=0;k<j;k++){
+                       pchar(&x,'#');
+                       x.line--;
+               }
+               for(k=0;k<j;k++){
+                       pchar(&x,'#');
+                       x.col++;
+               }
+               j++;
+               for(k=0;k<j;k++){
+                       pchar(&x,'#');
+                       x.line++;
+               }
+               for(k=0;k<j;k++){
+                       pchar(&x,'#');
+                       x.col--;
+               }
+       }
+       fflush(stdout);
+}
+
+pushsnake()
+{
+       int i, bonus;
+       int issame = 0;
+
+       /*
+        * My manual says times doesn't return a value.  Furthermore, the
+        * snake should get his turn every time no matter if the user is
+        * on a fast terminal with typematic keys or not.
+        * So I have taken the call to times out.
+        */
+       for(i=4; i>=0; i--)
+               if (same(&snake[i], &snake[5]))
+                       issame++;
+       if (!issame)
+               pchar(&snake[5],' ');
+       for(i=4; i>=0; i--)
+               snake[i+1]= snake[i];
+       chase(&snake[0], &snake[1]);
+       pchar(&snake[1],SNAKETAIL);
+       pchar(&snake[0],SNAKEHEAD);
+       for(i=0; i<6; i++)
+       {
+               if (same(&snake[i],&you))
+               {
+                       surround(&you);
+                       i = (cashvalue) % 10;
+                       bonus = ((rand()>>8) & 0377)% 10;
+                       ll();
+                       pr("%d\n", bonus);
+                       delay(30);
+                       if (bonus == i) {
+                               spacewarp(1);
+                               logit("bonus");
+                               flushi();
+                               return(1);
+                       }
+                       if ( loot >= penalty ){
+                               pr("You and your $%d have been eaten\n",
+                                   cashvalue);
+                       } else {
+                               pr("The snake ate you.  You owe $%d.\n",
+                                   -cashvalue);
+                       }
+                       logit("eaten");
+                       length(moves);
+                       done();
+               }
+       }
+       return(0);
+}
+       
+chk(sp)
+struct point *sp;
+{
+       int j;
+
+       if (same(sp,&money)) {
+               pchar(sp,TREASURE);
+               return(2);
+       }
+       if (same(sp,&finish)) {
+               pchar(sp,GOAL);
+               return(3);
+       }
+       if (same(sp,&snake[0])) {
+               pchar(sp,SNAKEHEAD);
+               return(4);
+       }
+       for(j=1;j<6;j++){
+               if(same(sp,&snake[j])){
+                       pchar(sp,SNAKETAIL);
+                       return(4);
+               }
+       }
+       if ((sp->col < 4) && (sp->line == 0)){
+               winnings(cashvalue);
+               if((you.line == 0) && (you.col < 4)) pchar(&you,ME);
+               return(5);
+       }
+       if (same(sp,&you)) {
+               pchar(sp,ME);
+               return(1);
+       }
+       pchar(sp,' ');
+       return(0);
+}
+winnings(won)
+int won;
+{
+       struct point p;
+
+       p.line = p.col = 1;
+       if(won>0){
+               move(&p);
+               pr("$%d",won);
+       }
+}
+
+void
+stop(){
+       signal(SIGINT,SIG_IGN);
+       ll();
+       length(moves);
+       done();
+}
+
+suspend()
+{
+       char *sh;
+
+       ll();
+       cook();
+       kill(getpid(), SIGTSTP);
+       raw();
+       setup();
+       winnings(cashvalue);
+}
+
+length(num)
+int num;
+{
+       pr("You made %d moves.\n",num);
+}
+
+logit(msg)
+char *msg;
+{
+       FILE *logfile;
+       long t;
+
+       if ((logfile=fopen(_PATH_LOGFILE, "a")) != NULL) {
+               time(&t);
+               fprintf(logfile, "%s $%d %dx%d %s %s",
+                   getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t));
+               fclose(logfile);
+       }
+}
diff --git a/usr/othersrc/games/snake/snake/snake.h b/usr/othersrc/games/snake/snake/snake.h
new file mode 100644 (file)
index 0000000..f8e7fd8
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1980 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     5.5 (Berkeley) 6/1/90
+ */
+
+# include <stdio.h>
+# include <assert.h>
+# include <sys/types.h>
+# include <sgtty.h>
+# include <signal.h>
+# include <math.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   xBC, PC;
+int    AM, BW;
+char   tbuf[1024], tcapbuf[128];
+char   *tgetstr(), *tgoto();
+int    Klength;        /* length of KX strings */
+int    chunk;          /* amount of money given at a time */
+#ifdef debug
+#define        cashvalue       (loot-penalty)/25
+#else
+#define cashvalue      chunk*(loot-penalty)/25
+#endif
+
+struct point {
+       int col, line;
+};
+struct point cursor;
+struct sgttyb orig, new;
+#ifdef TIOCLGET
+struct ltchars olttyc, nlttyc;
+#endif
+struct point *point();
+
+#define        same(s1, s2)    ((s1)->line == (s2)->line && (s1)->col == (s2)->col)
+
diff --git a/usr/othersrc/games/snake/snscore/snscore.c b/usr/othersrc/games/snake/snscore/snscore.c
new file mode 100644 (file)
index 0000000..2dc0917
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1980 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.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)snscore.c  5.7 (Berkeley) 2/28/91";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "pathnames.h"
+
+char *recfile = _PATH_RAWSCORES;
+#define MAXPLAYERS 256
+
+struct player  {
+       short   uids;
+       short   scores;
+       char    *name;
+} players[MAXPLAYERS], temp;
+
+main()
+{
+       char    buf[80], cp;
+       short   uid, score;
+       FILE    *fd;
+       int     noplayers;
+       int     i, j, notsorted;
+       short   whoallbest, allbest;
+       char    *q;
+       struct  passwd  *p;
+
+       fd = fopen(recfile, "r");
+       if (fd == NULL) {
+               perror(recfile);
+               exit(1);
+       }
+       printf("Snake players scores to date\n");
+       fread(&whoallbest, sizeof(short), 1, fd);
+       fread(&allbest, sizeof(short), 1, fd);
+       for (uid=2;;uid++) {
+               if(fread(&score, sizeof(short), 1, fd) == 0)
+                       break;
+               if (score > 0) {
+                       if (noplayers > MAXPLAYERS) {
+                               printf("too many players\n");
+                               exit(2);
+                       }
+                       players[noplayers].uids = uid;
+                       players[noplayers].scores = score;
+                       p = getpwuid(uid);
+                       if (p == NULL)
+                               continue;
+                       q = p -> pw_name;
+                       players[noplayers].name = malloc(strlen(q)+1);
+                       strcpy(players[noplayers].name, q);
+                       noplayers++;
+               }
+       }
+
+       /* bubble sort scores */
+       for (notsorted=1; notsorted; ) {
+               notsorted = 0;
+               for (i=0; i<noplayers-1; i++)
+                       if (players[i].scores < players[i+1].scores) {
+                               temp = players[i];
+                               players[i] = players[i+1];
+                               players[i+1] = temp;
+                               notsorted++;
+                       }
+       }
+
+       j = 1;
+       for (i=0; i<noplayers; i++) {
+               printf("%d:\t$%d\t%s\n", j, players[i].scores, players[i].name);
+               if (players[i].scores > players[i+1].scores)
+                       j = i+2;
+       }
+       exit(0);
+}