]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
Add some missing declarations to headers. Remove some redundant
[empserver] / src / util / fairland.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23  *  related information and legal notices. It is expected that any future
24  *  projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  fairland.c: Create a nice, new world
29  * 
30  *  Known contributors to this file:
31  *     Ken Stevens, 1995
32  *     Steve McClure, 1998
33  */
34
35 /* define ORE 1 to add resources, define ORE 0 if you want to use another
36    program to add the resources */
37 static int ORE = 1;
38 static int quiet = 0;
39
40 /* If you don't specify these command line arguments, then these are the
41    defaults */
42 #define DEFAULT_SPIKE 10
43 #define DEFAULT_MOUNTAIN 0
44 #define DEFAULT_CONTDIST 2
45 #define DEFAULT_ISLDIST 1
46
47 /* The following five numbers refer to elevation under which (in the case of
48    fertility or oil) or over which (in the case of iron, gold, and uranium)
49    sectors with that elevation will contain that resource.  Elevation ranges
50    from 0 to 100 */
51
52 /* raise FERT_MAX for more fertility */
53 #define FERT_MAX   56
54
55 /* raise OIL_MAX for more oil */
56 #define OIL_MAX    33
57
58 /* lower IRON_MIN for more iron */
59 #define IRON_MIN   22
60
61 /* lower GOLD_MIN for more gold */
62 #define GOLD_MIN   36
63
64 /* lower URAN_MIN for more uranium */
65 #define URAN_MIN   56
66
67 #if defined(aix) || defined(linux) || defined(solaris)
68 #include <unistd.h>
69 #endif /* aix or linux */
70
71 #include <stdio.h>
72 #include <fcntl.h>
73 #include "var.h"
74 #include "misc.h"
75 #include "power.h"
76 #include "nat.h"
77 #include "sect.h"
78 #include "gamesdef.h"
79 #include "file.h"
80 #include "xy.h"
81 #include "optlist.h"
82 #include "prototypes.h"
83
84 /* do not change these 4 defines */
85 #define LANDMIN         1       /* plate altitude for normal land */
86 #define HILLMIN         34      /* plate altitude for hills */
87 #define PLATMIN         36      /* plate altitude for plateau */
88 #define HIGHMIN         98      /* plate altitude for mountains */
89
90 static void qprint(const char *str);
91
92 static const char *outfile = "newcap_script";
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 #define XSIZE           ((WORLD_X) / 2) /* basically world x-y size */
102 #define YSIZE           (WORLD_Y)
103 #define STABLE_CYCLE 4          /* stability required for perterbed capitals */
104 #define INFINITY        999     /* a number which means "BIG" */
105
106 /* these defines prevent infinite loops:
107 */
108
109 #define COAST_SEARCH_MAX 200    /* how many times do we look for a coast sector
110                                    when growing continents and islands */
111 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
112 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
113 #define MOUNTAIN_SEARCH_MAX 1000        /* how long do we try to place mountains */
114
115 /* handy macros:
116 */
117
118 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
119 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
120 #if !defined(_WIN32)
121 #define max(a,b) (a>b?a:b)
122 #endif
123 #define rnd(x) (random() % (x))
124
125 int secs;                       /* number of sectors grown */
126 int ctot;                       /* total number of continents and islands grown */
127 int *isecs;                     /* array of how large each island is */
128
129 int nc, sc, di, sp, pm, ni, is, id;     /* the 8 arguments to this program */
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 int the_file;                   /* 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 parse_args(int argc, char *argv[]);
157 static int allocate_memory(void);
158 static void init(void);
159 static int drift(void);
160 static void grow_continents(void);
161 static void create_elevations(void);
162 static void write_sects(void);
163 static int write_file(void);
164 static void output(void);
165 static int write_newcap_script(void);
166 static int stable(void);
167 static void elevate_land(void);
168 static void elevate_sea(void);
169 static void translate_continents(void);
170 static int map_symbol(int x, int y);
171 static void fl_sct_init(coord x, coord y, s_char *ptr);
172
173 static void print_vars(void);
174 static void fl_move(int);
175 static void next_coast(int c, int x, int y, int *xp, int *yp);
176 static void grow_islands(void);
177
178 /****************************************************************************
179   MAIN
180 ****************************************************************************/
181
182 int
183 main(int argc, char *argv[])
184 {
185     int opt;
186     extern int optind;
187     extern char *optarg;
188     char *config_file = NULL;
189     char tbuf[512];
190     int i = 0;
191
192 #if !defined(_WIN32)
193     while ((opt = getopt(argc, argv, "ae:ioqs:")) != EOF) {
194         switch (opt) {
195         case 'a':
196             AIRPORT_MARKER = 1;
197             break;
198         case 'i':
199             DISTINCT_ISLANDS = 0;
200             break;
201         case 'e':
202             config_file = optarg;
203             break;
204         case 'o':
205             ORE = 0;
206             break;
207         case 'q':
208             quiet = 1;
209             break;
210         case 's':
211             outfile = optarg;
212             break;
213         }
214     }
215 #endif
216     if (config_file == NULL) {
217         sprintf(tbuf, "%s/econfig", datadir);
218         config_file = tbuf;
219     }
220     emp_config(config_file);
221
222 #if !defined(_WIN32)
223     parse_args(argc - optind, argv + optind);
224 #else
225     parse_args(argc - 1, argv + 1);
226 #endif
227     if (allocate_memory() == -1)
228         exit(-1);
229     print_vars();
230
231     do {
232         init();
233         if (!quiet && i)
234             printf("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
235         qprint("\n\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
236         qprint("placing capitals...\n");
237         if (!drift())
238             qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
239         qprint("growing continents...\n");
240         grow_continents();
241     } while (fl_status && ++i < NUMTRIES);
242     if (fl_status) {
243         fputs("ERROR: World not large enough to hold continents\n",
244               stderr);
245         exit(1);
246     }
247     qprint("growing islands:");
248     grow_islands();
249     qprint("\nelevating land...\n");
250     create_elevations();
251     qprint("designating sectors...\n");
252     if (ORE)
253         qprint("adding resources...\n");
254     write_sects();
255     qprint("writing to sectors file...\n");
256     if (write_file() == -1)
257         exit(-1);
258     output();
259     write_newcap_script();
260     exit(0);
261 }
262
263 static void
264 print_vars(void)
265 {
266     if (quiet)
267         return;
268     puts("Creating a planet with:\n");
269     printf("%d continents\n", nc);
270     printf("continent size: %d\n", sc);
271     printf("number of islands: %d\n", ni);
272     printf("average size of islands: %d\n", is);
273     printf("spike: %d%%\n", sp);
274     printf("%d%% of land is mountain (each continent will have %d mountains)\n",
275            pm, (pm * sc) / 100);
276     printf("minimum distance between continents: %d\n", di);
277     printf("minimum distance from islands to continents: %d\n", id);
278     printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
279 }
280
281 static int
282 my_sqrt(int n)
283 {
284     int i;
285
286     for (i = 1; i * i < n * 10000; ++i) ;
287     return (i + 50) / 100;
288 }
289
290 /****************************************************************************
291   PARSE COMMAND LINE ARGUMENTS
292 ****************************************************************************/
293
294 static void
295 parse_args(int argc, char *argv[])
296 {
297     if (argc < 2 || argc > 8) {
298         puts("fairland syntax:\n");
299         puts("fairland [-e config] [-aiqo] [-s script] <nc> <sc> [<ni>] [<is>] [<sp>] [<pm>] [<di>] [<id>]");
300         puts("-q = quiet, -o = no ore produced");
301         puts("-a = Airport marker for continents, -i = islands not distinct");
302         printf("-e = read config file, -s = name of script (default %s)\n",
303                outfile);
304         puts("nc = number of continents [MANDATORY]");
305         puts("sc = continent size [MANDATORY]");
306         puts("ni = number of islands (default = nc)");
307         puts("is = average size of islands (default = sc/2)");
308         printf("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n",
309                DEFAULT_SPIKE);
310         printf("pm = the percentage of land that is mountain (default = %d)\n",
311                DEFAULT_MOUNTAIN);
312         printf("di = the minimum distance between continents (default = %d)\n",
313                DEFAULT_CONTDIST);
314         printf("id = minimum distance from islands to continents (default = %d)\n",
315                DEFAULT_ISLDIST);
316         exit(1);
317     }
318     nc = atoi(argv[0]);
319     if (nc < 1) {
320         puts("fairland: error -- number of continents must be > 0");
321         exit(1);
322     }
323
324     sc = atoi(argv[1]);
325     if (sc < 1) {
326         puts("fairland: error -- size of continents must be > 0");
327         exit(1);
328     }
329
330     if (argc > 2)
331         ni = atoi(argv[2]);
332     else
333         ni = nc;
334
335     if (argc > 3)
336         is = atoi(argv[3]);
337     else
338         is = sc / 2;
339     if (is < 0)
340         is = 0;
341
342     if (argc > 4)
343         sp = atoi(argv[4]);
344     else
345         sp = DEFAULT_SPIKE;
346     if (sp < 0)
347         sp = 0;
348     if (sp > 100)
349         sp = 100;
350
351     if (argc > 5)
352         pm = atoi(argv[5]);
353     else
354         pm = DEFAULT_MOUNTAIN;
355     if (pm < 0)
356         pm = 0;
357
358     if (argc > 6)
359         di = atoi(argv[6]);
360     else
361         di = DEFAULT_CONTDIST;
362
363     if (di < 0) {
364         puts("fairland: error -- distance between continents must be >= 0");
365         exit(1);
366     }
367     if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
368         puts("fairland: error -- distance between continents too large");
369         exit(1);
370     }
371
372     if (argc > 7)
373         id = atoi(argv[7]);
374     else
375         id = DEFAULT_ISLDIST;
376     if (id < 0) {
377         puts("fairland: error -- distance from islands to continents must be >= 0");
378         exit(1);
379     }
380     if (id > WORLD_X || id > WORLD_Y) {
381         puts("fairland: error -- distance from islands to continents too large");
382         exit(1);
383     }
384     if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
385         puts("fairland: error -- world not big enough to fit continents.");
386         puts("arguments must satisfy:");
387         puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
388         exit(1);
389     }
390 }
391
392 /****************************************************************************
393   VARIABLE INITIALIZATION
394 ****************************************************************************/
395
396 static int
397 allocate_memory(void)
398 {
399     int i;
400     time_t now;
401
402 #if !defined(_WIN32)
403     the_file =
404         open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC, 0660);
405 #else
406     the_file =
407         open(empfile[EF_SECTOR].file,
408              O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0660);
409 #endif
410     if (the_file < 0) {
411         perror(empfile[EF_SECTOR].file);
412         return -1;
413     }
414     sectsbuf =
415         (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
416     sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
417     for (i = 0; i < YSIZE; i++)
418         sects[i] = &sectsbuf[XSIZE * i];
419     time(&now);
420 #if !defined(_WIN32)
421     srandom(now + getpid());
422 #else
423     srandom(now);
424 #endif
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         if (!quiet)
728             printf("fairland: error -- continent %c had no room to grow!\n",
729                    numletter[c % 62]);
730         fl_status |= STATUS_NO_ROOM;
731     }
732     return done;
733 }
734
735 /* Grow all the continents
736 */
737 static void
738 grow_continents(void)
739 {
740     int c;
741
742     for (c = 0; c < nc; ++c) {
743         sectx[c][0] = capx[c];
744         secty[c][0] = capy[c];
745         own[sectx[c][0]][secty[c][0]] = c;
746         sectx[c][1] = new_x(capx[c] + 2);
747         secty[c][1] = capy[c];
748         own[sectx[c][1]][secty[c][1]] = c;
749     }
750
751     for (secs = 2; secs < sc && !fl_status; ++secs) {
752         for (c = 0; c < nc; ++c) {
753             find_coast(c);
754             grow_one_sector(c);
755         }
756     }
757     if (fl_status && !quiet)
758         printf("Only managed to grow %d out of %d sectors.\n", secs, sc);
759     ctot = nc;
760 }
761
762 /****************************************************************************
763   GROW THE ISLANDS
764 ****************************************************************************/
765
766 /* Choose a place to start growing an island from
767 */
768 static int
769 place_island(int c, int *xp, int *yp)
770 {
771     int d, sx, sy;
772     int ssy = rnd(WORLD_Y);
773     int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
774
775     if (ssx > WORLD_X - 2)
776         ssx = new_x(ssx + 2);
777     for (d = di + id; d >= id; --d) {
778         sx = ssx;
779         sy = ssy;
780         *xp = new_x(sx + 2);
781         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
782             if (*xp >= WORLD_X) {
783                 *yp = new_y(*yp + 1);
784                 *xp = (*yp) % 2;
785                 if (*xp == sx && *yp == sy)
786                     break;
787             }
788             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
789                 return 1;
790         }
791     }
792     return 0;
793 }
794
795 /* Grow all the islands
796 */
797
798 static void
799 grow_islands(void)
800 {
801     int c, x, y, isiz;
802
803     for (c = nc; c < nc + ni; ++c) {
804         secs = 0;
805         if (!place_island(c, &x, &y))
806             return;
807         isiz = 1 + rnd(2 * is - 1);
808         do {
809             ++secs;
810             find_coast(c);
811         } while (secs < isiz && grow_one_sector(c));
812         if (quiet == 0)
813             printf(" %d(%d)", c - nc + 1, secs);
814         isecs[c] = secs;
815         ctot = c;
816     }
817 }
818
819 /****************************************************************************
820   CREATE ELEVATIONS
821 ****************************************************************************/
822 static void
823 create_elevations(void)
824 {
825     elevate_land();
826     elevate_sea();
827 }
828
829 /* Generic function for finding the distance to the closest sea, land, or
830    mountain
831 */
832 static int
833 distance_to_what(int x, int y, int flag)
834 {
835     int j, d, px, py;
836
837     for (d = 1; d < 5; ++d) {
838         for (j = 0; j < d; ++j)
839             vector[j] = 0;
840         do {
841             px = x;
842             py = y;
843             for (j = 0; j < d; ++j) {
844                 px = new_x(px + dirx[vector[j]]);
845                 py = new_y(py + diry[vector[j]]);
846             }
847             switch (flag) {
848             case 0:             /* distance to sea */
849                 if (own[px][py] == -1)
850                     return d;
851                 break;
852             case 1:             /* distance to land */
853                 if (own[px][py] != -1)
854                     return d;
855                 break;
856             case 2:             /* distance to mountain */
857                 if (elev[px][py] == INFINITY)
858                     return d;
859                 break;
860             }
861         } while (next_vector(d));
862     }
863     return d;
864 }
865
866 #define ELEV elev[sectx[c][i]][secty[c][i]]
867 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
868 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
869
870 /* Decide where the mountains go
871 */
872 static void
873 elevate_land(void)
874 {
875     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
876         r, dk;
877
878     for (c = 0; c < ctot; ++c) {
879         total = 0;
880         ns = (c < nc) ? sc : isecs[c];
881         nm = (pm * ns) / 100;
882
883 /* Place the mountains */
884
885         for (i = 0; i < ns; ++i) {
886             dsea[i] = distance_to_sea();
887             weight[i] = (total += (dsea[i] * dsea[i]));
888         }
889
890         for (k = nm, mountain_search = 0;
891              k && mountain_search < MOUNTAIN_SEARCH_MAX;
892              ++mountain_search) {
893             r = rnd(total);
894             for (i = 0; i < ns; ++i)
895                 if (r < weight[i] && ELEV == -INFINITY &&
896                     (c >= nc ||
897                      ((!(capx[c] == sectx[c][i] &&
898                          capy[c] == secty[c][i])) &&
899                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
900                          capy[c] == secty[c][i]))))) {
901                     ELEV = INFINITY;
902                     break;
903                 }
904             --k;
905         }
906
907 /* Elevate land that is not mountain and not capital */
908
909         for (i = 0; i < ns; ++i)
910             dmoun[i] = distance_to_mountain();
911         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
912           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
913           100 * INFINITY;
914         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
915             highest = -INFINITY;
916             where = -1;
917             for (i = 0; i < ns; ++i) {
918                 if (ELEV != INFINITY &&
919                     (c >= nc || ((!(capx[c] == sectx[c][i] &&
920                                     capy[c] == secty[c][i])) &&
921                                  (!(new_x(capx[c] + 2) == sectx[c][i] &&
922                                     capy[c] == secty[c][i]))))) {
923                     h = 3 * (5 - dmoun[i]) + dsea[i];
924                     if (h > highest) {
925                         highest = h;
926                         where = i;
927                     }
928                 }
929             }
930             if (where == -1)
931                 break;
932             newk = k / 100;
933             if (newk >= HILLMIN && newk < PLATMIN)
934                 newk = PLATMIN;
935             if (newk < LANDMIN)
936                 newk = LANDMIN;
937             elev[sectx[c][where]][secty[c][where]] = newk;
938             dsea[where] = -INFINITY;
939             dmoun[where] = INFINITY;
940         }
941
942 /* Elevate the mountains and capitals */
943
944         for (i = 0; i < ns; ++i) {
945             if (ELEV == INFINITY) {
946                 if (dsea[i] == 1)
947                     ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
948                 else
949                     ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
950                       rnd((256 - HIGHMIN) / 2);
951             } else if ((c < nc &&
952                         ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
953                        ((new_x(capx[c] + 2) == sectx[c][i] &&
954                          capy[c] == secty[c][i])))
955                 ELEV = PLATMIN;
956         }
957     }
958 }
959
960 #define distance_to_land() distance_to_what(x, y, 1)
961
962 static void
963 elevate_sea(void)
964 {
965     int x, y;
966
967     for (y = 0; y < WORLD_Y; ++y) {
968         for (x = y % 2; x < WORLD_X; x += 2) {
969             if (elev[x][y] == -INFINITY)
970                 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
971         }
972     }
973 }
974
975 /****************************************************************************
976   ADD THE RESOURCES
977 ****************************************************************************/
978
979 static int
980 set_fert(int e)
981 {
982     int fert = 0;
983     if (e < LANDMIN)
984         fert = LANDMIN - e + 40;
985     else if (e < FERT_MAX)
986         fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
987     if (fert > 120)
988         fert = 120;
989     return fert;
990 }
991
992 static int
993 set_oil(int e)
994 {
995     int oil = 0;
996     if (e < LANDMIN)
997         oil = (LANDMIN - e) * 2 + rnd(2);
998     else if (e <= OIL_MAX)
999         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1000     if (oil > 100)
1001         oil = 100;
1002     return oil;
1003 }
1004
1005 static int
1006 set_iron(int e)
1007 {
1008     int iron = 0;
1009     if (e >= IRON_MIN && e < HIGHMIN)
1010         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1011     if (iron > 100)
1012         iron = 100;
1013     return iron;
1014 }
1015
1016 static int
1017 set_gold(int e)
1018 {
1019     int gold = 0;
1020     if (e >= GOLD_MIN) {
1021         if (e < HIGHMIN)
1022             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1023         else
1024             gold = 100 - 20 * HIGHMIN / e;
1025     }
1026     if (gold > 100)
1027         gold = 100;
1028     return gold;
1029 }
1030
1031 static int
1032 set_uran(int e)
1033 {
1034     int uran = 0;
1035     if (e >= URAN_MIN && e < HIGHMIN)
1036         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1037     if (uran > 100)
1038         uran = 100;
1039     return uran;
1040 }
1041
1042 static void
1043 add_resources(struct sctstr *sct)
1044 {
1045     sct->sct_fertil = set_fert(sct->sct_elev);
1046     sct->sct_oil = set_oil(sct->sct_elev);
1047     sct->sct_min = set_iron(sct->sct_elev);
1048     sct->sct_gmin = set_gold(sct->sct_elev);
1049     sct->sct_uran = set_uran(sct->sct_elev);
1050 }
1051
1052 /****************************************************************************
1053   DESIGNATE THE SECTORS
1054 ****************************************************************************/
1055
1056 static void
1057 write_sects(void)
1058 {
1059     register struct sctstr *sct;
1060     int c, x, y, total;
1061
1062     /*  sct = &sects[0][0]; */
1063     sct = sectsbuf;
1064     for (y = 0; y < YSIZE; y++) {
1065         for (x = 0; x < XSIZE; x++, sct++) {
1066             fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1067             total = elev[sct->sct_x][y];
1068             if (total < LANDMIN) {
1069                 sct->sct_type = SCT_WATER;
1070             } else if (total < HILLMIN)
1071                 sct->sct_type = SCT_RURAL;
1072             else if (total < PLATMIN)
1073                 sct->sct_type = SCT_MOUNT;
1074             else if (total < HIGHMIN)
1075                 sct->sct_type = SCT_RURAL;
1076             else
1077                 sct->sct_type = SCT_MOUNT;
1078             sct->sct_elev = total;
1079             sct->sct_newtype = sct->sct_type;
1080             if (ORE)
1081                 add_resources(sct);
1082         }
1083     }
1084     if (AIRPORT_MARKER)
1085         for (c = 0; c < nc; ++c) {
1086             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1087             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1088         }
1089 }
1090
1091 /****************************************************************************
1092   WRITE ALL THIS STUFF TO THE FILE
1093 ****************************************************************************/
1094 static int
1095 write_file(void)
1096 {
1097     int n;
1098
1099     /*  if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1100     if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1101         perror(empfile[EF_SECTOR].file);
1102         return -1;
1103     }
1104     if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1105         printf("%s:partial write\n", empfile[EF_SECTOR].file);
1106         return -1;
1107     }
1108     close(the_file);
1109     return 0;
1110 }
1111
1112 /****************************************************************************
1113   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1114 ****************************************************************************/
1115 static void
1116 output(void)
1117 {
1118     int i, j;
1119     if (opt_BLITZ)
1120         translate_continents();
1121     if (quiet == 0) {
1122         for (i = 0; i < WORLD_Y; ++i) {
1123             puts("");
1124             if (i % 2)
1125                 printf(" ");
1126             for (j = i % 2; j < WORLD_X; j += 2) {
1127                 if (own[j][i] == -1)
1128                     printf(". ");
1129                 else {
1130                     printf("%c ", map_symbol(j, i));
1131                 }
1132             }
1133         }
1134     }
1135     if (AIRPORT_MARKER)
1136         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");
1137 }
1138
1139 /* Reorder the continents from top left to bottom right */
1140 static void
1141 translate_continents(void)
1142 {
1143     int i, j, n = 0, k, gotit, c;
1144     int *trans, *trans_cont, *oldcapx, *oldcapy;
1145
1146     trans = (int *)calloc(nc, sizeof(int));
1147     trans_cont = (int *)calloc(nc, sizeof(int));
1148     oldcapx = (int *)calloc(nc, sizeof(int));
1149     oldcapy = (int *)calloc(nc, sizeof(int));
1150
1151     for (i = 0; i < WORLD_Y; ++i) {
1152         for (j = i % 2; j < WORLD_X; j += 2) {
1153             if (own[j][i] > -1 && own[j][i] < nc) {
1154                 gotit = 0;
1155                 for (k = 0; k < n; ++k) {
1156                     if (trans[k] == own[j][i])
1157                         gotit = 1;
1158                 }
1159                 if (!gotit) {
1160                     if (n > nc) {
1161                         printf("fairland: BUG in translate continents!  mail stevens@math.utoronto.ca\n");
1162                         exit(2);
1163                     }
1164                     trans[n] = own[j][i];
1165                     trans_cont[own[j][i]] = n;
1166                     ++n;
1167                 }
1168             }
1169         }
1170     }
1171     for (i = 0; i < WORLD_Y; ++i) {
1172         for (j = i % 2; j < WORLD_X; j += 2) {
1173             if (own[j][i] > -1 && own[j][i] < nc) {
1174                 own[j][i] = trans_cont[own[j][i]];
1175             }
1176         }
1177     }
1178     for (c = 0; c < nc; ++c) {
1179         oldcapx[c] = capx[c];
1180         oldcapy[c] = capy[c];
1181     }
1182     for (c = 0; c < nc; ++c) {
1183         capx[c] = oldcapx[trans[c]];
1184         capy[c] = oldcapy[trans[c]];
1185     }
1186 }
1187
1188 static int
1189 map_symbol(int x, int y)
1190 {
1191     int c, iscap = 0;
1192
1193     for (c = 0; c < nc; ++c)
1194         if ((x == capx[c] && y == capy[c])
1195             || (x == new_x(capx[c] + 2) && y == capy[c]))
1196             iscap = 1;
1197     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1198         || elev[x][y] >= HIGHMIN)
1199         return '^';
1200     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1201 }
1202
1203 /***************************************************************************
1204   WRITE A SCRIPT FOR PLACING CAPITALS
1205 ****************************************************************************/
1206 static int
1207 write_newcap_script(void)
1208 {
1209     int c;
1210     FILE *script = fopen(outfile, "w");
1211
1212     if (!script) {
1213         printf("fairland: error, unable to write to %s.\n", outfile);
1214         return -1;
1215     }
1216
1217     for (c = 0; c < nc; ++c) {
1218         fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1219         if (AIRPORT_MARKER)
1220             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1221         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1222     }
1223     fprintf(script, "add %d visitor visitor v i\n", c + 1);
1224     ++c;
1225     fclose(script);
1226     if (quiet == 0)
1227         printf("\n\nA script for adding all the countries can be found in \"%s\".\n",
1228              outfile);
1229     if (ORE && quiet == 0)
1230         printf("\t***IMPORTANT: Resources have already been added***\n\tYou do NOT need to run the ore program.\n");
1231     return 0;
1232 }
1233
1234 static void
1235 qprint(const char *str)
1236 {
1237     if (quiet == 0)
1238         fputs(str, stdout);
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 }