Import NetBSD games/snake command.
Change-Id: Ie46c0acc09e5e8079f80301ae3a40172fcfb51dd
This commit is contained in:
parent
3a40bab785
commit
831337191b
9 changed files with 1326 additions and 1 deletions
|
@ -602,6 +602,8 @@
|
||||||
./usr/games/ppt minix-sys
|
./usr/games/ppt minix-sys
|
||||||
./usr/games/primes minix-sys
|
./usr/games/primes minix-sys
|
||||||
./usr/games/random minix-sys
|
./usr/games/random minix-sys
|
||||||
|
./usr/games/snake minix-sys
|
||||||
|
./usr/games/snscore minix-sys
|
||||||
./usr/games/strfile minix-sys
|
./usr/games/strfile minix-sys
|
||||||
./usr/games/tetris minix-sys
|
./usr/games/tetris minix-sys
|
||||||
./usr/games/unstr minix-sys
|
./usr/games/unstr minix-sys
|
||||||
|
@ -5033,6 +5035,7 @@
|
||||||
./usr/man/man6/ppt.6 minix-sys
|
./usr/man/man6/ppt.6 minix-sys
|
||||||
./usr/man/man6/primes.6 minix-sys
|
./usr/man/man6/primes.6 minix-sys
|
||||||
./usr/man/man6/random.6 minix-sys
|
./usr/man/man6/random.6 minix-sys
|
||||||
|
./usr/man/man6/snake.6 minix-sys
|
||||||
./usr/man/man6/tetris.6 minix-sys
|
./usr/man/man6/tetris.6 minix-sys
|
||||||
./usr/man/man6/wargames.6 minix-sys
|
./usr/man/man6/wargames.6 minix-sys
|
||||||
./usr/man/man7 minix-sys
|
./usr/man/man7 minix-sys
|
||||||
|
|
|
@ -13,7 +13,7 @@ SUBDIR= adventure arithmetic \
|
||||||
factor fortune \
|
factor fortune \
|
||||||
monop morse number \
|
monop morse number \
|
||||||
pig ppt primes \
|
pig ppt primes \
|
||||||
random tetris \
|
random snake tetris \
|
||||||
wargames
|
wargames
|
||||||
|
|
||||||
.if !defined(__MINIX)
|
.if !defined(__MINIX)
|
||||||
|
|
6
games/snake/Makefile
Normal file
6
games/snake/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# $NetBSD: Makefile,v 1.3 1995/04/22 08:34:18 cgd Exp $
|
||||||
|
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||||
|
|
||||||
|
SUBDIR= snake snscore
|
||||||
|
|
||||||
|
.include <bsd.subdir.mk>
|
13
games/snake/snake/Makefile
Normal file
13
games/snake/snake/Makefile
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# $NetBSD: Makefile,v 1.10 2010/02/06 23:45:26 he Exp $
|
||||||
|
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||||
|
|
||||||
|
PROG= snake
|
||||||
|
SRCS= snake.c
|
||||||
|
MAN= snake.6
|
||||||
|
DPADD= ${LIBM} ${LIBCURSES} ${LIBTERMINFO}
|
||||||
|
LDADD= -lm -lcurses -lterminfo
|
||||||
|
HIDEGAME=hidegame
|
||||||
|
SETGIDGAME=yes
|
||||||
|
|
||||||
|
.include "../../Makefile.inc"
|
||||||
|
.include <bsd.prog.mk>
|
35
games/snake/snake/pathnames.h
Normal file
35
games/snake/snake/pathnames.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* $NetBSD: pathnames.h,v 1.4 2003/08/07 09:37:45 agc Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1989, 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. 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 8.1 (Berkeley) 5/31/93
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _PATH_RAWSCORES "/var/games/snakerawscores"
|
||||||
|
#define _PATH_LOGFILE "/var/games/snake.log"
|
126
games/snake/snake/snake.6
Normal file
126
games/snake/snake/snake.6
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
.\" $NetBSD: snake.6,v 1.12 2009/03/11 13:05:59 joerg Exp $
|
||||||
|
.\"
|
||||||
|
.\" Copyright (c) 1980, 1993
|
||||||
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\" 3. 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 8.1 (Berkeley) 5/31/93
|
||||||
|
.\"
|
||||||
|
.Dd May 31, 1993
|
||||||
|
.Dt SNAKE 6
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm snake ,
|
||||||
|
.Nm snscore
|
||||||
|
.Nd display chase game
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.Nm
|
||||||
|
.Op Fl w Ar width
|
||||||
|
.Op Fl l Ar length
|
||||||
|
.Op Fl t
|
||||||
|
.Nm snscore
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
.Nm
|
||||||
|
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
|
||||||
|
.Fl l
|
||||||
|
and
|
||||||
|
.Fl w
|
||||||
|
options allow you to specify the length and width of the field.
|
||||||
|
By default the entire screen is used.
|
||||||
|
The
|
||||||
|
.Fl t
|
||||||
|
option makes the game assume you are on a slow terminal.
|
||||||
|
.Pp
|
||||||
|
You are represented on the screen by an I.
|
||||||
|
The snake is 6 squares long and is represented by s's with an S at its head.
|
||||||
|
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
|
||||||
|
.Xr vi 1 ,
|
||||||
|
the
|
||||||
|
.Ic h ,
|
||||||
|
.Ic j ,
|
||||||
|
.Ic k ,
|
||||||
|
and
|
||||||
|
.Ic l
|
||||||
|
keys work, as do the arrow keys.
|
||||||
|
Other possibilities include:
|
||||||
|
.Bl -tag -width indent
|
||||||
|
.It Ic sefc
|
||||||
|
These keys are like hjkl but form a directed pad around the d key.
|
||||||
|
.It Ic HJKL
|
||||||
|
These keys move you all the way in the indicated direction to the
|
||||||
|
same row or column as the money.
|
||||||
|
This does
|
||||||
|
.Em 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.
|
||||||
|
.It Ic SEFC
|
||||||
|
Likewise for the upper case versions on the left.
|
||||||
|
.It Ic 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.
|
||||||
|
.It Ic x
|
||||||
|
This lets you quit the game at any time.
|
||||||
|
.It Ic p
|
||||||
|
Points in a direction you might want to go.
|
||||||
|
.It Ic w
|
||||||
|
Space warp to get out of tight squeezes, at a price.
|
||||||
|
.El
|
||||||
|
.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
|
||||||
|
.Nm snscore .
|
||||||
|
.Sh FILES
|
||||||
|
.Bl -tag -width /var/games/snakerawscores -compact
|
||||||
|
.It Pa /var/games/snakerawscores
|
||||||
|
database of personal bests
|
||||||
|
.It Pa /var/games/snake.log
|
||||||
|
log of games played
|
||||||
|
.El
|
||||||
|
.Sh BUGS
|
||||||
|
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.
|
999
games/snake/snake/snake.c
Normal file
999
games/snake/snake/snake.c
Normal file
|
@ -0,0 +1,999 @@
|
||||||
|
/* $NetBSD: snake.c,v 1.28 2012/06/19 05:46:09 dholland Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1980, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
|
||||||
|
The Regents of the University of California. All rights reserved.");
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)snake.c 8.2 (Berkeley) 1/7/94";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: snake.c,v 1.28 2012/06/19 05:46:09 dholland Exp $");
|
||||||
|
#endif
|
||||||
|
#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 <curses.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
|
#include "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 LF '\n'
|
||||||
|
#define DEL '\177'
|
||||||
|
|
||||||
|
#define ME 'I'
|
||||||
|
#define SNAKEHEAD 'S'
|
||||||
|
#define SNAKETAIL 's'
|
||||||
|
#define TREASURE '$'
|
||||||
|
#define GOAL '#'
|
||||||
|
|
||||||
|
#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);
|
||||||
|
|
||||||
|
static struct point you;
|
||||||
|
static struct point money;
|
||||||
|
static struct point finish;
|
||||||
|
static struct point snake[6];
|
||||||
|
|
||||||
|
static int loot, penalty;
|
||||||
|
static int moves;
|
||||||
|
static int fast = 1;
|
||||||
|
|
||||||
|
static int rawscores;
|
||||||
|
static FILE *logfile;
|
||||||
|
|
||||||
|
static int lcnt, ccnt; /* user's idea of screen size */
|
||||||
|
static int chunk; /* amount of money given at a time */
|
||||||
|
|
||||||
|
static void chase(struct point *, struct point *);
|
||||||
|
static int chk(const struct point *);
|
||||||
|
static void drawbox(void);
|
||||||
|
static void flushi(void);
|
||||||
|
static void length(int);
|
||||||
|
static void logit(const char *);
|
||||||
|
static void mainloop(void) __dead;
|
||||||
|
static struct point *point(struct point *, int, int);
|
||||||
|
static int post(int, int);
|
||||||
|
static int pushsnake(void);
|
||||||
|
static void setup(void);
|
||||||
|
static void snap(void);
|
||||||
|
static void snrand(struct point *);
|
||||||
|
static void spacewarp(int);
|
||||||
|
static void stop(int) __dead;
|
||||||
|
static int stretch(const struct point *);
|
||||||
|
static void surround(struct point *);
|
||||||
|
static void suspend(void);
|
||||||
|
static void win(const struct point *);
|
||||||
|
static void winnings(int);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ch, i;
|
||||||
|
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");
|
||||||
|
if (logfile == NULL) {
|
||||||
|
warn("fopen %s", _PATH_LOGFILE);
|
||||||
|
sleep(2);
|
||||||
|
}
|
||||||
|
setgid(getgid());
|
||||||
|
|
||||||
|
(void) time(&tv);
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "l:w:t")) != -1)
|
||||||
|
switch ((char) ch) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
case 'd':
|
||||||
|
tv = atol(optarg);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 'w': /* width */
|
||||||
|
ccnt = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'l': /* length */
|
||||||
|
lcnt = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
fast = 0;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(stderr,
|
||||||
|
"usage: %s [-d seed] [-w width] [-l length] [-t]\n",
|
||||||
|
getprogname());
|
||||||
|
#else
|
||||||
|
fprintf(stderr,
|
||||||
|
"usage: %s [-w width] [-l length] [-t]\n",
|
||||||
|
getprogname());
|
||||||
|
#endif
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
srandom((int) tv);
|
||||||
|
|
||||||
|
penalty = loot = 0;
|
||||||
|
if (!initscr())
|
||||||
|
errx(0, "couldn't initialize screen");;
|
||||||
|
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) {
|
||||||
|
endwin();
|
||||||
|
errx(1, "screen too small for a fair game.");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
snrand(&finish);
|
||||||
|
snrand(&you);
|
||||||
|
snrand(&money);
|
||||||
|
snrand(&snake[0]);
|
||||||
|
|
||||||
|
for (i = 1; i < 6; i++)
|
||||||
|
chase(&snake[i], &snake[i - 1]);
|
||||||
|
setup();
|
||||||
|
mainloop();
|
||||||
|
/* NOTREACHED */
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct point *
|
||||||
|
point(struct point *ps, int x, int y)
|
||||||
|
{
|
||||||
|
ps->col = x;
|
||||||
|
ps->line = y;
|
||||||
|
return (ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Main command loop */
|
||||||
|
static void
|
||||||
|
mainloop(void)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
int repeat = 1;
|
||||||
|
int lastc = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
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 (!fast)
|
||||||
|
flushi();
|
||||||
|
lastc = c;
|
||||||
|
switch (c) {
|
||||||
|
case CTRL('z'):
|
||||||
|
suspend();
|
||||||
|
continue;
|
||||||
|
case EOT:
|
||||||
|
case 'x':
|
||||||
|
case 0177: /* del or end of file */
|
||||||
|
endwin();
|
||||||
|
length(moves);
|
||||||
|
logit("quit");
|
||||||
|
exit(0);
|
||||||
|
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':
|
||||||
|
#ifdef KEY_LEFT
|
||||||
|
case KEY_LEFT:
|
||||||
|
#endif
|
||||||
|
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':
|
||||||
|
#ifdef KEY_RIGHT
|
||||||
|
case KEY_RIGHT:
|
||||||
|
#endif
|
||||||
|
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':
|
||||||
|
#ifdef KEY_UP
|
||||||
|
case KEY_UP:
|
||||||
|
#endif
|
||||||
|
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':
|
||||||
|
#ifdef KEY_DOWN
|
||||||
|
case KEY_DOWN:
|
||||||
|
#endif
|
||||||
|
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)) {
|
||||||
|
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);
|
||||||
|
flushi();
|
||||||
|
endwin();
|
||||||
|
printf("You have won with $%d.\n", cashvalue);
|
||||||
|
fflush(stdout);
|
||||||
|
logit("won");
|
||||||
|
post(cashvalue, 1);
|
||||||
|
length(moves);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
if (pushsnake())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup the board
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
setup(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
erase();
|
||||||
|
pchar(&you, ME);
|
||||||
|
pchar(&finish, GOAL);
|
||||||
|
pchar(&money, TREASURE);
|
||||||
|
for (i = 1; i < 6; i++) {
|
||||||
|
pchar(&snake[i], SNAKETAIL);
|
||||||
|
}
|
||||||
|
pchar(&snake[0], SNAKEHEAD);
|
||||||
|
drawbox();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
drawbox(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 1; i <= ccnt; i++) {
|
||||||
|
mvaddch(0, i, '-');
|
||||||
|
mvaddch(lcnt + 1, i, '-');
|
||||||
|
}
|
||||||
|
for (i = 0; i <= lcnt + 1; i++) {
|
||||||
|
mvaddch(i, 0, '|');
|
||||||
|
mvaddch(i, ccnt + 1, '|');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
snrand(struct point *sp)
|
||||||
|
{
|
||||||
|
struct point p;
|
||||||
|
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 < 6; i++)
|
||||||
|
if (same(&p, &snake[i]))
|
||||||
|
break;
|
||||||
|
if (i < 6)
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*sp = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
post(int iscore, int flag)
|
||||||
|
{
|
||||||
|
short score = iscore;
|
||||||
|
short uid;
|
||||||
|
short oldbest = 0;
|
||||||
|
short allbwho = 0, allbscore = 0;
|
||||||
|
struct passwd *p;
|
||||||
|
|
||||||
|
/* I want to printf() the scores for terms that clear on cook(),
|
||||||
|
* but this routine also gets called with flag == 0 to see if
|
||||||
|
* the snake should wink. If (flag) then we're at game end and
|
||||||
|
* can printf.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Neg uid, 0, and 1 cannot have scores recorded.
|
||||||
|
*/
|
||||||
|
if ((uid = getuid()) <= 1) {
|
||||||
|
if (flag)
|
||||||
|
printf("No saved scores for uid %d.\n", uid);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
if (rawscores < 0) {
|
||||||
|
/* Error reported earlier */
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
/* Figure out what happened in the past */
|
||||||
|
read(rawscores, &allbscore, sizeof(short));
|
||||||
|
read(rawscores, &allbwho, sizeof(short));
|
||||||
|
lseek(rawscores, uid * sizeof(short), SEEK_SET);
|
||||||
|
read(rawscores, &oldbest, sizeof(short));
|
||||||
|
if (!flag) {
|
||||||
|
lseek(rawscores, 0, SEEK_SET);
|
||||||
|
return (score > oldbest ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update this jokers best */
|
||||||
|
if (score > oldbest) {
|
||||||
|
lseek(rawscores, uid * sizeof(short), SEEK_SET);
|
||||||
|
write(rawscores, &score, sizeof(short));
|
||||||
|
printf("You bettered your previous best of $%d\n", oldbest);
|
||||||
|
} else
|
||||||
|
printf("Your best to date is $%d\n", oldbest);
|
||||||
|
|
||||||
|
/* See if we have a new champ */
|
||||||
|
p = getpwuid(allbwho);
|
||||||
|
if (score > allbscore) {
|
||||||
|
lseek(rawscores, 0, SEEK_SET);
|
||||||
|
write(rawscores, &score, sizeof(short));
|
||||||
|
write(rawscores, &uid, sizeof(short));
|
||||||
|
if (allbwho) {
|
||||||
|
if (p)
|
||||||
|
printf("You beat %s's old record of $%d!\n",
|
||||||
|
p->pw_name, allbscore);
|
||||||
|
else
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
flushi(void)
|
||||||
|
{
|
||||||
|
tcflush(0, TCIFLUSH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int mx[8] = {
|
||||||
|
0, 1, 1, 1, 0, -1, -1, -1
|
||||||
|
};
|
||||||
|
static const int my[8] = {
|
||||||
|
-1, -1, 0, 1, 1, 1, 0, -1
|
||||||
|
};
|
||||||
|
static const float absv[8] = {
|
||||||
|
1, 1.4, 1, 1.4, 1, 1.4, 1, 1.4
|
||||||
|
};
|
||||||
|
static int oldw = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
chase(struct point *np, struct point *sp)
|
||||||
|
{
|
||||||
|
/* this algorithm has bugs; otherwise the snake would get too good */
|
||||||
|
struct point d;
|
||||||
|
int w, i, wt[8];
|
||||||
|
double 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 = ((random() >> 6) & 01777) % w;
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
if (vp < wt[i])
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
vp -= wt[i];
|
||||||
|
if (i == 8) {
|
||||||
|
printw("failure\n");
|
||||||
|
i = 0;
|
||||||
|
while (wt[i] == 0)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
oldw = w = i;
|
||||||
|
point(np, sp->col + mx[w], sp->line + my[w]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
spacewarp(int w)
|
||||||
|
{
|
||||||
|
struct point p;
|
||||||
|
int j;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
|
snrand(&you);
|
||||||
|
point(&p, COLS / 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++) {
|
||||||
|
erase();
|
||||||
|
refresh();
|
||||||
|
delay(5);
|
||||||
|
mvaddstr(p.line + 1, p.col + 1, str);
|
||||||
|
refresh();
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
setup();
|
||||||
|
winnings(cashvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
snap(void)
|
||||||
|
{
|
||||||
|
#if 0 /* This code doesn't really make sense. */
|
||||||
|
struct point p;
|
||||||
|
|
||||||
|
if (you.line < 3) {
|
||||||
|
mvaddch(1, you.col + 1, '-');
|
||||||
|
}
|
||||||
|
if (you.line > lcnt - 4) {
|
||||||
|
mvaddch(lcnt, you.col + 1, '_');
|
||||||
|
}
|
||||||
|
if (you.col < 10) {
|
||||||
|
mvaddch(you.line + 1, 1, '(');
|
||||||
|
}
|
||||||
|
if (you.col > ccnt - 10) {
|
||||||
|
mvaddch(you.line + 1, ccnt, ')');
|
||||||
|
}
|
||||||
|
#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, 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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
stretch(const struct point *ps)
|
||||||
|
{
|
||||||
|
struct point p;
|
||||||
|
|
||||||
|
point(&p, you.col, you.line);
|
||||||
|
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) < (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);
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
surround(struct point *ps)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
if (ps->col == 0)
|
||||||
|
ps->col++;
|
||||||
|
if (ps->line == 0)
|
||||||
|
ps->line++;
|
||||||
|
if (ps->line == LINES - 1)
|
||||||
|
ps->line--;
|
||||||
|
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)) {
|
||||||
|
mvaddstr(ps->line, ps->col, " ");
|
||||||
|
mvaddstr(ps->line + 1, ps->col, "o.o");
|
||||||
|
mvaddstr(ps->line + 2, ps->col, "\\_/");
|
||||||
|
refresh();
|
||||||
|
delay(6);
|
||||||
|
mvaddstr(ps->line, ps->col, " ");
|
||||||
|
mvaddstr(ps->line + 1, ps->col, "o.-");
|
||||||
|
mvaddstr(ps->line + 2, ps->col, "\\_/");
|
||||||
|
refresh();
|
||||||
|
delay(6);
|
||||||
|
}
|
||||||
|
mvaddstr(ps->line, ps->col, " ");
|
||||||
|
mvaddstr(ps->line + 1, ps->col, "o.o");
|
||||||
|
mvaddstr(ps->line + 2, ps->col, "\\_/");
|
||||||
|
refresh();
|
||||||
|
delay(6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
win(const 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--;
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pushsnake(void)
|
||||||
|
{
|
||||||
|
int i, bonus;
|
||||||
|
int issame = 0;
|
||||||
|
struct point tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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], ' ');
|
||||||
|
/* Need the following to catch you if you step on the snake's tail */
|
||||||
|
tmp.col = snake[5].col;
|
||||||
|
tmp.line = snake[5].line;
|
||||||
|
for (i = 4; i >= 0; i--)
|
||||||
|
snake[i + 1] = snake[i];
|
||||||
|
chase(&snake[0], &snake[1]);
|
||||||
|
pchar(&snake[1], SNAKETAIL);
|
||||||
|
pchar(&snake[0], SNAKEHEAD);
|
||||||
|
for (i = 0; i < 6; i++) {
|
||||||
|
if (same(&snake[i], &you) || same(&tmp, &you)) {
|
||||||
|
surround(&you);
|
||||||
|
i = (cashvalue) % 10;
|
||||||
|
bonus = ((random() >> 8) & 0377) % 10;
|
||||||
|
mvprintw(lcnt + 1, 0, "%d\n", bonus);
|
||||||
|
refresh();
|
||||||
|
delay(30);
|
||||||
|
if (bonus == i) {
|
||||||
|
spacewarp(1);
|
||||||
|
logit("bonus");
|
||||||
|
flushi();
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
flushi();
|
||||||
|
endwin();
|
||||||
|
if (loot >= penalty) {
|
||||||
|
printf("\nYou and your $%d have been eaten\n",
|
||||||
|
cashvalue);
|
||||||
|
} else {
|
||||||
|
printf("\nThe snake ate you. You owe $%d.\n",
|
||||||
|
-cashvalue);
|
||||||
|
}
|
||||||
|
logit("eaten");
|
||||||
|
length(moves);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
chk(const 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
winnings(int won)
|
||||||
|
{
|
||||||
|
if (won > 0) {
|
||||||
|
mvprintw(1, 1, "$%d", won);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
stop(int dummy __unused)
|
||||||
|
{
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
endwin();
|
||||||
|
length(moves);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
suspend(void)
|
||||||
|
{
|
||||||
|
endwin();
|
||||||
|
kill(getpid(), SIGTSTP);
|
||||||
|
refresh();
|
||||||
|
winnings(cashvalue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
length(int num)
|
||||||
|
{
|
||||||
|
printf("You made %d moves.\n", num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
logit(const char *msg)
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
|
||||||
|
if (logfile != NULL) {
|
||||||
|
time(&t);
|
||||||
|
fprintf(logfile, "%s $%d %dx%d %s %s",
|
||||||
|
getlogin(), cashvalue, lcnt, ccnt, msg, ctime(&t));
|
||||||
|
fflush(logfile);
|
||||||
|
}
|
||||||
|
}
|
11
games/snake/snscore/Makefile
Normal file
11
games/snake/snscore/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# $NetBSD: Makefile,v 1.7 2002/09/18 06:16:41 lukem Exp $
|
||||||
|
# @(#)Makefile 8.1 (Berkeley) 5/31/93
|
||||||
|
|
||||||
|
NOMAN= # defined
|
||||||
|
|
||||||
|
PROG= snscore
|
||||||
|
CPPFLAGS+= -I${.CURDIR}/../snake
|
||||||
|
HIDEGAME= hidegame
|
||||||
|
|
||||||
|
.include "../../Makefile.inc"
|
||||||
|
.include <bsd.prog.mk>
|
132
games/snake/snscore/snscore.c
Normal file
132
games/snake/snscore/snscore.c
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/* $NetBSD: snscore.c,v 1.19 2012/06/19 05:46:09 dholland Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1980, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#ifndef lint
|
||||||
|
__COPYRIGHT("@(#) Copyright (c) 1980, 1993\
|
||||||
|
The Regents of the University of California. All rights reserved.");
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#ifndef lint
|
||||||
|
#if 0
|
||||||
|
static char sccsid[] = "@(#)snscore.c 8.1 (Berkeley) 7/19/93";
|
||||||
|
#else
|
||||||
|
__RCSID("$NetBSD: snscore.c,v 1.19 2012/06/19 05:46:09 dholland Exp $");
|
||||||
|
#endif
|
||||||
|
#endif /* not lint */
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
static const char *recfile = _PATH_RAWSCORES;
|
||||||
|
#define MAXPLAYERS 256
|
||||||
|
|
||||||
|
struct player {
|
||||||
|
short uids;
|
||||||
|
short scores;
|
||||||
|
char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct player players[MAXPLAYERS], temp;
|
||||||
|
|
||||||
|
int main(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
short uid, score;
|
||||||
|
FILE *fd;
|
||||||
|
int noplayers;
|
||||||
|
int i, j, notsorted;
|
||||||
|
short whoallbest, allbest;
|
||||||
|
const char *q;
|
||||||
|
struct passwd *p;
|
||||||
|
|
||||||
|
/* Revoke setgid privileges */
|
||||||
|
setgid(getgid());
|
||||||
|
|
||||||
|
fd = fopen(recfile, "r");
|
||||||
|
if (fd == NULL)
|
||||||
|
err(1, "opening `%s'", recfile);
|
||||||
|
printf("Snake players scores to date\n");
|
||||||
|
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) {
|
||||||
|
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 = strdup(q);
|
||||||
|
if (players[noplayers].name == NULL)
|
||||||
|
err(1, NULL);
|
||||||
|
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);
|
||||||
|
}
|
Loading…
Reference in a new issue