source: trunk/minix/commands/simple/life.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.6 KB
RevLine 
[9]1/* life - Conway's game of life Author: Jim King */
2
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.
6 *
7 * Flags: -d draw your own screen using arrows and space bar
8 * -p print statistics on the bottom line during the game
9 */
10
11#include <sys/types.h>
12#include <signal.h>
13#include <time.h>
14#include <curses.h>
15#include <stdlib.h>
16#include <unistd.h>
17#include <stdio.h>
18
19#if __minix_vmd /* Use a more random rand(). */
20#define srand(seed) srandom(seed)
21#define rand() random()
22#endif
23
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 */
27
28int present[23][80]; /* screen 1 cycle ago */
29int past[23][80]; /* screen this cycle */
30int total; /* total # of changes */
31int icnt; /* counter to check for repetition */
32int maxrow = 22; /* some defines to represent the screen */
33int maxcol = 79;
34int minrow = 0;
35int mincol = 0;
36int pri = 0; /* flag for printing stats on bottom line */
37int draw = 0; /* flag for drawing your own screen */
38int i, j, k; /* loop counters */
39int cycle; /* current cycle # */
40int changes; /* # of changes this cycle (live + die) */
41int die; /* number of deaths this cycle */
42int live; /* number of births this cycle */
43
44WINDOW *mns; /* Main Screen */
45WINDOW *info; /* Bottom line */
46
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[]));
53
54/* Cleanup - cleanup then exit */
55void cleanup(s)
56int s;
57{
58 move(23, 0); /* go to bottom of screen */
59 refresh(); /* update cursor */
60
61 endwin(); /* shutdown curses */
62 exit(1); /* exit */
63}
64
65/* Initialize - init windows, variables, and signals */
66
67void initialize()
68{
69 srand(getpid()); /* init random seed */
70 initscr(); /* init curses */
71 noecho();
72 curs_set(0);
73 signal(SIGINT, cleanup); /* catch ^C */
74 mns = newwin(maxrow, maxcol, 0, 0); /* new window */
75 scrollok(mns, FALSE);
76 info = newwin(1, 80, 23, 0);
77 scrollok(info, FALSE);
78 wclear(mns);
79 wclear(info);
80 wmove(info, 0, 0);
81 wrefresh(info);
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++;
87 }
88 }
89 }
90}
91
92/* Makscr - make your own screen using arrow keys and space bar */
93void makscr()
94{
95 int curx, cury; /* current point on screen */
96 char c; /* input char */
97
98 wclear(info);
99 wmove(info, 0, 0);
100 wprintw(info, "Use arrow keys to move, space to place / erase, ^D to start", NULL);
101 wrefresh(info);
102 curx = cury = 1;
103 wmove(mns, cury - 1, curx - 1);
104 wrefresh(mns);
105 noecho();
106 for (;;) {
107 c = wgetch(mns);
108 if (c == '\004')
109 break;
110 else if (c == ' ') {
111 if (present[cury][curx]) {
112 --present[cury][curx];
113 changes++;
114 die++;
115 mvwaddch(mns, cury, curx, ' ');
116 } else {
117 ++present[cury][curx];
118 changes++;
119 live++;
120 mvwaddch(mns, cury, curx, '*');
121 }
122 } else if (c == '\033') {
123 wgetch(mns);
124 switch (wgetch(mns)) {
125 case 'A': --cury; break;
126 case 'B': ++cury; break;
127 case 'C': ++curx; break;
128 case 'D': --curx; break;
129 default: break;
130 }
131 }
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);
137 wrefresh(mns);
138 }
139 wclear(info);
140}
141
142/* Update rules: 2 or 3 adjacent alive --- stay alive
143 * 3 adjacent alive -- dead to live
144 * all else die or stay dead
145 */
146void update()
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++) {
152 w = j - 1;
153 x = j + 1;
154 y = k - 1;
155 z = k + 1;
156
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]);
160
161 switch (howmany) {
162 case 0:
163 case 1:
164 case 4:
165 case 5:
166 case 6:
167 case 7:
168 case 8:
169 present[j][k] = 0;
170 if (past[j][k]) changes++, die++;
171 break;
172 case 3:
173 present[j][k] = 1;
174 if (!past[j][k]) changes++, live++;
175 break;
176 default: break;
177 }
178 }
179 }
180 if (live == die)
181 ++icnt;
182 else
183 icnt = 0;
184
185 if (icnt == REPSTOP) cleanup(0);
186}
187
188/* Print - updates the screen according to changes from past to present */
189void print()
190{
191/* Updates the screen, greatly improved using curses */
192 if (pri) {
193 wmove(info, 0, 0);
194 total += changes;
195 cycle++;
196 wprintw(info, "Cycle %5d | %5d changes: %5d died + %5d born = %5u total changes", (char *) cycle, changes, die, live, total);
197 wclrtoeol(info);
198 }
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) {
202 wmove(mns, j, k);
203 wprintw(mns, "*", NULL);
204 } else if (present[j][k] != past[j][k] && present[j][k] == 0) {
205 wmove(mns, j, k);
206 wprintw(mns, " ", NULL);
207 }
208 }
209 }
210 if (pri) wrefresh(info);
211 wrefresh(mns);
212}
213
214/* Main - main procedure */
215int main(ac, av)
216int ac;
217char *av[];
218{
219 if (ac > 1) {
220 for (j = 1; j < ac; j++) {
221 switch (av[j][1]) {
222 case 'd': ++draw; break;
223 case 'p': ++pri; break;
224 default:
225 fprintf(stderr, "%s: usage: %s [-d] [-p]\n", av[0], av[0]);
226 exit(1);
227 }
228 }
229 }
230
231 initialize();
232 if (draw) makscr();
233
234 for (;;) {
235 print();
236 for (j = 0; j < maxrow; j++) {
237 for (k = 0; k < maxcol; k++) past[j][k] = present[j][k];
238 }
239 update();
240 }
241}
Note: See TracBrowser for help on using the repository browser.