14 static struct climate climates[] = {
15 { "Af", "Tropical Rain Forest", 3, 0, { 161,26,20 } },
16 { "Am", "Tropical Monsoon", 45, 0, { 255,33,26 } },
17 { "As", "Dry Savanna", 50, 0, { 255,163,150 } },
18 { "Aw", "Wet Savanna", 125, 0, { 255,205, 199 } },
19 { "Awf", "Wet Savanna forest", 100, 0, { 255,205, 199 } },
20 { "BSh", "Hot Steppe", 12, 0, { 211,139,27 } },
21 { "BSk", "Cold Steppe", 12, 0, { 207,169,81 } },
22 { "BWk", "Cold Desert", 3, 0, { 254,245,91 } },
23 { "BWh", "Hot Desert", 3, 0, { 255,197,13 } },
24 { "Cfa", "Warm Temperate", 125, 0, { 14,43,13 } },
25 { "Cfb", "Maritime", 50, 0, { 21,68,22 } },
26 { "Csa", "Med", 50, 0, { 17,214,16 } },
27 { "Csb", "Med", 50, 0, { 140,230,18 } },
28 { "Cwa", "Warm Termperate", 125, 0, { 184,103,24 } },
29 { "Cwb", "Maritime", 125, 0, { 154,100,25 } },
30 { "Lf", "Lake", 0, 0, { 0,0,245 } },
34 struct alt_climate_search {
38 static int alt_climate_compare(const void *key, const void *climate) {
39 const struct climaterange *v;
40 const struct alt_climate_search *k;
45 if (v->hex > k->hex) return -1; /* later hex */
46 if (v->hex < k->hex) return 1; /* earlier hex */
47 if (v->end < k->year) return 1; /* ends before year */
48 if (v->start > k->year) return -1; /* hasn't started yet */
53 static int compare_cr(const void *av, const void *bv) {
54 const struct climaterange *a, *b;
57 if (a->hex < b->hex) return -1;
58 if (a->hex > b->hex) return 1;
59 if (a->start < b->start) return -1;
60 if (a->start > b->start) return 1;
64 struct climate *find_climate(char *code) {
66 for (i=0; climates[i].code[0]; i++) {
67 if (!strcmp(code, climates[i].code)) {
74 struct afrhex *search_hex(struct afrhex *map, int64_t hex) {
75 for (; map; map = map->next) {
76 printf("checking %lld for %lld\n", map->hex, hex);
77 if (map->hex == hex) {
85 struct afrhex *find_hex(struct afrhex *map, int64_t hex) {
86 for (; map; map = map->next) {
87 if (map->hex == hex) {
94 uint64_t total_pop(struct afrhex *map) {
97 for (; map; map = map->next) {
98 count += map->freq[0];
99 count += map->freq[1];
104 /* set up climate cap */
105 /* base is people per 100 sq km */
106 /* we divide by an additional 4.0 for the small pop model */
107 #define SQRT3 1.73205080756887729352
108 void climate_init(double width, double capfactor) {
112 area = width * width * SQRT3 / 2.0;
113 for (i = 0; climates[i].code[0]; i++) {
114 climates[i].cap = climates[i].basecap * area / 100.0 * capfactor;
120 struct afrhex *map_init(struct maphex *maphexes, double width, double capfactor) {
122 struct afrhex *hex, *prev, *map;
125 climate_init(width, capfactor);
127 for (i=0; maphexes[i].hex; i++) {
128 hex = malloc(sizeof *hex);
129 hex->hex = maphexes[i].hex;
131 for (j=0; j < 2; j++) {
133 hex->outmigrate[j] = 0;
134 hex->inmigrate[j] = 0;
137 hex->climate = find_climate(maphexes[i].climate);
138 hex->map = &maphexes[i];
148 /* pre-compute hex pointers to adjacent hexes */
149 for (hex = map; hex; hex = hex->next) {
150 for (i = 0; i < hex->map->nadj; i++) {
151 hex->map->adjhex[i] = find_hex(map, hex->map->adjacent[i]);
157 struct climaterange *find_alt_climate(int hex, int year) {
158 static int sorted = 0;
159 static size_t nmemb = -1;
160 struct alt_climate_search s;
165 while (altclimates[nmemb].code[0]) nmemb++;
169 qsort(altclimates, nmemb, sizeof(struct climaterange), compare_cr);
176 return bsearch(&s, altclimates, nmemb, sizeof(struct climaterange), alt_climate_compare);
180 //fprintf(stderr, "scanning altclimate %d %d\n", hex, year);
181 for (i=0; altclimates[i].code[0]; i++) {
182 if (altclimates[i].hex == hex && altclimates[i].start <= year && altclimates[i].end >= year) {
183 return &altclimates[i];
190 /* TODO implement change */
191 struct climate *climateyear(struct afrhex *hex, int year) {
192 struct climate *c = 0;
193 struct climaterange *alt;
195 alt = find_alt_climate(hex->hex, year);
198 c = find_climate(alt->code);
200 c = find_climate(hex->map->climate);
203 if (c != hex->climate || hex->hex == 187)
204 fprintf(stderr, "%d got new climate %s in %d\n", hex->hex, c->code, year);
210 #define POP(x) ( ((x[0]) + (x[1])) / 2)
212 void nextgen(struct afrhex *hexlist, int year, unsigned int climate) {
215 for (hex = hexlist; hex; hex = hex->next) {
216 hex->outmigrate[0] = hex->outmigrate[1] = 0;
217 hex->inmigrate[0] = hex->inmigrate[1] = 0;
219 hex->climate = climateyear(hex, year);
223 /* growth and emmigration */
224 for (hex = hexlist; hex; hex = hex->next) {
228 hex->pop = POP(hex->freq);
229 pop = (hex->freq[0] + hex->freq[1])/2;
232 hex->attract = hex->climate->cap;
233 continue; /* nothing else to do here */
237 printf("hex %lld (%s) pop = [%u, %u] (%d/%d ind)\n", hex->hex, hex->climate->code, hex->freq[0], hex->freq[1], hex->pop, hex->climate->cap);
239 /* poisson distribution on births ? */
240 if (pop > hex->climate->cap) {
241 pop *= 0.6; /* should probably round down */
243 pop *= 1.15; /* should probably round up */
246 /* pick pop * 2 since we're diploid */
247 var_rmultinom(pop * 2, hex->freq, new);
248 hex->freq[0] = new[0] ; hex->freq[1] = new[1];
251 /* TODO if too small, say under 25, either move everyone or die */
252 hex->migrants = hex->pop - hex->climate->cap;
254 hex->migrants = hex->pop;
256 if (hex->migrants > 0) {
257 var_rhyperv(hex->migrants * 2, hex->freq, hex->outmigrate);
258 /* TODO could just set it to a quarter of the cap or something */
261 printf("hex %lld new pop = [%u, %u] (%d ind) (-%u,-%u) (+%u,+%u)\n",
262 hex->hex, hex->freq[0], hex->freq[1], hex->pop,
263 hex->outmigrate[0], hex->outmigrate[1],
264 hex->inmigrate[0], hex->inmigrate[1]
268 hex->attract = (int)sqrt((double)hex->climate->cap);
269 if (hex->attract < hex->climate->cap - hex->pop) {
270 hex->attract = hex->climate->cap - hex->pop;
274 /* now handle immigration */
275 for (hex = hexlist; hex; hex = hex->next) {
276 unsigned int attr[18];
279 struct afrhex *target;
281 if (hex->migrants <= 0) continue;
282 /* gather attractiveness of migration targets */
284 printf("hex %lld migrating: ( ", hex->hex);
286 for (i = 0; i < hex->map->nadj; i++) {
287 attr[i] = hex->map->adjhex[i]->attract;
290 printf("%lld:%u ", hex->map->adjhex[i]->hex, attr[i]);
297 /* no where to go ? */
299 hex->outmigrate[0] = 0;
300 hex->outmigrate[1] = 0;
305 i = var_pick(i, attr);
307 printf("choose %d = %lld\n", i+1, hex->map->adjhex[i]->hex);
309 target = hex->map->adjhex[i];
310 target->inmigrate[0] += hex->outmigrate[0];
311 target->inmigrate[1] += hex->outmigrate[1];
314 /* and finally sum up population so we're ready for the next generation */
315 for (hex = hexlist; hex; hex = hex->next) {
316 hex->freq[0] += hex->inmigrate[0];
317 hex->freq[1] += hex->inmigrate[1];
318 hex->freq[0] -= hex->outmigrate[0];
319 hex->freq[1] -= hex->outmigrate[1];
320 hex->pop = (hex->freq[0] + hex->freq[1])/2;
323 printf("hex %lld new pop = [%u, %u] (%d/%u ind) (-%u,-%u) (+%u,+%u)\n",
324 hex->hex, hex->freq[0], hex->freq[1], hex->pop, hex->climate->cap,
325 hex->outmigrate[0], hex->outmigrate[1],
326 hex->inmigrate[0], hex->inmigrate[1]