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