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