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