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