]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
Use unsigned instead of unsigned long for fairland's random seed
[empserver] / src / util / fairland.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2013, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire 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 3 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, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  fairland.c: Create a nice, new world
28  *
29  *  Known contributors to this file:
30  *     Ken Stevens, 1995
31  *     Steve McClure, 1998
32  *     Markus Armbruster, 2004-2012
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 <assert.h>
70 #include <errno.h>
71 #include <stdarg.h>
72 #include <stdio.h>
73 #include <unistd.h>
74 #include "chance.h"
75 #include "file.h"
76 #include "optlist.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 STABLE_CYCLE 4          /* stability required for perterbed capitals */
104 #define INFINITY        999     /* a number which means "BIG" */
105
106 /* these defines prevent infinite loops:
107 */
108
109 #define COAST_SEARCH_MAX 200    /* how many times do we look for a coast sector
110                                    when growing continents and islands */
111 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
112 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
113 #define MOUNTAIN_SEARCH_MAX 1000        /* how long do we try to place mountains */
114
115 /* handy macros:
116 */
117
118 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
119 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
120
121 static int secs;                /* number of sectors grown */
122 static int ctot;                /* total number of continents and islands grown */
123 static int *isecs;              /* array of how large each island is */
124
125 static int nc, sc, di, sp, pm, ni, is, id; /* the 8 args to this program */
126 static int *capx, *capy;        /* location of the nc capitals */
127 static int *mc, mcc;            /* array and counter used for stability
128                                    check when perturbing */
129 static int spike;               /* are we spiking? */
130 static int mind;                /* the final distance between capitals that
131                                    we achieved */
132 static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
133 static int diry[] = { 0, -1, -1, 0, 1, 1 };
134
135 static int **own;               /* owner of the sector.  -1 means water */
136 static int **elev;              /* elevation of the sectors */
137 static int **sectx, **secty;    /* the sectors for each continent */
138 static int **sectc;             /* which sectors are on the coast? */
139 static int *vector;             /* used for measuring distances */
140 static int *weight;             /* used for placing mountains */
141 static int *dsea, *dmoun;       /* the dist to the ocean and mountain */
142 static int fl_status;           /* is anything wrong? */
143 #define STATUS_NO_ROOM 1        /* there was no room to grow */
144 #define NUMTRIES 10             /* keep trying to grow this many times */
145
146 static const char *numletter =
147     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
148
149 static void help(char *);
150 static void usage(void);
151 static void parse_args(int argc, char *argv[]);
152 static void allocate_memory(void);
153 static void init(void);
154 static int drift(void);
155 static void grow_continents(void);
156 static void create_elevations(void);
157 static void write_sects(void);
158 static void output(void);
159 static int write_newcap_script(void);
160 static int stable(void);
161 static void elevate_land(void);
162 static void elevate_sea(void);
163 static int map_symbol(int x, int y);
164 static void set_coastal_flags(void);
165
166 static void print_vars(void);
167 static void fl_move(int);
168 static void next_coast(int c, int x, int y, int *xp, int *yp);
169 static void grow_islands(void);
170
171 /****************************************************************************
172   MAIN
173 ****************************************************************************/
174
175 int
176 main(int argc, char *argv[])
177 {
178     int opt;
179     char *config_file = NULL;
180     int i = 0;
181     unsigned rnd_seed = 0;
182     int seed_set = 0;
183
184     program_name = argv[0];
185
186     while ((opt = getopt(argc, argv, "ae:hioqR:s:v")) != EOF) {
187         switch (opt) {
188         case 'a':
189             AIRPORT_MARKER = 1;
190             break;
191         case 'e':
192             config_file = optarg;
193             break;
194         case 'i':
195             DISTINCT_ISLANDS = 0;
196             break;
197         case 'o':
198             ORE = 0;
199             break;
200         case 'q':
201             quiet = 1;
202             break;
203         case 'R':
204             rnd_seed = strtoul(optarg, NULL, 10);
205             seed_set = 1;
206             break;
207         case 's':
208             outfile = optarg;
209             break;
210         case 'h':
211             usage();
212             exit(0);
213         case 'v':
214             printf("%s\n\n%s", version, legal);
215             exit(0);
216         default:
217             help(NULL);
218             exit(1);
219         }
220     }
221     parse_args(argc - optind, argv + optind);
222
223     if (!seed_set)
224         rnd_seed = pick_seed();
225     seed_prng(rnd_seed);
226     empfile_init();
227     if (emp_config(config_file) < 0)
228         exit(1);
229     empfile_fixup();
230
231     allocate_memory();
232     print_vars();
233
234     qprint("\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
235     qprint("seed is %u\n", rnd_seed);
236     do {
237         init();
238         if (i)
239             qprint("\ntry #%d (out of %d)...\n", i + 1, NUMTRIES);
240         qprint("placing capitals...\n");
241         if (!drift())
242             qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
243         qprint("growing continents...\n");
244         grow_continents();
245     } while (fl_status && ++i < NUMTRIES);
246     if (fl_status) {
247         fputs("ERROR: World not large enough to hold continents\n",
248               stderr);
249         exit(1);
250     }
251     qprint("growing islands:");
252     grow_islands();
253     qprint("\nelevating land...\n");
254     create_elevations();
255     qprint("designating sectors...\n");
256     if (ORE)
257         qprint("adding resources...\n");
258     write_newcap_script();
259
260     if (chdir(gamedir)) {
261         fprintf(stderr, "Can't chdir to %s (%s)\n", gamedir, strerror(errno));
262         exit(EXIT_FAILURE);
263     }
264     if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
265         exit(1);
266     write_sects();
267     qprint("writing to sectors file...\n");
268     if (!ef_close(EF_SECTOR))
269         exit(1);
270
271     output();
272     qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
273            outfile);
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 < 1)
376         is = 1;
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: warning -- world might be too small to fit continents.");
422         puts("arguments should satisfy:");
423         puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
424     }
425 }
426
427 /****************************************************************************
428   VARIABLE INITIALIZATION
429 ****************************************************************************/
430
431 static void
432 allocate_memory(void)
433 {
434     int i;
435
436     capx = calloc(nc, sizeof(int));
437     capy = calloc(nc, sizeof(int));
438     vector = calloc(WORLD_X + WORLD_Y, sizeof(int));
439     mc = calloc(STABLE_CYCLE, sizeof(int));
440     own = calloc(WORLD_X, sizeof(int *));
441     elev = calloc(WORLD_X, sizeof(int *));
442     for (i = 0; i < WORLD_X; ++i) {
443         own[i] = calloc(WORLD_Y, sizeof(int));
444         elev[i] = calloc(WORLD_Y, sizeof(int));
445     }
446     sectx = calloc(nc + ni, sizeof(int *));
447     secty = calloc(nc + ni, sizeof(int *));
448     sectc = calloc(nc + ni, sizeof(int *));
449     isecs = calloc(nc + ni, sizeof(int));
450     weight = calloc(MAX(sc, is * 2), sizeof(int));
451     dsea = calloc(MAX(sc, is * 2), sizeof(int));
452     dmoun = calloc(MAX(sc, is * 2), sizeof(int));
453     for (i = 0; i < nc; ++i) {
454         sectx[i] = calloc(sc, sizeof(int));
455         secty[i] = calloc(sc, sizeof(int));
456         sectc[i] = calloc(sc, sizeof(int));
457     }
458     for (i = nc; i < nc + ni; ++i) {
459         sectx[i] = calloc(is * 2, sizeof(int));
460         secty[i] = calloc(is * 2, sizeof(int));
461         sectc[i] = calloc(is * 2, sizeof(int));
462     }
463
464 }
465
466 static void
467 init(void)
468 {
469     int i, j, xx = 0, yy = 0;
470
471     mcc = 0;
472     fl_status = 0;
473
474     for (i = 0; i < WORLD_X; ++i) {
475         for (j = 0; j < WORLD_Y; ++j) {
476             own[i][j] = -1;
477             elev[i][j] = -INFINITY;
478         }
479     }
480
481     for (i = 0; i < nc; ++i) {
482         if (xx >= WORLD_X) {
483             ++yy;
484             xx = yy % 2;
485             if (yy == WORLD_Y) {
486                 puts("fairland error: world not big enough for all the continents.\n");
487                 exit(1);
488             }
489         }
490         capx[i] = xx;
491         capy[i] = yy;
492         xx += 2;
493     }
494     for (i = 0; i < STABLE_CYCLE; ++i)
495         mc[i] = i;
496 }
497
498 /****************************************************************************
499   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
500 ****************************************************************************/
501
502 /* How isolated is capital j?
503 */
504 static int
505 iso(int j, int newx, int newy)
506 {
507     int i, md, d = WORLD_X + WORLD_Y;
508
509     for (i = 0; i < nc; ++i) {
510         if (i == j)
511             continue;
512         md = mapdist(capx[i], capy[i], newx, newy);
513         if (md < d)
514             d = md;
515     }
516
517     return d;
518 }
519
520 /* Drift all the capitals
521 */
522 static int
523 drift(void)
524 {
525     int i, turns;
526
527     for (turns = 0; turns < DRIFT_MAX; ++turns) {
528         if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
529             return 1;
530         for (i = 0; i < nc; ++i)
531             fl_move(i);
532     }
533     return 0;
534 }
535
536 /* Check to see if we have stabilized--can we stop drifting the capitals?
537 */
538
539 static int
540 stable(void)
541 {
542     int i, isod, d = 0, stab = 1;
543
544     for (i = 0; i < nc; ++i) {
545         isod = iso(i, capx[i], capy[i]);
546         if (isod > d)
547             d = isod;
548     }
549     for (i = 0; i < STABLE_CYCLE; ++i)
550         if (d != mc[i])
551             stab = 0;
552     mc[mcc] = d;
553     mcc = (mcc + 1) % STABLE_CYCLE;
554     return stab ? d : 0;
555 }
556
557 /* This routine does the actual drifting
558 */
559
560 static void
561 fl_move(int j)
562 {
563     int i, n, newx, newy;
564
565     for (i = roll0(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
566         newx = new_x(capx[j] + dirx[i]);
567         newy = new_y(capy[j] + diry[i]);
568         if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
569             capx[j] = newx;
570             capy[j] = newy;
571             return;
572         }
573     }
574 }
575
576 /****************************************************************************
577   GROW THE CONTINENTS
578 ****************************************************************************/
579
580 /* Look for a coastal sector of continent c
581 */
582
583 static void
584 find_coast(int c)
585 {
586     int i, j;
587
588     for (i = 0; i < secs; ++i) {
589         sectc[c][i] = 0;
590         for (j = 0; j < 6; ++j)
591             if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
592                 sectc[c][i] = 1;
593     }
594 }
595
596 /* Used for measuring distances
597 */
598 static int
599 next_vector(int n)
600 {
601     int i;
602
603     if (n == 1) {
604         vector[0] += 1;
605         vector[0] %= 6;
606         return vector[0];
607     }
608     for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
609     vector[i - 1] += 1;
610     vector[i - 1] %= 6;
611     return i > 1 || vector[0] > 0;
612 }
613
614 /* Test to see if we're allowed to grow there: the arguments di and id
615 */
616 static int
617 try_to_grow(int c, int newx, int newy, int d)
618 {
619     int i, j, px, py;
620
621     for (i = 1; i <= d; ++i) {
622         for (j = 0; j < i; ++j)
623             vector[j] = 0;
624         do {
625             px = newx;
626             py = newy;
627             for (j = 0; j < i; ++j) {
628                 px = new_x(px + dirx[vector[j]]);
629                 py = new_y(py + diry[vector[j]]);
630             }
631             if (own[px][py] != -1 &&
632                 own[px][py] != c &&
633                 (DISTINCT_ISLANDS || own[px][py] < nc))
634                 return 0;
635         } while (next_vector(i));
636     }
637     sectx[c][secs] = newx;
638     secty[c][secs] = newy;
639     own[newx][newy] = c;
640     return 1;
641 }
642
643 /* Move along the coast in a clockwise direction.
644 */
645
646 static void
647 next_coast(int c, int x, int y, int *xp, int *yp)
648 {
649     int i, nx, ny, wat = 0;
650
651     if (secs == 1) {
652         *xp = x;
653         *yp = y;
654         return;
655     }
656
657     for (i = 0; i < 12; ++i) {
658         nx = new_x(x + dirx[i % 6]);
659         ny = new_y(y + diry[i % 6]);
660         if (own[nx][ny] == -1)
661             wat = 1;
662         if (wat && own[nx][ny] == c) {
663             *xp = nx;
664             *yp = ny;
665             return;
666         }
667     }
668 }
669
670 /* Choose a sector to grow from
671 */
672
673 static int
674 new_try(int c)
675 {
676     int i, starti;
677
678     if (secs == 1) {
679         if (sectc[c][0])
680             return 0;
681     } else {
682         i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : roll0(secs);
683         do {
684             if (sectc[c][i])
685                 return i;
686             i = (i + 1) % secs;
687         } while (i != starti);
688         assert(c >= nc);
689         return -1;
690     }
691     return -1;
692 }
693
694 /* Grow continent c by 1 sector
695 */
696
697 static int
698 grow_one_sector(int c)
699 {
700     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
701
702     spike = roll0(100) < sp;
703     if ((try1 = new_try(c)) == -1)
704         return 0;
705     x = sx = sectx[c][try1];
706     y = sy = secty[c][try1];
707     coast_search = 0;
708     done = 0;
709     do {
710         if (spike) {
711             for (i = roll0(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
712                 newx = new_x(x + dirx[i]);
713                 newy = new_y(y + diry[i]);
714                 if (own[newx][newy] == -1 &&
715                     (n > 5 ||
716                      (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
717                       own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
718                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
719                         done = 1;
720             }
721         } else
722             for (i = roll0(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
723                 newx = new_x(x + dirx[i]);
724                 newy = new_y(y + diry[i]);
725                 if (own[newx][newy] == -1)
726                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
727                         done = 1;
728             }
729         next_coast(c, x, y, &x, &y);
730         ++coast_search;
731     } while (!done && coast_search < COAST_SEARCH_MAX &&
732              (secs == 1 || x != sx || y != sy));
733     if (!done && c < nc) {
734         qprint("fairland: error -- continent %c had no room to grow!\n",
735                numletter[c % 62]);
736         fl_status |= STATUS_NO_ROOM;
737     }
738     return done;
739 }
740
741 /* Grow all the continents
742 */
743 static void
744 grow_continents(void)
745 {
746     int c;
747
748     for (c = 0; c < nc; ++c) {
749         sectx[c][0] = capx[c];
750         secty[c][0] = capy[c];
751         own[sectx[c][0]][secty[c][0]] = c;
752         sectx[c][1] = new_x(capx[c] + 2);
753         secty[c][1] = capy[c];
754         own[sectx[c][1]][secty[c][1]] = c;
755     }
756
757     for (secs = 2; secs < sc && !fl_status; ++secs) {
758         for (c = 0; c < nc; ++c) {
759             find_coast(c);
760             grow_one_sector(c);
761         }
762     }
763     for (c = 0; c < nc; ++c)
764         find_coast(c);
765
766     if (fl_status)
767         qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
768     ctot = nc;
769 }
770
771 /****************************************************************************
772   GROW THE ISLANDS
773 ****************************************************************************/
774
775 /* Choose a place to start growing an island from
776 */
777 static int
778 place_island(int c, int *xp, int *yp)
779 {
780     int d, sx, sy;
781     int ssy = roll0(WORLD_Y);
782     int ssx = new_x(roll0(WORLD_X / 2) * 2 + ssy % 2);
783
784     if (ssx > WORLD_X - 2)
785         ssx = new_x(ssx + 2);
786     for (d = di + id; d >= id; --d) {
787         sx = ssx;
788         sy = ssy;
789         *xp = new_x(sx + 2);
790         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
791             if (*xp >= WORLD_X) {
792                 *yp = new_y(*yp + 1);
793                 *xp = *yp % 2;
794                 if (*xp == sx && *yp == sy)
795                     break;
796             }
797             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
798                 return 1;
799         }
800     }
801     return 0;
802 }
803
804 /* Grow all the islands
805 */
806
807 static void
808 grow_islands(void)
809 {
810     int c, x, y, isiz;
811
812     for (c = nc; c < nc + ni; ++c) {
813         secs = 0;
814         if (!place_island(c, &x, &y))
815             return;
816         isiz = roll(2 * is - 1);
817         do {
818             ++secs;
819             find_coast(c);
820         } while (secs < isiz && grow_one_sector(c));
821         find_coast(c);
822         qprint(" %d(%d)", c - nc + 1, secs);
823         isecs[c] = secs;
824         ctot++;
825     }
826 }
827
828 /****************************************************************************
829   CREATE ELEVATIONS
830 ****************************************************************************/
831 static void
832 create_elevations(void)
833 {
834     elevate_land();
835     elevate_sea();
836 }
837
838 /* Generic function for finding the distance to the closest sea, land, or
839    mountain
840 */
841 static int
842 distance_to_what(int x, int y, int flag)
843 {
844     int j, d, px, py;
845
846     for (d = 1; d < 5; ++d) {
847         for (j = 0; j < d; ++j)
848             vector[j] = 0;
849         do {
850             px = x;
851             py = y;
852             for (j = 0; j < d; ++j) {
853                 px = new_x(px + dirx[vector[j]]);
854                 py = new_y(py + diry[vector[j]]);
855             }
856             switch (flag) {
857             case 0:             /* distance to sea */
858                 if (own[px][py] == -1)
859                     return d;
860                 break;
861             case 1:             /* distance to land */
862                 if (own[px][py] != -1)
863                     return d;
864                 break;
865             case 2:             /* distance to mountain */
866                 if (elev[px][py] == INFINITY)
867                     return d;
868                 break;
869             }
870         } while (next_vector(d));
871     }
872     return d;
873 }
874
875 #define ELEV elev[sectx[c][i]][secty[c][i]]
876 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
877 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
878
879 /* Decide where the mountains go
880 */
881 static void
882 elevate_land(void)
883 {
884     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
885         r, dk;
886
887     for (c = 0; c < ctot; ++c) {
888         total = 0;
889         ns = (c < nc) ? sc : isecs[c];
890         nm = (pm * ns) / 100;
891
892 /* Place the mountains */
893
894         for (i = 0; i < ns; ++i) {
895             dsea[i] = distance_to_sea();
896             weight[i] = (total += (dsea[i] * dsea[i]));
897         }
898
899         for (k = nm, mountain_search = 0;
900              k && mountain_search < MOUNTAIN_SEARCH_MAX;
901              ++mountain_search) {
902             r = roll0(total);
903             for (i = 0; i < ns; ++i)
904                 if (r < weight[i] && ELEV == -INFINITY &&
905                     (c >= nc ||
906                      ((!(capx[c] == sectx[c][i] &&
907                          capy[c] == secty[c][i])) &&
908                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
909                          capy[c] == secty[c][i]))))) {
910                     ELEV = INFINITY;
911                     break;
912                 }
913             --k;
914         }
915
916 /* Elevate land that is not mountain and not capital */
917
918         for (i = 0; i < ns; ++i)
919             dmoun[i] = distance_to_mountain();
920         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
921           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
922           100 * INFINITY;
923         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
924             highest = -INFINITY;
925             where = -1;
926             for (i = 0; i < ns; ++i) {
927                 if (ELEV != INFINITY &&
928                     (c >= nc || ((!(capx[c] == sectx[c][i] &&
929                                     capy[c] == secty[c][i])) &&
930                                  (!(new_x(capx[c] + 2) == sectx[c][i] &&
931                                     capy[c] == secty[c][i]))))) {
932                     h = 3 * (5 - dmoun[i]) + dsea[i];
933                     if (h > highest) {
934                         highest = h;
935                         where = i;
936                     }
937                 }
938             }
939             if (where == -1)
940                 break;
941             newk = k / 100;
942             if (newk >= HILLMIN && newk < PLATMIN)
943                 newk = PLATMIN;
944             if (newk < LANDMIN)
945                 newk = LANDMIN;
946             elev[sectx[c][where]][secty[c][where]] = newk;
947             dsea[where] = -INFINITY;
948             dmoun[where] = INFINITY;
949         }
950
951 /* Elevate the mountains and capitals */
952
953         for (i = 0; i < ns; ++i) {
954             if (ELEV == INFINITY) {
955                 if (dsea[i] == 1)
956                     ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
957                 else
958                     ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
959                       roll0((256 - HIGHMIN) / 2);
960             } else if (c < nc &&
961                        (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
962                         ((new_x(capx[c] + 2) == sectx[c][i] &&
963                           capy[c] == secty[c][i]))))
964                 ELEV = PLATMIN;
965         }
966     }
967 }
968
969 #define distance_to_land() distance_to_what(x, y, 1)
970
971 static void
972 elevate_sea(void)
973 {
974     int x, y;
975
976     for (y = 0; y < WORLD_Y; ++y) {
977         for (x = y % 2; x < WORLD_X; x += 2) {
978             if (elev[x][y] == -INFINITY)
979                 elev[x][y] = -roll(distance_to_land() * 20 + 27);
980         }
981     }
982 }
983
984 /****************************************************************************
985   ADD THE RESOURCES
986 ****************************************************************************/
987
988 static int
989 set_fert(int e)
990 {
991     int fert = 0;
992     if (e < LANDMIN)
993         fert = LANDMIN - e + 40;
994     else if (e < FERT_MAX)
995         fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
996     if (fert > 100)
997         fert = 100;
998     return fert;
999 }
1000
1001 static int
1002 set_oil(int e)
1003 {
1004     int oil = 0;
1005     if (e < LANDMIN)
1006         oil = (LANDMIN - e) * 2 + roll0(2);
1007     else if (e <= OIL_MAX)
1008         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1009     if (oil > 100)
1010         oil = 100;
1011     return oil;
1012 }
1013
1014 static int
1015 set_iron(int e)
1016 {
1017     int iron = 0;
1018     if (e >= IRON_MIN && e < HIGHMIN)
1019         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1020     if (iron > 100)
1021         iron = 100;
1022     return iron;
1023 }
1024
1025 static int
1026 set_gold(int e)
1027 {
1028     int gold = 0;
1029     if (e >= GOLD_MIN) {
1030         if (e < HIGHMIN)
1031             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1032         else
1033             gold = 100 - 20 * HIGHMIN / e;
1034     }
1035     if (gold > 100)
1036         gold = 100;
1037     return gold;
1038 }
1039
1040 static int
1041 set_uran(int e)
1042 {
1043     int uran = 0;
1044     if (e >= URAN_MIN && e < HIGHMIN)
1045         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1046     if (uran > 100)
1047         uran = 100;
1048     return uran;
1049 }
1050
1051 static void
1052 add_resources(struct sctstr *sct)
1053 {
1054     sct->sct_fertil = set_fert(sct->sct_elev);
1055     sct->sct_oil = set_oil(sct->sct_elev);
1056     sct->sct_min = set_iron(sct->sct_elev);
1057     sct->sct_gmin = set_gold(sct->sct_elev);
1058     sct->sct_uran = set_uran(sct->sct_elev);
1059 }
1060
1061 /****************************************************************************
1062   DESIGNATE THE SECTORS
1063 ****************************************************************************/
1064
1065 static void
1066 write_sects(void)
1067 {
1068     struct sctstr *sct;
1069     int c, x, y, total;
1070
1071     for (y = 0; y < WORLD_Y; y++) {
1072         for (x = y % 2; x < WORLD_X; x += 2) {
1073             sct = getsectp(x, y);
1074             total = elev[x][y];
1075             if (total < LANDMIN) {
1076                 sct->sct_type = SCT_WATER;
1077             } else if (total < HILLMIN)
1078                 sct->sct_type = SCT_RURAL;
1079             else if (total < PLATMIN)
1080                 sct->sct_type = SCT_MOUNT;
1081             else if (total < HIGHMIN)
1082                 sct->sct_type = SCT_RURAL;
1083             else
1084                 sct->sct_type = SCT_MOUNT;
1085             sct->sct_elev = total;
1086             sct->sct_newtype = sct->sct_type;
1087             if (ORE)
1088                 add_resources(sct);
1089         }
1090     }
1091     if (AIRPORT_MARKER)
1092         for (c = 0; c < nc; ++c) {
1093             sct = getsectp(capx[c], capy[c]);
1094             sct->sct_type = SCT_AIRPT;
1095             sct->sct_newtype = SCT_AIRPT;
1096         }
1097     set_coastal_flags();
1098 }
1099
1100 /****************************************************************************
1101   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1102 ****************************************************************************/
1103 static void
1104 output(void)
1105 {
1106     int i, j;
1107     if (quiet == 0) {
1108         for (i = 0; i < WORLD_Y; ++i) {
1109             puts("");
1110             if (i % 2)
1111                 printf(" ");
1112             for (j = i % 2; j < WORLD_X; j += 2) {
1113                 if (own[j][i] == -1)
1114                     printf(". ");
1115                 else {
1116                     printf("%c ", map_symbol(j, i));
1117                 }
1118             }
1119         }
1120     }
1121     if (AIRPORT_MARKER)
1122         printf("\n\nEach continent is marked by a \"*\" on the map (to distinguish them from\n"
1123                "the islands).  You can redesignate these airfields to wilderness sectors\n"
1124                "one at a time, each time you add a new country to the game.\n");
1125 }
1126
1127 static int
1128 map_symbol(int x, int y)
1129 {
1130     int c, iscap = 0;
1131
1132     for (c = 0; c < nc; ++c)
1133         if ((x == capx[c] && y == capy[c])
1134             || (x == new_x(capx[c] + 2) && y == capy[c]))
1135             iscap = 1;
1136     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1137         || elev[x][y] >= HIGHMIN)
1138         return '^';
1139     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1140 }
1141
1142 /***************************************************************************
1143   WRITE A SCRIPT FOR PLACING CAPITALS
1144 ****************************************************************************/
1145 static int
1146 write_newcap_script(void)
1147 {
1148     int c;
1149     FILE *script = fopen(outfile, "w");
1150
1151     if (!script) {
1152         printf("fairland: error, unable to write to %s.\n", outfile);
1153         return -1;
1154     }
1155
1156     for (c = 0; c < nc; ++c) {
1157         fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1158         if (AIRPORT_MARKER)
1159             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1160         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1161     }
1162     fprintf(script, "add %d visitor visitor v\n", c + 1);
1163     fclose(script);
1164     return 0;
1165 }
1166
1167 static void
1168 qprint(const char *const fmt, ...)
1169 {
1170     va_list ap;
1171
1172     if (!quiet) {
1173         va_start(ap, fmt);
1174         vfprintf(stdout, fmt, ap);
1175         va_end(ap);
1176     }
1177 }
1178
1179 static void
1180 set_coastal_flags(void)
1181 {
1182     int i, j;
1183     struct sctstr *sp;
1184
1185     qprint("setting coastal flags...\n");
1186     for (i = 0; i < nc; ++i) {
1187         for (j = 0; j < sc; j++) {
1188             sp = getsectp(sectx[i][j], secty[i][j]);
1189             sp->sct_coastal = sectc[i][j];
1190         }
1191     }
1192     for (i = nc; i < nc + ni; ++i) {
1193         for (j = 0; j < isecs[i]; j++) {
1194             sp = getsectp(sectx[i][j], secty[i][j]);
1195             sp->sct_coastal = sectc[i][j];
1196         }
1197     }
1198 }