home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
misc
/
volume18
/
clife
/
part01
next >
Wrap
Internet Message Format
|
1991-04-20
|
14KB
From: jek5036@ultb.isc.rit.edu (J.E. King)
Newsgroups: comp.sources.misc
Subject: v18i056: clife - Curses based Life simulator, Part01/01
Message-ID: <1991Apr19.024645.8063@sparky.IMD.Sterling.COM>
Date: 19 Apr 91 02:46:45 GMT
Approved: kent@sparky.imd.sterling.com
X-Checksum-Snefru: 4955564a 9bb48de2 8d5f88a0 c6e15a04
Submitted-by: J.E. King <jek5036@ultb.isc.rit.edu>
Posting-number: Volume 18, Issue 56
Archive-name: clife/part01
Supersedes: clife: Volume 17, Issue 61
With some help from someone out on the net (read the man page)
I have improved the life program. Because it is such a small program
I thought I would repost it instead of patches (because the p[atches were
larger than the original).
This is called clife, or a curses implementation life simulator. It
simulates the life 'function' which is described in the manual page.
Basically it could be thought of as a game, but it isn't. That's
why the manual page is under clife.6.
Jim King, (jek5036@ultb.isc.rit.edu)
-- cut here -- cut here -- cut here -- cut here -- cut here -- cut here --
#!/bin/sh
# to extract, remove the header and type "sh filename"
if `test ! -s ./Makefile`
then
echo "writing ./Makefile"
cat > ./Makefile << '\End\Of\Shar\'
# On the next line, add a -DHJKL if you wish to use HJKL instead of
# arrow keys when building a life screen.
CFLAGS = -g #-DHJKL
DEST = .
MANDEST = /usr/man/man6
EXTHDRS = /usr/include/curses.h \
/usr/include/sgtty.h \
/usr/include/signal.h \
/usr/include/stdio.h \
/usr/include/sys/ioctl.h \
/usr/include/sys/ttychars.h \
/usr/include/sys/ttydev.h \
/usr/include/sys/ttyio.h \
/usr/include/time.h
HDRS =
LDFLAGS = -g
LIBS = -lcurses -ltermlib
LINKER = cc
MAKEFILE = Makefile
OBJS = clife.o
PRINT = lpr
PROGRAM = clife
SRCS = clife.c
all: $(PROGRAM)
$(PROGRAM): $(OBJS)
@echo -n "Loading $(PROGRAM) ... "
@$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
@echo "done"
clean:; @rm -f $(OBJS)
depend:; @mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
index:; @ctags -wx $(HDRS) $(SRCS)
install: $(PROGRAM)
@echo Installing $(PROGRAM) in $(DEST)
@install -s $(PROGRAM) $(DEST)
@echo Copying manual pages...
@cp clife.6 $(MANDEST)
@chmod 644 $(MANDEST)/clife.6
print:; @$(PRINT) $(HDRS) $(SRCS)
program: $(PROGRAM)
tags: $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
update: $(DEST)/$(PROGRAM)
$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
@make -f $(MAKEFILE) DEST=$(DEST)
###
clife.o: /usr/include/signal.h /usr/include/time.h /usr/include/stdio.h \
/usr/include/curses.h /usr/include/sgtty.h /usr/include/sys/ioctl.h \
/usr/sys/h/ttychars.h /usr/sys/h/ttydev.h /usr/sys/h/ttyio.h \
/usr/sys/h/sgtty.h /usr/include/sys/ttychars.h \
/usr/include/sys/ttydev.h /usr/include/sys/ttyio.h
\End\Of\Shar\
else
echo "will not over write ./Makefile"
fi
if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 1646 ]
then
echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 1646}'`
fi
if `test ! -s ./Makefile.sysv`
then
echo "writing ./Makefile.sysv"
cat > ./Makefile.sysv << '\End\Of\Shar\'
# On the next line, add a -DHJKL if you wish to use HJKL instead of
# arrow keys when building a life screen.
CFLAGS = -O -DHJKL
DEST = .
MANDEST = /usr/man/man6
EXTHDRS = /usr/include/curses.h \
/usr/include/sgtty.h \
/usr/include/signal.h \
/usr/include/stdio.h \
/usr/include/time.h
HDRS =
LDFLAGS = -O
LIBS = -lcurses
LINKER = cc
MAKEFILE = Makefile
OBJS = clife.o
PRINT = lpr
PROGRAM = clife
SRCS = clife.c
all: $(PROGRAM)
$(PROGRAM): $(OBJS)
@echo -n "Loading $(PROGRAM) ... "
@$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
@echo "done"
clean:; @rm -f $(OBJS)
depend:; @mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
index:; @ctags -wx $(HDRS) $(SRCS)
install: $(PROGRAM)
@echo Installing $(PROGRAM) in $(DEST)
@install -s $(PROGRAM) $(DEST)
@echo Copying manual pages...
@cp clife.6 $(MANDEST)
@chmod 644 $(MANDEST)/clife.6
print:; @$(PRINT) $(HDRS) $(SRCS)
program: $(PROGRAM)
tags: $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
update: $(DEST)/$(PROGRAM)
$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
@make -f $(MAKEFILE) DEST=$(DEST)
###
clife.o: /usr/include/signal.h /usr/include/time.h /usr/include/stdio.h \
/usr/include/curses.h
\End\Of\Shar\
else
echo "will not over write ./Makefile.sysv"
fi
if [ `wc -c ./Makefile.sysv | awk '{printf $1}'` -ne 1302 ]
then
echo `wc -c ./Makefile.sysv | awk '{print "Got " $1 ", Expected " 1302}'`
fi
if `test ! -s ./clife.6`
then
echo "writing ./clife.6"
cat > ./clife.6 << '\End\Of\Shar\'
.TH clife 6
.SH Name
clife \- Life simulation using curses
.SH Syntax
.B clife
\fI[-dp]\fR
.SH Description
The
.PN clife
program is a simulator which has been around for quite some time.
The screen is set up with random 'people' on the screen. Each
person is represented by a '*'. The rules are simple: If
three people are around any given square, a person is born there. If
only two people are around any given square, then that person stays.
Any other number around a square kills the person there. (not enough food)
.PP
The clife (which stands for curses life) simulator will produce certain
distinguishable patterns attributable to the life equation.
.SH Options
The
.PN \-d
option allows you to draw your own pattern on the screen
and run it through the simulator. This is done by moving around the
screen with the arrow keys, (or using the 'hjkl' keys if the program
was compiled with that option) and using the spacebar to put a person in the
square you are currently over. If a person is there already,
kill the person. (blank the space)
The
.PN \-p
option will print out information about the life cycles on the bottom
of the screen after each cycle.
.SH Author
Jim King, (jek5036@ritvax.isc.rit.edu)
.SH Additions
Sameer Parekh (zane@ddsw1.MCS.COM) added wrap ability, fixed quit bug,
enhanced draw segment to allow HJKL or arrows at compile time, and
enhanced argument parsing.
\End\Of\Shar\
else
echo "will not over write ./clife.6"
fi
if [ `wc -c ./clife.6 | awk '{printf $1}'` -ne 1399 ]
then
echo `wc -c ./clife.6 | awk '{print "Got " $1 ", Expected " 1399}'`
fi
if `test ! -s ./clife.c`
then
echo "writing ./clife.c"
cat > ./clife.c << '\End\Of\Shar\'
/*
* clife.c - curses life simulator. Translated from Pascal to C implementing
* curses Oct 1988 by pulsar@lsrhs, now jek5036@ritvax.isc.rit.edu
*
* V2 pulsar@lsrhs Oct 1988
* - Draw your own pattern then 'life' it.
*
* V2.1 zane@ddsw1.MCS.COM Apr 1991
* - Addition so the screen wraps around.
* - Fix of the bug which caused the shell to mess up after
* quitting with SIGINT.
* - Also enable all options with one argument. (clife -dp
* instead of clife -d -p, both are usable.)
* - Enable choice of arrow keys or HJKL at compile-time.
*
* jek5036@ultb.isc.rit.edu (formerly pulsar@lsrhs)
* - SYSV Makefile (I hope it works..)
* - Couple of minor fixes including random() instead of rand()
*/
#include <signal.h>
#include <time.h>
#include <stdio.h>
#include <curses.h>
/* a value of -1 will make it go forever */
/* a value of 0 will make it exit immed. */
#define REPSTOP -1 /* number of repetitions before stop */
/* in a looping pattern */
/*
* I don't need any flames about global variables.
*/
#define MAXROW 23
#define MAXCOL 79
int present[MAXROW+1][MAXCOL+1], /* screen 1 cycle ago */
past[MAXROW+1][MAXCOL+1], /* screen this cycle */
total, /* total # of changes */
icnt, /* counter to check for repetition */
minrow = 0,
mincol = 0,
pri = 0,
draw = 0,
i, j, k, /* loop counters */
cycle, /* current cycle # */
changes, /* # of changes this cycle (live + die) */
die, /* number of deaths this cycle */
live; /* number of births this cycle */
WINDOW *mns, /* Main Screen */
*info; /* Bottom line */
/*
* cleanup - cleanup then go back to makscr
*/
cleanup()
{
move(23, 0); /* go to bottom of screen */
refresh(); /* update cursor */
endwin(); /* Clean up curses */
exit(1);
}
/*
* initialize - init windows, variables, and signals
*/
initialize()
{
srandom(getpid()); /* init rand seed */
initscr(); /* init curses */
signal(SIGINT, cleanup); /* catch ^C */
signal(SIGTERM, exit); /* exit on kill -15 */
mns = newwin(MAXROW, MAXCOL, 0, 0); /* new window */
scrollok(mns, FALSE);
info = newwin(1, 80, 23, 0);
scrollok(info, FALSE);
wclear(mns);
if (!draw) { /* if no draw, make rand pattern */
for (j = 0; j < MAXROW; j++) {
for (k = 0; k < MAXCOL; k++) {
present[j][k] = random()%2;
if (present[j][k] == 1) changes++, live++;
}
}
}
}
/*
* makscr - make your own screen using arrow keys and space bar
*/
makscr()
{
int curx, cury; /* current point on screen */
char c; /* input char */
wclear(info);
wmove(info, 0, 0);
#ifdef HJKL
wprintw(info, "Use 'hjkl' keys to move, space to place / erase, ^D to start");
#else
wprintw(info, "Use arrow keys to move, space to place / erase, ^D to start");
#endif
wrefresh(info);
curx = cury = 1;
wmove(mns, cury-1, curx-1); wrefresh(mns);
noecho(); crmode();
for (;;) {
c = wgetch(mns);
if (c == '\004')
break;
else if (c == ' ') {
if (present[cury][curx]) {
--present[cury][curx];
changes++;
die++;
mvwaddch(mns, cury, curx, ' ');
} else {
++present[cury][curx];
changes++;
live++;
mvwaddch(mns, cury, curx, '*');
}
#ifndef HJKL /* This portion is used for the arrow keys */
} else if (c == '\033') {
wgetch(mns);
switch(wgetch(mns)) {
case 'A':
--cury; break;
case 'B':
++cury; break;
case 'C':
++curx; break;
case 'D':
--curx; break;
default:
break;
}
}
#else /* This portion for HJKL */
} else {
switch(c) {
case 'H':
case 'h':
--curx; break;
case 'J':
case 'j':
++cury; break;
case 'K':
case 'k':
--cury; break;
case 'L':
case 'l':
++curx; break;
default:
break;
}
}
#endif /* End the HJKL section */
if (cury > MAXROW) cury = minrow;
if (cury < minrow) cury = MAXROW;
if (curx > MAXCOL) curx = mincol;
if (curx < mincol) curx = MAXCOL;
wmove(mns, cury, curx);
wrefresh(mns);
}
wclear(info);
}
/* Update rules: 2 or 3 adjacent alive --- stay alive
* 3 adjacent alive -- dead to live
* all else die or stay dead
*/
update() /* Does all mathmatical calculations */
{
int howmany, w, x, y, z;
changes = die = live = 0;
for (j = 0; j < MAXROW; j++) {
for (k = 0; k < MAXCOL; k++) {
w = (j-1 < 0) ? (MAXROW-1) : j-1;
x = (j+1 > MAXROW-1) ? 0 : j+1;
y = (k-1 < 0) ? (MAXCOL-1) : k-1;
z = (k+1 > MAXCOL-1) ? 0 : k+1;
/*
* Nice addition above four lines for wrap.. wouldn't have thought
* of it myself.. -- Jim
*/
howmany = (past[w][y] + past[w][k] + past[w][z] +
past[j][y] + past[j][z] + past[x][y] +
past[x][k] + past[x][z]);
switch(howmany) {
case 0:
case 1:
case 4:
case 5:
case 6:
case 7:
case 8:
present[j][k] = 0;
if (past[j][k]) changes++, die++;
break;
case 3:
present[j][k] = 1;
if (!past[j][k]) changes++, live++;
break;
default:
break;
}
}
}
if (live == die)
++icnt;
else
icnt = 0;
if (icnt == REPSTOP)
cleanup();
}
/*
* print - updates the screen according to changes from past to present
*/
print() /* Updates the screen, greatly improved using curses */
{
if (pri) {
wmove(info, 0, 0);
total += changes;
wprintw(info, "Cycle %d | %d changes: %d died and %d born & %d total changes", ++cycle, changes, die, live, total);
wclrtoeol(info);
}
for (j = 0; j < MAXROW; j++) {
for (k = 0; k < MAXCOL; k++) {
if (present[j][k] != past[j][k] && present[j][k] == 1) {
wmove(mns, j, k);
wprintw(mns, "*");
} else if (present[j][k] != past[j][k] && present[j][k] == 0) {
wmove(mns, j, k);
wprintw(mns, " ");
}
}
}
if (pri) wrefresh(info);
wrefresh(mns);
}
/*
* main - main procedure
*/
main(ac, av)
int ac;
char *av[];
{
if (ac > 1) {
for (j = 1; j < ac; j++) {
if (av[j][0] == '-') {
for(i = 1; i < strlen(av[j]); i++) {
switch(av[j][i]) {
case 'd':
++draw;
break;
case 'p':
++pri;
break;
default:
fprintf(stderr, "%s: usage: %s [-dpf] <filename>]\n", av[0], av[0]);
exit(1);
}
}
}
}
}
if (draw)
printf("User-built screen\n");
if (pri)
printf("Print statistics\n");
initialize();
if (draw)
makscr();
wclear(info);
wmove(info, 0, 0);
wprintw(info, "Life V2.1 by Jim King (jek5036@ultb.isc.rit.edu), additions by Sameer Parekh");
wrefresh(info);
for (;;) {
print();
for (j = 0; j < MAXROW; j++) {
for (k = 0; k < MAXCOL; k++)
past[j][k] = present[j][k];
}
update();
}
}
\End\Of\Shar\
else
echo "will not over write ./clife.c"
fi
if [ `wc -c ./clife.c | awk '{printf $1}'` -ne 6649 ]
then
echo `wc -c ./clife.c | awk '{print "Got " $1 ", Expected " 6649}'`
fi
echo "Finished archive 1 of 1"
exit
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.