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