/* LIFE.C The much implemented game of Life invented by John Conway This version was written to illustrate the use of the C88 screen and keyboard interface. Use C option for color display. To generate: A>C88 B:LIFE A>ASM88 B:PCIO A>BIND B:LIFE B:PCIO */ /* global constant and data declarations */ #define ROWS 24 #define COLS 80 /* control key translations */ #define up_char 30 #define down_char 31 #define left_char 29 #define right_char 28 #define bol_char 200 #define eol_char 201 #define pageup_char 202 #define pagedown_char 203 #define bof_char 204 #define eof_char 205 #define Ins_char 206 #define Del_char 207 #define NextWord_char 208 #define PrevWord_char 209 /* function keys */ #define M1 210 #define M2 211 #define M3 212 #define M4 213 #define M5 214 #define M6 215 #define M7 216 #define M8 217 #define M9 218 #define M10 219 char world[ROWS][COLS],create_mode=1,quit_flag; int population,generation,crow,ccol; char color_opt,color; main(argc,argv) int argc; char *argv[]; { if (argc > 1 && toupper(*argv[1]) == 'C') color_opt=1; scr_setup(); scr_clr(); instruct(); setup(); do { generation++; cycle(); screen(); } while (population && !quit_flag); scr_rowcol(ROWS,10); if (population == 0) puts("Nobody left, sorry about that. "); else puts("bye "); scr_curson(); } instruct() { /* print instructions */ puts(" The game of Life by John Conway\n\n"); puts(" Use LIFE C with color monitor.\n"); puts(" If started with a number, a random pattern starts the game.\n\n"); puts(" Otherwise, move the cursor with the four arrow keys to create life.\n\n"); puts(" DEL changes cursor movement to mean that cells are deleted\n\n"); puts(" INS flips back to create mode.\n\n"); puts(" The '+' key will toggle the game on or off.\n\n"); puts(" Hit ESC to bail out.\n\n"); puts(" Enter starting number of cells or hit CR "); } setup() { int rnumber; int i,row,col,seed,rnum; char ch; rnumber=0; while (1) { while ((ch=scr_csts()) == 0) seed++; if (ch < '0' || ch > '9') break; scr_co(ch); rnumber*=10; rnumber+=ch-'0'; } scr_cursoff(); scr_clr(); scr_rowcol(ROWS,20); /* print population message */ puts("Generation 0 Population 0"); srand(seed); /* initilize random number generator */ for (i=0; i < rnumber; i++) { rnum=rand(); row=rnum%ROWS; col=(rnum/ROWS)%COLS; world[row][col]='X'; /* put in a cell */ scr_rowcol(row,col); if (color_opt) scr_aputs("\2",++color | 0X80); else scr_co(2); } if (rnumber == 0) create(1); } screen() { /* update the screen and set world back to x's */ int row,col; char cell; population=0; for (row=0; row < ROWS; row++) { for (col=0; col < COLS; col++) { cell=world[row][col]; /* stay alive if 3 neighbors, born if next to 2 or 3 */ if (cell && (cell == 3 || cell == 'X'+2 || cell == 'X'+3)) { population++; if (cell < 'X') { scr_rowcol(row,col); if (color_opt) scr_aputs("\2",++color | 0X80); else scr_co(2); } cell='X'; } else { if (cell >= 'X') { scr_rowcol(row,col); scr_co(' '); } cell=0; } world[row][col]=cell; } } scr_rowcol(ROWS,31); printf("%4d",generation); scr_rowcol(ROWS,51); printf("%4d",population); } create(suspend) /* see if need to create or kill cells */ char suspend; { char ch,wait; while ((ch=scr_csts()) || suspend) { switch (ch) { case up_char: crow=crow ? crow-1: ROWS-1; break; case down_char: crow=crow == ROWS-1 ? 0: crow+1; break; case left_char: ccol=ccol ? ccol-1: COLS-1; break; case right_char:ccol=ccol == COLS-1 ? 0: ccol+1; break; case bol_char: ccol=0; break; case eol_char: ccol=COLS-1; break; case '+': suspend=!suspend; continue; case Ins_char: create_mode=1; continue; case Del_char: create_mode=0; continue; case 0x1b: quit_flag=1; /* flag for stop */ return; default: continue; } world[crow][ccol]= create_mode ? 'X': 0; scr_rowcol(crow,ccol); if (create_mode) { if (color_opt) scr_aputs("\2",++color | 0X80); else scr_co(2); population++; } else { wait=30; while (wait--) { if (color_opt) scr_aputs("\1",++color | 0X80); else scr_co(1); scr_rowcol(crow,ccol); } scr_co(' '); } } } cycle() { /* cycle to the next generation */ int row,col; create(0); /* take care of left and right column first */ for (row=0; row < ROWS; row++) { if (world[row][0] >= 'X') add8(row,0); if (world[row][COLS-1] >= 'X') add8(row,COLS-1); } /* take care of top and bottom line */ for (col=1; col < COLS-1;col++) { if (world[0][col] >= 'X') add8(0,col); if (world[ROWS-1][col] >= 'X') add8(ROWS-1,col); } /* fill in the box, ignoring border conditions */ for (row=1; row < ROWS-1; row++) { for (col=1; col < COLS-1; col++) { if (world[row][col] >= 'X' ) { world[row-1][col-1]++; world[row-1][col]++; world[row-1][col+1]++; world[row][col-1]++; world[row][col+1]++; world[row+1][col-1]++; world[row+1][col]++; world[row+1][col+1]++; } } } } add8(row,col) int row,col; { int rrow,ccol,rr,cc; for (rr=row-1; rr <= row+1; rr++) { for (cc=col-1; cc <= col+1; cc++) { rrow=rr != -1 ? rr : ROWS-1; ccol=cc != -1 ? cc : COLS-1; if (rrow >= ROWS) rrow=0; if (ccol >= COLS) ccol=0; world[rrow][ccol]++; } } world[row][col]--; }