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