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