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