jek5036@ultb.isc.rit.edu (J.E. King) (03/22/91)
Submitted-by: J.E. King <jek5036@ultb.isc.rit.edu> Posting-number: Volume 17, Issue 61 Archive-name: clife/part01 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\' CFLAGS = -O 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 = -O 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 `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[-d] [-p]\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 there are three people around any given square, a person is born there. If there are only two people around any given square, then it does not change. Any other number around a square kills the person there. .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 and using space to put a person in the square you are currently over, or if there is a person there already, kill it. The .PN \-p option will print out information about the life cycles on the bottom of the screen. .SH Author Jim King, (jek5036@ritvax.isc.rit.edu) \End\Of\Shar\ else echo "will not over write ./clife.6" 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, not jek5036@ritvax.isc.rit.edu * * V2 - Draw your own pattern then 'life' it. */ #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 */ int present[23][80], /* screen 1 cycle ago */ past[23][80], /* screen this cycle */ total, /* total # of changes */ icnt, /* counter to check for repetition */ maxrow = 22, /* some defines to represent the screen */ maxcol = 79, minrow = 0, mincol = 0, pri = 0, /* flag for printing stats on bottom line */ draw = 0, /* flag for drawing your own screen */ 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 exit */ cleanup() { move(23, 0); /* go to bottom of screen */ refresh(); /* update cursor */ exit(1); /* exit */ } /* * initialize - init windows, variables, and signals */ initialize() { srandom(getpid()); /* init random seed */ initscr(); /* init curses */ signal(SIGINT, cleanup); /* catch ^C */ mns = newwin(maxrow, maxcol, 0, 0); /* new window */ scrollok(mns, FALSE); info = newwin(1, 80, 23, 0); scrollok(info, FALSE); wclear(mns); wclear(info); wmove(info, 0, 0); wprintw(info, "Life V2 by Jim King (pulsar@lsrhs)"); wrefresh(info); sleep(3); if (!draw) { /* if no draw, make random 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); wprintw(info, "Use arrow keys to move, space to place / erase, ^D to start"); 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, '*'); } } 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; } } 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; x = j+1; y = k-1; z = k+1; 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 = 1; j < maxrow; j++) { for (k = 1; 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++) { switch(av[j][1]) { case 'd': ++draw; break; case 'p': ++pri; break; default: fprintf(stderr, "%s: usage: %s [-d] [-p]\n", av[0]); exit(1); } } } if (draw) printf("User-built screen\n"); if (pri) printf("Print statistics\n"); sleep(2); initialize(); if (draw) makscr(); 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 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.