miles@vax135.UUCP (Miles Murdocca) (11/05/85)
> Does anyone out there have a good full-screen implementation of Conway's > Game of Life (as detailed in Scientific American sometime back about 72-73)? > If so, I'd be interested in seeing it... Here's my version. Enjoy. Miles Murdocca, 4G-538, AT&T Bell Laboratories, Crawfords Corner Rd, Holmdel, NJ, 07733, (201) 949-2504, ...{ihnp4}!vax135!miles ---------------CUT---------------CUT----------------CUT------------------- /*----------------------------------------------------------------------*/ /* */ /* The game of Life. */ /* */ /* cc life.c -o life -lcurses -ltermlib */ /* */ /* Miles Murdocca */ /* January, 1984 */ /* */ /*----------------------------------------------------------------------*/ #include <stdio.h> #include <curses.h> #include <signal.h> #define XMAX 88 /* Max expected number of columns */ #define YMAX 72 /* Max expected number of row */ #define SET 1 #define RESET 0 unsigned char universe[XMAX][YMAX]; /* Max expected size of screen */ int singlestep; /* Boolean - if TRUE, single step (wait for char to continue) */ main(argc, argv) int argc; char *argv[]; { int i, j; int die(); initscr(); /* Initialize screen package */ if (evalargs(argc, argv) == 0) /* Evaluate arguments */ for (i = 0; i < XMAX; i++) for (j = 0; j < YMAX; j++) universe[i][j] = RESET; signal(SIGINT, die); /* Set to restore tty stats */ crmode(); /* set for char-by-char */ noecho(); /* input */ nonl(); /* For optimization */ getstart(); /* Get starting position */ for (;;) { prboard(); /* Print out current board */ update(); /* Update board position */ if (singlestep) getchar(); } } die() { char str[80]; int fp1, i, j; signal(SIGINT, SIG_IGN); /* Ignore rubouts */ mvcur(0, COLS-1, LINES-1, 0); /* Go to bottom of screen */ endwin(); /* Set terminal to initial state */ printf("Save game? "); scanf("%s", str); if (str[0] == 'y' || str[0] == 'Y') { printf("File name: "); scanf("%s", str); if ((fp1 = creat(str, 0644)) < 0) { printf("Cannot open %s. You get one more chance.\n",str); printf("File name: "); scanf("%s", str); if ((fp1 = creat(str, 0)) < 0) { printf("Cannot open %s. Tough luck.\n",str); exit(0); } } for (j = 1; j < LINES - 1; j++) for (i = 1; i < COLS - 1; i++) { move(j, i); if (inch() == 'X') universe[i][j] = SET; } for (i = 0; i < COLS; i++) write(fp1, universe[i], LINES); close(fp1); } exit(0); } getstart() { reg char c; reg int x, y; char buf[100]; prboard(); move(11, 36); /* Move to middle */ refresh(); c = getch(); while (c != 'q') { switch(c) { case 'h': if (stdscr->_curx == 1) break; move(stdscr->_cury, stdscr->_curx-1); break; case 'j': if (stdscr->_cury >= LINES - 2) break; move(stdscr->_cury+1, stdscr->_curx); break; case 'k': if (stdscr->_cury == 1) break; move(stdscr->_cury-1, stdscr->_curx); break; case 'l': if (stdscr->_curx >= COLS - 2) break; move(stdscr->_cury, stdscr->_curx+1); break; case '?': help(); break; case 'x': if (stdscr->_curx >= COLS - 1) break; addch('X'); break; case ' ': if (stdscr->_curx >= COLS - 1) break; addch(' '); break; default: break; } refresh(); /* Print current position */ c = getch(); } for (y = 1; y < LINES - 1; y++) for (x = 1; x < COLS - 1; x++) { move(y, x); if (inch() == 'X') universe[x][y] = SET; } } prboard() { int x, y; erase(); /* Clear out last position */ box(stdscr, '|', '_'); /* Box in the screen */ for (y = 1; y < LINES - 1; y++) for (x = 1; x < COLS - 1; x++) if (universe[x][y] == SET) { move(y, x); addch('X'); } refresh(); } evalargs(argc, argv) int argc; char *argv[]; { int i, j, k, fp; unsigned char c; singlestep = FALSE; if (argc == 1) return(0); if (argc > 3) { printf("Usage: clo [filename] [-s]\n"); exit(0); } for (k = 1; k < argc; k++) { if (argv[k][0] == '-') { switch(argv[k][1]) { case 's': singlestep = TRUE; break; default: printf("Bad option: %s\n",argv[k]); break; } continue; } if ((fp = open(argv[1], 0)) < 0) { printf("Cannot open %s\n",argv[1]); exit(0); } for (i = 0; i < COLS; i++) read(fp, universe[i], LINES); close(fp); } return(1); } /*-------------------------------------------------------------------*/ /* */ /* Rules: if less than 2 neighbors are set, then die. If exactly */ /* 2 neighbors set then stay the same. If 3 neighbors are set */ /* then birth. If more than 3 neighbors are set then die. */ /* */ /*-------------------------------------------------------------------*/ update() { int i, j, c; unsigned char tmpuniverse[XMAX][YMAX]; /* Max expected size of screen */ for (i = 0; i < COLS; i++) for (j = 0; j < LINES; j++) tmpuniverse[i][j] = universe[i][j]; for (i = 1; i < COLS - 1; i++) { for (j = 1; j < LINES - 1; j++) { c = count(i, j); switch(c) { case 0: tmpuniverse[i][j] = RESET; break; case 1: tmpuniverse[i][j] = RESET; break; case 2: break; case 3: tmpuniverse[i][j] = SET; break; case 4: case 5: case 6: case 7: case 8: tmpuniverse[i][j] = RESET; break; default: printf("Bad count\n"); break; } } } for (i = 0; i < COLS; i++) for (j = 0; j < LINES; j++) universe[i][j] = tmpuniverse[i][j]; } help() { int x, y, savex, savey; savex = stdscr->_curx; savey = stdscr->_cury; for (y = 1; y < LINES - 1; y++) for (x = 1; x < COLS - 1; x++) { move(y, x); if (inch() == 'X') universe[x][y] = SET; } erase(); move(3, 15); printw("The Game of Life"); move(5, 15); printw("h - left\n"); move(6, 15); printw("j - down\n"); move(7, 15); printw("k - up\n"); move(8, 15); printw("l - right\n"); move(9, 15); printw("x - set point\n"); move(10, 15); printw("<space> - reset point\n"); move(11, 15); printw("q - start\n"); move(12, 15); printw("[DEL] - exit (with save)\n"); move(14, 15); printw("Hit any character to continue: "); refresh(); getch(); prboard(); stdscr->_curx = savex; stdscr->_cury = savey; move(stdscr->_cury, stdscr->_curx); refresh(); } count(x, y) int x, y; { int c; c = 0; if (universe[x-1][y-1] == SET) c++; if (universe[x][y-1] == SET) c++; if (universe[x+1][y-1] == SET) c++; if (universe[x-1][y] == SET) c++; if (universe[x+1][y] == SET) c++; if (universe[x-1][y+1] == SET) c++; if (universe[x][y+1] == SET) c++; if (universe[x+1][y+1] == SET) c++; return(c); }