1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
/*
* Copyright (c) 2021 Ben Fuller
*/
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include "cgol.h"
#ifndef __TEST
#define NROWS 20
#define NCOLS 20
#else
#define NROWS 10
#define NCOLS 10
#endif
/* check errno and the result of ato* for an error */
void
check(int res) {
if (res == 0 && errno != 0) {
fprintf(stderr, "bad argument\n");
fprintf(stderr, "usage: cgol [width height [gens]]\nthe defaults are \"800\" \"600\" \"200\"\n");
exit(1);
}
errno = 0;
}
int
main(int argc, char **argv) {
int c;
double width, height;
int gens;
int check_births = 0;
while ((c = getopt(argc, argv, "hw:l:g:")) != -1) {
switch (c) {
case 'h':
fprintf(stderr, "usage: %s [ -w width -l height -g gens]\nthe defaults are \"-w 800 -l 600 -g 200\"\n", *argv);
return 1;
case 'w':
errno = 0;
width = atof(optarg);
check(width);
break;
case 'l':
errno = 0;
height = atof(optarg);
check(height);
break;
}
}
argc -= optind;
argv += optind - 1;
if (argc > 2) {
errno = 0;
width = atof(*++argv);
check(width);
height = atof(*++argv);
check(height);
if (argc > 3) {
gens = atoi(*++argv);
check(gens);
if (gens == 0) {
gens = 999999;
check_births = 1;
}
if (gens < 1 || gens > 999999) {
/* the upper limit is to ensure the gen number fits onto the
* image filenames */
fprintf(stderr, "bad gens arg\n");
return 1;
}
} else
gens = 200;
} else {
width = 800;
height = 600;
gens = 200;
}
struct imgdata img = {
width, height,
NROWS, NCOLS,
{ 1, 1, 1, },
{ 0.1, 0.1, 0.1 },
{ 0, 0, 0 }
};
#ifndef __TEST
short cells[NROWS][NCOLS] = { 0 };
randomize(&cells[0][0], NCOLS, NROWS);
#else
short cells[NROWS][NCOLS] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 0, 0, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
#endif
int gen, n_alive;
char *fn = malloc(12 + 6);
int n_alive1, n_alive2, n_alive3;
n_alive3 = n_alive2 = n_alive1 = 0;
for (gen = 0; gen < gens; gen++) {
#ifdef __TEST
printf("==> GEN %d <==\r", gen);
#endif
/* %06d because gens <= 999999 */
sprintf(fn, "images/%06d.png", gen);
if (png(&img, &cells[0][0], fn) != 0) {
free(fn);
return 1;
}
n_alive = evolve(&cells[0][0], NCOLS, NROWS);
if (check_births) {
if (n_alive == n_alive1 && n_alive == n_alive2 && n_alive == n_alive3)
break;
n_alive3 = n_alive2;
n_alive2 = n_alive1;
n_alive1 = n_alive;
}
#ifndef __TEST
printf("%d\n", n_alive);
#endif
}
free(fn);
#ifdef __TEST
puts("");
#endif
return 0;
}
void
randomize(short *cells, int nx, int ny) {
srand(time(NULL));
int i, j;
for (i = 0; i < ny; i++)
for (j = 0; j < nx; j++)
*(cells + i * nx + j) = rand() % 2 ? 1 : 0;
}
|