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