pci: don't do sanity check for missing pci bus, the check can misfire.
[minix.git] / commands / simple / life.c
blob31bfbcd922fc6f8846893c9119f9e4d71a17d7ae
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
9 */
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>
19 #if __minix_vmd /* Use a more random rand(). */
20 #define srand(seed) srandom(seed)
21 #define rand() random()
22 #endif
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 */
33 int maxcol = 79;
34 int minrow = 0;
35 int mincol = 0;
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 */
55 void cleanup(s)
56 int s;
58 move(23, 0); /* go to bottom of screen */
59 refresh(); /* update cursor */
61 endwin(); /* shutdown curses */
62 exit(1); /* exit */
65 /* Initialize - init windows, variables, and signals */
67 void initialize()
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++;
92 /* Makscr - make your own screen using arrow keys and space bar */
93 void makscr()
95 int curx, cury; /* current point on screen */
96 char c; /* input char */
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, '*');
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;
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);
139 wclear(info);
142 /* Update rules: 2 or 3 adjacent alive --- stay alive
143 * 3 adjacent alive -- dead to live
144 * all else die or stay dead
146 void 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;
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]);
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;
180 if (live == die)
181 ++icnt;
182 else
183 icnt = 0;
185 if (icnt == REPSTOP) cleanup(0);
188 /* Print - updates the screen according to changes from past to present */
189 void print()
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);
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);
210 if (pri) wrefresh(info);
211 wrefresh(mns);
214 /* Main - main procedure */
215 int main(ac, av)
216 int ac;
217 char *av[];
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);
231 initialize();
232 if (draw) makscr();
234 for (;;) {
235 print();
236 for (j = 0; j < maxrow; j++) {
237 for (k = 0; k < maxcol; k++) past[j][k] = present[j][k];
239 update();