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