1 /* life - Conway's game of life Author: Jim King */
3 /* clife.c - curses life simulator. Translated from Pascal to C implementing
4 * curses Oct 1988 by pulsar@lsrhs, not jek5036@ritvax.isc.rit.edu
5 * life needs about 18kb stack space on MINIX.
7 * Flags: -d draw your own screen using arrows and space bar
8 * -p print statistics on the bottom line during the game
11 #include <sys/types.h>
19 #if __minix_vmd /* Use a more random rand(). */
20 #define srand(seed) srandom(seed)
21 #define rand() random()
24 /* A value of -1 will make it go forever */
25 /* A value of 0 will make it exit immediately */
26 #define REPSTOP -1 /* number of repetitions before stop */
28 int present
[23][80]; /* screen 1 cycle ago */
29 int past
[23][80]; /* screen this cycle */
30 int total
; /* total # of changes */
31 int icnt
; /* counter to check for repetition */
32 int maxrow
= 22; /* some defines to represent the screen */
36 int pri
= 0; /* flag for printing stats on bottom line */
37 int draw
= 0; /* flag for drawing your own screen */
38 int i
, j
, k
; /* loop counters */
39 int cycle
; /* current cycle # */
40 int changes
; /* # of changes this cycle (live + die) */
41 int die
; /* number of deaths this cycle */
42 int live
; /* number of births this cycle */
44 WINDOW
*mns
; /* Main Screen */
45 WINDOW
*info
; /* Bottom line */
47 _PROTOTYPE(void cleanup
, (int s
));
48 _PROTOTYPE(void initialize
, (void));
49 _PROTOTYPE(void makscr
, (void));
50 _PROTOTYPE(void update
, (void));
51 _PROTOTYPE(void print
, (void));
52 _PROTOTYPE(int main
, (int ac
, char *av
[]));
54 /* Cleanup - cleanup then exit */
58 move(23, 0); /* go to bottom of screen */
59 refresh(); /* update cursor */
61 endwin(); /* shutdown curses */
65 /* Initialize - init windows, variables, and signals */
69 srand(getpid()); /* init random seed */
70 initscr(); /* init curses */
73 signal(SIGINT
, cleanup
); /* catch ^C */
74 mns
= newwin(maxrow
, maxcol
, 0, 0); /* new window */
76 info
= newwin(1, 80, 23, 0);
77 scrollok(info
, FALSE
);
82 if (!draw
) { /* if no draw, make random pattern */
83 for (j
= 0; j
< maxrow
; j
++) {
84 for (k
= 0; k
< maxcol
; k
++) {
85 present
[j
][k
] = rand() % 2;
86 if (present
[j
][k
] == 1) changes
++, live
++;
92 /* Makscr - make your own screen using arrow keys and space bar */
95 int curx
, cury
; /* current point on screen */
96 char c
; /* input char */
100 wprintw(info
, "Use arrow keys to move, space to place / erase, ^D to start", NULL
);
103 wmove(mns
, cury
- 1, curx
- 1);
111 if (present
[cury
][curx
]) {
112 --present
[cury
][curx
];
115 mvwaddch(mns
, cury
, curx
, ' ');
117 ++present
[cury
][curx
];
120 mvwaddch(mns
, cury
, curx
, '*');
122 } else if (c
== '\033') {
124 switch (wgetch(mns
)) {
125 case 'A': --cury
; break;
126 case 'B': ++cury
; break;
127 case 'C': ++curx
; break;
128 case 'D': --curx
; break;
132 if (cury
> maxrow
) cury
= minrow
;
133 if (cury
< minrow
) cury
= maxrow
;
134 if (curx
> maxcol
) curx
= mincol
;
135 if (curx
< mincol
) curx
= maxcol
;
136 wmove(mns
, cury
, curx
);
142 /* Update rules: 2 or 3 adjacent alive --- stay alive
143 * 3 adjacent alive -- dead to live
144 * all else die or stay dead
147 { /* Does all mathmatical calculations */
148 int howmany
, w
, x
, y
, z
;
149 changes
= die
= live
= 0;
150 for (j
= 0; j
< maxrow
; j
++) {
151 for (k
= 0; k
< maxcol
; k
++) {
157 howmany
= (past
[w
][y
] + past
[w
][k
] + past
[w
][z
] +
158 past
[j
][y
] + past
[j
][z
] + past
[x
][y
] +
159 past
[x
][k
] + past
[x
][z
]);
170 if (past
[j
][k
]) changes
++, die
++;
174 if (!past
[j
][k
]) changes
++, live
++;
185 if (icnt
== REPSTOP
) cleanup(0);
188 /* Print - updates the screen according to changes from past to present */
191 /* Updates the screen, greatly improved using curses */
196 wprintw(info
, "Cycle %5d | %5d changes: %5d died + %5d born = %5u total changes", (char *) cycle
, changes
, die
, live
, total
);
199 for (j
= 1; j
< maxrow
; j
++) {
200 for (k
= 1; k
< maxcol
; k
++) {
201 if (present
[j
][k
] != past
[j
][k
] && present
[j
][k
] == 1) {
203 wprintw(mns
, "*", NULL
);
204 } else if (present
[j
][k
] != past
[j
][k
] && present
[j
][k
] == 0) {
206 wprintw(mns
, " ", NULL
);
210 if (pri
) wrefresh(info
);
214 /* Main - main procedure */
220 for (j
= 1; j
< ac
; j
++) {
222 case 'd': ++draw
; break;
223 case 'p': ++pri
; break;
225 fprintf(stderr
, "%s: usage: %s [-d] [-p]\n", av
[0], av
[0]);
236 for (j
= 0; j
< maxrow
; j
++) {
237 for (k
= 0; k
< maxcol
; k
++) past
[j
][k
] = present
[j
][k
];