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