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