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