]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
(wrmakesrc,wripglob,wrgamesdef,info,apro,mobupdate,rea,turn
[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 FILE *sect_fptr;                        /* 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     sect_fptr = fopen(empfile[EF_SECTOR].file, "wb");
411     if (sect_fptr == NULL) {
412         perror(empfile[EF_SECTOR].file);
413         return -1;
414     }
415     sectsbuf =
416         (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
417     sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
418     for (i = 0; i < YSIZE; i++)
419         sects[i] = &sectsbuf[XSIZE * i];
420     capx = (int *)calloc(nc, sizeof(int));
421     capy = (int *)calloc(nc, sizeof(int));
422     vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
423     mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
424     own = (int **)calloc(WORLD_X, sizeof(int *));
425     elev = (int **)calloc(WORLD_X, sizeof(int *));
426     for (i = 0; i < WORLD_X; ++i) {
427         own[i] = (int *)calloc(WORLD_Y, sizeof(int));
428         elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
429     }
430     sectx = (int **)calloc(nc + ni, sizeof(int *));
431     secty = (int **)calloc(nc + ni, sizeof(int *));
432     sectc = (int **)calloc(nc + ni, sizeof(int *));
433     isecs = (int *)calloc(nc + ni, sizeof(int));
434     weight = (int *)calloc(max(sc, is * 2), sizeof(int));
435     dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
436     dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
437     for (i = 0; i < nc; ++i) {
438         sectx[i] = (int *)calloc(sc, sizeof(int));
439         secty[i] = (int *)calloc(sc, sizeof(int));
440         sectc[i] = (int *)calloc(sc, sizeof(int));
441     }
442     for (i = nc; i < nc + ni; ++i) {
443         sectx[i] = (int *)calloc(is * 2, sizeof(int));
444         secty[i] = (int *)calloc(is * 2, sizeof(int));
445         sectc[i] = (int *)calloc(is * 2, sizeof(int));
446     }
447
448     return 0;
449 }
450
451 static void
452 init(void)
453 {
454     int i, j, xx = 0, yy = 0;
455
456     mcc = 0;
457     fl_status = 0;
458
459     for (i = 0; i < WORLD_X; ++i) {
460         for (j = 0; j < WORLD_Y; ++j) {
461             own[i][j] = -1;
462             elev[i][j] = -INFINITY;
463         }
464     }
465
466     for (i = 0; i < nc; ++i, xx += 2) {
467         if (xx >= WORLD_X) {
468             ++yy;
469             xx = yy % 2;
470             if (yy == WORLD_Y) {
471                 puts("fairland error: world not big enough for all the continents.\n");
472                 exit(1);
473             }
474         }
475         capx[i] = xx;
476         capy[i] = yy;
477     }
478     for (i = 0; i < STABLE_CYCLE; ++i)
479         mc[i] = i;
480 }
481
482 /****************************************************************************
483   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
484 ****************************************************************************/
485
486 /* How isolated is capital j?
487 */
488 static int
489 iso(int j, int newx, int newy)
490 {
491     int i, md, d = WORLD_X + WORLD_Y;
492
493     for (i = 0; i < nc; ++i) {
494         if (i == j)
495             continue;
496         md = mapdist(capx[i], capy[i], newx, newy);
497         if (md < d)
498             d = md;
499     }
500
501     return d;
502 }
503
504 /* Drift all the capitals
505 */
506 static int
507 drift(void)
508 {
509     int i, turns;
510
511     for (turns = 0; turns < DRIFT_MAX; ++turns) {
512         if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
513             return 1;
514         for (i = 0; i < nc; ++i)
515             fl_move(i);
516     }
517     return 0;
518 }
519
520 /* Check to see if we have stabilized--can we stop drifting the capitals?
521 */
522
523 static int
524 stable(void)
525 {
526     int i, isod, d = 0, stab = 1;
527
528     for (i = 0; i < nc; ++i) {
529         isod = iso(i, capx[i], capy[i]);
530         if (isod > d)
531             d = isod;
532     }
533     for (i = 0; i < STABLE_CYCLE; ++i)
534         if (d != mc[i])
535             stab = 0;
536     mc[mcc] = d;
537     mcc = (mcc + 1) % STABLE_CYCLE;
538     return stab ? d : 0;
539 }
540
541 /* This routine does the actual drifting
542 */
543
544 static void
545 fl_move(int j)
546 {
547     int i, n, newx, newy;
548
549     for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
550         newx = new_x(capx[j] + dirx[i]);
551         newy = new_y(capy[j] + diry[i]);
552         if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
553             capx[j] = newx;
554             capy[j] = newy;
555             return;
556         }
557     }
558 }
559
560 /****************************************************************************
561   GROW THE CONTINENTS
562 ****************************************************************************/
563
564 /* Look for a coastal sector of continent c
565 */
566
567 static void
568 find_coast(int c)
569 {
570     int i, j;
571
572     for (i = 0; i < secs; ++i) {
573         sectc[c][i] = 0;
574         for (j = 0; j < 6; ++j)
575             if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
576                 sectc[c][i] = 1;
577     }
578 }
579
580 /* Used for measuring distances
581 */
582 static int
583 next_vector(int n)
584 {
585     int i;
586
587     if (n == 1) {
588         vector[0] += 1;
589         vector[0] %= 6;
590         return vector[0];
591     }
592     for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
593     vector[i - 1] += 1;
594     vector[i - 1] %= 6;
595     return i > 1 || vector[0] > 0;
596 }
597
598 /* Test to see if we're allowed to grow there: the arguments di and id
599 */
600 static int
601 try_to_grow(int c, int newx, int newy, int d)
602 {
603     int i, j, px, py;
604
605     for (i = 1; i <= d; ++i) {
606         for (j = 0; j < i; ++j)
607             vector[j] = 0;
608         do {
609             px = newx;
610             py = newy;
611             for (j = 0; j < i; ++j) {
612                 px = new_x(px + dirx[vector[j]]);
613                 py = new_y(py + diry[vector[j]]);
614             }
615             if (own[px][py] != -1 &&
616                 own[px][py] != c &&
617                 (DISTINCT_ISLANDS || own[px][py] < nc))
618                 return 0;
619         } while (next_vector(i));
620     }
621     sectx[c][secs] = newx;
622     secty[c][secs] = newy;
623     own[newx][newy] = c;
624     return 1;
625 }
626
627 /* Move along the coast in a clockwise direction.
628 */
629
630 static void
631 next_coast(int c, int x, int y, int *xp, int *yp)
632 {
633     int i, nx, ny, wat = 0;
634
635     if (secs == 1) {
636         *xp = x;
637         *yp = y;
638         return;
639     }
640
641     for (i = 0; i < 12; ++i) {
642         nx = new_x(x + dirx[i % 6]);
643         ny = new_y(y + diry[i % 6]);
644         if (own[nx][ny] == -1)
645             wat = 1;
646         if (wat && own[nx][ny] == c) {
647             *xp = nx;
648             *yp = ny;
649             return;
650         }
651     }
652 }
653
654 /* Choose a sector to grow from
655 */
656
657 static int
658 new_try(int c)
659 {
660     int i, starti;
661
662     if (secs == 1) {
663         if (sectc[c][0])
664             return 0;
665     } else {
666         i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
667         do {
668             if (sectc[c][i])
669                 return i;
670             i = (i + 1) % secs;
671         } while (i != starti);
672         if (c < nc) {
673             printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
674                    c + 'a', secs);
675             exit(1);
676         } else
677             return -1;
678     }
679     return -1;
680 }
681
682 /* Grow continent c by 1 sector
683 */
684
685 static int
686 grow_one_sector(int c)
687 {
688     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
689
690     spike = rnd(100) < sp;
691     if ((try1 = new_try(c)) == -1)
692         return 0;
693     x = sx = sectx[c][try1];
694     y = sy = secty[c][try1];
695     coast_search = 0;
696     done = 0;
697     do {
698         if (spike) {
699             for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
700                 newx = new_x(x + dirx[i]);
701                 newy = new_y(y + diry[i]);
702                 if (own[newx][newy] == -1 &&
703                     (n > 5 ||
704                      (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
705                       own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
706                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
707                         done = 1;
708             }
709         } else
710             for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
711                 newx = new_x(x + dirx[i]);
712                 newy = new_y(y + diry[i]);
713                 if (own[newx][newy] == -1)
714                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
715                         done = 1;
716             }
717         next_coast(c, x, y, &x, &y);
718         ++coast_search;
719     } while (!done && coast_search < COAST_SEARCH_MAX &&
720              (secs == 1 || x != sx || y != sy));
721     if (!done && c < nc) {
722         qprint("fairland: error -- continent %c had no room to grow!\n",
723                numletter[c % 62]);
724         fl_status |= STATUS_NO_ROOM;
725     }
726     return done;
727 }
728
729 /* Grow all the continents
730 */
731 static void
732 grow_continents(void)
733 {
734     int c;
735
736     for (c = 0; c < nc; ++c) {
737         sectx[c][0] = capx[c];
738         secty[c][0] = capy[c];
739         own[sectx[c][0]][secty[c][0]] = c;
740         sectx[c][1] = new_x(capx[c] + 2);
741         secty[c][1] = capy[c];
742         own[sectx[c][1]][secty[c][1]] = c;
743     }
744
745     for (secs = 2; secs < sc && !fl_status; ++secs) {
746         for (c = 0; c < nc; ++c) {
747             find_coast(c);
748             grow_one_sector(c);
749         }
750     }
751     if (fl_status)
752         qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
753     ctot = nc;
754 }
755
756 /****************************************************************************
757   GROW THE ISLANDS
758 ****************************************************************************/
759
760 /* Choose a place to start growing an island from
761 */
762 static int
763 place_island(int c, int *xp, int *yp)
764 {
765     int d, sx, sy;
766     int ssy = rnd(WORLD_Y);
767     int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
768
769     if (ssx > WORLD_X - 2)
770         ssx = new_x(ssx + 2);
771     for (d = di + id; d >= id; --d) {
772         sx = ssx;
773         sy = ssy;
774         *xp = new_x(sx + 2);
775         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
776             if (*xp >= WORLD_X) {
777                 *yp = new_y(*yp + 1);
778                 *xp = (*yp) % 2;
779                 if (*xp == sx && *yp == sy)
780                     break;
781             }
782             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
783                 return 1;
784         }
785     }
786     return 0;
787 }
788
789 /* Grow all the islands
790 */
791
792 static void
793 grow_islands(void)
794 {
795     int c, x, y, isiz;
796
797     for (c = nc; c < nc + ni; ++c) {
798         secs = 0;
799         if (!place_island(c, &x, &y))
800             return;
801         isiz = 1 + rnd(2 * is - 1);
802         do {
803             ++secs;
804             find_coast(c);
805         } while (secs < isiz && grow_one_sector(c));
806         qprint(" %d(%d)", c - nc + 1, secs);
807         isecs[c] = secs;
808         ctot = c;
809     }
810 }
811
812 /****************************************************************************
813   CREATE ELEVATIONS
814 ****************************************************************************/
815 static void
816 create_elevations(void)
817 {
818     elevate_land();
819     elevate_sea();
820 }
821
822 /* Generic function for finding the distance to the closest sea, land, or
823    mountain
824 */
825 static int
826 distance_to_what(int x, int y, int flag)
827 {
828     int j, d, px, py;
829
830     for (d = 1; d < 5; ++d) {
831         for (j = 0; j < d; ++j)
832             vector[j] = 0;
833         do {
834             px = x;
835             py = y;
836             for (j = 0; j < d; ++j) {
837                 px = new_x(px + dirx[vector[j]]);
838                 py = new_y(py + diry[vector[j]]);
839             }
840             switch (flag) {
841             case 0:             /* distance to sea */
842                 if (own[px][py] == -1)
843                     return d;
844                 break;
845             case 1:             /* distance to land */
846                 if (own[px][py] != -1)
847                     return d;
848                 break;
849             case 2:             /* distance to mountain */
850                 if (elev[px][py] == INFINITY)
851                     return d;
852                 break;
853             }
854         } while (next_vector(d));
855     }
856     return d;
857 }
858
859 #define ELEV elev[sectx[c][i]][secty[c][i]]
860 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
861 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
862
863 /* Decide where the mountains go
864 */
865 static void
866 elevate_land(void)
867 {
868     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
869         r, dk;
870
871     for (c = 0; c < ctot; ++c) {
872         total = 0;
873         ns = (c < nc) ? sc : isecs[c];
874         nm = (pm * ns) / 100;
875
876 /* Place the mountains */
877
878         for (i = 0; i < ns; ++i) {
879             dsea[i] = distance_to_sea();
880             weight[i] = (total += (dsea[i] * dsea[i]));
881         }
882
883         for (k = nm, mountain_search = 0;
884              k && mountain_search < MOUNTAIN_SEARCH_MAX;
885              ++mountain_search) {
886             r = rnd(total);
887             for (i = 0; i < ns; ++i)
888                 if (r < weight[i] && ELEV == -INFINITY &&
889                     (c >= nc ||
890                      ((!(capx[c] == sectx[c][i] &&
891                          capy[c] == secty[c][i])) &&
892                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
893                          capy[c] == secty[c][i]))))) {
894                     ELEV = INFINITY;
895                     break;
896                 }
897             --k;
898         }
899
900 /* Elevate land that is not mountain and not capital */
901
902         for (i = 0; i < ns; ++i)
903             dmoun[i] = distance_to_mountain();
904         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
905           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
906           100 * INFINITY;
907         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
908             highest = -INFINITY;
909             where = -1;
910             for (i = 0; i < ns; ++i) {
911                 if (ELEV != INFINITY &&
912                     (c >= nc || ((!(capx[c] == sectx[c][i] &&
913                                     capy[c] == secty[c][i])) &&
914                                  (!(new_x(capx[c] + 2) == sectx[c][i] &&
915                                     capy[c] == secty[c][i]))))) {
916                     h = 3 * (5 - dmoun[i]) + dsea[i];
917                     if (h > highest) {
918                         highest = h;
919                         where = i;
920                     }
921                 }
922             }
923             if (where == -1)
924                 break;
925             newk = k / 100;
926             if (newk >= HILLMIN && newk < PLATMIN)
927                 newk = PLATMIN;
928             if (newk < LANDMIN)
929                 newk = LANDMIN;
930             elev[sectx[c][where]][secty[c][where]] = newk;
931             dsea[where] = -INFINITY;
932             dmoun[where] = INFINITY;
933         }
934
935 /* Elevate the mountains and capitals */
936
937         for (i = 0; i < ns; ++i) {
938             if (ELEV == INFINITY) {
939                 if (dsea[i] == 1)
940                     ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
941                 else
942                     ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
943                       rnd((256 - HIGHMIN) / 2);
944             } else if ((c < nc &&
945                         ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
946                        ((new_x(capx[c] + 2) == sectx[c][i] &&
947                          capy[c] == secty[c][i])))
948                 ELEV = PLATMIN;
949         }
950     }
951 }
952
953 #define distance_to_land() distance_to_what(x, y, 1)
954
955 static void
956 elevate_sea(void)
957 {
958     int x, y;
959
960     for (y = 0; y < WORLD_Y; ++y) {
961         for (x = y % 2; x < WORLD_X; x += 2) {
962             if (elev[x][y] == -INFINITY)
963                 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
964         }
965     }
966 }
967
968 /****************************************************************************
969   ADD THE RESOURCES
970 ****************************************************************************/
971
972 static int
973 set_fert(int e)
974 {
975     int fert = 0;
976     if (e < LANDMIN)
977         fert = LANDMIN - e + 40;
978     else if (e < FERT_MAX)
979         fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
980     if (fert > 120)
981         fert = 120;
982     return fert;
983 }
984
985 static int
986 set_oil(int e)
987 {
988     int oil = 0;
989     if (e < LANDMIN)
990         oil = (LANDMIN - e) * 2 + rnd(2);
991     else if (e <= OIL_MAX)
992         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
993     if (oil > 100)
994         oil = 100;
995     return oil;
996 }
997
998 static int
999 set_iron(int e)
1000 {
1001     int iron = 0;
1002     if (e >= IRON_MIN && e < HIGHMIN)
1003         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1004     if (iron > 100)
1005         iron = 100;
1006     return iron;
1007 }
1008
1009 static int
1010 set_gold(int e)
1011 {
1012     int gold = 0;
1013     if (e >= GOLD_MIN) {
1014         if (e < HIGHMIN)
1015             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1016         else
1017             gold = 100 - 20 * HIGHMIN / e;
1018     }
1019     if (gold > 100)
1020         gold = 100;
1021     return gold;
1022 }
1023
1024 static int
1025 set_uran(int e)
1026 {
1027     int uran = 0;
1028     if (e >= URAN_MIN && e < HIGHMIN)
1029         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1030     if (uran > 100)
1031         uran = 100;
1032     return uran;
1033 }
1034
1035 static void
1036 add_resources(struct sctstr *sct)
1037 {
1038     sct->sct_fertil = set_fert(sct->sct_elev);
1039     sct->sct_oil = set_oil(sct->sct_elev);
1040     sct->sct_min = set_iron(sct->sct_elev);
1041     sct->sct_gmin = set_gold(sct->sct_elev);
1042     sct->sct_uran = set_uran(sct->sct_elev);
1043 }
1044
1045 /****************************************************************************
1046   DESIGNATE THE SECTORS
1047 ****************************************************************************/
1048
1049 static void
1050 write_sects(void)
1051 {
1052     struct sctstr *sct;
1053     int c, x, y, total;
1054
1055     /*  sct = &sects[0][0]; */
1056     sct = sectsbuf;
1057     for (y = 0; y < YSIZE; y++) {
1058         for (x = 0; x < XSIZE; x++, sct++) {
1059             fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1060             total = elev[sct->sct_x][y];
1061             if (total < LANDMIN) {
1062                 sct->sct_type = SCT_WATER;
1063             } else if (total < HILLMIN)
1064                 sct->sct_type = SCT_RURAL;
1065             else if (total < PLATMIN)
1066                 sct->sct_type = SCT_MOUNT;
1067             else if (total < HIGHMIN)
1068                 sct->sct_type = SCT_RURAL;
1069             else
1070                 sct->sct_type = SCT_MOUNT;
1071             sct->sct_elev = total;
1072             sct->sct_newtype = sct->sct_type;
1073             if (ORE)
1074                 add_resources(sct);
1075         }
1076     }
1077     if (AIRPORT_MARKER)
1078         for (c = 0; c < nc; ++c) {
1079             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1080             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1081         }
1082 }
1083
1084 /****************************************************************************
1085   WRITE ALL THIS STUFF TO THE FILE
1086 ****************************************************************************/
1087 static int
1088 write_file(void)
1089 {
1090     int n;
1091
1092     if ((n = fwrite((void *)sectsbuf, sizeof(struct sctstr),
1093                     YSIZE * XSIZE, sect_fptr)) <= 0) {
1094         perror(empfile[EF_SECTOR].file);
1095         return -1;
1096     }
1097     if (n != YSIZE * XSIZE) {
1098         printf("%s:partial write\n", empfile[EF_SECTOR].file);
1099         return -1;
1100     }
1101     fclose(sect_fptr);
1102     return 0;
1103 }
1104
1105 /****************************************************************************
1106   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1107 ****************************************************************************/
1108 static void
1109 output(void)
1110 {
1111     int i, j;
1112     if (opt_BLITZ)
1113         translate_continents();
1114     if (quiet == 0) {
1115         for (i = 0; i < WORLD_Y; ++i) {
1116             puts("");
1117             if (i % 2)
1118                 printf(" ");
1119             for (j = i % 2; j < WORLD_X; j += 2) {
1120                 if (own[j][i] == -1)
1121                     printf(". ");
1122                 else {
1123                     printf("%c ", map_symbol(j, i));
1124                 }
1125             }
1126         }
1127     }
1128     if (AIRPORT_MARKER)
1129         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");
1130 }
1131
1132 /* Reorder the continents from top left to bottom right */
1133 static void
1134 translate_continents(void)
1135 {
1136     int i, j, n = 0, k, gotit, c;
1137     int *trans, *trans_cont, *oldcapx, *oldcapy;
1138
1139     trans = (int *)calloc(nc, sizeof(int));
1140     trans_cont = (int *)calloc(nc, sizeof(int));
1141     oldcapx = (int *)calloc(nc, sizeof(int));
1142     oldcapy = (int *)calloc(nc, sizeof(int));
1143
1144     for (i = 0; i < WORLD_Y; ++i) {
1145         for (j = i % 2; j < WORLD_X; j += 2) {
1146             if (own[j][i] > -1 && own[j][i] < nc) {
1147                 gotit = 0;
1148                 for (k = 0; k < n; ++k) {
1149                     if (trans[k] == own[j][i])
1150                         gotit = 1;
1151                 }
1152                 if (!gotit) {
1153                     if (n > nc) {
1154                         printf("fairland: BUG in translate continents!  mail stevens@math.utoronto.ca\n");
1155                         exit(2);
1156                     }
1157                     trans[n] = own[j][i];
1158                     trans_cont[own[j][i]] = n;
1159                     ++n;
1160                 }
1161             }
1162         }
1163     }
1164     for (i = 0; i < WORLD_Y; ++i) {
1165         for (j = i % 2; j < WORLD_X; j += 2) {
1166             if (own[j][i] > -1 && own[j][i] < nc) {
1167                 own[j][i] = trans_cont[own[j][i]];
1168             }
1169         }
1170     }
1171     for (c = 0; c < nc; ++c) {
1172         oldcapx[c] = capx[c];
1173         oldcapy[c] = capy[c];
1174     }
1175     for (c = 0; c < nc; ++c) {
1176         capx[c] = oldcapx[trans[c]];
1177         capy[c] = oldcapy[trans[c]];
1178     }
1179 }
1180
1181 static int
1182 map_symbol(int x, int y)
1183 {
1184     int c, iscap = 0;
1185
1186     for (c = 0; c < nc; ++c)
1187         if ((x == capx[c] && y == capy[c])
1188             || (x == new_x(capx[c] + 2) && y == capy[c]))
1189             iscap = 1;
1190     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1191         || elev[x][y] >= HIGHMIN)
1192         return '^';
1193     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1194 }
1195
1196 /***************************************************************************
1197   WRITE A SCRIPT FOR PLACING CAPITALS
1198 ****************************************************************************/
1199 static int
1200 write_newcap_script(void)
1201 {
1202     int c;
1203     FILE *script = fopen(outfile, "w");
1204
1205     if (!script) {
1206         printf("fairland: error, unable to write to %s.\n", outfile);
1207         return -1;
1208     }
1209
1210     for (c = 0; c < nc; ++c) {
1211         fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1212         if (AIRPORT_MARKER)
1213             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1214         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1215     }
1216     fprintf(script, "add %d visitor visitor v i\n", c + 1);
1217     ++c;
1218     fclose(script);
1219     qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1220            outfile);
1221     return 0;
1222 }
1223
1224 static void
1225 qprint(const char * const fmt, ...)
1226 {
1227     va_list ap;
1228
1229     if (!quiet) {
1230         va_start(ap, fmt);
1231         vfprintf(stdout, fmt, ap);
1232         va_end(ap);
1233     }
1234 }
1235
1236 static void
1237 fl_sct_init(coord x, coord y, s_char *ptr)
1238 {
1239     struct sctstr *sp = (struct sctstr *)ptr;
1240
1241     sp->ef_type = EF_SECTOR;
1242     sp->sct_x = x;
1243     sp->sct_y = y;
1244     sp->sct_dist_x = x;
1245     sp->sct_dist_y = y;
1246     sp->sct_road = 0;
1247     sp->sct_rail = 0;
1248     sp->sct_defense = 0;
1249 }