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