# @(#)Makefile 8.1 (Berkeley) 5/31/93
# $FreeBSD: src/games/snake/snake/Makefile,v 1.5.2.3 2002/08/07 16:31:42 ru Exp $
-# $DragonFly: src/games/snake/snake/Makefile,v 1.2 2003/06/17 04:25:25 dillon Exp $
+# $DragonFly: src/games/snake/snake/Makefile,v 1.3 2006/09/03 23:23:10 pavalos Exp $
PROG= snake
-SRCS= snake.c move.c
+SRCS= snake.c
MAN= snake.6
-DPADD= ${LIBM} ${LIBTERMCAP} ${LIBCOMPAT}
-LDADD= -lm -ltermcap -lcompat
+DPADD= ${LIBM} ${LIBCURSES}
+LDADD= -lm -lcurses
HIDEGAME=hidegame
MLINKS= snake.6 snscore.6
+++ /dev/null
-/*
- * 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.
- *
- * @(#)move.c 8.1 (Berkeley) 7/19/93
- * $FreeBSD: src/games/snake/snake/move.c,v 1.5.2.1 2000/08/17 06:21:44 jhb Exp $
- * $DragonFly: src/games/snake/snake/Attic/move.c,v 1.3 2004/07/27 07:37:39 asmodai Exp $
- */
-
-/*************************************************************************
- *
- * 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() returns the baudrate of the terminal.
- * delay(t) causes an approximately constant delay
- * independent of baudrate.
- * Duration is ~ t/20 seconds.
- *
- ******************************************************************************/
-
-#include <errno.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.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;
-
- 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 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;
- }
-}
-
-void
-apr(struct point *ps, const 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);
-}
-
-void
-pr(const 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);
-}
-
-#if 0
-baudrate()
-{
-
- switch (orig.sg_ospeed){
- case B300:
- return(300);
- case B1200:
- return(1200);
- case B4800:
- return(4800);
- case B9600:
- return(9600);
- default:
- return(0);
- }
-}
-#endif
-
-delay(t)
-unsigned int t;
-{
- while (usleep(t*50000U) == -1 && errno == EINTR) ;
-}
-
-done()
-{
- cook();
- exit(0);
-}
-
-cook()
-{
- delay(1);
- putpad(TE);
- putpad(KE);
- putpad(VE);
- 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;
- void stop();
-#ifdef TIOCGWINSZ
- struct winsize win;
-#endif
-
- 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;
-
-#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("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);
- if (KL)
- Klength = strlen(KL);
- else
- 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);
-
- VI = tgetstr("vi", &ap);
- VE = tgetstr("ve", &ap);
-
- xPC = tgetstr("pc", &ap);
- if (xPC)
- PC = *xPC;
-
- if (ND)
- NDlength = strlen(ND);
- else
- NDlength = 0;
-
- if (BS)
- BSlength = strlen(BS);
- else
- BSlength = 0;
-
- if ((CM == 0) &&
- (HO == 0 || DO == 0 || UP==0 || BS==0 || ND==0))
- {
- /* XXX as written in rev.1.6, we can assert(DO) */
- 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);
-}
.\"
.\" @(#)snake.6 8.1 (Berkeley) 5/31/93
.\" $FreeBSD: src/games/snake/snake/snake.6,v 1.4.2.1 2001/07/22 11:01:23 dd Exp $
-.\" $DragonFly: src/games/snake/snake/snake.6,v 1.2 2003/06/17 04:25:25 dillon Exp $
+.\" $DragonFly: src/games/snake/snake/snake.6,v 1.3 2006/09/03 23:23:10 pavalos Exp $
.\"
.TH SNAKE 6 "May 31, 1993"
.UC 4
.B -w width
] [
.B -l length
+] [
+.B -t
]
.br
.B snscore
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.
+By default the entire screen is used. The
+.B \-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.
* @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
* @(#)snake.c 8.2 (Berkeley) 1/7/94
* $FreeBSD: src/games/snake/snake/snake.c,v 1.11.2.1 2000/08/17 06:21:44 jhb Exp $
- * $DragonFly: src/games/snake/snake/snake.c,v 1.2 2003/06/17 04:25:25 dillon Exp $
+ * $DragonFly: src/games/snake/snake/snake.c,v 1.3 2006/09/03 23:23:10 pavalos Exp $
*/
/*
#include <sys/param.h>
-#include <errno.h>
+#include <curses.h>
#include <fcntl.h>
#include <pwd.h>
#include <time.h>
#include <stdlib.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'
#define TREASURE '$'
#define GOAL '#'
-#define BSIZE 80
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define pchar(point, c) mvaddch((point)->line + 1, (point)->col + 1, (c))
+#define delay(t) usleep(t * 50000);
struct point you;
struct point money;
struct point 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;
+int fast = 1;
int rawscores;
FILE *logfile;
+int lcnt, ccnt; /* user's idea of screen size */
+int chunk; /* amount of money given at a time */
+
+void chase(struct point *, struct point *);
+int chk(const struct point *);
+void drawbox(void);
+void flushi(void);
+void home(void);
+void length(int);
+void logit(const char *);
+int main(int, char **);
+void mainloop(void) __attribute__((__noreturn__));
+struct point *point(struct point *, int, int);
+int post(int, int);
+int pushsnake(void);
+void right(const struct point *);
+void setup(void);
+void snap(void);
+void snrand(struct point *);
+void spacewarp(int);
+void stop(int) __attribute__((__noreturn__));
+int stretch(const struct point *);
+void surround(struct point *);
+void suspend(void);
+void win(const struct point *);
+void winnings(int);
+
main(argc,argv)
int argc;
char **argv;
{
- extern char *optarg;
- extern int optind;
int ch, i;
- void stop();
+ time_t tv;
+ /* Open score files then revoke setgid privileges */
rawscores = open(_PATH_RAWSCORES, O_RDWR|O_CREAT, 0664);
+ if (rawscores < 0) {
+ warn("open %s", _PATH_RAWSCORES);
+ sleep(2);
+ } else if (rawscores < 3)
+ exit(1);
logfile = fopen(_PATH_LOGFILE, "a");
-
- /* revoke privs */
+ if (logfile == NULL) {
+ warn("fopen %s", _PATH_LOGFILE);
+ sleep(2);
+ }
setgid(getgid());
- srandomdev();
+ (void) time(&tv);
- while ((ch = getopt(argc, argv, "l:w:")) != -1)
- switch((char)ch) {
-#ifdef notdef
+ while ((ch = getopt(argc, argv, "l:w:t")) != -1)
+ switch ((char) ch) {
+#ifdef DEBUG
case 'd':
tv = atol(optarg);
break;
case 'l': /* length */
lcnt = atoi(optarg);
break;
+ case 't':
+ fast = 0;
+ break;
case '?':
default:
- fputs("usage: snake [-d seed] [-w width] [-l length]\n", stderr);
+#ifdef DEBUG
+ fputs("usage: snake [-d seed] [-w width] [-l length] [-t]\n", stderr);
+#else
+ fputs("usage: snake [-w width] [-l length] [-t]\n", stderr);
+#endif
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 = (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 */
- putpad(VI); /* Hide cursor */
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();
+ /* NOTREACHED */
+ 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;
-
- 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;
}
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 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);
switch(c) {
case 's':
case 'h':
+#ifdef KEY_LEFT
+ case KEY_LEFT:
+#endif
case '\b':
if (you.col >0) {
if((fast)||(k == 1))
break;
case 'f':
case 'l':
+#ifdef KEY_RIGHT
+ case KEY_RIGHT:
+#endif
case ' ':
if (you.col < ccnt-1) {
if((fast)||(k == 1))
case CTRL('p'):
case 'e':
case 'k':
+#ifdef KEY_UP
+ case KEY_UP:
+#endif
case 'i':
if (you.line > 0) {
if((fast)||(k == 1))
case CTRL('n'):
case 'c':
case 'j':
+#ifdef KEY_DOWN
+ case KEY_DOWN:
+#endif
case LF:
case 'm':
if (you.line+1 < lcnt) {
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);
}
}
*/
int i;
- clear();
+ erase();
pchar(&you,ME);
pchar(&finish,GOAL);
pchar(&money,TREASURE);
}
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, '-');
+ for (i = 1; i <= ccnt; i++) {
+ mvaddch(0, i, '-');
+ mvaddch(lcnt + 1, i, '-');
}
- 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, '-');
+ for (i = 0; i <= lcnt + 1; i++) {
+ mvaddch(i, 0, '|');
+ mvaddch(i, ccnt + 1, '|');
}
}
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;
}
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 == -1) {
- pr("No score file %s: %s.\n", _PATH_RAWSCORES,
- strerror(errno));
+ if (rawscores < 0) {
+ /* Error reported earlier */
return(1);
}
/* Figure out what happened in the past */
read(rawscores, &allbwho, sizeof(short));
lseek(rawscores, ((off_t)uid)*sizeof(short), 0);
read(rawscores, &oldbest, sizeof(short));
- if (!flag)
+ if (!flag) {
+ lseek(rawscores, 0, SEEK_SET);
return (score > oldbest ? 1 : 0);
+ }
/* Update this jokers best */
if (score > oldbest) {
lseek(rawscores, ((off_t)uid)*sizeof(short), 0);
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);
- if (p == NULL || score > allbscore) {
- lseek(rawscores, (off_t)0, 0);
+ if (score > allbscore) {
+ lseek(rawscores, 0, SEEK_SET);
write(rawscores, &score, sizeof(short));
write(rawscores, &uid, sizeof(short));
- if (allbwho)
- pr("You beat %s's old record of $%d!\n",
+ if (allbwho) {
+ if (p)
+ printf("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);
+ printf("You beat (%d)'s old record of $%d!\n",
+ (int)allbwho, allbscore);
+ }
+ else
+ printf("You set a new record!\n");
+ } else if (p)
+ printf("The highest is %s with $%d\n", p->pw_name, allbscore);
+ else
+ printf("The highest is (%d) with $%d\n", (int)allbwho,
+ allbscore);
+ lseek(rawscores, 0, SEEK_SET);
return (1);
}
*/
flushi()
{
- stty(0, &new);
+ tcflush(0, TCIFLUSH);
}
int mx [8] = {
0, 1, 1, 1, 0,-1,-1,-1};
}
for(w=i=0; i<8; i++)
w+= wt[i];
- vp = random() % 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++;
}
int w;{
struct point p;
int j;
- char *str;
+ 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)
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();
snap()
{
+#if 0 /* This code doesn't really make sense. */
struct point p;
- if(you.line < 3){
- pchar(point(&p,you.col,0),'-');
+ if (you.line < 3) {
+ mvaddch(1, you.col + 1, '-');
}
- if(you.line > lcnt-4){
- pchar(point(&p,you.col,lcnt-1),'_');
+ if (you.line > lcnt - 4) {
+ mvaddch(lcnt, you.col + 1, '_');
}
- if(you.col < 10){
- pchar(point(&p,0,you.line),'(');
+ if (you.col < 10) {
+ mvaddch(you.line + 1, 1, '(');
}
- if(you.col > ccnt-10){
- pchar(point(&p,ccnt-1,you.line),')');
+ if (you.col > ccnt - 10) {
+ mvaddch(you.line + 1, ccnt, ')');
}
- if (! stretch(&money)) if (! stretch(&finish)) delay(10);
- if(you.line < 3){
- point(&p,you.col,0);
+#endif
+ if (!stretch(&money))
+ if (!stretch(&finish)) {
+ pchar(&you, '?');
+ refresh();
+ delay(10);
+ pchar(&you, ME);
+ }
+#if 0
+ if (you.line < 3) {
+ point(&p, you.col, 0);
chk(&p);
}
if(you.line > lcnt-4){
point(&p,ccnt-1,you.line);
chk(&p);
}
- fflush(stdout);
+#endif
+ refresh();
}
stretch(ps)
-struct point *ps;{
+const struct point *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++)
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--)
pchar(&p,'^');
+ refresh();
delay(10);
for (;p.line < you.line;p.line++)
chk(&p);
}
return(1);
- } else if(abs(ps->line-you.line) < 3){
+ } else
+ 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++)
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--)
pchar(&p,'<');
+ refresh();
delay(10);
for (;p.col < you.col;p.col++)
chk(&p);
surround(ps)
struct point *ps;{
- struct point x;
int j;
if(ps->col == 0)ps->col++;
if(ps->line == 0)ps->line++;
if(ps->line == LINES -1)ps->line--;
- if(ps->col == COLUMNS -1)ps->col--;
- apr(point(&x,ps->col-1,ps->line-1),"/*\\\r* *\r\\*/");
+ if(ps->col == COLS -1)ps->col--;
+ 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, "\\_/");
+ refresh();
+ delay(6);
}
win(ps)
-struct point *ps;
+const struct point *ps;
{
struct point x;
int j,k;
pchar(&x,'#');
x.col--;
}
+ refresh();
+ delay(1);
}
- fflush(stdout);
}
pushsnake()
{
int i, bonus;
int issame = 0;
+ struct point tmp;
/*
* My manual says times doesn't return a value. Furthermore, the
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[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 = random() % 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);
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);
}
chk(sp)
-struct point *sp;
+const struct point *sp;
{
int j;
winnings(won)
int won;
{
- struct point p;
-
- p.line = p.col = 1;
- if(won>0){
- move(&p);
- pr("$%d",won);
+ if (won > 0) {
+ mvprintw(1, 1, "$%d", won);
}
}
void
-stop(){
+stop(dummy){
signal(SIGINT,SIG_IGN);
- ll();
+ endwin();
length(moves);
- done();
+ exit(0);
}
suspend()
{
- ll();
- cook();
+ endwin();
kill(getpid(), SIGTSTP);
- raw();
- setup();
+ refresh();
winnings(cashvalue);
}
length(num)
int num;
{
- pr("You made %d moves.\n",num);
+ printf("You made %d moves.\n", num);
}
logit(msg)
-char *msg;
+const char *msg;
{
time_t t;
time(&t);
fprintf(logfile, "%s $%d %dx%d %s %s",
getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t));
- fclose(logfile);
+ fflush(logfile);
}
}
+++ /dev/null
-/*
- * 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
- *
- * $FreeBSD: src/games/snake/snake/snake.h,v 1.1.1.1.14.1 2000/08/17 06:21:44 jhb Exp $
- * $DragonFly: src/games/snake/snake/Attic/snake.h,v 1.2 2003/06/17 04:25:25 dillon Exp $
- */
-
-# 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,
- *VI, *VE;
-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();
-#if __STDC__
-void apr(struct point *, const char *, ...);
-void pr(const char *, ...);
-#else
-void apr();
-void pr();
-#endif
-
-#define same(s1, s2) ((s1)->line == (s2)->line && (s1)->col == (s2)->col)
* @(#) Copyright (c) 1980, 1993 The Regents of the University of California. All rights reserved.
* @(#)snscore.c 8.1 (Berkeley) 7/19/93
* $FreeBSD: src/games/snake/snscore/snscore.c,v 1.5 1999/11/30 03:49:42 billf Exp $
- * $DragonFly: src/games/snake/snscore/snscore.c,v 1.2 2003/06/17 04:25:25 dillon Exp $
+ * $DragonFly: src/games/snake/snscore/snscore.c,v 1.3 2006/09/03 23:23:10 pavalos Exp $
*/
#include <sys/types.h>
+#include <err.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "pathnames.h"
-char *recfile = _PATH_RAWSCORES;
+const char *recfile = _PATH_RAWSCORES;
#define MAXPLAYERS 256
struct player {
int noplayers;
int i, j, notsorted;
short whoallbest, allbest;
- char *q;
+ const char *q;
struct passwd *p;
- fd = fopen(recfile, "r");
-
- if (fd == NULL) {
- perror(recfile);
- exit(1);
- }
+ /* Revoke setgid privileges */
+ setgid(getgid());
+ fd = fopen(recfile, "r");
+ if (fd == NULL)
+ err(1, "opening `%s'", recfile);
printf("Snake players scores to date\n");
- fread(&whoallbest, sizeof(short), 1, fd);
+ if (fread(&whoallbest, sizeof(short), 1, fd) == 0) {
+ printf("No scores recorded yet!\n");
+ exit(0);
+ }
fread(&allbest, sizeof(short), 1, fd);
noplayers = 0;
for (uid = 2; ;uid++) {
if(fread(&score, sizeof(short), 1, fd) == 0)
break;
if (score > 0) {
- if (noplayers > MAXPLAYERS) {
+ if (noplayers >= MAXPLAYERS) {
printf("too many players\n");
exit(2);
}
if (p == NULL)
continue;
q = p -> pw_name;
- players[noplayers].name = malloc(strlen(q) + 1);
- strcpy(players[noplayers].name, q);
+ players[noplayers].name = strdup(q);
+ if (players[noplayers].name == NULL)
+ err(1, NULL);
noplayers++;
}
}