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