]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
(main) [_WIN32]: remove getpid() from the random seed as
[empserver] / src / util / fairland.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2004, 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 #if defined(_WIN32)
71 #include "../lib/gen/getopt.h"
72 #endif
73
74 #include <stdarg.h>
75 #include <stdio.h>
76 #include <stdlib.h>
77 #include <fcntl.h>
78 #include "misc.h"
79 #include "power.h"
80 #include "nat.h"
81 #include "sect.h"
82 #include "gamesdef.h"
83 #include "file.h"
84 #include "xy.h"
85 #include "optlist.h"
86 #include "prototypes.h"
87
88 /* do not change these 4 defines */
89 #define LANDMIN         1       /* plate altitude for normal land */
90 #define HILLMIN         34      /* plate altitude for hills */
91 #define PLATMIN         36      /* plate altitude for plateau */
92 #define HIGHMIN         98      /* plate altitude for mountains */
93
94 static void qprint(const char * const fmt, ...)
95     ATTRIBUTE((format (printf, 1, 2)));
96
97 #define DEFAULT_OUTFILE_NAME "newcap_script"
98 static const char *outfile = DEFAULT_OUTFILE_NAME;
99 /* mark the continents with a * so you can tell them
100    from the islands 1 = mark, 0 = don't mark. */
101 static int AIRPORT_MARKER = 0;
102
103 /* don't let the islands crash into each other.
104    1 = don't merge, 0 = merge. */
105 static int DISTINCT_ISLANDS = 1;
106
107 #define XSIZE           ((WORLD_X) / 2) /* basically world x-y size */
108 #define YSIZE           (WORLD_Y)
109 #define STABLE_CYCLE 4          /* stability required for perterbed capitals */
110 #define INFINITY        999     /* a number which means "BIG" */
111
112 /* these defines prevent infinite loops:
113 */
114
115 #define COAST_SEARCH_MAX 200    /* how many times do we look for a coast sector
116                                    when growing continents and islands */
117 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
118 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
119 #define MOUNTAIN_SEARCH_MAX 1000        /* how long do we try to place mountains */
120
121 /* handy macros:
122 */
123
124 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
125 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
126 #if !defined(_WIN32)
127 #define max(a,b) (a>b?a:b)
128 #endif
129 #define rnd(x) (random() % (x))
130
131 int secs;                       /* number of sectors grown */
132 int ctot;                       /* total number of continents and islands grown */
133 int *isecs;                     /* array of how large each island is */
134
135 int nc, sc, di, sp, pm, ni, is, id;     /* the 8 arguments to this program */
136 unsigned long rnd_seed;         /* optional seed can be passed as an argument */
137 int *capx, *capy;               /* location of the nc capitals */
138 int *mc, mcc;                   /* array and counter used for stability
139                                    check when perturbing */
140 int spike;                      /* are we spiking? */
141 int mind;                       /* the final distance between capitals that
142                                    we achieved */
143 int dirx[] = { -2, -1, 1, 2, 1, -1 };   /* gyujnb */
144 int diry[] = { 0, -1, -1, 0, 1, 1 };
145
146 int **own;                      /* owner of the sector.  -1 means water */
147 int **elev;                     /* elevation of the sectors */
148 int **sectx, **secty;           /* the sectors for each continent */
149 int **sectc;                    /* which sectors are on the coast? */
150 int *vector;                    /* used for measuring distances */
151 int *weight;                    /* used for placing mountains */
152 int *dsea, *dmoun;              /* the dist to the ocean and mountain */
153 int the_file;                   /* the file we write everything to */
154 struct sctstr **sects;
155 struct sctstr *sectsbuf;
156 int fl_status;                  /* is anything wrong? */
157 #define STATUS_NO_ROOM (1)      /* there was no room to grow */
158 #define NUMTRIES 10             /* keep trying to grow this many times */
159
160 const char *numletter =
161     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
162
163 static void parse_args(int argc, char *argv[]);
164 static int allocate_memory(void);
165 static void init(void);
166 static int drift(void);
167 static void grow_continents(void);
168 static void create_elevations(void);
169 static void write_sects(void);
170 static int write_file(void);
171 static void output(void);
172 static int write_newcap_script(void);
173 static int stable(void);
174 static void elevate_land(void);
175 static void elevate_sea(void);
176 static void translate_continents(void);
177 static int map_symbol(int x, int y);
178 static void fl_sct_init(coord x, coord y, s_char *ptr);
179
180 static void print_vars(void);
181 static void fl_move(int);
182 static void next_coast(int c, int x, int y, int *xp, int *yp);
183 static void grow_islands(void);
184
185 /****************************************************************************
186   MAIN
187 ****************************************************************************/
188
189 int
190 main(int argc, char *argv[])
191 {
192     int opt;
193     char *config_file = NULL;
194     char tbuf[512];
195     int i = 0;
196
197     rnd_seed = time(NULL);
198
199     while ((opt = getopt(argc, argv, "ae:ioqs:R:")) != EOF) {
200         switch (opt) {
201         case 'a':
202             AIRPORT_MARKER = 1;
203             break;
204         case 'i':
205             DISTINCT_ISLANDS = 0;
206             break;
207         case 'e':
208             config_file = optarg;
209             break;
210         case 'o':
211             ORE = 0;
212             break;
213         case 'q':
214             quiet = 1;
215             break;
216         case 's':
217             outfile = optarg;
218             break;
219         case 'R':
220             rnd_seed = strtoul(optarg, NULL, 10);
221             break;
222         }
223     }
224     srandom(rnd_seed);
225     if (config_file == NULL) {
226         sprintf(tbuf, "%s/econfig", datadir);
227         config_file = tbuf;
228     }
229     emp_config(config_file);
230
231     parse_args(argc - optind, argv + optind);
232     if (allocate_memory() == -1)
233         exit(-1);
234     print_vars();
235
236     do {
237         init();
238         if (i)
239             qprint("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
240         qprint("\n\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
241         qprint("seed is %lu\n", rnd_seed);
242         qprint("placing capitals...\n");
243         if (!drift())
244             qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
245         qprint("growing continents...\n");
246         grow_continents();
247     } while (fl_status && ++i < NUMTRIES);
248     if (fl_status) {
249         fputs("ERROR: World not large enough to hold continents\n",
250               stderr);
251         exit(1);
252     }
253     qprint("growing islands:");
254     grow_islands();
255     qprint("\nelevating land...\n");
256     create_elevations();
257     qprint("designating sectors...\n");
258     if (ORE)
259         qprint("adding resources...\n");
260     write_sects();
261     qprint("writing to sectors file...\n");
262     if (write_file() == -1)
263         exit(-1);
264     output();
265     write_newcap_script();
266     if (!ORE)
267         qprint("\t*** Resources have not been added ***\n");
268     exit(0);
269 }
270
271 static void
272 print_vars(void)
273 {
274     if (quiet)
275         return;
276     puts("Creating a planet with:\n");
277     printf("%d continents\n", nc);
278     printf("continent size: %d\n", sc);
279     printf("number of islands: %d\n", ni);
280     printf("average size of islands: %d\n", is);
281     printf("spike: %d%%\n", sp);
282     printf("%d%% of land is mountain (each continent will have %d mountains)\n",
283            pm, (pm * sc) / 100);
284     printf("minimum distance between continents: %d\n", di);
285     printf("minimum distance from islands to continents: %d\n", id);
286     printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
287 }
288
289 static int
290 my_sqrt(int n)
291 {
292     int i;
293
294     for (i = 1; i * i < n * 10000; ++i) ;
295     return (i + 50) / 100;
296 }
297
298 /****************************************************************************
299   PARSE COMMAND LINE ARGUMENTS
300 ****************************************************************************/
301
302 static void
303 parse_args(int argc, char *argv[])
304 {
305     if (argc < 2 || argc > 8) {
306         puts("fairland syntax:\n");
307         puts("fairland [-e config] [-aiqo] [-s script] [-R seed] <nc> <sc> [<ni>] [<is>] [<sp>] [<pm>] [<di>] [<id>]");
308         puts("-q = quiet, -o = no ore produced");
309         puts("-a = Airport marker for continents, -i = islands not distinct");
310         puts("-R = seed to use for random, -e = read config file");
311         printf("-s = name of script (default = %s)\n",
312                DEFAULT_OUTFILE_NAME);
313         puts("nc = number of continents [MANDATORY]");
314         puts("sc = continent size [MANDATORY]");
315         puts("ni = number of islands (default = nc)");
316         puts("is = average size of islands (default = sc/2)");
317         printf("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n",
318                DEFAULT_SPIKE);
319         printf("pm = the percentage of land that is mountain (default = %d)\n",
320                DEFAULT_MOUNTAIN);
321         printf("di = the minimum distance between continents (default = %d)\n",
322                DEFAULT_CONTDIST);
323         printf("id = minimum distance from islands to continents (default = %d)\n",
324                DEFAULT_ISLDIST);
325         exit(1);
326     }
327     nc = atoi(argv[0]);
328     if (nc < 1) {
329         puts("fairland: error -- number of continents must be > 0");
330         exit(1);
331     }
332
333     sc = atoi(argv[1]);
334     if (sc < 1) {
335         puts("fairland: error -- size of continents must be > 0");
336         exit(1);
337     }
338
339     if (argc > 2)
340         ni = atoi(argv[2]);
341     else
342         ni = nc;
343
344     if (argc > 3)
345         is = atoi(argv[3]);
346     else
347         is = sc / 2;
348     if (is < 0)
349         is = 0;
350
351     if (argc > 4)
352         sp = atoi(argv[4]);
353     else
354         sp = DEFAULT_SPIKE;
355     if (sp < 0)
356         sp = 0;
357     if (sp > 100)
358         sp = 100;
359
360     if (argc > 5)
361         pm = atoi(argv[5]);
362     else
363         pm = DEFAULT_MOUNTAIN;
364     if (pm < 0)
365         pm = 0;
366
367     if (argc > 6)
368         di = atoi(argv[6]);
369     else
370         di = DEFAULT_CONTDIST;
371
372     if (di < 0) {
373         puts("fairland: error -- distance between continents must be >= 0");
374         exit(1);
375     }
376     if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
377         puts("fairland: error -- distance between continents too large");
378         exit(1);
379     }
380
381     if (argc > 7)
382         id = atoi(argv[7]);
383     else
384         id = DEFAULT_ISLDIST;
385     if (id < 0) {
386         puts("fairland: error -- distance from islands to continents must be >= 0");
387         exit(1);
388     }
389     if (id > WORLD_X || id > WORLD_Y) {
390         puts("fairland: error -- distance from islands to continents too large");
391         exit(1);
392     }
393     if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
394         puts("fairland: error -- world not big enough to fit continents.");
395         puts("arguments must satisfy:");
396         puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
397         exit(1);
398     }
399 }
400
401 /****************************************************************************
402   VARIABLE INITIALIZATION
403 ****************************************************************************/
404
405 static int
406 allocate_memory(void)
407 {
408     int i;
409
410 #if !defined(_WIN32)
411     the_file =
412         open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC, 0660);
413 #else
414     the_file =
415         open(empfile[EF_SECTOR].file,
416              O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0660);
417 #endif
418     if (the_file < 0) {
419         perror(empfile[EF_SECTOR].file);
420         return -1;
421     }
422     sectsbuf =
423         (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
424     sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
425     for (i = 0; i < YSIZE; i++)
426         sects[i] = &sectsbuf[XSIZE * i];
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         qprint("fairland: error -- continent %c had no room to grow!\n",
730                numletter[c % 62]);
731         fl_status |= STATUS_NO_ROOM;
732     }
733     return done;
734 }
735
736 /* Grow all the continents
737 */
738 static void
739 grow_continents(void)
740 {
741     int c;
742
743     for (c = 0; c < nc; ++c) {
744         sectx[c][0] = capx[c];
745         secty[c][0] = capy[c];
746         own[sectx[c][0]][secty[c][0]] = c;
747         sectx[c][1] = new_x(capx[c] + 2);
748         secty[c][1] = capy[c];
749         own[sectx[c][1]][secty[c][1]] = c;
750     }
751
752     for (secs = 2; secs < sc && !fl_status; ++secs) {
753         for (c = 0; c < nc; ++c) {
754             find_coast(c);
755             grow_one_sector(c);
756         }
757     }
758     if (fl_status)
759         qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
760     ctot = nc;
761 }
762
763 /****************************************************************************
764   GROW THE ISLANDS
765 ****************************************************************************/
766
767 /* Choose a place to start growing an island from
768 */
769 static int
770 place_island(int c, int *xp, int *yp)
771 {
772     int d, sx, sy;
773     int ssy = rnd(WORLD_Y);
774     int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
775
776     if (ssx > WORLD_X - 2)
777         ssx = new_x(ssx + 2);
778     for (d = di + id; d >= id; --d) {
779         sx = ssx;
780         sy = ssy;
781         *xp = new_x(sx + 2);
782         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
783             if (*xp >= WORLD_X) {
784                 *yp = new_y(*yp + 1);
785                 *xp = (*yp) % 2;
786                 if (*xp == sx && *yp == sy)
787                     break;
788             }
789             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
790                 return 1;
791         }
792     }
793     return 0;
794 }
795
796 /* Grow all the islands
797 */
798
799 static void
800 grow_islands(void)
801 {
802     int c, x, y, isiz;
803
804     for (c = nc; c < nc + ni; ++c) {
805         secs = 0;
806         if (!place_island(c, &x, &y))
807             return;
808         isiz = 1 + rnd(2 * is - 1);
809         do {
810             ++secs;
811             find_coast(c);
812         } while (secs < isiz && grow_one_sector(c));
813         qprint(" %d(%d)", c - nc + 1, secs);
814         isecs[c] = secs;
815         ctot = c;
816     }
817 }
818
819 /****************************************************************************
820   CREATE ELEVATIONS
821 ****************************************************************************/
822 static void
823 create_elevations(void)
824 {
825     elevate_land();
826     elevate_sea();
827 }
828
829 /* Generic function for finding the distance to the closest sea, land, or
830    mountain
831 */
832 static int
833 distance_to_what(int x, int y, int flag)
834 {
835     int j, d, px, py;
836
837     for (d = 1; d < 5; ++d) {
838         for (j = 0; j < d; ++j)
839             vector[j] = 0;
840         do {
841             px = x;
842             py = y;
843             for (j = 0; j < d; ++j) {
844                 px = new_x(px + dirx[vector[j]]);
845                 py = new_y(py + diry[vector[j]]);
846             }
847             switch (flag) {
848             case 0:             /* distance to sea */
849                 if (own[px][py] == -1)
850                     return d;
851                 break;
852             case 1:             /* distance to land */
853                 if (own[px][py] != -1)
854                     return d;
855                 break;
856             case 2:             /* distance to mountain */
857                 if (elev[px][py] == INFINITY)
858                     return d;
859                 break;
860             }
861         } while (next_vector(d));
862     }
863     return d;
864 }
865
866 #define ELEV elev[sectx[c][i]][secty[c][i]]
867 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
868 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
869
870 /* Decide where the mountains go
871 */
872 static void
873 elevate_land(void)
874 {
875     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
876         r, dk;
877
878     for (c = 0; c < ctot; ++c) {
879         total = 0;
880         ns = (c < nc) ? sc : isecs[c];
881         nm = (pm * ns) / 100;
882
883 /* Place the mountains */
884
885         for (i = 0; i < ns; ++i) {
886             dsea[i] = distance_to_sea();
887             weight[i] = (total += (dsea[i] * dsea[i]));
888         }
889
890         for (k = nm, mountain_search = 0;
891              k && mountain_search < MOUNTAIN_SEARCH_MAX;
892              ++mountain_search) {
893             r = rnd(total);
894             for (i = 0; i < ns; ++i)
895                 if (r < weight[i] && ELEV == -INFINITY &&
896                     (c >= nc ||
897                      ((!(capx[c] == sectx[c][i] &&
898                          capy[c] == secty[c][i])) &&
899                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
900                          capy[c] == secty[c][i]))))) {
901                     ELEV = INFINITY;
902                     break;
903                 }
904             --k;
905         }
906
907 /* Elevate land that is not mountain and not capital */
908
909         for (i = 0; i < ns; ++i)
910             dmoun[i] = distance_to_mountain();
911         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
912           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
913           100 * INFINITY;
914         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
915             highest = -INFINITY;
916             where = -1;
917             for (i = 0; i < ns; ++i) {
918                 if (ELEV != INFINITY &&
919                     (c >= nc || ((!(capx[c] == sectx[c][i] &&
920                                     capy[c] == secty[c][i])) &&
921                                  (!(new_x(capx[c] + 2) == sectx[c][i] &&
922                                     capy[c] == secty[c][i]))))) {
923                     h = 3 * (5 - dmoun[i]) + dsea[i];
924                     if (h > highest) {
925                         highest = h;
926                         where = i;
927                     }
928                 }
929             }
930             if (where == -1)
931                 break;
932             newk = k / 100;
933             if (newk >= HILLMIN && newk < PLATMIN)
934                 newk = PLATMIN;
935             if (newk < LANDMIN)
936                 newk = LANDMIN;
937             elev[sectx[c][where]][secty[c][where]] = newk;
938             dsea[where] = -INFINITY;
939             dmoun[where] = INFINITY;
940         }
941
942 /* Elevate the mountains and capitals */
943
944         for (i = 0; i < ns; ++i) {
945             if (ELEV == INFINITY) {
946                 if (dsea[i] == 1)
947                     ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
948                 else
949                     ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
950                       rnd((256 - HIGHMIN) / 2);
951             } else if ((c < nc &&
952                         ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
953                        ((new_x(capx[c] + 2) == sectx[c][i] &&
954                          capy[c] == secty[c][i])))
955                 ELEV = PLATMIN;
956         }
957     }
958 }
959
960 #define distance_to_land() distance_to_what(x, y, 1)
961
962 static void
963 elevate_sea(void)
964 {
965     int x, y;
966
967     for (y = 0; y < WORLD_Y; ++y) {
968         for (x = y % 2; x < WORLD_X; x += 2) {
969             if (elev[x][y] == -INFINITY)
970                 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
971         }
972     }
973 }
974
975 /****************************************************************************
976   ADD THE RESOURCES
977 ****************************************************************************/
978
979 static int
980 set_fert(int e)
981 {
982     int fert = 0;
983     if (e < LANDMIN)
984         fert = LANDMIN - e + 40;
985     else if (e < FERT_MAX)
986         fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
987     if (fert > 120)
988         fert = 120;
989     return fert;
990 }
991
992 static int
993 set_oil(int e)
994 {
995     int oil = 0;
996     if (e < LANDMIN)
997         oil = (LANDMIN - e) * 2 + rnd(2);
998     else if (e <= OIL_MAX)
999         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1000     if (oil > 100)
1001         oil = 100;
1002     return oil;
1003 }
1004
1005 static int
1006 set_iron(int e)
1007 {
1008     int iron = 0;
1009     if (e >= IRON_MIN && e < HIGHMIN)
1010         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1011     if (iron > 100)
1012         iron = 100;
1013     return iron;
1014 }
1015
1016 static int
1017 set_gold(int e)
1018 {
1019     int gold = 0;
1020     if (e >= GOLD_MIN) {
1021         if (e < HIGHMIN)
1022             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1023         else
1024             gold = 100 - 20 * HIGHMIN / e;
1025     }
1026     if (gold > 100)
1027         gold = 100;
1028     return gold;
1029 }
1030
1031 static int
1032 set_uran(int e)
1033 {
1034     int uran = 0;
1035     if (e >= URAN_MIN && e < HIGHMIN)
1036         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1037     if (uran > 100)
1038         uran = 100;
1039     return uran;
1040 }
1041
1042 static void
1043 add_resources(struct sctstr *sct)
1044 {
1045     sct->sct_fertil = set_fert(sct->sct_elev);
1046     sct->sct_oil = set_oil(sct->sct_elev);
1047     sct->sct_min = set_iron(sct->sct_elev);
1048     sct->sct_gmin = set_gold(sct->sct_elev);
1049     sct->sct_uran = set_uran(sct->sct_elev);
1050 }
1051
1052 /****************************************************************************
1053   DESIGNATE THE SECTORS
1054 ****************************************************************************/
1055
1056 static void
1057 write_sects(void)
1058 {
1059     struct sctstr *sct;
1060     int c, x, y, total;
1061
1062     /*  sct = &sects[0][0]; */
1063     sct = sectsbuf;
1064     for (y = 0; y < YSIZE; y++) {
1065         for (x = 0; x < XSIZE; x++, sct++) {
1066             fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1067             total = elev[sct->sct_x][y];
1068             if (total < LANDMIN) {
1069                 sct->sct_type = SCT_WATER;
1070             } else if (total < HILLMIN)
1071                 sct->sct_type = SCT_RURAL;
1072             else if (total < PLATMIN)
1073                 sct->sct_type = SCT_MOUNT;
1074             else if (total < HIGHMIN)
1075                 sct->sct_type = SCT_RURAL;
1076             else
1077                 sct->sct_type = SCT_MOUNT;
1078             sct->sct_elev = total;
1079             sct->sct_newtype = sct->sct_type;
1080             if (ORE)
1081                 add_resources(sct);
1082         }
1083     }
1084     if (AIRPORT_MARKER)
1085         for (c = 0; c < nc; ++c) {
1086             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1087             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1088         }
1089 }
1090
1091 /****************************************************************************
1092   WRITE ALL THIS STUFF TO THE FILE
1093 ****************************************************************************/
1094 static int
1095 write_file(void)
1096 {
1097     int n;
1098
1099     /*  if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1100     if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1101         perror(empfile[EF_SECTOR].file);
1102         return -1;
1103     }
1104     if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1105         printf("%s:partial write\n", empfile[EF_SECTOR].file);
1106         return -1;
1107     }
1108     close(the_file);
1109     return 0;
1110 }
1111
1112 /****************************************************************************
1113   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1114 ****************************************************************************/
1115 static void
1116 output(void)
1117 {
1118     int i, j;
1119     if (opt_BLITZ)
1120         translate_continents();
1121     if (quiet == 0) {
1122         for (i = 0; i < WORLD_Y; ++i) {
1123             puts("");
1124             if (i % 2)
1125                 printf(" ");
1126             for (j = i % 2; j < WORLD_X; j += 2) {
1127                 if (own[j][i] == -1)
1128                     printf(". ");
1129                 else {
1130                     printf("%c ", map_symbol(j, i));
1131                 }
1132             }
1133         }
1134     }
1135     if (AIRPORT_MARKER)
1136         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");
1137 }
1138
1139 /* Reorder the continents from top left to bottom right */
1140 static void
1141 translate_continents(void)
1142 {
1143     int i, j, n = 0, k, gotit, c;
1144     int *trans, *trans_cont, *oldcapx, *oldcapy;
1145
1146     trans = (int *)calloc(nc, sizeof(int));
1147     trans_cont = (int *)calloc(nc, sizeof(int));
1148     oldcapx = (int *)calloc(nc, sizeof(int));
1149     oldcapy = (int *)calloc(nc, sizeof(int));
1150
1151     for (i = 0; i < WORLD_Y; ++i) {
1152         for (j = i % 2; j < WORLD_X; j += 2) {
1153             if (own[j][i] > -1 && own[j][i] < nc) {
1154                 gotit = 0;
1155                 for (k = 0; k < n; ++k) {
1156                     if (trans[k] == own[j][i])
1157                         gotit = 1;
1158                 }
1159                 if (!gotit) {
1160                     if (n > nc) {
1161                         printf("fairland: BUG in translate continents!  mail stevens@math.utoronto.ca\n");
1162                         exit(2);
1163                     }
1164                     trans[n] = own[j][i];
1165                     trans_cont[own[j][i]] = n;
1166                     ++n;
1167                 }
1168             }
1169         }
1170     }
1171     for (i = 0; i < WORLD_Y; ++i) {
1172         for (j = i % 2; j < WORLD_X; j += 2) {
1173             if (own[j][i] > -1 && own[j][i] < nc) {
1174                 own[j][i] = trans_cont[own[j][i]];
1175             }
1176         }
1177     }
1178     for (c = 0; c < nc; ++c) {
1179         oldcapx[c] = capx[c];
1180         oldcapy[c] = capy[c];
1181     }
1182     for (c = 0; c < nc; ++c) {
1183         capx[c] = oldcapx[trans[c]];
1184         capy[c] = oldcapy[trans[c]];
1185     }
1186 }
1187
1188 static int
1189 map_symbol(int x, int y)
1190 {
1191     int c, iscap = 0;
1192
1193     for (c = 0; c < nc; ++c)
1194         if ((x == capx[c] && y == capy[c])
1195             || (x == new_x(capx[c] + 2) && y == capy[c]))
1196             iscap = 1;
1197     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1198         || elev[x][y] >= HIGHMIN)
1199         return '^';
1200     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1201 }
1202
1203 /***************************************************************************
1204   WRITE A SCRIPT FOR PLACING CAPITALS
1205 ****************************************************************************/
1206 static int
1207 write_newcap_script(void)
1208 {
1209     int c;
1210     FILE *script = fopen(outfile, "w");
1211
1212     if (!script) {
1213         printf("fairland: error, unable to write to %s.\n", outfile);
1214         return -1;
1215     }
1216
1217     for (c = 0; c < nc; ++c) {
1218         fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1219         if (AIRPORT_MARKER)
1220             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1221         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1222     }
1223     fprintf(script, "add %d visitor visitor v i\n", c + 1);
1224     ++c;
1225     fclose(script);
1226     qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1227            outfile);
1228     return 0;
1229 }
1230
1231 static void
1232 qprint(const char * const fmt, ...)
1233 {
1234     va_list ap;
1235
1236     if (!quiet) {
1237         va_start(ap, fmt);
1238         vfprintf(stdout, fmt, ap);
1239         va_end(ap);
1240     }
1241 }
1242
1243 static void
1244 fl_sct_init(coord x, coord y, s_char *ptr)
1245 {
1246     struct sctstr *sp = (struct sctstr *)ptr;
1247
1248     sp->ef_type = EF_SECTOR;
1249     sp->sct_x = x;
1250     sp->sct_y = y;
1251     sp->sct_dist_x = x;
1252     sp->sct_dist_y = y;
1253     sp->sct_road = 0;
1254     sp->sct_rail = 0;
1255     sp->sct_defense = 0;
1256 }