]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
Encapsulate direct use of random(), srandom() in chance.c
[empserver] / src / util / fairland.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2013, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  fairland.c: Create a nice, new world
28  *
29  *  Known contributors to this file:
30  *     Ken Stevens, 1995
31  *     Steve McClure, 1998
32  *     Markus Armbruster, 2004-2012
33  */
34
35 #include <config.h>
36
37 /* define ORE 1 to add resources, define ORE 0 if you want to use another
38    program to add the resources */
39 static int ORE = 1;
40 static int quiet = 0;
41
42 /* If you don't specify these command line arguments, then these are the
43    defaults */
44 #define DEFAULT_SPIKE 10
45 #define DEFAULT_MOUNTAIN 0
46 #define DEFAULT_CONTDIST 2
47 #define DEFAULT_ISLDIST 1
48
49 /* The following five numbers refer to elevation under which (in the case of
50    fertility or oil) or over which (in the case of iron, gold, and uranium)
51    sectors with that elevation will contain that resource.  Elevation ranges
52    from 0 to 100 */
53
54 /* raise FERT_MAX for more fertility */
55 #define FERT_MAX   56
56
57 /* raise OIL_MAX for more oil */
58 #define OIL_MAX    33
59
60 /* lower IRON_MIN for more iron */
61 #define IRON_MIN   22
62
63 /* lower GOLD_MIN for more gold */
64 #define GOLD_MIN   36
65
66 /* lower URAN_MIN for more uranium */
67 #define URAN_MIN   56
68
69 #include <assert.h>
70 #include <errno.h>
71 #include <stdarg.h>
72 #include <stdio.h>
73 #include <unistd.h>
74 #include "chance.h"
75 #include "file.h"
76 #include "optlist.h"
77 #include "prototypes.h"
78 #include "sect.h"
79 #include "version.h"
80 #include "xy.h"
81
82 /* do not change these 4 defines */
83 #define LANDMIN         1       /* plate altitude for normal land */
84 #define HILLMIN         34      /* plate altitude for hills */
85 #define PLATMIN         36      /* plate altitude for plateau */
86 #define HIGHMIN         98      /* plate altitude for mountains */
87
88 static void qprint(const char * const fmt, ...)
89     ATTRIBUTE((format (printf, 1, 2)));
90
91 #define DEFAULT_OUTFILE_NAME "newcap_script"
92 static const char *outfile = DEFAULT_OUTFILE_NAME;
93 /* mark the continents with a * so you can tell them
94    from the islands 1 = mark, 0 = don't mark. */
95 static int AIRPORT_MARKER = 0;
96
97 /* don't let the islands crash into each other.
98    1 = don't merge, 0 = merge. */
99 static int DISTINCT_ISLANDS = 1;
100
101 static char *program_name;
102
103 #define STABLE_CYCLE 4          /* stability required for perterbed capitals */
104 #define INFINITY        999     /* a number which means "BIG" */
105
106 /* these defines prevent infinite loops:
107 */
108
109 #define COAST_SEARCH_MAX 200    /* how many times do we look for a coast sector
110                                    when growing continents and islands */
111 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
112 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
113 #define MOUNTAIN_SEARCH_MAX 1000        /* how long do we try to place mountains */
114
115 /* handy macros:
116 */
117
118 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
119 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
120 #define rnd(x) roll0((x))
121
122 static int secs;                /* number of sectors grown */
123 static int ctot;                /* total number of continents and islands grown */
124 static int *isecs;              /* array of how large each island is */
125
126 static int nc, sc, di, sp, pm, ni, is, id; /* the 8 args to this program */
127 static unsigned long rnd_seed;  /* optional seed argument */
128 static int *capx, *capy;        /* location of the nc capitals */
129 static int *mc, mcc;            /* array and counter used for stability
130                                    check when perturbing */
131 static int spike;               /* are we spiking? */
132 static int mind;                /* the final distance between capitals that
133                                    we achieved */
134 static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
135 static int diry[] = { 0, -1, -1, 0, 1, 1 };
136
137 static int **own;               /* owner of the sector.  -1 means water */
138 static int **elev;              /* elevation of the sectors */
139 static int **sectx, **secty;    /* the sectors for each continent */
140 static int **sectc;             /* which sectors are on the coast? */
141 static int *vector;             /* used for measuring distances */
142 static int *weight;             /* used for placing mountains */
143 static int *dsea, *dmoun;       /* the dist to the ocean and mountain */
144 static int fl_status;           /* is anything wrong? */
145 #define STATUS_NO_ROOM 1        /* there was no room to grow */
146 #define NUMTRIES 10             /* keep trying to grow this many times */
147
148 static const char *numletter =
149     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
150
151 static void help(char *);
152 static void usage(void);
153 static void parse_args(int argc, char *argv[]);
154 static void allocate_memory(void);
155 static void init(void);
156 static int drift(void);
157 static void grow_continents(void);
158 static void create_elevations(void);
159 static void write_sects(void);
160 static void output(void);
161 static int write_newcap_script(void);
162 static int stable(void);
163 static void elevate_land(void);
164 static void elevate_sea(void);
165 static int map_symbol(int x, int y);
166 static void set_coastal_flags(void);
167
168 static void print_vars(void);
169 static void fl_move(int);
170 static void next_coast(int c, int x, int y, int *xp, int *yp);
171 static void grow_islands(void);
172
173 /****************************************************************************
174   MAIN
175 ****************************************************************************/
176
177 int
178 main(int argc, char *argv[])
179 {
180     int opt;
181     char *config_file = NULL;
182     int i = 0;
183
184     program_name = argv[0];
185     rnd_seed = time(NULL);
186
187     while ((opt = getopt(argc, argv, "ae:hioqR:s:v")) != EOF) {
188         switch (opt) {
189         case 'a':
190             AIRPORT_MARKER = 1;
191             break;
192         case 'e':
193             config_file = optarg;
194             break;
195         case 'i':
196             DISTINCT_ISLANDS = 0;
197             break;
198         case 'o':
199             ORE = 0;
200             break;
201         case 'q':
202             quiet = 1;
203             break;
204         case 'R':
205             rnd_seed = strtoul(optarg, NULL, 10);
206             break;
207         case 's':
208             outfile = optarg;
209             break;
210         case 'h':
211             usage();
212             exit(0);
213         case 'v':
214             printf("%s\n\n%s", version, legal);
215             exit(0);
216         default:
217             help(NULL);
218             exit(1);
219         }
220     }
221     parse_args(argc - optind, argv + optind);
222
223     seed_prng(rnd_seed);
224     empfile_init();
225     if (emp_config(config_file) < 0)
226         exit(1);
227     empfile_fixup();
228
229     allocate_memory();
230     print_vars();
231
232     do {
233         init();
234         if (i)
235             qprint("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
236         qprint("\n\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
237         qprint("seed is %lu\n", rnd_seed);
238         qprint("placing capitals...\n");
239         if (!drift())
240             qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
241         qprint("growing continents...\n");
242         grow_continents();
243     } while (fl_status && ++i < NUMTRIES);
244     if (fl_status) {
245         fputs("ERROR: World not large enough to hold continents\n",
246               stderr);
247         exit(1);
248     }
249     qprint("growing islands:");
250     grow_islands();
251     qprint("\nelevating land...\n");
252     create_elevations();
253     qprint("designating sectors...\n");
254     if (ORE)
255         qprint("adding resources...\n");
256     write_newcap_script();
257
258     if (chdir(gamedir)) {
259         fprintf(stderr, "Can't chdir to %s (%s)\n", gamedir, strerror(errno));
260         exit(EXIT_FAILURE);
261     }
262     if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
263         exit(1);
264     write_sects();
265     qprint("writing to sectors file...\n");
266     if (!ef_close(EF_SECTOR))
267         exit(1);
268
269     output();
270     qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
271            outfile);
272     if (!ORE)
273         qprint("\t*** Resources have not been added ***\n");
274     exit(0);
275 }
276
277 static void
278 print_vars(void)
279 {
280     if (quiet)
281         return;
282     puts("Creating a planet with:\n");
283     printf("%d continents\n", nc);
284     printf("continent size: %d\n", sc);
285     printf("number of islands: %d\n", ni);
286     printf("average size of islands: %d\n", is);
287     printf("spike: %d%%\n", sp);
288     printf("%d%% of land is mountain (each continent will have %d mountains)\n",
289            pm, (pm * sc) / 100);
290     printf("minimum distance between continents: %d\n", di);
291     printf("minimum distance from islands to continents: %d\n", id);
292     printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
293 }
294
295 static int
296 my_sqrt(int n)
297 {
298     int i;
299
300     for (i = 1; i * i < n * 10000; ++i) ;
301     return (i + 50) / 100;
302 }
303
304 /****************************************************************************
305   PARSE COMMAND LINE ARGUMENTS
306 ****************************************************************************/
307
308 static void
309 help(char *complaint)
310 {
311     if (complaint)
312         fprintf(stderr, "%s: %s\n", program_name, complaint);
313     fprintf(stderr, "Try -h for help.\n");
314 }
315
316 static void
317 usage(void)
318 {
319     printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
320            "  -a              airport marker for continents\n"
321            "  -e CONFIG-FILE  configuration file\n"
322            "                  (default %s)\n"
323            "  -h              display this help and exit\n"
324            "  -i              islands may merge\n"
325            "  -o              don't set resources\n"
326            "  -q              quiet\n"
327            "  -R SEED         seed for random number generator\n"
328            "  -s SCRIPT       name of script to create (default %s)\n"
329            "  NC              number of continents\n"
330            "  SC              continent size\n"
331            "  NI              number of islands (default NC)\n"
332            "  IS              average island size (default SC/2)\n"
333            "  SP              spike percentage: 0 = round, 100 = snake (default %d)\n"
334            "  PM              percentage of land that is mountain (default %d)\n"
335            "  DI              minimum distance between continents (default %d)\n"
336            "  ID              minimum distance from islands to continents (default %d)\n",
337            program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
338            DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
339 }
340
341 static void
342 parse_args(int argc, char *argv[])
343 {
344     if (argc < 2) {
345         help("missing arguments");
346         exit(1);
347     }
348     if (argc > 8) {
349         help("too many arguments");
350         exit(1);
351     }
352     nc = atoi(argv[0]);
353     if (nc < 1) {
354         puts("fairland: error -- number of continents must be > 0");
355         exit(1);
356     }
357
358     sc = atoi(argv[1]);
359     if (sc < 1) {
360         puts("fairland: error -- size of continents must be > 0");
361         exit(1);
362     }
363
364     if (argc > 2)
365         ni = atoi(argv[2]);
366     else
367         ni = nc;
368
369     if (argc > 3)
370         is = atoi(argv[3]);
371     else
372         is = sc / 2;
373     if (is < 1)
374         is = 1;
375
376     if (argc > 4)
377         sp = atoi(argv[4]);
378     else
379         sp = DEFAULT_SPIKE;
380     if (sp < 0)
381         sp = 0;
382     if (sp > 100)
383         sp = 100;
384
385     if (argc > 5)
386         pm = atoi(argv[5]);
387     else
388         pm = DEFAULT_MOUNTAIN;
389     if (pm < 0)
390         pm = 0;
391
392     if (argc > 6)
393         di = atoi(argv[6]);
394     else
395         di = DEFAULT_CONTDIST;
396
397     if (di < 0) {
398         puts("fairland: error -- distance between continents must be >= 0");
399         exit(1);
400     }
401     if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
402         puts("fairland: error -- distance between continents too large");
403         exit(1);
404     }
405
406     if (argc > 7)
407         id = atoi(argv[7]);
408     else
409         id = DEFAULT_ISLDIST;
410     if (id < 0) {
411         puts("fairland: error -- distance from islands to continents must be >= 0");
412         exit(1);
413     }
414     if (id > WORLD_X || id > WORLD_Y) {
415         puts("fairland: error -- distance from islands to continents too large");
416         exit(1);
417     }
418     if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
419         puts("fairland: warning -- world might be too small to fit continents.");
420         puts("arguments should satisfy:");
421         puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
422     }
423 }
424
425 /****************************************************************************
426   VARIABLE INITIALIZATION
427 ****************************************************************************/
428
429 static void
430 allocate_memory(void)
431 {
432     int i;
433
434     capx = calloc(nc, sizeof(int));
435     capy = calloc(nc, sizeof(int));
436     vector = calloc(WORLD_X + WORLD_Y, sizeof(int));
437     mc = calloc(STABLE_CYCLE, sizeof(int));
438     own = calloc(WORLD_X, sizeof(int *));
439     elev = calloc(WORLD_X, sizeof(int *));
440     for (i = 0; i < WORLD_X; ++i) {
441         own[i] = calloc(WORLD_Y, sizeof(int));
442         elev[i] = calloc(WORLD_Y, sizeof(int));
443     }
444     sectx = calloc(nc + ni, sizeof(int *));
445     secty = calloc(nc + ni, sizeof(int *));
446     sectc = calloc(nc + ni, sizeof(int *));
447     isecs = calloc(nc + ni, sizeof(int));
448     weight = calloc(MAX(sc, is * 2), sizeof(int));
449     dsea = calloc(MAX(sc, is * 2), sizeof(int));
450     dmoun = calloc(MAX(sc, is * 2), sizeof(int));
451     for (i = 0; i < nc; ++i) {
452         sectx[i] = calloc(sc, sizeof(int));
453         secty[i] = calloc(sc, sizeof(int));
454         sectc[i] = calloc(sc, sizeof(int));
455     }
456     for (i = nc; i < nc + ni; ++i) {
457         sectx[i] = calloc(is * 2, sizeof(int));
458         secty[i] = calloc(is * 2, sizeof(int));
459         sectc[i] = calloc(is * 2, sizeof(int));
460     }
461
462 }
463
464 static void
465 init(void)
466 {
467     int i, j, xx = 0, yy = 0;
468
469     mcc = 0;
470     fl_status = 0;
471
472     for (i = 0; i < WORLD_X; ++i) {
473         for (j = 0; j < WORLD_Y; ++j) {
474             own[i][j] = -1;
475             elev[i][j] = -INFINITY;
476         }
477     }
478
479     for (i = 0; i < nc; ++i) {
480         if (xx >= WORLD_X) {
481             ++yy;
482             xx = yy % 2;
483             if (yy == WORLD_Y) {
484                 puts("fairland error: world not big enough for all the continents.\n");
485                 exit(1);
486             }
487         }
488         capx[i] = xx;
489         capy[i] = yy;
490         xx += 2;
491     }
492     for (i = 0; i < STABLE_CYCLE; ++i)
493         mc[i] = i;
494 }
495
496 /****************************************************************************
497   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
498 ****************************************************************************/
499
500 /* How isolated is capital j?
501 */
502 static int
503 iso(int j, int newx, int newy)
504 {
505     int i, md, d = WORLD_X + WORLD_Y;
506
507     for (i = 0; i < nc; ++i) {
508         if (i == j)
509             continue;
510         md = mapdist(capx[i], capy[i], newx, newy);
511         if (md < d)
512             d = md;
513     }
514
515     return d;
516 }
517
518 /* Drift all the capitals
519 */
520 static int
521 drift(void)
522 {
523     int i, turns;
524
525     for (turns = 0; turns < DRIFT_MAX; ++turns) {
526         if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
527             return 1;
528         for (i = 0; i < nc; ++i)
529             fl_move(i);
530     }
531     return 0;
532 }
533
534 /* Check to see if we have stabilized--can we stop drifting the capitals?
535 */
536
537 static int
538 stable(void)
539 {
540     int i, isod, d = 0, stab = 1;
541
542     for (i = 0; i < nc; ++i) {
543         isod = iso(i, capx[i], capy[i]);
544         if (isod > d)
545             d = isod;
546     }
547     for (i = 0; i < STABLE_CYCLE; ++i)
548         if (d != mc[i])
549             stab = 0;
550     mc[mcc] = d;
551     mcc = (mcc + 1) % STABLE_CYCLE;
552     return stab ? d : 0;
553 }
554
555 /* This routine does the actual drifting
556 */
557
558 static void
559 fl_move(int j)
560 {
561     int i, n, newx, newy;
562
563     for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
564         newx = new_x(capx[j] + dirx[i]);
565         newy = new_y(capy[j] + diry[i]);
566         if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
567             capx[j] = newx;
568             capy[j] = newy;
569             return;
570         }
571     }
572 }
573
574 /****************************************************************************
575   GROW THE CONTINENTS
576 ****************************************************************************/
577
578 /* Look for a coastal sector of continent c
579 */
580
581 static void
582 find_coast(int c)
583 {
584     int i, j;
585
586     for (i = 0; i < secs; ++i) {
587         sectc[c][i] = 0;
588         for (j = 0; j < 6; ++j)
589             if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
590                 sectc[c][i] = 1;
591     }
592 }
593
594 /* Used for measuring distances
595 */
596 static int
597 next_vector(int n)
598 {
599     int i;
600
601     if (n == 1) {
602         vector[0] += 1;
603         vector[0] %= 6;
604         return vector[0];
605     }
606     for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
607     vector[i - 1] += 1;
608     vector[i - 1] %= 6;
609     return i > 1 || vector[0] > 0;
610 }
611
612 /* Test to see if we're allowed to grow there: the arguments di and id
613 */
614 static int
615 try_to_grow(int c, int newx, int newy, int d)
616 {
617     int i, j, px, py;
618
619     for (i = 1; i <= d; ++i) {
620         for (j = 0; j < i; ++j)
621             vector[j] = 0;
622         do {
623             px = newx;
624             py = newy;
625             for (j = 0; j < i; ++j) {
626                 px = new_x(px + dirx[vector[j]]);
627                 py = new_y(py + diry[vector[j]]);
628             }
629             if (own[px][py] != -1 &&
630                 own[px][py] != c &&
631                 (DISTINCT_ISLANDS || own[px][py] < nc))
632                 return 0;
633         } while (next_vector(i));
634     }
635     sectx[c][secs] = newx;
636     secty[c][secs] = newy;
637     own[newx][newy] = c;
638     return 1;
639 }
640
641 /* Move along the coast in a clockwise direction.
642 */
643
644 static void
645 next_coast(int c, int x, int y, int *xp, int *yp)
646 {
647     int i, nx, ny, wat = 0;
648
649     if (secs == 1) {
650         *xp = x;
651         *yp = y;
652         return;
653     }
654
655     for (i = 0; i < 12; ++i) {
656         nx = new_x(x + dirx[i % 6]);
657         ny = new_y(y + diry[i % 6]);
658         if (own[nx][ny] == -1)
659             wat = 1;
660         if (wat && own[nx][ny] == c) {
661             *xp = nx;
662             *yp = ny;
663             return;
664         }
665     }
666 }
667
668 /* Choose a sector to grow from
669 */
670
671 static int
672 new_try(int c)
673 {
674     int i, starti;
675
676     if (secs == 1) {
677         if (sectc[c][0])
678             return 0;
679     } else {
680         i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
681         do {
682             if (sectc[c][i])
683                 return i;
684             i = (i + 1) % secs;
685         } while (i != starti);
686         assert(c >= nc);
687         return -1;
688     }
689     return -1;
690 }
691
692 /* Grow continent c by 1 sector
693 */
694
695 static int
696 grow_one_sector(int c)
697 {
698     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
699
700     spike = rnd(100) < sp;
701     if ((try1 = new_try(c)) == -1)
702         return 0;
703     x = sx = sectx[c][try1];
704     y = sy = secty[c][try1];
705     coast_search = 0;
706     done = 0;
707     do {
708         if (spike) {
709             for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
710                 newx = new_x(x + dirx[i]);
711                 newy = new_y(y + diry[i]);
712                 if (own[newx][newy] == -1 &&
713                     (n > 5 ||
714                      (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
715                       own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
716                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
717                         done = 1;
718             }
719         } else
720             for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
721                 newx = new_x(x + dirx[i]);
722                 newy = new_y(y + diry[i]);
723                 if (own[newx][newy] == -1)
724                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
725                         done = 1;
726             }
727         next_coast(c, x, y, &x, &y);
728         ++coast_search;
729     } while (!done && coast_search < COAST_SEARCH_MAX &&
730              (secs == 1 || x != sx || y != sy));
731     if (!done && c < nc) {
732         qprint("fairland: error -- continent %c had no room to grow!\n",
733                numletter[c % 62]);
734         fl_status |= STATUS_NO_ROOM;
735     }
736     return done;
737 }
738
739 /* Grow all the continents
740 */
741 static void
742 grow_continents(void)
743 {
744     int c;
745
746     for (c = 0; c < nc; ++c) {
747         sectx[c][0] = capx[c];
748         secty[c][0] = capy[c];
749         own[sectx[c][0]][secty[c][0]] = c;
750         sectx[c][1] = new_x(capx[c] + 2);
751         secty[c][1] = capy[c];
752         own[sectx[c][1]][secty[c][1]] = c;
753     }
754
755     for (secs = 2; secs < sc && !fl_status; ++secs) {
756         for (c = 0; c < nc; ++c) {
757             find_coast(c);
758             grow_one_sector(c);
759         }
760     }
761     for (c = 0; c < nc; ++c)
762         find_coast(c);
763
764     if (fl_status)
765         qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
766     ctot = nc;
767 }
768
769 /****************************************************************************
770   GROW THE ISLANDS
771 ****************************************************************************/
772
773 /* Choose a place to start growing an island from
774 */
775 static int
776 place_island(int c, int *xp, int *yp)
777 {
778     int d, sx, sy;
779     int ssy = rnd(WORLD_Y);
780     int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
781
782     if (ssx > WORLD_X - 2)
783         ssx = new_x(ssx + 2);
784     for (d = di + id; d >= id; --d) {
785         sx = ssx;
786         sy = ssy;
787         *xp = new_x(sx + 2);
788         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
789             if (*xp >= WORLD_X) {
790                 *yp = new_y(*yp + 1);
791                 *xp = *yp % 2;
792                 if (*xp == sx && *yp == sy)
793                     break;
794             }
795             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
796                 return 1;
797         }
798     }
799     return 0;
800 }
801
802 /* Grow all the islands
803 */
804
805 static void
806 grow_islands(void)
807 {
808     int c, x, y, isiz;
809
810     for (c = nc; c < nc + ni; ++c) {
811         secs = 0;
812         if (!place_island(c, &x, &y))
813             return;
814         isiz = 1 + rnd(2 * is - 1);
815         do {
816             ++secs;
817             find_coast(c);
818         } while (secs < isiz && grow_one_sector(c));
819         find_coast(c);
820         qprint(" %d(%d)", c - nc + 1, secs);
821         isecs[c] = secs;
822         ctot++;
823     }
824 }
825
826 /****************************************************************************
827   CREATE ELEVATIONS
828 ****************************************************************************/
829 static void
830 create_elevations(void)
831 {
832     elevate_land();
833     elevate_sea();
834 }
835
836 /* Generic function for finding the distance to the closest sea, land, or
837    mountain
838 */
839 static int
840 distance_to_what(int x, int y, int flag)
841 {
842     int j, d, px, py;
843
844     for (d = 1; d < 5; ++d) {
845         for (j = 0; j < d; ++j)
846             vector[j] = 0;
847         do {
848             px = x;
849             py = y;
850             for (j = 0; j < d; ++j) {
851                 px = new_x(px + dirx[vector[j]]);
852                 py = new_y(py + diry[vector[j]]);
853             }
854             switch (flag) {
855             case 0:             /* distance to sea */
856                 if (own[px][py] == -1)
857                     return d;
858                 break;
859             case 1:             /* distance to land */
860                 if (own[px][py] != -1)
861                     return d;
862                 break;
863             case 2:             /* distance to mountain */
864                 if (elev[px][py] == INFINITY)
865                     return d;
866                 break;
867             }
868         } while (next_vector(d));
869     }
870     return d;
871 }
872
873 #define ELEV elev[sectx[c][i]][secty[c][i]]
874 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
875 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
876
877 /* Decide where the mountains go
878 */
879 static void
880 elevate_land(void)
881 {
882     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
883         r, dk;
884
885     for (c = 0; c < ctot; ++c) {
886         total = 0;
887         ns = (c < nc) ? sc : isecs[c];
888         nm = (pm * ns) / 100;
889
890 /* Place the mountains */
891
892         for (i = 0; i < ns; ++i) {
893             dsea[i] = distance_to_sea();
894             weight[i] = (total += (dsea[i] * dsea[i]));
895         }
896
897         for (k = nm, mountain_search = 0;
898              k && mountain_search < MOUNTAIN_SEARCH_MAX;
899              ++mountain_search) {
900             r = rnd(total);
901             for (i = 0; i < ns; ++i)
902                 if (r < weight[i] && ELEV == -INFINITY &&
903                     (c >= nc ||
904                      ((!(capx[c] == sectx[c][i] &&
905                          capy[c] == secty[c][i])) &&
906                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
907                          capy[c] == secty[c][i]))))) {
908                     ELEV = INFINITY;
909                     break;
910                 }
911             --k;
912         }
913
914 /* Elevate land that is not mountain and not capital */
915
916         for (i = 0; i < ns; ++i)
917             dmoun[i] = distance_to_mountain();
918         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
919           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
920           100 * INFINITY;
921         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
922             highest = -INFINITY;
923             where = -1;
924             for (i = 0; i < ns; ++i) {
925                 if (ELEV != INFINITY &&
926                     (c >= nc || ((!(capx[c] == sectx[c][i] &&
927                                     capy[c] == secty[c][i])) &&
928                                  (!(new_x(capx[c] + 2) == sectx[c][i] &&
929                                     capy[c] == secty[c][i]))))) {
930                     h = 3 * (5 - dmoun[i]) + dsea[i];
931                     if (h > highest) {
932                         highest = h;
933                         where = i;
934                     }
935                 }
936             }
937             if (where == -1)
938                 break;
939             newk = k / 100;
940             if (newk >= HILLMIN && newk < PLATMIN)
941                 newk = PLATMIN;
942             if (newk < LANDMIN)
943                 newk = LANDMIN;
944             elev[sectx[c][where]][secty[c][where]] = newk;
945             dsea[where] = -INFINITY;
946             dmoun[where] = INFINITY;
947         }
948
949 /* Elevate the mountains and capitals */
950
951         for (i = 0; i < ns; ++i) {
952             if (ELEV == INFINITY) {
953                 if (dsea[i] == 1)
954                     ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
955                 else
956                     ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
957                       rnd((256 - HIGHMIN) / 2);
958             } else if (c < nc &&
959                        (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
960                         ((new_x(capx[c] + 2) == sectx[c][i] &&
961                           capy[c] == secty[c][i]))))
962                 ELEV = PLATMIN;
963         }
964     }
965 }
966
967 #define distance_to_land() distance_to_what(x, y, 1)
968
969 static void
970 elevate_sea(void)
971 {
972     int x, y;
973
974     for (y = 0; y < WORLD_Y; ++y) {
975         for (x = y % 2; x < WORLD_X; x += 2) {
976             if (elev[x][y] == -INFINITY)
977                 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
978         }
979     }
980 }
981
982 /****************************************************************************
983   ADD THE RESOURCES
984 ****************************************************************************/
985
986 static int
987 set_fert(int e)
988 {
989     int fert = 0;
990     if (e < LANDMIN)
991         fert = LANDMIN - e + 40;
992     else if (e < FERT_MAX)
993         fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
994     if (fert > 100)
995         fert = 100;
996     return fert;
997 }
998
999 static int
1000 set_oil(int e)
1001 {
1002     int oil = 0;
1003     if (e < LANDMIN)
1004         oil = (LANDMIN - e) * 2 + rnd(2);
1005     else if (e <= OIL_MAX)
1006         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1007     if (oil > 100)
1008         oil = 100;
1009     return oil;
1010 }
1011
1012 static int
1013 set_iron(int e)
1014 {
1015     int iron = 0;
1016     if (e >= IRON_MIN && e < HIGHMIN)
1017         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1018     if (iron > 100)
1019         iron = 100;
1020     return iron;
1021 }
1022
1023 static int
1024 set_gold(int e)
1025 {
1026     int gold = 0;
1027     if (e >= GOLD_MIN) {
1028         if (e < HIGHMIN)
1029             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1030         else
1031             gold = 100 - 20 * HIGHMIN / e;
1032     }
1033     if (gold > 100)
1034         gold = 100;
1035     return gold;
1036 }
1037
1038 static int
1039 set_uran(int e)
1040 {
1041     int uran = 0;
1042     if (e >= URAN_MIN && e < HIGHMIN)
1043         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1044     if (uran > 100)
1045         uran = 100;
1046     return uran;
1047 }
1048
1049 static void
1050 add_resources(struct sctstr *sct)
1051 {
1052     sct->sct_fertil = set_fert(sct->sct_elev);
1053     sct->sct_oil = set_oil(sct->sct_elev);
1054     sct->sct_min = set_iron(sct->sct_elev);
1055     sct->sct_gmin = set_gold(sct->sct_elev);
1056     sct->sct_uran = set_uran(sct->sct_elev);
1057 }
1058
1059 /****************************************************************************
1060   DESIGNATE THE SECTORS
1061 ****************************************************************************/
1062
1063 static void
1064 write_sects(void)
1065 {
1066     struct sctstr *sct;
1067     int c, x, y, total;
1068
1069     for (y = 0; y < WORLD_Y; y++) {
1070         for (x = y % 2; x < WORLD_X; x += 2) {
1071             sct = getsectp(x, y);
1072             total = elev[x][y];
1073             if (total < LANDMIN) {
1074                 sct->sct_type = SCT_WATER;
1075             } else if (total < HILLMIN)
1076                 sct->sct_type = SCT_RURAL;
1077             else if (total < PLATMIN)
1078                 sct->sct_type = SCT_MOUNT;
1079             else if (total < HIGHMIN)
1080                 sct->sct_type = SCT_RURAL;
1081             else
1082                 sct->sct_type = SCT_MOUNT;
1083             sct->sct_elev = total;
1084             sct->sct_newtype = sct->sct_type;
1085             if (ORE)
1086                 add_resources(sct);
1087         }
1088     }
1089     if (AIRPORT_MARKER)
1090         for (c = 0; c < nc; ++c) {
1091             sct = getsectp(capx[c], capy[c]);
1092             sct->sct_type = SCT_AIRPT;
1093             sct->sct_newtype = SCT_AIRPT;
1094         }
1095     set_coastal_flags();
1096 }
1097
1098 /****************************************************************************
1099   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1100 ****************************************************************************/
1101 static void
1102 output(void)
1103 {
1104     int i, j;
1105     if (quiet == 0) {
1106         for (i = 0; i < WORLD_Y; ++i) {
1107             puts("");
1108             if (i % 2)
1109                 printf(" ");
1110             for (j = i % 2; j < WORLD_X; j += 2) {
1111                 if (own[j][i] == -1)
1112                     printf(". ");
1113                 else {
1114                     printf("%c ", map_symbol(j, i));
1115                 }
1116             }
1117         }
1118     }
1119     if (AIRPORT_MARKER)
1120         printf("\n\nEach continent is marked by a \"*\" on the map (to distinguish them from\n"
1121                "the islands).  You can redesignate these airfields to wilderness sectors\n"
1122                "one at a time, each time you add a new country to the game.\n");
1123 }
1124
1125 static int
1126 map_symbol(int x, int y)
1127 {
1128     int c, iscap = 0;
1129
1130     for (c = 0; c < nc; ++c)
1131         if ((x == capx[c] && y == capy[c])
1132             || (x == new_x(capx[c] + 2) && y == capy[c]))
1133             iscap = 1;
1134     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1135         || elev[x][y] >= HIGHMIN)
1136         return '^';
1137     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1138 }
1139
1140 /***************************************************************************
1141   WRITE A SCRIPT FOR PLACING CAPITALS
1142 ****************************************************************************/
1143 static int
1144 write_newcap_script(void)
1145 {
1146     int c;
1147     FILE *script = fopen(outfile, "w");
1148
1149     if (!script) {
1150         printf("fairland: error, unable to write to %s.\n", outfile);
1151         return -1;
1152     }
1153
1154     for (c = 0; c < nc; ++c) {
1155         fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1156         if (AIRPORT_MARKER)
1157             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1158         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1159     }
1160     fprintf(script, "add %d visitor visitor v\n", c + 1);
1161     fclose(script);
1162     return 0;
1163 }
1164
1165 static void
1166 qprint(const char *const fmt, ...)
1167 {
1168     va_list ap;
1169
1170     if (!quiet) {
1171         va_start(ap, fmt);
1172         vfprintf(stdout, fmt, ap);
1173         va_end(ap);
1174     }
1175 }
1176
1177 static void
1178 set_coastal_flags(void)
1179 {
1180     int i, j;
1181     struct sctstr *sp;
1182
1183     qprint("setting coastal flags...\n");
1184     for (i = 0; i < nc; ++i) {
1185         for (j = 0; j < sc; j++) {
1186             sp = getsectp(sectx[i][j], secty[i][j]);
1187             sp->sct_coastal = sectc[i][j];
1188         }
1189     }
1190     for (i = nc; i < nc + ni; ++i) {
1191         for (j = 0; j < isecs[i]; j++) {
1192             sp = getsectp(sectx[i][j], secty[i][j]);
1193             sp->sct_coastal = sectc[i][j];
1194         }
1195     }
1196 }