[comp.sources.games] v06i098: greed2 - v2.0a of the screen oriented grid game, Part01/01

billr@saab.CNA.TEK.COM (Bill Randle) (07/06/89)

Submitted-by: "Matthew T. Day" <ohs!mday@uunet.uu.net>
Posting-number: Volume 6, Issue 98
Archive-name: greed2/Part01
Supersedes: greed; Volume 6, Issue 77



[[Here's the latest version of Greed, v2.0a.  I don't think it really does
enough stuff v1.2 to validate a jump to 2.0, but this has to be official,
sort of like a restarting point.  Anyway, there are some new things:

1) Externally, you can now use the '-p' option to highlight the possible
moves around you.  Kind of hard to explain, but take a look at it, it's really
useful!  Thanks to Quinn Jensen for adding that part.

2) Now uses it's own lockfile routine, for portability.  See the README for
more.

3) Makefile caters to Xenix better, plus see README about using Berkeley curses
in a SYSV environment.  Thanks to Scott Reynolds for pointing out that stuff.

4) Of course, more code cleanup, uses void, etc...

Have fun!

md]]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  README Makefile greed.c
# Wrapped by billr@saab on Wed Jul  5 15:03:24 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1482 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XWelcome to Greed v2.0a!.
XTo install Greed, simply edit the Makefile to configure your system type, and
Xrun "make install".  It should compile the program and install it correctly.
XNote: If you are a SYSV site running Berkeley curses, you will need to delete
Xthe macro defination of crmode, line 17 of greed.c.
XIt does run set-uid, but there is no danger of security problems.
X
XI do not take credit for inventing the game, I once saw it on an IBM,
Xand wrote it for Unix in C.
X
XIf anyone has a comment or problem, please to mail to mday@ohs.uucp.
X
XHere's the current high score file at Orem High School:
XRank  Score  Name     Percentage
X1     1542   stay     89.03%
X2     1504   ndes     86.84%
X3     1504   dvar     86.84%
X4     1501   stay     86.66%
X5     1497   stay     86.43%
X6     1490   skel     86.03%
X7     1464   dvar     84.53%
X8     1463   stay     84.47%
X9     1463   stay     84.47%
X10    1460   stay     84.30%
X
XProgram note for v2.0a:  For portability, I wrote my own lockfile routine.
XThe LOCKPATH macro defined at the beginning of greed.c should be defined
Xto a path where normal users can't write, like /usr/games/lib.  It's defined
Xas /tmp/Greed.lock initially.
X
X+----------------------------------------------+-------------------------+
X| Matthew T. Day, Orem High School, Orem, Utah | "He who laughs, lasts." |
X| Email: mday@ohs (..!uunet!iconsys!ohs!mday)  |    day++, dollar++;     |
X+----------------------------------------------+-------------------------+
END_OF_FILE
if test 1482 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(602 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile for Greed v2.0a, by Matthew T. Day (mday@ohs.uucp)
X
X# Choose BSD for Berkeley Unix, NOTBSD for all others
XSYSDEF=BSD
X#SYSDEF=NOTBSD
X
X# Location of high score file
XSFILE=/usr/games/lib/greed.hs
X# Location of game executable
XBIN=/usr/games
X
XCFLAGS=-O -s
X# You may need to modify the libraries used below according to your site,
X# e.g. -ltermcap for Berkeley and Xenix, -ltermlib for AT&T SYSV.
XLIBS=-lcurses -ltermcap
X#LIBS=-lcurses -ltermlib
X
Xgreed: greed.c
X	cc -DSCOREFILE=\"$(SFILE)\" -D$(SYSDEF) -o greed greed.c $(CFLAGS) $(LIBS)
X
Xinstall: greed
X	mv greed $(BIN)
X	chmod 4711 $(BIN)/greed
END_OF_FILE
if test 602 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'greed.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'greed.c'\"
else
echo shar: Extracting \"'greed.c'\" \(8818 characters\)
sed "s/^X//" >'greed.c' <<'END_OF_FILE'
X/* greed.c v2.0a - Written by Matthew T. Day (mday@ohs.uucp), 06/30/89       *
X * Document and send all source code changes to the above address, I'll make *
X * sure the approved patches are posted.  Please don't redistribute this.    */
X
Xstatic char *version = "Greed v2.0a";
X
X#include <curses.h>
X#include <signal.h>
X#include <pwd.h>
X#ifdef NOTBSD
X#include <fcntl.h>
X#else
X#include <sys/file.h>
X#endif
X
X#ifdef NOTBSD
X#define crmode cbreak
X#define random lrand48
X#define srandom srand48
X#endif
X
X#define MAXSCORE 10
X#define FILESIZE (MAXSCORE * sizeof(struct score))
X#define rnd(x) (int) ((random() % (x))+1)
X#define ME '@'
X#define LOCKPATH "/tmp/Greed.lock"
X
Xstruct score {
X	char user[9];
X	int score;
X};
Xint allmoves = 0, score = 1, grid[22][79], y, x, havebotmsg = 0;
Xchar *cmdname;
Xextern long random();
Xvoid topscores();
X
Xvoid botmsg(msg, backcur)
Xregister char *msg;
Xregister backcur;
X{
X	standend();
X	mvaddstr(23, 40, msg);
X	clrtoeol();
X	standout();
X	if (backcur) move(y, x);
X	refresh();
X	havebotmsg = 1;
X}
X
Xquit() {
X	int (*osig)() = signal(SIGINT, SIG_IGN);
X	(void) signal(SIGQUIT, SIG_IGN);
X
X	if (stdscr) {
X		botmsg("Really quit? ", 0);
X		if (getch() != 'y') {
X			move(y, x);
X			(void) signal(SIGINT, osig);
X			(void) signal(SIGQUIT, osig);
X			refresh();
X			return(1);
X		}
X		move(23, 0);
X		refresh();
X		endwin();
X		puts("\n");
X		topscores(score);
X	}
X	exit(0);
X}
X
Xvoid out() {
X	if (stdscr) endwin();
X	exit(0);
X}
X
Xvoid usage() {
X	fprintf(stderr, "Usage: %s [-p] [-s]\n", cmdname);
X	exit(1);
X}
X
Xvoid showscore() {
X	standend();
X	mvprintw(23, 7, "%d  %.2f%%", score, (float) score / 17.32);
X	move(y, x);
X	standout();
X	refresh();
X}
X
Xvoid main(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	register val = 1;
X	extern long time();
X	void showmoves();
X
X	cmdname = argv[0];
X	if (argc == 2) {
X		if (strlen(argv[1]) != 2 || argv[1][0] != '-') usage();
X		switch(argv[1][1]) {
X		case 'p':
X			allmoves = 1;
X			break;
X		case 's':
X			topscores(0);
X			exit(0);
X		default:
X			usage();
X		}
X	} else if (argc > 2) usage();
X
X	(void) signal(SIGINT, quit);
X	(void) signal(SIGQUIT, quit);
X	(void) signal(SIGTERM, out);
X
X	initscr();
X	crmode();
X	noecho();
X	refresh();
X
X	srandom(time(0) ^ getpid() << 16);
X
X	for (y=0; y < 22; y++)
X		for (x=0; x < 79; x++)
X			mvaddch(y, x, (grid[y][x] = rnd(9)) + '0');
X
X	mvaddstr(23, 0, "Score: ");
X	mvprintw(23, 40, "%s - Hit '?' for help.", version);
X	standout();
X	y = rnd(22)-1; x = rnd(79)-1;
X	mvaddch(y, x, ME);
X	grid[y][x] = 0;
X
X	if (allmoves) showmoves(1);
X	showscore();
X
X	while ((val = tunnel(getch())) > 0);
X
X	if (!val) {
X		botmsg("Hit <Enter>", 0);
X		while (getch() != '\n');
X	}
X
X	move(23, 0);
X	refresh();
X	endwin();
X	puts("\n");
X	topscores(score);
X}
X
Xtunnel(cmd)
Xregister cmd;
X{
X	register dy, dx, distance;
X	void help();
X
X	switch (cmd) {
X	case 'h': case '4':
X		dy = 0; dx = -1;
X		break;
X	case 'j': case '2':
X		dy = 1; dx = 0;
X		break;
X	case 'k': case '8':
X		dy = -1; dx = 0;
X		break;
X	case 'l': case '6':
X		dy = 0; dx = 1;
X		break;
X	case 'b': case '1':
X		dy = 1; dx = -1;
X		break;
X	case 'n': case '3':
X		dy = dx = 1;
X		break;
X	case 'y': case '7':
X		dy = dx = -1;
X		break;
X	case 'u': case '9':
X		dy = -1; dx = 1;
X		break;
X	case 'q':
X		return(quit());
X	case '?':
X		help();
X		return(1);
X	case '\14':
X		wrefresh(curscr);
X	default:
X		return(1);
X	}
X	distance = grid[y+dy][x+dx];
X
X	{
X		register j = y, i = x, d = distance;
X
X		do {
X			j += dy;
X			i += dx;
X			if (j >= 0 && i >= 0 && j < 22 && i < 79 && grid[j][i])
X				continue;
X			else if (!othermove(dy, dx)) {
X				j -= dy;
X				i -= dx;
X				mvaddch(y, x, ' ');
X				while (y != j || x != i) {
X					y += dy;
X					x += dx;
X					score++;
X					mvaddch(y, x, ' ');
X				}
X				mvaddch(y, x, '*');
X				showscore();
X				return(0);
X			} else {
X				botmsg("Bad move.", 1);
X				return(1);
X			}
X		} while (--d);
X	}
X
X	if (allmoves) showmoves(0);
X
X	if (havebotmsg) {
X		standend();
X		mvprintw(23, 40, "%s - Hit '?' for help.", version);
X		standout();
X		havebotmsg = 0;
X	}
X
X	mvaddch(y, x, ' ');
X	do {
X		y += dy;
X		x += dx;
X		score++;
X		grid[y][x] = 0;
X		mvaddch(y, x, ' ');
X	} while (--distance);
X	mvaddch(y, x, ME);
X	if (allmoves) showmoves(1);
X	showscore();
X	return(1);
X}
X
Xothermove(bady, badx)
Xregister bady, badx;
X{
X	register dy = -1, dx;
X
X	for (; dy <= 1; dy++)
X		for (dx = -1; dx <= 1; dx++)
X			if ((!dy && !dx) || (dy == bady && dx == badx))
X				continue;
X			else {
X				register j=y, i=x, d=grid[y+dy][x+dx];
X
X				if (!d) continue;
X				do {
X					j += dy;
X					i += dx;
X					if (j < 0 || i < 0 || j >= 22 ||
X					    i >= 79 || !grid[j][i]) break;
X				} while (--d);
X				if (!d) return(1);
X			}
X	return(0);
X}
X
Xvoid showmoves(on)
Xregister on;
X{
X	register dy = -1, dx;
X
X	for (; dy <= 1; dy++)
X		for (dx = -1; dx <= 1; dx++) {
X			register j=y, i=x, d=grid[y+dy][x+dx];
X
X			if (!d) continue;
X			do {
X				j += dy;
X				i += dx;
X				if (j < 0 || i < 0 || j >= 22
X				    || i >= 79 || !grid[j][i]) break;
X			} while (--d);
X			if (!d) {
X				register j=y, i=x, d=grid[y+dy][x+dx];
X				if (on) standout();
X				else standend();
X				do {
X					j += dy;
X					i += dx;
X					move(j, i);
X					mvaddch(j, i, inch());
X				} while (--d);
X				if (!on) standout();
X			}
X		}
X}
X
Xvoid doputc(c)
Xregister char c;
X{
X	(void) fputc(c, stdout);
X}
X
Xvoid topscores(newscore)
Xregister int newscore;
X{
X	register fd, count = 1;
X	static char termbuf[512];
X	char *tptr = (char *) malloc(16), *boldon, *boldoff;
X	struct score *toplist = (struct score *) malloc(FILESIZE);
X	register struct score *ptrtmp, *eof = &toplist[MAXSCORE], *new = NULL;
X	extern char *getenv(), *tgetstr();
X	extern struct passwd *getpwuid();
X	void lockit();
X
X	(void) signal(SIGINT, SIG_IGN);
X	(void) signal(SIGQUIT, SIG_IGN);
X	(void) signal(SIGTERM, SIG_IGN);
X	(void) signal(SIGHUP, SIG_IGN);
X
X	if ((fd = open(SCOREFILE, O_RDWR | O_CREAT, 0600)) == -1) {
X		fprintf(stderr, "%s: %s: Cannot open.\n", cmdname, SCOREFILE);
X		exit(1);
X	}
X
X	lockit(1);
X	for (ptrtmp=toplist; ptrtmp < eof; ptrtmp++) ptrtmp->score = 0;
X	read(fd, toplist, FILESIZE);
X	if (newscore) {
X		for (ptrtmp=toplist; ptrtmp < eof; ptrtmp++)
X			if (newscore > ptrtmp->score) break;
X		if (ptrtmp < eof) {
X			new = ptrtmp;
X			ptrtmp = eof-1;
X			while (ptrtmp > new) {
X				*ptrtmp = *(ptrtmp-1);
X				ptrtmp--;
X			}
X
X			new->score = newscore;
X			strncpy(new->user, getpwuid(getuid())->pw_name, 8);
X			(void) lseek(fd, 0, 0);
X			write(fd, toplist, FILESIZE);
X		}
X	}
X
X	close(fd);
X	lockit(0);
X
X	if (toplist->score) puts("Rank  Score  Name     Percentage");
X	else puts("No high scores.");
X	if (new && tgetent(termbuf, getenv("TERM")) > 0) {
X		boldon = tgetstr("so", &tptr);
X		boldoff = tgetstr("se", &tptr);
X		if (!boldon || !boldoff) boldon = boldoff = 0;
X	}
X
X	for (ptrtmp=toplist; ptrtmp < eof && ptrtmp->score; ptrtmp++, count++) {
X		if (ptrtmp == new && boldon) tputs(boldon, 1, doputc);
X		printf("%-5d %-6d %-8s %.2f%%\n", count, ptrtmp->score,
X			ptrtmp->user, (float) ptrtmp->score / 17.32);
X		if (ptrtmp == new && boldoff) tputs(boldoff, 1, doputc);
X	}
X}
X
Xvoid lockit(on)
Xregister on;
X{
X	register fd, tries = 1;
X
X	if (on) {
X		while ((fd = creat(LOCKPATH, 0)) == -1) {
X			printf("Waiting for scorefile access... %d/15\n", tries);
X			if (tries++ >= 15) {
X				puts("Overriding stale lock...");
X				if (unlink(LOCKPATH) == -1) {
X					fprintf(stderr, "%s: %s: Can't unlink lock.\n",
X						cmdname, LOCKPATH);
X					exit(1);
X				}
X			}
X			sleep(1);
X		}
X		close(fd);
X	} else unlink(LOCKPATH);
X}
X
X#define msg(row, msg) mvwaddstr(helpwin, row, 2, msg);
X
Xvoid help() {
X	WINDOW *helpwin = newwin(18, 65, 1, 7);
X
X	(void) wclear(helpwin);
X	box(helpwin, '|', '-');
X	(void) waddch(helpwin, '+'); mvwaddch(helpwin, 0, 64, '+');
X	mvwaddch(helpwin, 17, 0, '+'); mvwaddch(helpwin, 17, 64, '+');
X
X	mvwprintw(helpwin, 1, 2,
X		"Welcome to %s, by Matthew T. Day (mday@ohs.uucp).", version);
X	msg(3, "The object of Greed is to erase as much of the screen as");
X	msg(4, "possible by moving around in a grid of numbers.  To move");
X	msg(5, "your cursor, simply use the 'hjklyubn' keys or your number");
X	mvwprintw(helpwin, 6, 2,
X		"keypad.  Your location is signified by the '%c' symbol.", ME);
X	msg(7, "When you move in a direction, you erase N number of grid");
X	msg(8, "squares in that direction, N being the first number in that");
X	msg(9, "direction.  Your score reflects the total number of squares");
X	msg(10, "eaten.  Greed will not let you make a move that would have");
X	msg(11, "placed you off the grid or over a previously eaten square");
X	msg(12, "unless no valid moves exist, in which case your game ends.");
X	msg(13, "Other Greed commands are 'Ctrl-L' to redraw the screen and");
X	msg(14, "'q' to quit.  Command line options to Greed are '-s' to output");
X	msg(15, "the high score file and '-p' to highlight the possible moves");
X	msg(16, "when playing.");
X
X	(void) wmove(helpwin, 17, 64);
X	wrefresh(helpwin);
X	(void) wgetch(helpwin);
X	delwin(helpwin);
X	touchwin(stdscr);
X	refresh();
X}
END_OF_FILE
if test 8818 -ne `wc -c <'greed.c'`; then
    echo shar: \"'greed.c'\" unpacked with wrong size!
fi
# end of 'greed.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0