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