]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
Import of Empire 4.2.12
[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 _PROTO((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 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
154
155 void parse_args(int argc, char *argv[]);
156 int allocate_memory(void);
157 void init(void);
158 int drift(void);
159 void grow_continents(void);
160 void create_elevations(void);
161 void write_sects(void);
162 int write_file(void);
163 void output(void);
164 int write_newcap_script(void);
165 int stable(void);
166 void elevate_land(void);
167 void elevate_sea(void);
168 void translate_continents(void);
169 int map_symbol(int x, int y);
170 static void fl_sct_init(coord x, coord y, s_char *ptr);
171
172 void    print_vars();
173 void    fl_move(int);
174 void    next_coast();
175 void    grow_islands();
176
177 /****************************************************************************
178   MAIN
179 ****************************************************************************/
180
181 int
182 main(int argc, char *argv[])
183 {
184   int opt;
185   extern int optind;
186   extern char *optarg;
187   extern s_char *datadir;
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", stderr);
244           exit(1);
245   }
246   qprint ("growing islands:");
247   grow_islands();
248   qprint ("\nelevating land...\n");
249   create_elevations();
250   qprint ("designating sectors...\n");
251   if (ORE)
252     qprint ("adding resources...\n");
253   write_sects();
254   qprint ("writing to sectors file...\n");
255   if (write_file() == -1)
256     exit (-1);
257   output();
258   write_newcap_script();
259   exit(0);
260 }
261
262 void
263 print_vars()
264 {
265   if (quiet)
266       return;
267   puts("Creating a planet with:\n");
268   printf("%d continents\n", nc);
269   printf("continent size: %d\n", sc);
270   printf("number of islands: %d\n", ni);
271   printf("average size of islands: %d\n", is);
272   printf("spike: %d%%\n", sp);
273   printf("%d%% of land is mountain (each continent will have %d mountains)\n",
274          pm, (pm*sc)/100);
275   printf("minimum distance between continents: %d\n", di);
276   printf("minimum distance from islands to continents: %d\n", id);
277   printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
278 }
279
280 int
281 my_sqrt(n)
282 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 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", DEFAULT_SPIKE);
309     printf("pm = the percentage of land that is mountain (default = %d)\n", DEFAULT_MOUNTAIN);
310     printf("di = the minimum distance between continents (default = %d)\n", DEFAULT_CONTDIST);
311     printf("id = minimum distance from islands to continents (default = %d)\n", DEFAULT_ISLDIST);
312     exit (1);
313   }
314   nc = atoi(argv[0]);
315   if (nc < 1) {
316     puts("fairland: error -- number of continents must be > 0");
317     exit (1);
318   }
319
320   sc = atoi(argv[1]);
321   if (sc < 1) {
322     puts("fairland: error -- size of continents must be > 0");
323     exit (1);
324   }
325
326   if (argc > 2)
327     ni = atoi(argv[2]);
328   else
329     ni = nc;
330
331   if (argc > 3)
332     is = atoi(argv[3]);
333   else
334     is = sc/2;
335   if (is < 0)
336     is = 0;
337
338   if (argc > 4)
339     sp = atoi(argv[4]);
340   else
341     sp = DEFAULT_SPIKE;
342   if (sp < 0)
343     sp = 0;
344   if (sp > 100)
345     sp = 100;
346
347   if (argc > 5)
348     pm = atoi(argv[5]);
349   else
350     pm = DEFAULT_MOUNTAIN;
351   if (pm < 0)
352     pm = 0;
353
354   if (argc > 6)
355     di = atoi(argv[6]);
356   else
357     di = DEFAULT_CONTDIST;
358
359   if (di < 0) {
360     puts("fairland: error -- distance between continents must be >= 0");
361     exit (1);
362   }
363   if (di > WORLD_X/2 || di > WORLD_Y/2) {
364     puts("fairland: error -- distance between continents too large");
365     exit (1);
366   }
367
368   if (argc > 7)
369     id = atoi(argv[7]);
370   else
371     id = DEFAULT_ISLDIST;
372   if (id < 0) {
373     puts("fairland: error -- distance from islands to continents must be >= 0");
374     exit (1);
375   }
376   if (id > WORLD_X || id > WORLD_Y) {
377     puts("fairland: error -- distance from islands to continents too large");
378     exit (1);
379   }
380   if (nc*sc + nc*my_sqrt(sc)*2*(di+1) > WORLD_X * WORLD_Y) {
381     puts("fairland: error -- world not big enough to fit continents.");
382     puts("arguments must satisfy:");
383     puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
384     exit (1);
385   }
386 }
387
388 /****************************************************************************
389   VARIABLE INITIALIZATION
390 ****************************************************************************/
391
392 int
393 allocate_memory(void)
394 {
395   int i;
396   time_t now;
397
398 #if !defined(_WIN32)
399   the_file = open(empfile[EF_SECTOR].file, O_RDWR|O_CREAT|O_TRUNC, 0660);
400 #else
401   the_file = open(empfile[EF_SECTOR].file, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0660);
402 #endif
403   if (the_file < 0) {
404     perror(empfile[EF_SECTOR].file);
405     return -1;
406   }
407   sectsbuf = (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
408   sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
409   for (i = 0; i < YSIZE; i++)
410     sects[i] = &sectsbuf[XSIZE * i];
411   time(&now);
412 #if !defined(_WIN32)
413   srandom(now+getpid());
414 #else
415   srandom(now);
416 #endif
417   capx = (int *)calloc(nc, sizeof(int));
418   capy = (int *)calloc(nc, sizeof(int));
419   vector = (int *)calloc(WORLD_X+WORLD_Y, sizeof(int));
420   mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
421   own = (int **)calloc(WORLD_X, sizeof(int*));
422   elev = (int **)calloc(WORLD_X, sizeof(int*));
423   for (i = 0; i < WORLD_X; ++i) {
424     own[i] = (int *)calloc(WORLD_Y, sizeof(int));
425     elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
426   }
427   sectx = (int **)calloc(nc+ni, sizeof(int*));
428   secty = (int **)calloc(nc+ni, sizeof(int*));
429   sectc = (int **)calloc(nc+ni, sizeof(int*));
430   isecs = (int *)calloc(nc+ni, sizeof(int));
431   weight = (int *)calloc(max(sc,is*2), sizeof(int));
432   dsea = (int *)calloc(max(sc,is*2), sizeof(int));
433   dmoun = (int *)calloc(max(sc,is*2), sizeof(int));
434   for (i = 0; i < nc; ++i) {
435     sectx[i] = (int *)calloc(sc, sizeof(int));
436     secty[i] = (int *)calloc(sc, sizeof(int));
437     sectc[i] = (int *)calloc(sc, sizeof(int));
438   }
439   for (i = nc; i < nc+ni; ++i) {
440     sectx[i] = (int *)calloc(is*2, sizeof(int));
441     secty[i] = (int *)calloc(is*2, sizeof(int));
442     sectc[i] = (int *)calloc(is*2, sizeof(int));
443   }
444
445   return 0;
446 }
447
448 void
449 init(void)
450 {
451   int i, j, xx = 0, yy = 0;
452
453   mcc = 0;
454   fl_status = 0;
455
456   for (i = 0; i < WORLD_X; ++i) {
457     for (j = 0; j < WORLD_Y; ++j) {
458       own[i][j] = -1;
459       elev[i][j] = -INFINITY;
460     }
461   }
462
463   for (i = 0; i < nc; ++i, xx += 2) {
464     if (xx >= WORLD_X) {
465       ++yy;
466       xx = yy%2;
467       if (yy == WORLD_Y) {
468         puts("fairland error: world not big enough for all the continents.\n");
469         exit(1);
470       }
471     }
472     capx[i] = xx;
473     capy[i] = yy;
474   }
475   for (i = 0; i < STABLE_CYCLE; ++i)
476     mc[i] = i;
477 }
478   
479 /****************************************************************************
480   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
481 ****************************************************************************/
482
483 /* How isolated is capital j?
484 */
485 int
486 iso(j, newx, newy)
487 int j, newx, newy;
488 {
489   int i, md, d = WORLD_X + WORLD_Y;
490   
491   for (i = 0; i < nc; ++i) {
492     if (i == j)
493       continue;
494     md = mapdist(capx[i], capy[i], newx, newy);
495     if (md < d)
496       d = md;
497   }
498
499   return d;
500 }
501
502 /* Drift all the capitals
503 */
504 int
505 drift(void)
506 {
507   int i, turns;
508   
509   for (turns = 0; turns < DRIFT_MAX; ++turns) {
510     if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
511       return 1;
512     for (i = 0; i < nc; ++i)
513       fl_move(i);
514   }
515   return 0;
516 }
517
518 /* Check to see if we have stabilized--can we stop drifting the capitals?
519 */
520
521 int
522 stable(void)
523 {
524   int i, isod, d = 0, stab = 1;
525
526   for (i = 0; i < nc; ++i) {
527     isod = iso(i, capx[i], capy[i]);
528     if (isod > d)
529       d = isod;
530   }
531   for (i = 0; i < STABLE_CYCLE; ++i)
532     if (d != mc[i])
533       stab = 0;
534   mc[mcc] = d;
535   mcc = (mcc + 1) % STABLE_CYCLE;
536   return stab?d:0;
537 }
538
539 /* This routine does the actual drifting
540 */
541
542 void
543 fl_move(j)
544 int j;
545 {
546   int i, n, newx, newy;
547
548   for (i = rnd(6), n = 0; n < 6; i = (i + 1)%6, ++n) {
549     newx = new_x(capx[j] + dirx[i]);
550     newy = new_y(capy[j] + diry[i]);
551     if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
552       capx[j] = newx;
553       capy[j] = newy;
554       return;
555     }
556   }
557 }
558
559 /****************************************************************************
560   GROW THE CONTINENTS
561 ****************************************************************************/
562
563 /* Look for a coastal sector of continent c
564 */
565
566 void
567 find_coast(c)
568 int c;
569 {
570   int i, j;
571   
572   for (i = 0; i < secs; ++i) {
573     sectc[c][i] = 0;
574     for (j = 0; j < 6; ++j)
575       if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
576         sectc[c][i] = 1;
577   }
578 }
579
580 /* Used for measuring distances
581 */
582 int
583 next_vector(n)
584 int n;
585 {
586   int i;
587
588   if (n == 1) {
589     vector[0] += 1;
590     vector[0] %= 6;
591     return vector[0];
592   }
593   for (i = 1; i < n && vector[i] == vector[i-1]; ++i);
594   vector[i-1] += 1;
595   vector[i-1] %= 6;
596   return i > 1 || vector[0] > 0;
597 }
598
599 /* Test to see if we're allowed to grow there: the arguments di and id
600 */
601 int
602 try_to_grow(c, newx, newy, d)
603 int c, newx, newy, d;
604 {
605   int i, j, px, py;
606
607   for (i = 1; i <= d; ++i) {
608     for (j = 0; j < i; ++j)
609       vector[j] = 0;
610     do {
611       px = newx;
612       py = newy;
613       for (j = 0; j < i; ++j) {
614         px = new_x(px + dirx[vector[j]]);
615         py = new_y(py + diry[vector[j]]);
616       }
617       if (own[px][py] != -1 &&
618           own[px][py] != c &&
619           (DISTINCT_ISLANDS || own[px][py] < nc))
620         return 0;
621     } while (next_vector(i));
622   }
623   sectx[c][secs] = newx;
624   secty[c][secs] = newy;
625   own[newx][newy] = c;
626   return 1;
627 }
628
629 /* Move along the coast in a clockwise direction.
630 */
631
632 void
633 next_coast(c, x, y, xp, yp)
634 int c, x, y, *xp, *yp;
635 {
636   int i, nx, ny, wat = 0;
637
638   if (secs == 1) {
639     *xp = x;
640     *yp = y;
641     return;
642   }
643
644   for (i = 0; i < 12; ++i) {
645     nx = new_x(x+dirx[i%6]);
646     ny = new_y(y+diry[i%6]);
647     if (own[nx][ny] == -1)
648       wat = 1;
649     if (wat && own[nx][ny] == c) {
650       *xp = nx;
651       *yp = ny;
652       return;
653     }
654   }
655 }
656
657 /* Choose a sector to grow from
658 */
659
660 int
661 new_try(int c)
662 {
663   int i, starti;
664
665   if (secs == 1) {
666     if (sectc[c][0])
667       return 0;
668   }
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", c + 'a', secs);
678       exit (1);
679     }
680     else
681       return -1;
682   }
683   return -1;
684 }
685
686 /* Grow continent c by 1 sector
687 */
688
689 int
690 grow_one_sector(c)
691 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     }
715     else
716       for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1)%6, ++n) {
717         newx = new_x(x+dirx[i]);
718         newy = new_y(y+diry[i]);
719         if (own[newx][newy] == -1)
720           if (try_to_grow(c, newx, newy, c<nc?di:id))
721             done = 1;
722       }
723     next_coast(c, x, y, &x, &y);
724     ++coast_search;
725   } while (!done && coast_search < COAST_SEARCH_MAX &&
726            (secs == 1 || x != sx || y != sy));
727   if (!done && c < nc) {
728     if (!quiet)
729       printf("fairland: error -- continent %c had no room to grow!\n",
730              numletter[c % 62]);
731     fl_status |= STATUS_NO_ROOM;
732   }
733   return done;
734 }
735
736 /* Grow all the continents
737 */
738 void
739 grow_continents(void)
740 {
741   int c;
742
743   for (c = 0; c < nc; ++c) {
744     sectx[c][0] = capx[c];
745     secty[c][0] = capy[c];
746     own[sectx[c][0]][secty[c][0]] = c;
747     sectx[c][1] = new_x(capx[c] + 2);
748     secty[c][1] = capy[c];
749     own[sectx[c][1]][secty[c][1]] = c;
750   }
751
752   for (secs = 2; secs < sc && !fl_status; ++secs) {
753     for (c = 0; c < nc; ++c) {
754       find_coast(c);
755       grow_one_sector(c);
756     }
757   }
758   if (fl_status && !quiet)
759     printf("Only managed to grow %d out of %d sectors.\n", secs, sc);
760   ctot = nc;
761 }
762
763 /****************************************************************************
764   GROW THE ISLANDS
765 ****************************************************************************/
766
767 /* Choose a place to start growing an island from
768 */
769 int
770 place_island(c, xp, yp)
771 int c, *xp, *yp;
772 {
773   int d, sx, sy;
774   int ssy = rnd(WORLD_Y);
775   int ssx = new_x(rnd(WORLD_X/2)*2 + ssy%2);
776
777   if (ssx > WORLD_X - 2)
778     ssx = new_x(ssx + 2);
779   for (d = di + id; d >= id; --d) {
780     sx = ssx;
781     sy = ssy;
782     *xp = new_x(sx + 2);
783     for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
784       if (*xp >= WORLD_X) {
785         *yp = new_y(*yp + 1);
786         *xp = (*yp)%2;
787         if (*xp == sx && *yp == sy)
788           break;
789       }
790       if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
791         return 1;
792     }
793   }
794   return 0;
795 }
796
797 /* Grow all the islands
798 */
799
800 void
801 grow_islands()
802 {
803   int c, x, y, isiz;
804
805   for (c = nc; c < nc+ni; ++c) {
806     secs = 0;
807     if (!place_island(c, &x, &y))
808       return;
809     isiz = 1 + rnd(2*is - 1);
810     do {
811       ++secs;
812       find_coast(c);
813       } while (secs < isiz && grow_one_sector(c));
814     if (quiet == 0) printf(" %d(%d)", c - nc + 1, secs);
815     isecs[c] = secs;
816     ctot = c;
817   }
818 }
819
820 /****************************************************************************
821   CREATE ELEVATIONS
822 ****************************************************************************/
823 void
824 create_elevations(void)
825 {
826   elevate_land();
827   elevate_sea();
828 }
829
830 /* Generic function for finding the distance to the closest sea, land, or
831    mountain
832 */
833 int
834 distance_to_what(x,y,flag)
835 int x, y, flag;
836 {
837   int j, d, px, py;
838
839   for (d = 1; d < 5; ++d) {
840     for (j = 0; j < d; ++j)
841       vector[j] = 0;
842     do {
843       px = x;
844       py = y;
845       for (j = 0; j < d; ++j) {
846         px = new_x(px + dirx[vector[j]]);
847         py = new_y(py + diry[vector[j]]);
848       }
849       switch(flag) {
850       case 0: /* distance to sea */
851         if (own[px][py] == -1)
852           return d;
853         break;
854       case 1: /* distance to land */
855         if (own[px][py] != -1)
856           return d;
857         break;
858       case 2: /* distance to mountain */
859         if (elev[px][py] == INFINITY)
860           return d;
861         break;
862       }
863     } while (next_vector(d));
864   }
865   return d;
866 }
867
868 #define ELEV elev[sectx[c][i]][secty[c][i]]
869 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
870 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
871
872 /* Decide where the mountains go
873 */
874 void
875 elevate_land(void)
876 {
877   int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk, r, dk;
878
879   for (c = 0; c < ctot; ++c) {
880     total = 0;
881     ns = (c < nc)?sc:isecs[c];
882     nm = (pm*ns)/100;
883
884 /* Place the mountains */
885
886     for (i = 0; i < ns; ++i) {
887       dsea[i] = distance_to_sea();
888       weight[i] = (total += (dsea[i]*dsea[i]));
889     }
890     
891     for (k = nm, mountain_search = 0;
892          k && mountain_search < MOUNTAIN_SEARCH_MAX;
893          ++mountain_search) {
894       r = rnd(total);
895       for (i = 0; i < ns; ++i)
896         if (r < weight[i] && ELEV == -INFINITY && (c >= nc || 
897             ((!(capx[c] == sectx[c][i] && capy[c] == secty[c][i])) &&
898              (!(new_x(capx[c] + 2) == sectx[c][i] && 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)?(100*(HIGHMIN-LANDMIN))/(ns-nm-((c<nc)?3:1)):100*INFINITY;
910     for (k = 100*(HIGHMIN - 1);; k -= dk) {
911       highest = -INFINITY;
912       where = -1;
913       for (i = 0; i < ns; ++i) {
914         if (ELEV != INFINITY && (c >= nc ||
915             ((!(capx[c] == sectx[c][i] && capy[c] == secty[c][i])) &&
916              (!(new_x(capx[c] + 2) == sectx[c][i] && capy[c] == secty[c][i])))))
917           {
918             h = 3*(5 - dmoun[i]) + dsea[i];
919             if (h > highest) {
920               highest = h;
921               where = i;
922             }
923           }
924       }
925       if (where == -1)
926         break;
927       newk = k/100;
928       if (newk >= HILLMIN && newk < PLATMIN)
929         newk = PLATMIN;
930       if (newk < LANDMIN)
931         newk = LANDMIN;
932       elev[sectx[c][where]][secty[c][where]] = newk;    
933       dsea[where] = -INFINITY;
934       dmoun[where] = INFINITY;
935     }
936
937 /* Elevate the mountains and capitals */
938
939     for (i = 0; i < ns; ++i) {
940       if (ELEV == INFINITY) {
941         if (dsea[i] == 1)
942           ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
943         else
944           ELEV = HIGHMIN + rnd((256-HIGHMIN)/2) + rnd((256-HIGHMIN)/2);
945       }
946       else if ((c < nc &&
947             ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
948             ((new_x(capx[c] + 2) == sectx[c][i] && capy[c] == secty[c][i])))
949         ELEV = PLATMIN;
950     }
951   }
952 }
953
954 #define distance_to_land() distance_to_what(x, y, 1)
955
956 void
957 elevate_sea(void)
958 {
959   int x, y;
960
961   for (y = 0; y < WORLD_Y; ++y) {
962     for (x = y%2; x < WORLD_X; x +=2) {
963       if (elev[x][y] == -INFINITY)
964         elev[x][y] = - rnd((distance_to_land()*20 + 27)) - 1;
965         }
966   }
967 }
968
969 /****************************************************************************
970   ADD THE RESOURCES
971 ****************************************************************************/
972
973 int
974 set_fert(e)
975 int e;
976 {
977   int fert = 0;
978   if (e < LANDMIN)
979     fert = LANDMIN - e + 40;
980   else if (e < FERT_MAX)
981     fert = (140*(FERT_MAX - e))/(FERT_MAX - LANDMIN);
982   if (fert > 120)
983     fert = 120;
984   return fert;
985 }
986
987 int
988 set_oil(e)
989 int e;
990 {
991   int oil = 0;
992   if (e < LANDMIN)
993     oil = (LANDMIN - e)*2 + rnd(2);
994   else if (e <= OIL_MAX)
995     oil = (120*(OIL_MAX - e + 1))/(OIL_MAX - LANDMIN + 1);
996   if (oil > 100)
997     oil = 100;
998   return oil;
999 }
1000
1001 int
1002 set_iron(e)
1003 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 int
1014 set_gold(e)
1015 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 int
1030 set_uran(e)
1031 int e;
1032 {
1033   int uran = 0;
1034   if (e >= URAN_MIN && e < HIGHMIN)
1035     uran = (120*(e - URAN_MIN + 1))/(HIGHMIN - URAN_MIN);
1036   if (uran > 100)
1037     uran = 100;
1038   return uran;
1039 }
1040
1041 void
1042 add_resources(sct)
1043 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 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 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 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 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 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]) || (x == new_x(capx[c]+2) && y == capy[c]))
1195       iscap = 1;
1196   if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN) || 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 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   if (quiet == 0)
1225       printf("\n\nA script for adding all the countries can be found in \"%s\".\n",
1226              outfile);
1227   if (ORE && quiet == 0)
1228     printf("\t***IMPORTANT: Resources have already been added***\n\tYou do NOT need to run the ore program.\n");
1229   return 0;
1230 }
1231
1232 static void qprint (str)
1233 const char *str;
1234 {
1235   if (quiet == 0)
1236       fputs (str, stdout);
1237 }
1238
1239 void
1240 fl_sct_init(coord x, coord y, s_char *ptr)
1241 {
1242         struct  sctstr *sp = (struct sctstr *) ptr;
1243
1244         sp->ef_type = EF_SECTOR;
1245         sp->sct_x = x;
1246         sp->sct_y = y;
1247         sp->sct_dist_x = x;
1248         sp->sct_dist_y = y;
1249         sp->sct_road = 0;
1250         sp->sct_rail = 0;
1251         sp->sct_defense = 0;
1252 }