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