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