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