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