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