]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
(main,allocate_memory) [_WIN32]: switch the default file mode to
[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 int the_file;                   /* 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     the_file = open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC,
415                     0660);
416     if (the_file < 0) {
417         perror(empfile[EF_SECTOR].file);
418         return -1;
419     }
420     sectsbuf =
421         (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
422     sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
423     for (i = 0; i < YSIZE; i++)
424         sects[i] = &sectsbuf[XSIZE * i];
425     capx = (int *)calloc(nc, sizeof(int));
426     capy = (int *)calloc(nc, sizeof(int));
427     vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
428     mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
429     own = (int **)calloc(WORLD_X, sizeof(int *));
430     elev = (int **)calloc(WORLD_X, sizeof(int *));
431     for (i = 0; i < WORLD_X; ++i) {
432         own[i] = (int *)calloc(WORLD_Y, sizeof(int));
433         elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
434     }
435     sectx = (int **)calloc(nc + ni, sizeof(int *));
436     secty = (int **)calloc(nc + ni, sizeof(int *));
437     sectc = (int **)calloc(nc + ni, sizeof(int *));
438     isecs = (int *)calloc(nc + ni, sizeof(int));
439     weight = (int *)calloc(max(sc, is * 2), sizeof(int));
440     dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
441     dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
442     for (i = 0; i < nc; ++i) {
443         sectx[i] = (int *)calloc(sc, sizeof(int));
444         secty[i] = (int *)calloc(sc, sizeof(int));
445         sectc[i] = (int *)calloc(sc, sizeof(int));
446     }
447     for (i = nc; i < nc + ni; ++i) {
448         sectx[i] = (int *)calloc(is * 2, sizeof(int));
449         secty[i] = (int *)calloc(is * 2, sizeof(int));
450         sectc[i] = (int *)calloc(is * 2, sizeof(int));
451     }
452
453     return 0;
454 }
455
456 static void
457 init(void)
458 {
459     int i, j, xx = 0, yy = 0;
460
461     mcc = 0;
462     fl_status = 0;
463
464     for (i = 0; i < WORLD_X; ++i) {
465         for (j = 0; j < WORLD_Y; ++j) {
466             own[i][j] = -1;
467             elev[i][j] = -INFINITY;
468         }
469     }
470
471     for (i = 0; i < nc; ++i, xx += 2) {
472         if (xx >= WORLD_X) {
473             ++yy;
474             xx = yy % 2;
475             if (yy == WORLD_Y) {
476                 puts("fairland error: world not big enough for all the continents.\n");
477                 exit(1);
478             }
479         }
480         capx[i] = xx;
481         capy[i] = yy;
482     }
483     for (i = 0; i < STABLE_CYCLE; ++i)
484         mc[i] = i;
485 }
486
487 /****************************************************************************
488   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
489 ****************************************************************************/
490
491 /* How isolated is capital j?
492 */
493 static int
494 iso(int j, int newx, int newy)
495 {
496     int i, md, d = WORLD_X + WORLD_Y;
497
498     for (i = 0; i < nc; ++i) {
499         if (i == j)
500             continue;
501         md = mapdist(capx[i], capy[i], newx, newy);
502         if (md < d)
503             d = md;
504     }
505
506     return d;
507 }
508
509 /* Drift all the capitals
510 */
511 static int
512 drift(void)
513 {
514     int i, turns;
515
516     for (turns = 0; turns < DRIFT_MAX; ++turns) {
517         if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
518             return 1;
519         for (i = 0; i < nc; ++i)
520             fl_move(i);
521     }
522     return 0;
523 }
524
525 /* Check to see if we have stabilized--can we stop drifting the capitals?
526 */
527
528 static int
529 stable(void)
530 {
531     int i, isod, d = 0, stab = 1;
532
533     for (i = 0; i < nc; ++i) {
534         isod = iso(i, capx[i], capy[i]);
535         if (isod > d)
536             d = isod;
537     }
538     for (i = 0; i < STABLE_CYCLE; ++i)
539         if (d != mc[i])
540             stab = 0;
541     mc[mcc] = d;
542     mcc = (mcc + 1) % STABLE_CYCLE;
543     return stab ? d : 0;
544 }
545
546 /* This routine does the actual drifting
547 */
548
549 static void
550 fl_move(int j)
551 {
552     int i, n, newx, newy;
553
554     for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
555         newx = new_x(capx[j] + dirx[i]);
556         newy = new_y(capy[j] + diry[i]);
557         if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
558             capx[j] = newx;
559             capy[j] = newy;
560             return;
561         }
562     }
563 }
564
565 /****************************************************************************
566   GROW THE CONTINENTS
567 ****************************************************************************/
568
569 /* Look for a coastal sector of continent c
570 */
571
572 static void
573 find_coast(int c)
574 {
575     int i, j;
576
577     for (i = 0; i < secs; ++i) {
578         sectc[c][i] = 0;
579         for (j = 0; j < 6; ++j)
580             if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
581                 sectc[c][i] = 1;
582     }
583 }
584
585 /* Used for measuring distances
586 */
587 static int
588 next_vector(int n)
589 {
590     int i;
591
592     if (n == 1) {
593         vector[0] += 1;
594         vector[0] %= 6;
595         return vector[0];
596     }
597     for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
598     vector[i - 1] += 1;
599     vector[i - 1] %= 6;
600     return i > 1 || vector[0] > 0;
601 }
602
603 /* Test to see if we're allowed to grow there: the arguments di and id
604 */
605 static int
606 try_to_grow(int c, int newx, int newy, int d)
607 {
608     int i, j, px, py;
609
610     for (i = 1; i <= d; ++i) {
611         for (j = 0; j < i; ++j)
612             vector[j] = 0;
613         do {
614             px = newx;
615             py = newy;
616             for (j = 0; j < i; ++j) {
617                 px = new_x(px + dirx[vector[j]]);
618                 py = new_y(py + diry[vector[j]]);
619             }
620             if (own[px][py] != -1 &&
621                 own[px][py] != c &&
622                 (DISTINCT_ISLANDS || own[px][py] < nc))
623                 return 0;
624         } while (next_vector(i));
625     }
626     sectx[c][secs] = newx;
627     secty[c][secs] = newy;
628     own[newx][newy] = c;
629     return 1;
630 }
631
632 /* Move along the coast in a clockwise direction.
633 */
634
635 static void
636 next_coast(int c, int x, int y, int *xp, int *yp)
637 {
638     int i, nx, ny, wat = 0;
639
640     if (secs == 1) {
641         *xp = x;
642         *yp = y;
643         return;
644     }
645
646     for (i = 0; i < 12; ++i) {
647         nx = new_x(x + dirx[i % 6]);
648         ny = new_y(y + diry[i % 6]);
649         if (own[nx][ny] == -1)
650             wat = 1;
651         if (wat && own[nx][ny] == c) {
652             *xp = nx;
653             *yp = ny;
654             return;
655         }
656     }
657 }
658
659 /* Choose a sector to grow from
660 */
661
662 static int
663 new_try(int c)
664 {
665     int i, starti;
666
667     if (secs == 1) {
668         if (sectc[c][0])
669             return 0;
670     } else {
671         i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
672         do {
673             if (sectc[c][i])
674                 return i;
675             i = (i + 1) % secs;
676         } while (i != starti);
677         if (c < nc) {
678             printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
679                    c + 'a', secs);
680             exit(1);
681         } else
682             return -1;
683     }
684     return -1;
685 }
686
687 /* Grow continent c by 1 sector
688 */
689
690 static int
691 grow_one_sector(int c)
692 {
693     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
694
695     spike = rnd(100) < sp;
696     if ((try1 = new_try(c)) == -1)
697         return 0;
698     x = sx = sectx[c][try1];
699     y = sy = secty[c][try1];
700     coast_search = 0;
701     done = 0;
702     do {
703         if (spike) {
704             for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
705                 newx = new_x(x + dirx[i]);
706                 newy = new_y(y + diry[i]);
707                 if (own[newx][newy] == -1 &&
708                     (n > 5 ||
709                      (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
710                       own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
711                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
712                         done = 1;
713             }
714         } else
715             for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
716                 newx = new_x(x + dirx[i]);
717                 newy = new_y(y + diry[i]);
718                 if (own[newx][newy] == -1)
719                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
720                         done = 1;
721             }
722         next_coast(c, x, y, &x, &y);
723         ++coast_search;
724     } while (!done && coast_search < COAST_SEARCH_MAX &&
725              (secs == 1 || x != sx || y != sy));
726     if (!done && c < nc) {
727         qprint("fairland: error -- continent %c had no room to grow!\n",
728                numletter[c % 62]);
729         fl_status |= STATUS_NO_ROOM;
730     }
731     return done;
732 }
733
734 /* Grow all the continents
735 */
736 static void
737 grow_continents(void)
738 {
739     int c;
740
741     for (c = 0; c < nc; ++c) {
742         sectx[c][0] = capx[c];
743         secty[c][0] = capy[c];
744         own[sectx[c][0]][secty[c][0]] = c;
745         sectx[c][1] = new_x(capx[c] + 2);
746         secty[c][1] = capy[c];
747         own[sectx[c][1]][secty[c][1]] = c;
748     }
749
750     for (secs = 2; secs < sc && !fl_status; ++secs) {
751         for (c = 0; c < nc; ++c) {
752             find_coast(c);
753             grow_one_sector(c);
754         }
755     }
756     if (fl_status)
757         qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
758     ctot = nc;
759 }
760
761 /****************************************************************************
762   GROW THE ISLANDS
763 ****************************************************************************/
764
765 /* Choose a place to start growing an island from
766 */
767 static int
768 place_island(int c, int *xp, int *yp)
769 {
770     int d, sx, sy;
771     int ssy = rnd(WORLD_Y);
772     int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
773
774     if (ssx > WORLD_X - 2)
775         ssx = new_x(ssx + 2);
776     for (d = di + id; d >= id; --d) {
777         sx = ssx;
778         sy = ssy;
779         *xp = new_x(sx + 2);
780         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
781             if (*xp >= WORLD_X) {
782                 *yp = new_y(*yp + 1);
783                 *xp = (*yp) % 2;
784                 if (*xp == sx && *yp == sy)
785                     break;
786             }
787             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
788                 return 1;
789         }
790     }
791     return 0;
792 }
793
794 /* Grow all the islands
795 */
796
797 static void
798 grow_islands(void)
799 {
800     int c, x, y, isiz;
801
802     for (c = nc; c < nc + ni; ++c) {
803         secs = 0;
804         if (!place_island(c, &x, &y))
805             return;
806         isiz = 1 + rnd(2 * is - 1);
807         do {
808             ++secs;
809             find_coast(c);
810         } while (secs < isiz && grow_one_sector(c));
811         qprint(" %d(%d)", c - nc + 1, secs);
812         isecs[c] = secs;
813         ctot = c;
814     }
815 }
816
817 /****************************************************************************
818   CREATE ELEVATIONS
819 ****************************************************************************/
820 static void
821 create_elevations(void)
822 {
823     elevate_land();
824     elevate_sea();
825 }
826
827 /* Generic function for finding the distance to the closest sea, land, or
828    mountain
829 */
830 static int
831 distance_to_what(int x, int y, int flag)
832 {
833     int j, d, px, py;
834
835     for (d = 1; d < 5; ++d) {
836         for (j = 0; j < d; ++j)
837             vector[j] = 0;
838         do {
839             px = x;
840             py = y;
841             for (j = 0; j < d; ++j) {
842                 px = new_x(px + dirx[vector[j]]);
843                 py = new_y(py + diry[vector[j]]);
844             }
845             switch (flag) {
846             case 0:             /* distance to sea */
847                 if (own[px][py] == -1)
848                     return d;
849                 break;
850             case 1:             /* distance to land */
851                 if (own[px][py] != -1)
852                     return d;
853                 break;
854             case 2:             /* distance to mountain */
855                 if (elev[px][py] == INFINITY)
856                     return d;
857                 break;
858             }
859         } while (next_vector(d));
860     }
861     return d;
862 }
863
864 #define ELEV elev[sectx[c][i]][secty[c][i]]
865 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
866 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
867
868 /* Decide where the mountains go
869 */
870 static void
871 elevate_land(void)
872 {
873     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
874         r, dk;
875
876     for (c = 0; c < ctot; ++c) {
877         total = 0;
878         ns = (c < nc) ? sc : isecs[c];
879         nm = (pm * ns) / 100;
880
881 /* Place the mountains */
882
883         for (i = 0; i < ns; ++i) {
884             dsea[i] = distance_to_sea();
885             weight[i] = (total += (dsea[i] * dsea[i]));
886         }
887
888         for (k = nm, mountain_search = 0;
889              k && mountain_search < MOUNTAIN_SEARCH_MAX;
890              ++mountain_search) {
891             r = rnd(total);
892             for (i = 0; i < ns; ++i)
893                 if (r < weight[i] && ELEV == -INFINITY &&
894                     (c >= nc ||
895                      ((!(capx[c] == sectx[c][i] &&
896                          capy[c] == secty[c][i])) &&
897                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
898                          capy[c] == secty[c][i]))))) {
899                     ELEV = INFINITY;
900                     break;
901                 }
902             --k;
903         }
904
905 /* Elevate land that is not mountain and not capital */
906
907         for (i = 0; i < ns; ++i)
908             dmoun[i] = distance_to_mountain();
909         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
910           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
911           100 * INFINITY;
912         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
913             highest = -INFINITY;
914             where = -1;
915             for (i = 0; i < ns; ++i) {
916                 if (ELEV != INFINITY &&
917                     (c >= nc || ((!(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                     h = 3 * (5 - dmoun[i]) + dsea[i];
922                     if (h > highest) {
923                         highest = h;
924                         where = i;
925                     }
926                 }
927             }
928             if (where == -1)
929                 break;
930             newk = k / 100;
931             if (newk >= HILLMIN && newk < PLATMIN)
932                 newk = PLATMIN;
933             if (newk < LANDMIN)
934                 newk = LANDMIN;
935             elev[sectx[c][where]][secty[c][where]] = newk;
936             dsea[where] = -INFINITY;
937             dmoun[where] = INFINITY;
938         }
939
940 /* Elevate the mountains and capitals */
941
942         for (i = 0; i < ns; ++i) {
943             if (ELEV == INFINITY) {
944                 if (dsea[i] == 1)
945                     ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
946                 else
947                     ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
948                       rnd((256 - HIGHMIN) / 2);
949             } else if ((c < nc &&
950                         ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
951                        ((new_x(capx[c] + 2) == sectx[c][i] &&
952                          capy[c] == secty[c][i])))
953                 ELEV = PLATMIN;
954         }
955     }
956 }
957
958 #define distance_to_land() distance_to_what(x, y, 1)
959
960 static void
961 elevate_sea(void)
962 {
963     int x, y;
964
965     for (y = 0; y < WORLD_Y; ++y) {
966         for (x = y % 2; x < WORLD_X; x += 2) {
967             if (elev[x][y] == -INFINITY)
968                 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
969         }
970     }
971 }
972
973 /****************************************************************************
974   ADD THE RESOURCES
975 ****************************************************************************/
976
977 static int
978 set_fert(int e)
979 {
980     int fert = 0;
981     if (e < LANDMIN)
982         fert = LANDMIN - e + 40;
983     else if (e < FERT_MAX)
984         fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
985     if (fert > 120)
986         fert = 120;
987     return fert;
988 }
989
990 static int
991 set_oil(int e)
992 {
993     int oil = 0;
994     if (e < LANDMIN)
995         oil = (LANDMIN - e) * 2 + rnd(2);
996     else if (e <= OIL_MAX)
997         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
998     if (oil > 100)
999         oil = 100;
1000     return oil;
1001 }
1002
1003 static int
1004 set_iron(int e)
1005 {
1006     int iron = 0;
1007     if (e >= IRON_MIN && e < HIGHMIN)
1008         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1009     if (iron > 100)
1010         iron = 100;
1011     return iron;
1012 }
1013
1014 static int
1015 set_gold(int e)
1016 {
1017     int gold = 0;
1018     if (e >= GOLD_MIN) {
1019         if (e < HIGHMIN)
1020             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1021         else
1022             gold = 100 - 20 * HIGHMIN / e;
1023     }
1024     if (gold > 100)
1025         gold = 100;
1026     return gold;
1027 }
1028
1029 static int
1030 set_uran(int e)
1031 {
1032     int uran = 0;
1033     if (e >= URAN_MIN && e < HIGHMIN)
1034         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1035     if (uran > 100)
1036         uran = 100;
1037     return uran;
1038 }
1039
1040 static void
1041 add_resources(struct sctstr *sct)
1042 {
1043     sct->sct_fertil = set_fert(sct->sct_elev);
1044     sct->sct_oil = set_oil(sct->sct_elev);
1045     sct->sct_min = set_iron(sct->sct_elev);
1046     sct->sct_gmin = set_gold(sct->sct_elev);
1047     sct->sct_uran = set_uran(sct->sct_elev);
1048 }
1049
1050 /****************************************************************************
1051   DESIGNATE THE SECTORS
1052 ****************************************************************************/
1053
1054 static void
1055 write_sects(void)
1056 {
1057     struct sctstr *sct;
1058     int c, x, y, total;
1059
1060     /*  sct = &sects[0][0]; */
1061     sct = sectsbuf;
1062     for (y = 0; y < YSIZE; y++) {
1063         for (x = 0; x < XSIZE; x++, sct++) {
1064             fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1065             total = elev[sct->sct_x][y];
1066             if (total < LANDMIN) {
1067                 sct->sct_type = SCT_WATER;
1068             } else if (total < HILLMIN)
1069                 sct->sct_type = SCT_RURAL;
1070             else if (total < PLATMIN)
1071                 sct->sct_type = SCT_MOUNT;
1072             else if (total < HIGHMIN)
1073                 sct->sct_type = SCT_RURAL;
1074             else
1075                 sct->sct_type = SCT_MOUNT;
1076             sct->sct_elev = total;
1077             sct->sct_newtype = sct->sct_type;
1078             if (ORE)
1079                 add_resources(sct);
1080         }
1081     }
1082     if (AIRPORT_MARKER)
1083         for (c = 0; c < nc; ++c) {
1084             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1085             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1086         }
1087 }
1088
1089 /****************************************************************************
1090   WRITE ALL THIS STUFF TO THE FILE
1091 ****************************************************************************/
1092 static int
1093 write_file(void)
1094 {
1095     int n;
1096
1097     /*  if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1098     if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1099         perror(empfile[EF_SECTOR].file);
1100         return -1;
1101     }
1102     if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1103         printf("%s:partial write\n", empfile[EF_SECTOR].file);
1104         return -1;
1105     }
1106     close(the_file);
1107     return 0;
1108 }
1109
1110 /****************************************************************************
1111   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1112 ****************************************************************************/
1113 static void
1114 output(void)
1115 {
1116     int i, j;
1117     if (opt_BLITZ)
1118         translate_continents();
1119     if (quiet == 0) {
1120         for (i = 0; i < WORLD_Y; ++i) {
1121             puts("");
1122             if (i % 2)
1123                 printf(" ");
1124             for (j = i % 2; j < WORLD_X; j += 2) {
1125                 if (own[j][i] == -1)
1126                     printf(". ");
1127                 else {
1128                     printf("%c ", map_symbol(j, i));
1129                 }
1130             }
1131         }
1132     }
1133     if (AIRPORT_MARKER)
1134         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");
1135 }
1136
1137 /* Reorder the continents from top left to bottom right */
1138 static void
1139 translate_continents(void)
1140 {
1141     int i, j, n = 0, k, gotit, c;
1142     int *trans, *trans_cont, *oldcapx, *oldcapy;
1143
1144     trans = (int *)calloc(nc, sizeof(int));
1145     trans_cont = (int *)calloc(nc, sizeof(int));
1146     oldcapx = (int *)calloc(nc, sizeof(int));
1147     oldcapy = (int *)calloc(nc, sizeof(int));
1148
1149     for (i = 0; i < WORLD_Y; ++i) {
1150         for (j = i % 2; j < WORLD_X; j += 2) {
1151             if (own[j][i] > -1 && own[j][i] < nc) {
1152                 gotit = 0;
1153                 for (k = 0; k < n; ++k) {
1154                     if (trans[k] == own[j][i])
1155                         gotit = 1;
1156                 }
1157                 if (!gotit) {
1158                     if (n > nc) {
1159                         printf("fairland: BUG in translate continents!  mail stevens@math.utoronto.ca\n");
1160                         exit(2);
1161                     }
1162                     trans[n] = own[j][i];
1163                     trans_cont[own[j][i]] = n;
1164                     ++n;
1165                 }
1166             }
1167         }
1168     }
1169     for (i = 0; i < WORLD_Y; ++i) {
1170         for (j = i % 2; j < WORLD_X; j += 2) {
1171             if (own[j][i] > -1 && own[j][i] < nc) {
1172                 own[j][i] = trans_cont[own[j][i]];
1173             }
1174         }
1175     }
1176     for (c = 0; c < nc; ++c) {
1177         oldcapx[c] = capx[c];
1178         oldcapy[c] = capy[c];
1179     }
1180     for (c = 0; c < nc; ++c) {
1181         capx[c] = oldcapx[trans[c]];
1182         capy[c] = oldcapy[trans[c]];
1183     }
1184 }
1185
1186 static int
1187 map_symbol(int x, int y)
1188 {
1189     int c, iscap = 0;
1190
1191     for (c = 0; c < nc; ++c)
1192         if ((x == capx[c] && y == capy[c])
1193             || (x == new_x(capx[c] + 2) && y == capy[c]))
1194             iscap = 1;
1195     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1196         || elev[x][y] >= HIGHMIN)
1197         return '^';
1198     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1199 }
1200
1201 /***************************************************************************
1202   WRITE A SCRIPT FOR PLACING CAPITALS
1203 ****************************************************************************/
1204 static int
1205 write_newcap_script(void)
1206 {
1207     int c;
1208     FILE *script = fopen(outfile, "w");
1209
1210     if (!script) {
1211         printf("fairland: error, unable to write to %s.\n", outfile);
1212         return -1;
1213     }
1214
1215     for (c = 0; c < nc; ++c) {
1216         fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1217         if (AIRPORT_MARKER)
1218             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1219         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1220     }
1221     fprintf(script, "add %d visitor visitor v i\n", c + 1);
1222     ++c;
1223     fclose(script);
1224     qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1225            outfile);
1226     return 0;
1227 }
1228
1229 static void
1230 qprint(const char * const fmt, ...)
1231 {
1232     va_list ap;
1233
1234     if (!quiet) {
1235         va_start(ap, fmt);
1236         vfprintf(stdout, fmt, ap);
1237         va_end(ap);
1238     }
1239 }
1240
1241 static void
1242 fl_sct_init(coord x, coord y, s_char *ptr)
1243 {
1244     struct sctstr *sp = (struct sctstr *)ptr;
1245
1246     sp->ef_type = EF_SECTOR;
1247     sp->sct_x = x;
1248     sp->sct_y = y;
1249     sp->sct_dist_x = x;
1250     sp->sct_dist_y = y;
1251     sp->sct_road = 0;
1252     sp->sct_rail = 0;
1253     sp->sct_defense = 0;
1254 }