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