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