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