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