]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
Indented with src/scripts/indent-emp.
[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 =
154     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
155
156 void parse_args(int argc, char *argv[]);
157 int allocate_memory(void);
158 void init(void);
159 int drift(void);
160 void grow_continents(void);
161 void create_elevations(void);
162 void write_sects(void);
163 int write_file(void);
164 void output(void);
165 int write_newcap_script(void);
166 int stable(void);
167 void elevate_land(void);
168 void elevate_sea(void);
169 void translate_continents(void);
170 int map_symbol(int x, int y);
171 static void fl_sct_init(coord x, coord y, s_char *ptr);
172
173 void print_vars();
174 void fl_move(int);
175 void next_coast();
176 void grow_islands();
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     extern s_char *datadir;
189     char *config_file = NULL;
190     char tbuf[512];
191     int i = 0;
192
193 #if !defined(_WIN32)
194     while ((opt = getopt(argc, argv, "ae:ioqs:")) != EOF) {
195         switch (opt) {
196         case 'a':
197             AIRPORT_MARKER = 1;
198             break;
199         case 'i':
200             DISTINCT_ISLANDS = 0;
201             break;
202         case 'e':
203             config_file = optarg;
204             break;
205         case 'o':
206             ORE = 0;
207             break;
208         case 'q':
209             quiet = 1;
210             break;
211         case 's':
212             outfile = optarg;
213             break;
214         }
215     }
216 #endif
217     if (config_file == NULL) {
218         sprintf(tbuf, "%s/econfig", datadir);
219         config_file = tbuf;
220     }
221     emp_config(config_file);
222
223 #if !defined(_WIN32)
224     parse_args(argc - optind, argv + optind);
225 #else
226     parse_args(argc - 1, argv + 1);
227 #endif
228     if (allocate_memory() == -1)
229         exit(-1);
230     print_vars();
231
232     do {
233         init();
234         if (!quiet && i)
235             printf("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
236         qprint
237             ("\n\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
238         qprint("placing capitals...\n");
239         if (!drift())
240             qprint
241                 ("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
242         qprint("growing continents...\n");
243         grow_continents();
244     } while (fl_status && ++i < NUMTRIES);
245     if (fl_status) {
246         fputs("ERROR: World not large enough to hold continents\n",
247               stderr);
248         exit(1);
249     }
250     qprint("growing islands:");
251     grow_islands();
252     qprint("\nelevating land...\n");
253     create_elevations();
254     qprint("designating sectors...\n");
255     if (ORE)
256         qprint("adding resources...\n");
257     write_sects();
258     qprint("writing to sectors file...\n");
259     if (write_file() == -1)
260         exit(-1);
261     output();
262     write_newcap_script();
263     exit(0);
264 }
265
266 void
267 print_vars()
268 {
269     if (quiet)
270         return;
271     puts("Creating a planet with:\n");
272     printf("%d continents\n", nc);
273     printf("continent size: %d\n", sc);
274     printf("number of islands: %d\n", ni);
275     printf("average size of islands: %d\n", is);
276     printf("spike: %d%%\n", sp);
277     printf
278         ("%d%% of land is mountain (each continent will have %d mountains)\n",
279          pm, (pm * sc) / 100);
280     printf("minimum distance between continents: %d\n", di);
281     printf("minimum distance from islands to continents: %d\n", id);
282     printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
283 }
284
285 int
286 my_sqrt(n)
287 int n;
288 {
289     int i;
290
291     for (i = 1; i * i < n * 10000; ++i) ;
292     return (i + 50) / 100;
293 }
294
295 /****************************************************************************
296   PARSE COMMAND LINE ARGUMENTS
297 ****************************************************************************/
298
299 void
300 parse_args(int argc, char *argv[])
301 {
302     if (argc < 2 || argc > 8) {
303         puts("fairland syntax:\n");
304         puts("fairland [-e config] [-aiqo] [-s script] <nc> <sc> [<ni>] [<is>] [<sp>] [<pm>] [<di>] [<id>]");
305         puts("-q = quiet, -o = no ore produced");
306         puts("-a = Airport marker for continents, -i = islands not distinct");
307         printf("-e = read config file, -s = name of script (default %s)\n",
308                outfile);
309         puts("nc = number of continents [MANDATORY]");
310         puts("sc = continent size [MANDATORY]");
311         puts("ni = number of islands (default = nc)");
312         puts("is = average size of islands (default = sc/2)");
313         printf
314             ("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n",
315              DEFAULT_SPIKE);
316         printf
317             ("pm = the percentage of land that is mountain (default = %d)\n",
318              DEFAULT_MOUNTAIN);
319         printf
320             ("di = the minimum distance between continents (default = %d)\n",
321              DEFAULT_CONTDIST);
322         printf
323             ("id = minimum distance from islands to continents (default = %d)\n",
324              DEFAULT_ISLDIST);
325         exit(1);
326     }
327     nc = atoi(argv[0]);
328     if (nc < 1) {
329         puts("fairland: error -- number of continents must be > 0");
330         exit(1);
331     }
332
333     sc = atoi(argv[1]);
334     if (sc < 1) {
335         puts("fairland: error -- size of continents must be > 0");
336         exit(1);
337     }
338
339     if (argc > 2)
340         ni = atoi(argv[2]);
341     else
342         ni = nc;
343
344     if (argc > 3)
345         is = atoi(argv[3]);
346     else
347         is = sc / 2;
348     if (is < 0)
349         is = 0;
350
351     if (argc > 4)
352         sp = atoi(argv[4]);
353     else
354         sp = DEFAULT_SPIKE;
355     if (sp < 0)
356         sp = 0;
357     if (sp > 100)
358         sp = 100;
359
360     if (argc > 5)
361         pm = atoi(argv[5]);
362     else
363         pm = DEFAULT_MOUNTAIN;
364     if (pm < 0)
365         pm = 0;
366
367     if (argc > 6)
368         di = atoi(argv[6]);
369     else
370         di = DEFAULT_CONTDIST;
371
372     if (di < 0) {
373         puts("fairland: error -- distance between continents must be >= 0");
374         exit(1);
375     }
376     if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
377         puts("fairland: error -- distance between continents too large");
378         exit(1);
379     }
380
381     if (argc > 7)
382         id = atoi(argv[7]);
383     else
384         id = DEFAULT_ISLDIST;
385     if (id < 0) {
386         puts("fairland: error -- distance from islands to continents must be >= 0");
387         exit(1);
388     }
389     if (id > WORLD_X || id > WORLD_Y) {
390         puts("fairland: error -- distance from islands to continents too large");
391         exit(1);
392     }
393     if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
394         puts("fairland: error -- world not big enough to fit continents.");
395         puts("arguments must satisfy:");
396         puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
397         exit(1);
398     }
399 }
400
401 /****************************************************************************
402   VARIABLE INITIALIZATION
403 ****************************************************************************/
404
405 int
406 allocate_memory(void)
407 {
408     int i;
409     time_t now;
410
411 #if !defined(_WIN32)
412     the_file =
413         open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC, 0660);
414 #else
415     the_file =
416         open(empfile[EF_SECTOR].file,
417              O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0660);
418 #endif
419     if (the_file < 0) {
420         perror(empfile[EF_SECTOR].file);
421         return -1;
422     }
423     sectsbuf =
424         (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
425     sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
426     for (i = 0; i < YSIZE; i++)
427         sects[i] = &sectsbuf[XSIZE * i];
428     time(&now);
429 #if !defined(_WIN32)
430     srandom(now + getpid());
431 #else
432     srandom(now);
433 #endif
434     capx = (int *)calloc(nc, sizeof(int));
435     capy = (int *)calloc(nc, sizeof(int));
436     vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
437     mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
438     own = (int **)calloc(WORLD_X, sizeof(int *));
439     elev = (int **)calloc(WORLD_X, sizeof(int *));
440     for (i = 0; i < WORLD_X; ++i) {
441         own[i] = (int *)calloc(WORLD_Y, sizeof(int));
442         elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
443     }
444     sectx = (int **)calloc(nc + ni, sizeof(int *));
445     secty = (int **)calloc(nc + ni, sizeof(int *));
446     sectc = (int **)calloc(nc + ni, sizeof(int *));
447     isecs = (int *)calloc(nc + ni, sizeof(int));
448     weight = (int *)calloc(max(sc, is * 2), sizeof(int));
449     dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
450     dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
451     for (i = 0; i < nc; ++i) {
452         sectx[i] = (int *)calloc(sc, sizeof(int));
453         secty[i] = (int *)calloc(sc, sizeof(int));
454         sectc[i] = (int *)calloc(sc, sizeof(int));
455     }
456     for (i = nc; i < nc + ni; ++i) {
457         sectx[i] = (int *)calloc(is * 2, sizeof(int));
458         secty[i] = (int *)calloc(is * 2, sizeof(int));
459         sectc[i] = (int *)calloc(is * 2, sizeof(int));
460     }
461
462     return 0;
463 }
464
465 void
466 init(void)
467 {
468     int i, j, xx = 0, yy = 0;
469
470     mcc = 0;
471     fl_status = 0;
472
473     for (i = 0; i < WORLD_X; ++i) {
474         for (j = 0; j < WORLD_Y; ++j) {
475             own[i][j] = -1;
476             elev[i][j] = -INFINITY;
477         }
478     }
479
480     for (i = 0; i < nc; ++i, xx += 2) {
481         if (xx >= WORLD_X) {
482             ++yy;
483             xx = yy % 2;
484             if (yy == WORLD_Y) {
485                 puts("fairland error: world not big enough for all the continents.\n");
486                 exit(1);
487             }
488         }
489         capx[i] = xx;
490         capy[i] = yy;
491     }
492     for (i = 0; i < STABLE_CYCLE; ++i)
493         mc[i] = i;
494 }
495
496 /****************************************************************************
497   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
498 ****************************************************************************/
499
500 /* How isolated is capital j?
501 */
502 int
503 iso(j, newx, newy)
504 int j, newx, newy;
505 {
506     int i, md, d = WORLD_X + WORLD_Y;
507
508     for (i = 0; i < nc; ++i) {
509         if (i == j)
510             continue;
511         md = mapdist(capx[i], capy[i], newx, newy);
512         if (md < d)
513             d = md;
514     }
515
516     return d;
517 }
518
519 /* Drift all the capitals
520 */
521 int
522 drift(void)
523 {
524     int i, turns;
525
526     for (turns = 0; turns < DRIFT_MAX; ++turns) {
527         if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
528             return 1;
529         for (i = 0; i < nc; ++i)
530             fl_move(i);
531     }
532     return 0;
533 }
534
535 /* Check to see if we have stabilized--can we stop drifting the capitals?
536 */
537
538 int
539 stable(void)
540 {
541     int i, isod, d = 0, stab = 1;
542
543     for (i = 0; i < nc; ++i) {
544         isod = iso(i, capx[i], capy[i]);
545         if (isod > d)
546             d = isod;
547     }
548     for (i = 0; i < STABLE_CYCLE; ++i)
549         if (d != mc[i])
550             stab = 0;
551     mc[mcc] = d;
552     mcc = (mcc + 1) % STABLE_CYCLE;
553     return stab ? d : 0;
554 }
555
556 /* This routine does the actual drifting
557 */
558
559 void
560 fl_move(j)
561 int j;
562 {
563     int i, n, newx, newy;
564
565     for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
566         newx = new_x(capx[j] + dirx[i]);
567         newy = new_y(capy[j] + diry[i]);
568         if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
569             capx[j] = newx;
570             capy[j] = newy;
571             return;
572         }
573     }
574 }
575
576 /****************************************************************************
577   GROW THE CONTINENTS
578 ****************************************************************************/
579
580 /* Look for a coastal sector of continent c
581 */
582
583 void
584 find_coast(c)
585 int c;
586 {
587     int i, j;
588
589     for (i = 0; i < secs; ++i) {
590         sectc[c][i] = 0;
591         for (j = 0; j < 6; ++j)
592             if (own[new_x(sectx[c][i] + dirx[j])]
593                 [new_y(secty[c][i] + diry[j])] == -1)
594                 sectc[c][i] = 1;
595     }
596 }
597
598 /* Used for measuring distances
599 */
600 int
601 next_vector(n)
602 int n;
603 {
604     int i;
605
606     if (n == 1) {
607         vector[0] += 1;
608         vector[0] %= 6;
609         return vector[0];
610     }
611     for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
612     vector[i - 1] += 1;
613     vector[i - 1] %= 6;
614     return i > 1 || vector[0] > 0;
615 }
616
617 /* Test to see if we're allowed to grow there: the arguments di and id
618 */
619 int
620 try_to_grow(c, newx, newy, d)
621 int c, newx, newy, d;
622 {
623     int i, j, px, py;
624
625     for (i = 1; i <= d; ++i) {
626         for (j = 0; j < i; ++j)
627             vector[j] = 0;
628         do {
629             px = newx;
630             py = newy;
631             for (j = 0; j < i; ++j) {
632                 px = new_x(px + dirx[vector[j]]);
633                 py = new_y(py + diry[vector[j]]);
634             }
635             if (own[px][py] != -1 &&
636                 own[px][py] != c && (DISTINCT_ISLANDS || own[px][py] < nc))
637                 return 0;
638         } while (next_vector(i));
639     }
640     sectx[c][secs] = newx;
641     secty[c][secs] = newy;
642     own[newx][newy] = c;
643     return 1;
644 }
645
646 /* Move along the coast in a clockwise direction.
647 */
648
649 void
650 next_coast(c, x, y, xp, yp)
651 int c, x, y, *xp, *yp;
652 {
653     int i, nx, ny, wat = 0;
654
655     if (secs == 1) {
656         *xp = x;
657         *yp = y;
658         return;
659     }
660
661     for (i = 0; i < 12; ++i) {
662         nx = new_x(x + dirx[i % 6]);
663         ny = new_y(y + diry[i % 6]);
664         if (own[nx][ny] == -1)
665             wat = 1;
666         if (wat && own[nx][ny] == c) {
667             *xp = nx;
668             *yp = ny;
669             return;
670         }
671     }
672 }
673
674 /* Choose a sector to grow from
675 */
676
677 int
678 new_try(int c)
679 {
680     int i, starti;
681
682     if (secs == 1) {
683         if (sectc[c][0])
684             return 0;
685     } else {
686         i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
687         do {
688             if (sectc[c][i])
689                 return i;
690             i = (i + 1) % secs;
691         } while (i != starti);
692         if (c < nc) {
693             printf
694                 ("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
695                  c + 'a', secs);
696             exit(1);
697         } else
698             return -1;
699     }
700     return -1;
701 }
702
703 /* Grow continent c by 1 sector
704 */
705
706 int
707 grow_one_sector(c)
708 int c;
709 {
710     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
711
712     spike = rnd(100) < sp;
713     if ((try1 = new_try(c)) == -1)
714         return 0;
715     x = sx = sectx[c][try1];
716     y = sy = secty[c][try1];
717     coast_search = 0;
718     done = 0;
719     do {
720         if (spike) {
721             for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
722                 newx = new_x(x + dirx[i]);
723                 newy = new_y(y + diry[i]);
724                 if (own[newx][newy] == -1 &&
725                     (n > 5 ||
726                      (own[new_x(x + dirx[(i + 5) % 6])]
727                       [new_y(y + diry[(i + 5) % 6])] == -1
728                       &&
729                       own[new_x(x + dirx[(i + 1) % 6])][new_y
730                                                         (y +
731                                                          diry[(i +
732                                                                1) % 6])] ==
733                       -1)))
734                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
735                         done = 1;
736             }
737         } else
738             for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
739                 newx = new_x(x + dirx[i]);
740                 newy = new_y(y + diry[i]);
741                 if (own[newx][newy] == -1)
742                     if (try_to_grow(c, newx, newy, c < nc ? di : id))
743                         done = 1;
744             }
745         next_coast(c, x, y, &x, &y);
746         ++coast_search;
747     } while (!done && coast_search < COAST_SEARCH_MAX &&
748              (secs == 1 || x != sx || y != sy));
749     if (!done && c < nc) {
750         if (!quiet)
751             printf
752                 ("fairland: error -- continent %c had no room to grow!\n",
753                  numletter[c % 62]);
754         fl_status |= STATUS_NO_ROOM;
755     }
756     return done;
757 }
758
759 /* Grow all the continents
760 */
761 void
762 grow_continents(void)
763 {
764     int c;
765
766     for (c = 0; c < nc; ++c) {
767         sectx[c][0] = capx[c];
768         secty[c][0] = capy[c];
769         own[sectx[c][0]][secty[c][0]] = c;
770         sectx[c][1] = new_x(capx[c] + 2);
771         secty[c][1] = capy[c];
772         own[sectx[c][1]][secty[c][1]] = c;
773     }
774
775     for (secs = 2; secs < sc && !fl_status; ++secs) {
776         for (c = 0; c < nc; ++c) {
777             find_coast(c);
778             grow_one_sector(c);
779         }
780     }
781     if (fl_status && !quiet)
782         printf("Only managed to grow %d out of %d sectors.\n", secs, sc);
783     ctot = nc;
784 }
785
786 /****************************************************************************
787   GROW THE ISLANDS
788 ****************************************************************************/
789
790 /* Choose a place to start growing an island from
791 */
792 int
793 place_island(c, xp, yp)
794 int c, *xp, *yp;
795 {
796     int d, sx, sy;
797     int ssy = rnd(WORLD_Y);
798     int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
799
800     if (ssx > WORLD_X - 2)
801         ssx = new_x(ssx + 2);
802     for (d = di + id; d >= id; --d) {
803         sx = ssx;
804         sy = ssy;
805         *xp = new_x(sx + 2);
806         for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
807             if (*xp >= WORLD_X) {
808                 *yp = new_y(*yp + 1);
809                 *xp = (*yp) % 2;
810                 if (*xp == sx && *yp == sy)
811                     break;
812             }
813             if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
814                 return 1;
815         }
816     }
817     return 0;
818 }
819
820 /* Grow all the islands
821 */
822
823 void
824 grow_islands()
825 {
826     int c, x, y, isiz;
827
828     for (c = nc; c < nc + ni; ++c) {
829         secs = 0;
830         if (!place_island(c, &x, &y))
831             return;
832         isiz = 1 + rnd(2 * is - 1);
833         do {
834             ++secs;
835             find_coast(c);
836         } while (secs < isiz && grow_one_sector(c));
837         if (quiet == 0)
838             printf(" %d(%d)", c - nc + 1, secs);
839         isecs[c] = secs;
840         ctot = c;
841     }
842 }
843
844 /****************************************************************************
845   CREATE ELEVATIONS
846 ****************************************************************************/
847 void
848 create_elevations(void)
849 {
850     elevate_land();
851     elevate_sea();
852 }
853
854 /* Generic function for finding the distance to the closest sea, land, or
855    mountain
856 */
857 int
858 distance_to_what(x, y, flag)
859 int x, y, flag;
860 {
861     int j, d, px, py;
862
863     for (d = 1; d < 5; ++d) {
864         for (j = 0; j < d; ++j)
865             vector[j] = 0;
866         do {
867             px = x;
868             py = y;
869             for (j = 0; j < d; ++j) {
870                 px = new_x(px + dirx[vector[j]]);
871                 py = new_y(py + diry[vector[j]]);
872             }
873             switch (flag) {
874             case 0:             /* distance to sea */
875                 if (own[px][py] == -1)
876                     return d;
877                 break;
878             case 1:             /* distance to land */
879                 if (own[px][py] != -1)
880                     return d;
881                 break;
882             case 2:             /* distance to mountain */
883                 if (elev[px][py] == INFINITY)
884                     return d;
885                 break;
886             }
887         } while (next_vector(d));
888     }
889     return d;
890 }
891
892 #define ELEV elev[sectx[c][i]][secty[c][i]]
893 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
894 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
895
896 /* Decide where the mountains go
897 */
898 void
899 elevate_land(void)
900 {
901     int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
902         r, dk;
903
904     for (c = 0; c < ctot; ++c) {
905         total = 0;
906         ns = (c < nc) ? sc : isecs[c];
907         nm = (pm * ns) / 100;
908
909 /* Place the mountains */
910
911         for (i = 0; i < ns; ++i) {
912             dsea[i] = distance_to_sea();
913             weight[i] = (total += (dsea[i] * dsea[i]));
914         }
915
916         for (k = nm, mountain_search = 0;
917              k && mountain_search < MOUNTAIN_SEARCH_MAX;
918              ++mountain_search) {
919             r = rnd(total);
920             for (i = 0; i < ns; ++i)
921                 if (r < weight[i] && ELEV == -INFINITY && (c >= nc ||
922                                                            ((!(capx[c] ==
923                                                                sectx[c][i]
924                                                                && capy[c]
925                                                                ==
926                                                                secty[c]
927                                                                [i]))
928                                                             &&
929                                                             (!(new_x
930                                                                (capx[c] +
931                                                                 2) ==
932                                                                sectx[c][i]
933                                                                && capy[c]
934                                                                ==
935                                                                secty[c]
936                                                                [i]))))) {
937                     ELEV = INFINITY;
938                     break;
939                 }
940             --k;
941         }
942
943 /* Elevate land that is not mountain and not capital */
944
945         for (i = 0; i < ns; ++i)
946             dmoun[i] = distance_to_mountain();
947         dk = (ns - nm - ((c < nc) ? 3 : 1) >
948               0) ? (100 * (HIGHMIN - LANDMIN)) / (ns - nm -
949                                                   ((c <
950                                                     nc) ? 3 : 1)) : 100 *
951             INFINITY;
952         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
953             highest = -INFINITY;
954             where = -1;
955             for (i = 0; i < ns; ++i) {
956                 if (ELEV != INFINITY && (c >= nc ||
957                                          ((!(capx[c] == sectx[c][i]
958                                              && capy[c] == secty[c][i]))
959                                           &&
960                                           (!(new_x(capx[c] + 2) ==
961                                              sectx[c][i]
962                                              && capy[c] ==
963                                              secty[c][i]))))) {
964                     h = 3 * (5 - dmoun[i]) + dsea[i];
965                     if (h > highest) {
966                         highest = h;
967                         where = i;
968                     }
969                 }
970             }
971             if (where == -1)
972                 break;
973             newk = k / 100;
974             if (newk >= HILLMIN && newk < PLATMIN)
975                 newk = PLATMIN;
976             if (newk < LANDMIN)
977                 newk = LANDMIN;
978             elev[sectx[c][where]][secty[c][where]] = newk;
979             dsea[where] = -INFINITY;
980             dmoun[where] = INFINITY;
981         }
982
983 /* Elevate the mountains and capitals */
984
985         for (i = 0; i < ns; ++i) {
986             if (ELEV == INFINITY) {
987                 if (dsea[i] == 1)
988                     ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
989                 else
990                     ELEV =
991                         HIGHMIN + rnd((256 - HIGHMIN) / 2) +
992                         rnd((256 - HIGHMIN) / 2);
993             } else
994                 if ((c < nc
995                      &&
996                      ((capx[c] == sectx[c][i] && capy[c] == secty[c][i])))
997                     ||
998                     ((new_x(capx[c] + 2) == sectx[c][i]
999                       && capy[c] == secty[c][i])))
1000                 ELEV = PLATMIN;
1001         }
1002     }
1003 }
1004
1005 #define distance_to_land() distance_to_what(x, y, 1)
1006
1007 void
1008 elevate_sea(void)
1009 {
1010     int x, y;
1011
1012     for (y = 0; y < WORLD_Y; ++y) {
1013         for (x = y % 2; x < WORLD_X; x += 2) {
1014             if (elev[x][y] == -INFINITY)
1015                 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
1016         }
1017     }
1018 }
1019
1020 /****************************************************************************
1021   ADD THE RESOURCES
1022 ****************************************************************************/
1023
1024 int
1025 set_fert(e)
1026 int e;
1027 {
1028     int fert = 0;
1029     if (e < LANDMIN)
1030         fert = LANDMIN - e + 40;
1031     else if (e < FERT_MAX)
1032         fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1033     if (fert > 120)
1034         fert = 120;
1035     return fert;
1036 }
1037
1038 int
1039 set_oil(e)
1040 int e;
1041 {
1042     int oil = 0;
1043     if (e < LANDMIN)
1044         oil = (LANDMIN - e) * 2 + rnd(2);
1045     else if (e <= OIL_MAX)
1046         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1047     if (oil > 100)
1048         oil = 100;
1049     return oil;
1050 }
1051
1052 int
1053 set_iron(e)
1054 int e;
1055 {
1056     int iron = 0;
1057     if (e >= IRON_MIN && e < HIGHMIN)
1058         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1059     if (iron > 100)
1060         iron = 100;
1061     return iron;
1062 }
1063
1064 int
1065 set_gold(e)
1066 int e;
1067 {
1068     int gold = 0;
1069     if (e >= GOLD_MIN) {
1070         if (e < HIGHMIN)
1071             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1072         else
1073             gold = 100 - 20 * HIGHMIN / e;
1074     }
1075     if (gold > 100)
1076         gold = 100;
1077     return gold;
1078 }
1079
1080 int
1081 set_uran(e)
1082 int e;
1083 {
1084     int uran = 0;
1085     if (e >= URAN_MIN && e < HIGHMIN)
1086         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1087     if (uran > 100)
1088         uran = 100;
1089     return uran;
1090 }
1091
1092 void
1093 add_resources(sct)
1094 struct sctstr *sct;
1095 {
1096     sct->sct_fertil = set_fert(sct->sct_elev);
1097     sct->sct_oil = set_oil(sct->sct_elev);
1098     sct->sct_min = set_iron(sct->sct_elev);
1099     sct->sct_gmin = set_gold(sct->sct_elev);
1100     sct->sct_uran = set_uran(sct->sct_elev);
1101 }
1102
1103 /****************************************************************************
1104   DESIGNATE THE SECTORS
1105 ****************************************************************************/
1106
1107 void
1108 write_sects(void)
1109 {
1110     register struct sctstr *sct;
1111     int c, x, y, total;
1112
1113     /*  sct = &sects[0][0]; */
1114     sct = sectsbuf;
1115     for (y = 0; y < YSIZE; y++) {
1116         for (x = 0; x < XSIZE; x++, sct++) {
1117             fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1118             total = elev[sct->sct_x][y];
1119             if (total < LANDMIN) {
1120                 sct->sct_type = SCT_WATER;
1121             } else if (total < HILLMIN)
1122                 sct->sct_type = SCT_RURAL;
1123             else if (total < PLATMIN)
1124                 sct->sct_type = SCT_MOUNT;
1125             else if (total < HIGHMIN)
1126                 sct->sct_type = SCT_RURAL;
1127             else
1128                 sct->sct_type = SCT_MOUNT;
1129             sct->sct_elev = total;
1130             sct->sct_newtype = sct->sct_type;
1131             if (ORE)
1132                 add_resources(sct);
1133         }
1134     }
1135     if (AIRPORT_MARKER)
1136         for (c = 0; c < nc; ++c) {
1137             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1138             sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype =
1139                 SCT_AIRPT;
1140         }
1141 }
1142
1143 /****************************************************************************
1144   WRITE ALL THIS STUFF TO THE FILE
1145 ****************************************************************************/
1146 int
1147 write_file(void)
1148 {
1149     int n;
1150
1151     /*  if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1152     if ((n =
1153          write(the_file, sectsbuf,
1154                YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1155         perror(empfile[EF_SECTOR].file);
1156         return -1;
1157     }
1158     if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1159         printf("%s:partial write\n", empfile[EF_SECTOR].file);
1160         return -1;
1161     }
1162     close(the_file);
1163     return 0;
1164 }
1165
1166 /****************************************************************************
1167   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1168 ****************************************************************************/
1169 void
1170 output(void)
1171 {
1172     int i, j;
1173     if (opt_BLITZ)
1174         translate_continents();
1175     if (quiet == 0) {
1176         for (i = 0; i < WORLD_Y; ++i) {
1177             puts("");
1178             if (i % 2)
1179                 printf(" ");
1180             for (j = i % 2; j < WORLD_X; j += 2) {
1181                 if (own[j][i] == -1)
1182                     printf(". ");
1183                 else {
1184                     printf("%c ", map_symbol(j, i));
1185                 }
1186             }
1187         }
1188     }
1189     if (AIRPORT_MARKER)
1190         printf
1191             ("\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");
1192 }
1193
1194 /* Reorder the continents from top left to bottom right */
1195 void
1196 translate_continents(void)
1197 {
1198     int i, j, n = 0, k, gotit, c;
1199     int *trans, *trans_cont, *oldcapx, *oldcapy;
1200
1201     trans = (int *)calloc(nc, sizeof(int));
1202     trans_cont = (int *)calloc(nc, sizeof(int));
1203     oldcapx = (int *)calloc(nc, sizeof(int));
1204     oldcapy = (int *)calloc(nc, sizeof(int));
1205
1206     for (i = 0; i < WORLD_Y; ++i) {
1207         for (j = i % 2; j < WORLD_X; j += 2) {
1208             if (own[j][i] > -1 && own[j][i] < nc) {
1209                 gotit = 0;
1210                 for (k = 0; k < n; ++k) {
1211                     if (trans[k] == own[j][i])
1212                         gotit = 1;
1213                 }
1214                 if (!gotit) {
1215                     if (n > nc) {
1216                         printf
1217                             ("fairland: BUG in translate continents!  mail stevens@math.utoronto.ca\n");
1218                         exit(2);
1219                     }
1220                     trans[n] = own[j][i];
1221                     trans_cont[own[j][i]] = n;
1222                     ++n;
1223                 }
1224             }
1225         }
1226     }
1227     for (i = 0; i < WORLD_Y; ++i) {
1228         for (j = i % 2; j < WORLD_X; j += 2) {
1229             if (own[j][i] > -1 && own[j][i] < nc) {
1230                 own[j][i] = trans_cont[own[j][i]];
1231             }
1232         }
1233     }
1234     for (c = 0; c < nc; ++c) {
1235         oldcapx[c] = capx[c];
1236         oldcapy[c] = capy[c];
1237     }
1238     for (c = 0; c < nc; ++c) {
1239         capx[c] = oldcapx[trans[c]];
1240         capy[c] = oldcapy[trans[c]];
1241     }
1242 }
1243
1244 int
1245 map_symbol(int x, int y)
1246 {
1247     int c, iscap = 0;
1248
1249     for (c = 0; c < nc; ++c)
1250         if ((x == capx[c] && y == capy[c])
1251             || (x == new_x(capx[c] + 2) && y == capy[c]))
1252             iscap = 1;
1253     if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1254         || elev[x][y] >= HIGHMIN)
1255         return '^';
1256     return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1257 }
1258
1259 /***************************************************************************
1260   WRITE A SCRIPT FOR PLACING CAPITALS
1261 ****************************************************************************/
1262 int
1263 write_newcap_script(void)
1264 {
1265     int c;
1266     FILE *script = fopen(outfile, "w");
1267
1268     if (!script) {
1269         printf("fairland: error, unable to write to %s.\n", outfile);
1270         return -1;
1271     }
1272
1273     for (c = 0; c < nc; ++c) {
1274         fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1275         if (AIRPORT_MARKER)
1276             fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1277         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1278     }
1279     fprintf(script, "add %d visitor visitor v i\n", c + 1);
1280     ++c;
1281     fclose(script);
1282     if (quiet == 0)
1283         printf
1284             ("\n\nA script for adding all the countries can be found in \"%s\".\n",
1285              outfile);
1286     if (ORE && quiet == 0)
1287         printf
1288             ("\t***IMPORTANT: Resources have already been added***\n\tYou do NOT need to run the ore program.\n");
1289     return 0;
1290 }
1291
1292 static void
1293 qprint(str)
1294 const char *str;
1295 {
1296     if (quiet == 0)
1297         fputs(str, stdout);
1298 }
1299
1300 void
1301 fl_sct_init(coord x, coord y, s_char *ptr)
1302 {
1303     struct sctstr *sp = (struct sctstr *)ptr;
1304
1305     sp->ef_type = EF_SECTOR;
1306     sp->sct_x = x;
1307     sp->sct_y = y;
1308     sp->sct_dist_x = x;
1309     sp->sct_dist_y = y;
1310     sp->sct_road = 0;
1311     sp->sct_rail = 0;
1312     sp->sct_defense = 0;
1313 }