]> git.pond.sub.org Git - empserver/blob - src/util/fairland.c
02f1ee0d13cfea67a75425f973d79affb83ee8a5
[empserver] / src / util / fairland.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2020, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire 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 3 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, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  fairland.c: Create a nice, new world
28  *
29  *  Known contributors to this file:
30  *     Ken Stevens, 1995
31  *     Steve McClure, 1998
32  *     Markus Armbruster, 2004-2020
33  */
34
35 /*
36  * How fairland works
37  *
38  * 1. Place capitals
39  *
40  * Place the capitals on the torus in such a way so as to maximize
41  * their distances from one another.  This uses the perturbation
42  * technique of calculus of variations.
43  *
44  * 2. Grow start islands ("continents")
45  *
46  * For all continents, add the first sector at the capital's location,
47  * and the second right to it.  These are the capital sectors.  Then
48  * add one sector to each continent in turn, until they have the
49  * specified size.
50  *
51  * Growth uses weighted random sampling to pick one sector from the
52  * set of adjacent sea sectors that aren't too close to another
53  * continent.  Growth operates in spiking mode with a chance given by
54  * the spike percentage.  When "spiking", a sector's weight increases
55  * with number of adjacent sea sectors.  This directs the growth away
56  * from land, resulting in spikes.  When not spiking, the weight
57  * increases with the number of adjacent land sectors.  This makes the
58  * island more rounded.
59  *
60  * If growing fails due to lack of room, start over.  If it fails too
61  * many times, give up and terminate unsuccessfully.
62  *
63  * 3. Place and grow additional islands
64  *
65  * Each continent has a "sphere of influence": the set of sectors
66  * closer to it than to any other continent.  Each island is entirely
67  * in one such sphere, and each sphere contains the same number of
68  * islands with the same sizes.
69  *
70  * First, split the specified number of island sectors per continent
71  * randomly into the island sizes.  Sort by size so that larger
72  * islands are grown before smaller ones, to give the large ones the
73  * best chance to grow to their planned size.
74  *
75  * Then place one island's first sector into each sphere, using
76  * weighted random sampling with weights favoring sectors away from
77  * land and other spheres.  Add one sector to each island in turn,
78  * until they have the intended size.  Repeat until the specified
79  * number of islands has been grown.
80  *
81  * If placement fails due to lack of room, start over, just like for
82  * continents.
83  *
84  * Growing works as for continents, except the minimum distance for
85  * additional islands applies, and growing simply stops when any of
86  * the islands being grown lacks the room to grow further.  The number
87  * of sectors not grown carries over to the next island size.
88  *
89  * 4. Compute elevation
90  *
91  * Elevate islands one after the other.
92  *
93  * First, place the specified number of mountains randomly.
94  * Probability increases with distance to sea.
95  *
96  * Last, elevate mountains and the capitals.  Pick coastal mountain
97  * elevation randomly from an interval of medium elevations reserved
98  * for them.  Pick non-coastal mountain elevation randomly from an
99  * interval of high elevation reserved for them.  Set capital
100  * elevation to a fixed, medium value.
101  *
102  * In between, elevate the remaining land one by one, working from
103  * mountains towards the sea, and from the elevation just below the
104  * non-coastal mountains' interval linearly down to 1, avoiding the
105  * coastal mountains' interval.
106  *
107  * This gives islands of the same size the same set of elevations,
108  * except for mountains.
109  *
110  * Elevate sea: pick a random depth from an interval that deepens with
111  * the distance to land.
112  *
113  * 5. Set resources
114  *
115  * Sector resources are simple functions of elevation.  You can alter
116  * macros OIL_MAX, IRON_MIN, GOLD_MIN, FERT_MAX, and URAN_MIN to
117  * customize them.
118  */
119
120 #include <config.h>
121
122 #include <assert.h>
123 #include <errno.h>
124 #include <limits.h>
125 #include <stdarg.h>
126 #include <stdio.h>
127 #include <unistd.h>
128 #include "chance.h"
129 #include "optlist.h"
130 #include "path.h"
131 #include "prototypes.h"
132 #include "sect.h"
133 #include "version.h"
134 #include "xy.h"
135
136 /* The following five numbers refer to elevation under which (in the case of
137    fertility or oil) or over which (in the case of iron, gold, and uranium)
138    sectors with that elevation will contain that resource.  Elevation ranges
139    from 0 to 100 */
140
141 /* raise FERT_MAX for more fertility */
142 #define FERT_MAX   56
143
144 /* raise OIL_MAX for more oil */
145 #define OIL_MAX    33
146
147 /* lower IRON_MIN for more iron */
148 #define IRON_MIN   22
149
150 /* lower GOLD_MIN for more gold */
151 #define GOLD_MIN   36
152
153 /* lower URAN_MIN for more uranium */
154 #define URAN_MIN   56
155
156 /* do not change these 4 defines */
157 #define LANDMIN         1       /* plate altitude for normal land */
158 #define HILLMIN         34      /* plate altitude for hills */
159 #define PLATMIN         36      /* plate altitude for plateau */
160 #define HIGHMIN         98      /* plate altitude for mountains */
161
162 static void qprint(const char * const fmt, ...)
163     ATTRIBUTE((format (printf, 1, 2)));
164
165 /*
166  * Program arguments and options
167  */
168 static char *program_name;
169 static int nc, sc;              /* number and size of continents */
170 static int ni, is;              /* number and size of islands */
171 #define DEFAULT_SPIKE 10
172 static int sp = DEFAULT_SPIKE;  /* spike percentage */
173 #define DEFAULT_MOUNTAIN 0
174 static int pm = DEFAULT_MOUNTAIN; /* mountain percentage */
175 #define DEFAULT_CONTDIST 2
176 static int di = DEFAULT_CONTDIST; /* min. distance between continents */
177 #define DEFAULT_ISLDIST 1
178 static int id = DEFAULT_ISLDIST;  /* ... continents and islands */
179 /* don't let the islands crash into each other.
180    1 = don't merge, 0 = merge. */
181 static int DISTINCT_ISLANDS = 1;
182 static int quiet;
183 #define DEFAULT_OUTFILE_NAME "newcap_script"
184 static const char *outfile = DEFAULT_OUTFILE_NAME;
185
186 #define STABLE_CYCLE 4          /* stability required for perterbed capitals */
187 #define INFINITE_ELEVATION 999
188
189 /* these defines prevent infinite loops:
190 */
191 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
192 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
193 #define MOUNTAIN_SEARCH_MAX 1000        /* how long do we try to place mountains */
194
195 /* handy macros:
196 */
197
198 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
199 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
200
201 /*
202  * Island sizes
203  * isecs[i] is the size of the i-th island.
204  */
205 static int *isecs;
206
207 static int *capx, *capy;        /* location of the nc capitals */
208
209 static int **own;               /* owner of the sector.  -1 means water */
210
211 /*
212  * Adjacent land sectors
213  * adj_land[XYOFFSET(x, y)] bit d is set exactly when the sector next
214  * to x, y in direction d is land.
215  */
216 static unsigned char *adj_land;
217
218 /*
219  * Exclusive zones
220  * Each island is surrounded by an exclusive zone where only it may
221  * grow.  The width of the zone depends on minimum distances.
222  * While growing continents, it is @di sectors wide.
223  * While growing additional islands, it is @id sectors wide.
224  * DISTINCT_ISLANDS nullifies the exclusive zone then.
225  * xzone[XYOFFSET(x, y)] is -1 when the sector is in no exclusive
226  * zone, a (non-negative) island number when it is in that island's
227  * exclusive zone and no other, and -2 when it is in multiple
228  * exclusive zones.
229  */
230 static short *xzone;
231
232 /*
233  * Set of sectors seen already
234  * Increment @cur_seen to empty the set of sectors seen, set
235  * seen[XYOFFSET(x, y)] to @cur_seen to add x,y to the set.
236  */
237 static unsigned *seen;
238 static unsigned cur_seen;
239
240 /*
241  * Closest continent and "distance"
242  * closest[XYOFFSET(x, y)] is the closest continent's number.
243  * distance[] is complicated; see init_spheres_of_influence().
244  */
245 static natid *closest;
246 static unsigned short *distance;
247
248 /*
249  * Queue for breadth-first search
250  */
251 static int *bfs_queue;
252 static int bfs_queue_head, bfs_queue_tail;
253
254 static int **elev;              /* elevation of the sectors */
255 static int **sectx, **secty;    /* the sectors for each continent */
256 static int **sectc;             /* which sectors are on the coast? */
257 static int *weight;             /* used for placing mountains */
258 static int *dsea, *dmoun;       /* the dist to the ocean and mountain */
259
260 #define NUMTRIES 10             /* keep trying to grow this many times */
261
262 static const char *numletter =
263     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
264
265 static void help(char *);
266 static void usage(void);
267 static void parse_args(int argc, char *argv[]);
268 static void allocate_memory(void);
269 static void init(void);
270 static int drift(void);
271 static int grow_continents(void);
272 static void create_elevations(void);
273 static void write_sects(void);
274 static void output(void);
275 static int write_newcap_script(void);
276 static int stable(int);
277 static void elevate_land(void);
278 static void elevate_sea(void);
279 static void set_coastal_flags(void);
280
281 static void print_vars(void);
282 static void fl_move(int);
283 static int grow_islands(void);
284
285 /* Debugging aids: */
286 void print_own_map(void);
287 void print_xzone_map(void);
288 void print_closest_map(void);
289 void print_distance_map(void);
290 void print_elev_map(void);
291
292 /****************************************************************************
293   MAIN
294 ****************************************************************************/
295
296 int
297 main(int argc, char *argv[])
298 {
299     int opt;
300     char *config_file = NULL;
301     int try, done;
302     unsigned rnd_seed = 0;
303     int seed_set = 0;
304
305     program_name = argv[0];
306
307     while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
308         switch (opt) {
309         case 'e':
310             config_file = optarg;
311             break;
312         case 'i':
313             DISTINCT_ISLANDS = 0;
314             break;
315         case 'q':
316             quiet = 1;
317             break;
318         case 'R':
319             rnd_seed = strtoul(optarg, NULL, 10);
320             seed_set = 1;
321             break;
322         case 's':
323             outfile = optarg;
324             break;
325         case 'h':
326             usage();
327             exit(0);
328         case 'v':
329             printf("%s\n\n%s", version, legal);
330             exit(0);
331         default:
332             help(NULL);
333             exit(1);
334         }
335     }
336
337     if (!seed_set)
338         rnd_seed = pick_seed();
339     seed_prng(rnd_seed);
340     empfile_init();
341     if (emp_config(config_file) < 0)
342         exit(1);
343     empfile_fixup();
344
345     parse_args(argc - optind, argv + optind);
346
347     allocate_memory();
348     print_vars();
349
350     qprint("\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
351     qprint("seed is %u\n", rnd_seed);
352     try = 0;
353     do {
354         init();
355         if (try)
356             qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
357         qprint("placing capitals...\n");
358         if (!drift())
359             qprint("unstable drift\n");
360         qprint("growing continents...\n");
361         done = grow_continents();
362         if (!done)
363             continue;
364         qprint("growing islands:");
365         done = grow_islands();
366     } while (!done && ++try < NUMTRIES);
367     if (!done) {
368         fprintf(stderr, "%s: world not large enough for this much land\n",
369                 program_name);
370         exit(1);
371     }
372     qprint("elevating land...\n");
373     create_elevations();
374
375     qprint("writing to sectors file...\n");
376     if (!write_newcap_script())
377         exit(1);
378     if (chdir(gamedir)) {
379         fprintf(stderr, "%s: can't chdir to %s (%s)\n",
380                 program_name, gamedir, strerror(errno));
381         exit(1);
382     }
383     if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
384         exit(1);
385     write_sects();
386     if (!ef_close(EF_SECTOR))
387         exit(1);
388
389     output();
390     qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
391            outfile);
392     exit(0);
393 }
394
395 static void
396 print_vars(void)
397 {
398     if (quiet)
399         return;
400     puts("Creating a planet with:\n");
401     printf("%d continents\n", nc);
402     printf("continent size: %d\n", sc);
403     printf("number of islands: %d\n", ni);
404     printf("average size of islands: %d\n", is);
405     printf("spike: %d%%\n", sp);
406     printf("%d%% of land is mountain (each continent will have %d mountains)\n",
407            pm, (pm * sc) / 100);
408     printf("minimum distance between continents: %d\n", di);
409     printf("minimum distance from islands to continents: %d\n", id);
410     printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
411 }
412
413 static void
414 help(char *complaint)
415 {
416     if (complaint)
417         fprintf(stderr, "%s: %s\n", program_name, complaint);
418     fprintf(stderr, "Try -h for help.\n");
419 }
420
421 static void
422 usage(void)
423 {
424     printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
425            "  -e CONFIG-FILE  configuration file\n"
426            "                  (default %s)\n"
427            "  -i              islands may merge\n"
428            "  -q              quiet\n"
429            "  -R SEED         seed for random number generator\n"
430            "  -s SCRIPT       name of script to create (default %s)\n"
431            "  -h              display this help and exit\n"
432            "  -v              display version information and exit\n"
433            "  NC              number of continents\n"
434            "  SC              continent size\n"
435            "  NI              number of islands (default NC)\n"
436            "  IS              average island size (default SC/2)\n"
437            "  SP              spike percentage: 0 = round, 100 = snake (default %d)\n"
438            "  PM              percentage of land that is mountain (default %d)\n"
439            "  DI              minimum distance between continents (default %d)\n"
440            "  ID              minimum distance from islands to continents (default %d)\n",
441            program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
442            DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
443 }
444
445 static void
446 parse_args(int argc, char *argv[])
447 {
448     int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
449
450     if (argc < 2) {
451         help("missing arguments");
452         exit(1);
453     }
454     if (argc > 8) {
455         help("too many arguments");
456         exit(1);
457     }
458     nc = atoi(argv[0]);
459     if (nc < 1) {
460         fprintf(stderr, "%s: number of continents must be > 0\n",
461                 program_name);
462         exit(1);
463     }
464
465     sc = atoi(argv[1]);
466     if (sc < 2) {
467         fprintf(stderr, "%s: size of continents must be > 1\n",
468                 program_name);
469         exit(1);
470     }
471
472     ni = nc;
473     is = sc / 2;
474
475     if (argc > 2)
476         ni = atoi(argv[2]);
477     if (ni < 0) {
478         fprintf(stderr, "%s: number of islands must be >= 0\n",
479                 program_name);
480         exit(1);
481     }
482     if (ni % nc) {
483         fprintf(stderr, "%s: number of islands must be a multiple of"
484                 " the number of continents\n",
485                 program_name);
486         exit(1);
487     }
488
489     if (argc > 3)
490         is = atoi(argv[3]);
491     if (is < 1) {
492         fprintf(stderr, "%s: size of islands must be > 0\n",
493                 program_name);
494         exit(1);
495     }
496
497     if (argc > 4)
498         sp = atoi(argv[4]);
499     if (sp < 0 || sp > 100) {
500         fprintf(stderr,
501                 "%s: spike percentage must be between 0 and 100\n",
502                 program_name);
503         exit(1);
504     }
505
506     if (argc > 5)
507         pm = atoi(argv[5]);
508     if (pm < 0 || pm > 100) {
509         fprintf(stderr,
510                 "%s: mountain percentage must be between 0 and 100\n",
511                 program_name);
512         exit(1);
513     }
514
515     if (argc > 6)
516         di = atoi(argv[6]);
517     if (di < 0) {
518         fprintf(stderr, "%s: distance between continents must be >= 0\n",
519                 program_name);
520         exit(1);
521     }
522     if (di > dist_max) {
523         fprintf(stderr, "%s: distance between continents too large\n",
524                 program_name);
525         exit(1);
526     }
527
528     if (argc > 7)
529         id = atoi(argv[7]);
530     if (id < 0) {
531         fprintf(stderr,
532                 "%s: distance from islands to continents must be >= 0\n",
533                 program_name);
534         exit(1);
535     }
536     if (id > dist_max) {
537         fprintf(stderr,
538                 "%s: distance from islands to continents too large\n",
539                 program_name);
540         exit(1);
541     }
542 }
543
544 /****************************************************************************
545   VARIABLE INITIALIZATION
546 ****************************************************************************/
547
548 static void
549 allocate_memory(void)
550 {
551     int i;
552
553     capx = calloc(nc, sizeof(int));
554     capy = calloc(nc, sizeof(int));
555     own = calloc(WORLD_X, sizeof(int *));
556     adj_land = malloc(WORLD_SZ() * sizeof(*adj_land));
557     xzone = malloc(WORLD_SZ() * sizeof(*xzone));
558     seen = calloc(WORLD_SZ(), sizeof(*seen));
559     closest = malloc(WORLD_SZ() * sizeof(*closest));
560     distance = malloc(WORLD_SZ() * sizeof(*distance));
561     bfs_queue = malloc(WORLD_SZ() * sizeof(*bfs_queue));
562     elev = calloc(WORLD_X, sizeof(int *));
563     for (i = 0; i < WORLD_X; ++i) {
564         own[i] = calloc(WORLD_Y, sizeof(int));
565         elev[i] = calloc(WORLD_Y, sizeof(int));
566     }
567     sectx = calloc(nc + ni, sizeof(int *));
568     secty = calloc(nc + ni, sizeof(int *));
569     sectc = calloc(nc + ni, sizeof(int *));
570     isecs = calloc(nc + ni, sizeof(int));
571     weight = calloc(MAX(sc, is * 2), sizeof(int));
572     dsea = calloc(MAX(sc, is * 2), sizeof(int));
573     dmoun = calloc(MAX(sc, is * 2), sizeof(int));
574     for (i = 0; i < nc; ++i) {
575         sectx[i] = calloc(sc, sizeof(int));
576         secty[i] = calloc(sc, sizeof(int));
577         sectc[i] = calloc(sc, sizeof(int));
578     }
579     for (i = nc; i < nc + ni; ++i) {
580         sectx[i] = calloc(is * 2, sizeof(int));
581         secty[i] = calloc(is * 2, sizeof(int));
582         sectc[i] = calloc(is * 2, sizeof(int));
583     }
584
585 }
586
587 static void
588 init(void)
589 {
590     int i, j;
591
592     for (i = 0; i < WORLD_X; ++i) {
593         for (j = 0; j < WORLD_Y; ++j) {
594             own[i][j] = -1;
595         }
596     }
597     memset(adj_land, 0, WORLD_SZ() * sizeof(*adj_land));
598 }
599
600 /****************************************************************************
601   DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
602 ****************************************************************************/
603
604 /*
605  * How isolated is capital @j at @newx,@newy?
606  * Return the distance to the closest other capital.
607  */
608 static int
609 iso(int j, int newx, int newy)
610 {
611     int d = INT_MAX;
612     int i, md;
613
614     for (i = 0; i < nc; ++i) {
615         if (i == j)
616             continue;
617         md = mapdist(capx[i], capy[i], newx, newy);
618         if (md < d)
619             d = md;
620     }
621
622     return d;
623 }
624
625 /*
626  * Drift the capitals
627  * Return 1 for a stable drift, 0 for an unstable one.
628  */
629 static int
630 drift(void)
631 {
632     int turns, i;
633
634     for (i = 0; i < nc; i++) {
635         capy[i] = (2 * i) / WORLD_X;
636         capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
637         if (capy[i] >= WORLD_Y) {
638             fprintf(stderr,
639                     "%s: world not big enough for all the continents\n",
640                     program_name);
641             exit(1);
642         }
643     }
644
645     for (turns = 0; turns < DRIFT_MAX; ++turns) {
646         if (stable(turns))
647             return 1;
648         for (i = 0; i < nc; ++i)
649             fl_move(i);
650     }
651     return 0;
652 }
653
654 /*
655  * Has the drift stabilized?
656  * @turns is the number of turns so far.
657  */
658 static int
659 stable(int turns)
660 {
661     static int mc[STABLE_CYCLE];
662     int i, isod, d = 0, stab = 1;
663
664     if (!turns) {
665         for (i = 0; i < STABLE_CYCLE; i++)
666             mc[i] = i;
667     }
668
669     if (turns <= DRIFT_BEFORE_CHECK)
670         return 0;
671
672     for (i = 0; i < nc; ++i) {
673         isod = iso(i, capx[i], capy[i]);
674         if (isod > d)
675             d = isod;
676     }
677
678     for (i = 0; i < STABLE_CYCLE; ++i)
679         if (d != mc[i])
680             stab = 0;
681
682     mc[turns % STABLE_CYCLE] = d;
683     return stab;
684 }
685
686 /* This routine does the actual drifting
687 */
688
689 static void
690 fl_move(int j)
691 {
692     int dir, i, newx, newy;
693
694     dir = DIR_L + roll0(6);
695     for (i = 0; i < 6; i++) {
696         if (dir > DIR_LAST)
697             dir -= 6;
698         newx = new_x(capx[j] + diroff[dir][0]);
699         newy = new_y(capy[j] + diroff[dir][1]);
700         dir++;
701         if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
702             capx[j] = newx;
703             capy[j] = newy;
704             return;
705         }
706     }
707 }
708
709 /****************************************************************************
710   GROW THE CONTINENTS
711 ****************************************************************************/
712
713 /* Look for a coastal sector of continent c
714 */
715
716 static void
717 find_coast(int c)
718 {
719     int i, dir, nx, ny;
720
721     for (i = 0; i < isecs[c]; ++i) {
722         sectc[c][i] = 0;
723         for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
724             nx = new_x(sectx[c][i] + diroff[dir][0]);
725             ny = new_y(secty[c][i] + diroff[dir][1]);
726             if (own[nx][ny] == -1)
727                 sectc[c][i] = 1;
728         }
729     }
730 }
731
732 struct hexagon_iter {
733     int dir, i, n;
734 };
735
736 /*
737  * Start iterating around @x0,@y0 at distance @d.
738  * Set *x,*y to coordinates of the first sector.
739  */
740 static inline void
741 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
742               int *x, int *y)
743 {
744     *x = new_x(x0 - 2 * n);
745     *y = y0;
746     iter->dir = DIR_FIRST;
747     iter->i = 0;
748     iter->n = n;
749 }
750
751 /*
752  * Continue iteration started with hexagon_first().
753  * Set *x,*y to coordinates of the next sector.
754  * Return whether we're back at the first sector, i.e. iteration is
755  * complete.
756  */
757 static inline int
758 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
759 {
760     *x = new_x(*x + diroff[iter->dir][0]);
761     *y = new_y(*y + diroff[iter->dir][1]);
762     iter->i++;
763     if (iter->i == iter->n) {
764         iter->i = 0;
765         iter->dir++;
766     }
767     return iter->dir <= DIR_LAST;
768 }
769
770 /*
771  * Is @x,@y in no exclusive zone other than perhaps @c's?
772  */
773 static int
774 xzone_ok(int c, int x, int y)
775 {
776     int off = XYOFFSET(x, y);
777
778     return xzone[off] == c || xzone[off] == -1;
779 }
780
781 /*
782  * Add sectors within distance @dist of @x,@y to @c's exclusive zone.
783  */
784 static void
785 xzone_around_sector(int c, int x, int y, int dist)
786 {
787     int d, x1, y1, off;
788     struct hexagon_iter hexit;
789
790     assert(xzone_ok(c, x, y));
791
792     xzone[XYOFFSET(x, y)] = c;
793     for (d = 1; d <= dist; d++) {
794         hexagon_first(&hexit, x, y, d, &x1, &y1);
795         do {
796             off = XYOFFSET(x1, y1);
797             if (xzone[off] == -1)
798                 xzone[off] = c;
799             else if (xzone[off] != c)
800                 xzone[off] = -2;
801         } while (hexagon_next(&hexit, &x1, &y1));
802     }
803 }
804
805 /*
806  * Add sectors within distance @dist to island @c's exclusive zone.
807  */
808 static void
809 xzone_around_island(int c, int dist)
810 {
811     int i;
812
813     for (i = 0; i < isecs[c]; i++)
814         xzone_around_sector(c, sectx[c][i], secty[c][i], dist);
815 }
816
817 /*
818  * Initialize exclusive zones around @n islands.
819  */
820 static void
821 xzone_init(int n)
822 {
823     int i, c;
824
825     for (i = 0; i < WORLD_SZ(); i++)
826         xzone[i] = -1;
827
828     for (c = 0; c < n; c++)
829         xzone_around_island(c, id);
830 }
831
832 /*
833  * Initialize breadth-first search.
834  */
835 static void
836 bfs_init(void)
837 {
838     int i;
839
840     for (i = 0; i < WORLD_SZ(); i++) {
841         closest[i] = -1;
842         distance[i] = USHRT_MAX;
843     }
844
845     bfs_queue_head = bfs_queue_tail = 0;
846 }
847
848 /*
849  * Add sector @x,@y to the BFS queue.
850  * It's closest to @c, with distance @dist.
851  */
852 static void
853 bfs_enqueue(int c, int x, int y, int dist)
854 {
855     int off = XYOFFSET(x, y);
856
857     assert(dist < distance[off]);
858     closest[off] = c;
859     distance[off] = dist;
860     bfs_queue[bfs_queue_tail] = off;
861     bfs_queue_tail++;
862     if (bfs_queue_tail >= WORLD_SZ())
863         bfs_queue_tail = 0;
864     assert(bfs_queue_tail != bfs_queue_head);
865 }
866
867 /*
868  * Search breadth-first until the queue is empty.
869  */
870 static void
871 bfs_run_queue(void)
872 {
873     int off, dist, i, noff, nx, ny;
874     coord x, y;
875
876     while (bfs_queue_head != bfs_queue_tail) {
877         off = bfs_queue[bfs_queue_head];
878         bfs_queue_head++;
879         if (bfs_queue_head >= WORLD_SZ())
880             bfs_queue_head = 0;
881         dist = distance[off] + 1;
882         sctoff2xy(&x, &y, off);
883         for (i = DIR_FIRST; i <= DIR_LAST; i++) {
884             nx = new_x(x + diroff[i][0]);
885             ny = new_y(y + diroff[i][1]);
886             noff = XYOFFSET(nx, ny);
887             if (dist < distance[noff]) {
888                 bfs_enqueue(closest[off], nx, ny, dist);
889             } else if (distance[noff] == dist) {
890                 if (closest[off] != closest[noff])
891                     closest[noff] = (natid)-1;
892             } else
893                 assert(distance[noff] < dist);
894         }
895     }
896 }
897
898 /*
899  * Add island @c's coastal sectors to the BFS queue, with distance 0.
900  */
901 static void
902 bfs_enqueue_island(int c)
903 {
904     int i;
905
906     for (i = 0; i < isecs[c]; i++) {
907         if (sectc[c][i])
908             bfs_enqueue(c, sectx[c][i], secty[c][i], 0);
909     }
910 }
911
912 /*
913  * Enqueue spheres of influence borders for breadth-first search.
914  */
915 static void
916 bfs_enqueue_border(void)
917 {
918     int x, y, off, dir, nx, ny, noff;
919
920     for (y = 0; y < WORLD_Y; y++) {
921         for (x = y % 2; x < WORLD_X; x += 2) {
922             off = XYOFFSET(x, y);
923             if (distance[off] <= id + 1)
924                 continue;
925             if (closest[off] == (natid)-1)
926                 continue;
927             for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
928                 nx = new_x(x + diroff[dir][0]);
929                 ny = new_y(y + diroff[dir][1]);
930                 noff = XYOFFSET(nx, ny);
931                 if (closest[noff] != closest[off]) {
932                     bfs_enqueue(closest[off], x, y, id + 1);
933                     break;
934                 }
935             }
936         }
937     }
938 }
939
940 /*
941  * Compute spheres of influence
942  * A continent's sphere of influence is the set of sectors closer to
943  * it than to any other continent.
944  * Set closest[XYOFFSET(x, y)] to the closest continent's number,
945  * -1 if no single continent is closest.
946  * Set distance[XYOFFSET(x, y)] to the minimum of the distance to the
947  * closest coastal land sector and the distance to just outside the
948  * sphere of influence plus @id.  For sea sectors within a continent's
949  * sphere of influence, distance[off] - id is the distance to the
950  * border of the area where additional islands can be placed.
951  */
952 static void
953 init_spheres_of_influence(void)
954 {
955     int c;
956
957     bfs_init();
958     for (c = 0; c < nc; c++)
959         bfs_enqueue_island(c);
960     bfs_run_queue();
961     bfs_enqueue_border();
962     bfs_run_queue();
963 }
964
965 /*
966  * Is @x,@y in the same sphere of influence as island @c?
967  * Always true when @c is a continent.
968  */
969 static int
970 is_in_sphere(int c, int x, int y)
971 {
972     return c < nc || closest[XYOFFSET(x, y)] == c % nc;
973 }
974
975 /*
976  * Can island @c grow at @x,@y?
977  */
978 static int
979 can_grow_at(int c, int x, int y)
980 {
981     return own[x][y] == -1 && xzone_ok(c, x, y) && is_in_sphere(c, x, y);
982 }
983
984 static void
985 adj_land_update(int x, int y)
986 {
987     int is_land = own[x][y] != -1;
988     int dir, nx, ny, noff;
989
990     for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
991         nx = new_x(x + diroff[dir][0]);
992         ny = new_y(y + diroff[dir][1]);
993         noff = XYOFFSET(nx, ny);
994         if (is_land)
995             adj_land[noff] |= 1u << DIR_BACK(dir);
996         else
997             adj_land[noff] &= ~(1u << DIR_BACK(dir));
998     }
999 }
1000
1001 static void
1002 add_sector(int c, int x, int y)
1003 {
1004     assert(own[x][y] == -1);
1005     xzone_around_sector(c, x, y, c < nc ? di : DISTINCT_ISLANDS ? id : 0);
1006     sectx[c][isecs[c]] = x;
1007     secty[c][isecs[c]] = y;
1008     isecs[c]++;
1009     own[x][y] = c;
1010     adj_land_update(x, y);
1011 }
1012
1013 static int grow_weight(int c, int x, int y, int spike)
1014 {
1015     int n, b;
1016
1017     /*
1018      * #Land neighbors is #bits set in adj_land[].
1019      * Count them Brian Kernighan's way.
1020      */
1021     n = 0;
1022     for (b = adj_land[XYOFFSET(x, y)]; b; b &= b - 1)
1023         n++;
1024     assert(n > 0 && n < 7);
1025
1026     if (spike)
1027         return (6 - n) * (6 - n);
1028
1029     return n * n * n;
1030 }
1031
1032 static int
1033 grow_one_sector(int c)
1034 {
1035     int spike = roll0(100) < sp;
1036     int wsum, newx, newy, i, x, y, off, dir, nx, ny, noff, w;
1037
1038     assert(cur_seen < UINT_MAX);
1039     cur_seen++;
1040     wsum = 0;
1041     newx = newy = -1;
1042
1043     for (i = 0; i < isecs[c]; i++) {
1044         x = sectx[c][i];
1045         y = secty[c][i];
1046         off = XYOFFSET(x, y);
1047
1048         for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
1049             if (adj_land[off] & (1u << dir))
1050                 continue;
1051             nx = new_x(x + diroff[dir][0]);
1052             ny = new_y(y + diroff[dir][1]);
1053             noff = XYOFFSET(nx, ny);
1054             if (seen[noff] == cur_seen)
1055                 continue;
1056             assert(seen[noff] < cur_seen);
1057             seen[noff] = cur_seen;
1058             if (!can_grow_at(c, nx, ny))
1059                 continue;
1060             w = grow_weight(c, nx, ny, spike);
1061             assert(wsum < INT_MAX - w);
1062             wsum += w;
1063             if (roll0(wsum) < w) {
1064                 newx = nx;
1065                 newy = ny;
1066             }
1067         }
1068     }
1069
1070     if (!wsum)
1071         return 0;
1072
1073     add_sector(c, newx, newy);
1074     return 1;
1075 }
1076
1077 /*
1078  * Grow the continents.
1079  * Return 1 on success, 0 on error.
1080  */
1081 static int
1082 grow_continents(void)
1083 {
1084     int done = 1;
1085     int c, secs;
1086
1087     xzone_init(0);
1088
1089     for (c = 0; c < nc; ++c) {
1090         isecs[c] = 0;
1091         if (!can_grow_at(c, capx[c], capy[c])
1092             || !can_grow_at(c, new_x(capx[c] + 2), capy[c])) {
1093             done = 0;
1094             continue;
1095         }
1096         add_sector(c, capx[c], capy[c]);
1097         add_sector(c, new_x(capx[c] + 2), capy[c]);
1098     }
1099
1100     if (!done) {
1101         qprint("No room for continents\n");
1102         return 0;
1103     }
1104
1105     for (secs = 2; secs < sc && done; secs++) {
1106         for (c = 0; c < nc; ++c) {
1107             if (!grow_one_sector(c))
1108                 done = 0;
1109         }
1110     }
1111
1112     for (c = 0; c < nc; ++c)
1113         find_coast(c);
1114
1115     if (!done)
1116         qprint("Only managed to grow %d out of %d sectors.\n",
1117                secs - 1, sc);
1118     return done;
1119 }
1120
1121 /****************************************************************************
1122   GROW THE ISLANDS
1123 ****************************************************************************/
1124
1125 /*
1126  * Place additional island @c's first sector.
1127  * Return 1 on success, 0 on error.
1128  */
1129 static int
1130 place_island(int c, int isiz)
1131 {
1132     int n, x, y, d, w, newx, newy;
1133
1134     n = 0;
1135
1136     for (y = 0; y < WORLD_Y; y++) {
1137         for (x = y % 2; x < WORLD_X; x += 2) {
1138             if (can_grow_at(c, x, y)) {
1139                 d = distance[XYOFFSET(x, y)];
1140                 assert(d > id);
1141                 w = (d - id) * (d - id);
1142                 n += MIN(w, (isiz + 2) / 3);
1143                 if (roll0(n) < w) {
1144                     newx = x;
1145                     newy = y;
1146                 }
1147             }
1148         }
1149     }
1150
1151     if (n)
1152         add_sector(c, newx, newy);
1153     return n;
1154 }
1155
1156 static int
1157 int_cmp(const void *a, const void *b)
1158 {
1159     return *(int *)b - *(int *)a;
1160 }
1161
1162 static int *
1163 size_islands(void)
1164 {
1165     int n = ni / nc;
1166     int *isiz = malloc(n * sizeof(*isiz));
1167     int r0, r1, i;
1168
1169     isiz[0] = n * is;
1170     r1 = roll0(is);
1171     for (i = 1; i < n; i++) {
1172         r0 = r1;
1173         r1 = roll0(is);
1174         isiz[i] = is + r1 - r0;
1175         isiz[0] -= isiz[i];
1176     }
1177
1178     qsort(isiz, n, sizeof(*isiz), int_cmp);
1179     return isiz;
1180 }
1181
1182 /*
1183  * Grow the additional islands.
1184  * Return 1 on success, 0 on error.
1185  */
1186 static int
1187 grow_islands(void)
1188 {
1189     int *island_size = size_islands();
1190     int xzone_valid = 0;
1191     int carry = 0;
1192     int i, j, c, done, secs, isiz, x, y;
1193
1194     init_spheres_of_influence();
1195
1196     for (i = 0; i < ni / nc; i++) {
1197         c = nc + i * nc;
1198
1199         if (!xzone_valid)
1200             xzone_init(c);
1201
1202         carry += island_size[i];
1203         isiz = MIN(2 * is, carry);
1204
1205         for (j = 0; j < nc; j++) {
1206             isecs[c + j] = 0;
1207             if (!place_island(c + j, isiz)) {
1208                 qprint("\nNo room for island #%d\n", c - nc + j + 1);
1209                 free(island_size);
1210                 return 0;
1211             }
1212         }
1213
1214         done = 1;
1215         for (secs = 1; secs < isiz && done; secs++) {
1216             for (j = 0; j < nc; j++) {
1217                 if (!grow_one_sector(c + j))
1218                     done = 0;
1219             }
1220         }
1221
1222         if (!done) {
1223             secs--;
1224             for (j = 0; j < nc; j++) {
1225                 if (isecs[c + j] != secs) {
1226                     isecs[c + j]--;
1227                     assert(isecs[c + j] == secs);
1228                     x = sectx[c + j][secs];
1229                     y = secty[c + j][secs];
1230                     own[x][y] = -1;
1231                     adj_land_update(x, y);
1232                 }
1233             }
1234             xzone_valid = 0;
1235         }
1236
1237         for (j = 0; j < nc; j++)
1238             qprint(" %d(%d)", c - nc + j + 1, isecs[c + j]);
1239
1240         carry -= secs;
1241     }
1242
1243     free(island_size);
1244     qprint("\n");
1245
1246     if (carry)
1247         qprint("Only managed to grow %d out of %d island sectors.\n",
1248                is * ni - carry * nc, is * ni);
1249
1250     for (c = nc; c < nc + ni; c++)
1251         find_coast(c);
1252
1253     return 1;
1254 }
1255
1256 /****************************************************************************
1257   CREATE ELEVATIONS
1258 ****************************************************************************/
1259 static void
1260 create_elevations(void)
1261 {
1262     int i, j;
1263
1264     for (i = 0; i < WORLD_X; i++) {
1265         for (j = 0; j < WORLD_Y; j++)
1266             elev[i][j] = -INFINITE_ELEVATION;
1267     }
1268     elevate_land();
1269     elevate_sea();
1270 }
1271
1272 /* Generic function for finding the distance to the closest sea, land, or
1273    mountain
1274 */
1275 static int
1276 distance_to_what(int x, int y, int flag)
1277 {
1278     int d, px, py;
1279     struct hexagon_iter hexit;
1280
1281     for (d = 1; d < 5; ++d) {
1282         hexagon_first(&hexit, x, y, d, &px, &py);
1283         do {
1284             switch (flag) {
1285             case 0:             /* distance to sea */
1286                 if (own[px][py] == -1)
1287                     return d;
1288                 break;
1289             case 1:             /* distance to land */
1290                 if (own[px][py] != -1)
1291                     return d;
1292                 break;
1293             case 2:             /* distance to mountain */
1294                 if (elev[px][py] == INFINITE_ELEVATION)
1295                     return d;
1296                 break;
1297             }
1298         } while (hexagon_next(&hexit, &px, &py));
1299     }
1300     return d;
1301 }
1302
1303 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1304 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1305
1306 /* Decide where the mountains go
1307 */
1308 static void
1309 elevate_land(void)
1310 {
1311     int i, mountain_search, k, c, total, ns, nm, r, x, y;
1312     int highest, where, h, newk, dk;
1313
1314     for (c = 0; c < nc + ni; ++c) {
1315         total = 0;
1316         ns = isecs[c];
1317         nm = (pm * ns) / 100;
1318
1319 /* Place the mountains */
1320
1321         for (i = 0; i < ns; ++i) {
1322             dsea[i] = distance_to_sea();
1323             weight[i] = (total += (dsea[i] * dsea[i]));
1324         }
1325
1326         for (k = nm, mountain_search = 0;
1327              k && mountain_search < MOUNTAIN_SEARCH_MAX;
1328              ++mountain_search) {
1329             r = roll0(total);
1330             for (i = 0; i < ns; ++i) {
1331                 x = sectx[c][i];
1332                 y = secty[c][i];
1333                 if (r < weight[i] && elev[x][y] == -INFINITE_ELEVATION &&
1334                     (c >= nc ||
1335                      ((!(capx[c] == sectx[c][i] &&
1336                          capy[c] == secty[c][i])) &&
1337                       (!(new_x(capx[c] + 2) == sectx[c][i] &&
1338                          capy[c] == secty[c][i]))))) {
1339                     elev[x][y] = INFINITE_ELEVATION;
1340                     break;
1341                 }
1342             }
1343             --k;
1344         }
1345
1346 /* Elevate land that is not mountain and not capital */
1347
1348         for (i = 0; i < ns; ++i)
1349             dmoun[i] = distance_to_mountain();
1350         dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1351           (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1352           100 * INFINITE_ELEVATION;
1353         for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1354             highest = 0;
1355             where = -1;
1356             for (i = 0; i < ns; ++i) {
1357                 x = sectx[c][i];
1358                 y = secty[c][i];
1359                 if (elev[x][y] == -INFINITE_ELEVATION &&
1360                     (c >= nc || ((!(capx[c] == sectx[c][i] &&
1361                                     capy[c] == secty[c][i])) &&
1362                                  (!(new_x(capx[c] + 2) == sectx[c][i] &&
1363                                     capy[c] == secty[c][i]))))) {
1364                     h = 3 * (5 - dmoun[i]) + dsea[i];
1365                     assert(h > 0);
1366                     if (h > highest) {
1367                         highest = h;
1368                         where = i;
1369                     }
1370                 }
1371             }
1372             if (where == -1)
1373                 break;
1374             newk = k / 100;
1375             if (newk >= HILLMIN && newk < PLATMIN)
1376                 newk = PLATMIN;
1377             if (newk < LANDMIN)
1378                 newk = LANDMIN;
1379             elev[sectx[c][where]][secty[c][where]] = newk;
1380         }
1381
1382 /* Elevate the mountains and capitals */
1383
1384         for (i = 0; i < ns; ++i) {
1385             x = sectx[c][i];
1386             y = secty[c][i];
1387             if (elev[x][y] == INFINITE_ELEVATION) {
1388                 if (dsea[i] == 1)
1389                     elev[x][y] = HILLMIN + roll0(PLATMIN - HILLMIN);
1390                 else
1391                     elev[x][y] = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1392                       roll0((256 - HIGHMIN) / 2);
1393             } else if (c < nc &&
1394                        (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1395                         ((new_x(capx[c] + 2) == sectx[c][i] &&
1396                           capy[c] == secty[c][i]))))
1397                 elev[x][y] = PLATMIN;
1398         }
1399     }
1400 }
1401
1402 #define distance_to_land() distance_to_what(x, y, 1)
1403
1404 static void
1405 elevate_sea(void)
1406 {
1407     int x, y;
1408
1409     for (y = 0; y < WORLD_Y; ++y) {
1410         for (x = y % 2; x < WORLD_X; x += 2) {
1411             if (elev[x][y] == -INFINITE_ELEVATION)
1412                 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1413         }
1414     }
1415 }
1416
1417 static int
1418 elev_to_sct_type(int elevation)
1419 {
1420     if (elevation < LANDMIN)
1421         return SCT_WATER;
1422     if (elevation < HILLMIN)
1423         return SCT_RURAL;
1424     if (elevation < PLATMIN)
1425         return SCT_MOUNT;
1426     if (elevation < HIGHMIN)
1427         return SCT_RURAL;
1428     return SCT_MOUNT;
1429 }
1430
1431 /****************************************************************************
1432   ADD THE RESOURCES
1433 ****************************************************************************/
1434
1435 static int
1436 set_fert(int e)
1437 {
1438     int fert = 0;
1439     if (e < LANDMIN)
1440         fert = LANDMIN - e + 40;
1441     else if (e < FERT_MAX)
1442         fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1443     if (fert > 100)
1444         fert = 100;
1445     return fert;
1446 }
1447
1448 static int
1449 set_oil(int e)
1450 {
1451     int oil = 0;
1452     if (e < LANDMIN)
1453         oil = (LANDMIN - e) * 2 + roll0(2);
1454     else if (e <= OIL_MAX)
1455         oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1456     if (oil > 100)
1457         oil = 100;
1458     return oil;
1459 }
1460
1461 static int
1462 set_iron(int e)
1463 {
1464     int iron = 0;
1465     if (e >= IRON_MIN && e < HIGHMIN)
1466         iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1467     if (iron > 100)
1468         iron = 100;
1469     return iron;
1470 }
1471
1472 static int
1473 set_gold(int e)
1474 {
1475     int gold = 0;
1476     if (e >= GOLD_MIN) {
1477         if (e < HIGHMIN)
1478             gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1479         else
1480             gold = 100 - 20 * HIGHMIN / e;
1481     }
1482     if (gold > 100)
1483         gold = 100;
1484     return gold;
1485 }
1486
1487 static int
1488 set_uran(int e)
1489 {
1490     int uran = 0;
1491     if (e >= URAN_MIN && e < HIGHMIN)
1492         uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1493     if (uran > 100)
1494         uran = 100;
1495     return uran;
1496 }
1497
1498 static void
1499 add_resources(struct sctstr *sct)
1500 {
1501     sct->sct_fertil = set_fert(sct->sct_elev);
1502     sct->sct_oil = set_oil(sct->sct_elev);
1503     sct->sct_min = set_iron(sct->sct_elev);
1504     sct->sct_gmin = set_gold(sct->sct_elev);
1505     sct->sct_uran = set_uran(sct->sct_elev);
1506 }
1507
1508 /****************************************************************************
1509   DESIGNATE THE SECTORS
1510 ****************************************************************************/
1511
1512 static void
1513 write_sects(void)
1514 {
1515     struct sctstr *sct;
1516     int x, y;
1517
1518     for (y = 0; y < WORLD_Y; y++) {
1519         for (x = y % 2; x < WORLD_X; x += 2) {
1520             sct = getsectp(x, y);
1521             sct->sct_elev = elev[x][y];
1522             sct->sct_type = elev_to_sct_type(elev[x][y]);
1523             sct->sct_newtype = sct->sct_type;
1524             sct->sct_dterr = own[sct->sct_x][y] + 1;
1525             add_resources(sct);
1526         }
1527     }
1528     set_coastal_flags();
1529 }
1530
1531 /****************************************************************************
1532   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1533 ****************************************************************************/
1534 static void
1535 output(void)
1536 {
1537     int sx, sy, x, y, c, type;
1538
1539     if (quiet == 0) {
1540         for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1541             y = YNORM(sy);
1542             puts("");
1543             if (y % 2)
1544                 printf(" ");
1545             for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1546                 x = XNORM(sx);
1547                 c = own[x][y];
1548                 type = elev_to_sct_type(elev[x][y]);
1549                 if (type == SCT_WATER)
1550                     printf(". ");
1551                 else if (type == SCT_MOUNT)
1552                     printf("^ ");
1553                 else if (c >= nc)
1554                     printf("%% ");
1555                 else {
1556                     assert(0 <= c && c < nc);
1557                     if ((x == capx[c] || x == new_x(capx[c] + 2))
1558                         && y == capy[c])
1559                         printf("%c ", numletter[c % 62]);
1560                     else
1561                         printf("# ");
1562                 }
1563             }
1564         }
1565     }
1566 }
1567
1568 /*
1569  * Print a map to help visualize own[][].
1570  * This is for debugging.
1571  */
1572 void
1573 print_own_map(void)
1574 {
1575     int sx, sy, x, y;
1576
1577     for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1578         y = YNORM(sy);
1579         printf("%4d ", sy);
1580         for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1581             x = XNORM(sx);
1582             if ((x + y) & 1)
1583                 putchar(' ');
1584             else if (own[x][y] == -1)
1585                 putchar('.');
1586             else
1587                 putchar(numletter[own[x][y] % 62]);
1588         }
1589         putchar('\n');
1590     }
1591 }
1592
1593 /*
1594  * Print a map to help visualize elev[][].
1595  * This is for debugging.  It expects the terminal to understand
1596  * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1597  */
1598 void
1599 print_elev_map(void)
1600 {
1601     int sx, sy, x, y, sat;
1602
1603     for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1604         y = YNORM(sy);
1605         printf("%4d ", sy);
1606         for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1607             x = XNORM(sx);
1608             if ((x + y) & 1)
1609                 putchar(' ');
1610             else if (!elev[x][y])
1611                 putchar(' ');
1612             else if (elev[x][y] < 0) {
1613                 sat = 256 + elev[x][y] * 2;
1614                 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1615             } else if (elev[x][y] < HIGHMIN / 2) {
1616                 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1617                 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1618             } else if (elev[x][y] < HIGHMIN) {
1619                 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1620                 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1621             } else {
1622                 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1623                 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1624             }
1625         }
1626         putchar('\n');
1627     }
1628 }
1629
1630 /*
1631  * Print a map to help visualize xzone[].
1632  * This is for debugging.
1633  */
1634 void
1635 print_xzone_map(void)
1636 {
1637     int sx, sy, x, y, off;
1638
1639     for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1640         y = YNORM(sy);
1641         printf("%4d ", sy);
1642         for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1643             x = XNORM(sx);
1644             off = XYOFFSET(x, y);
1645             if ((x + y) & 1)
1646                 putchar(' ');
1647             else if (own[x][y] >= 0)
1648                 putchar('-');
1649             else if (xzone[off] >= 0)
1650                 putchar(numletter[xzone[off] % 62]);
1651             else {
1652                 assert(own[x][y] == -1);
1653                 putchar(xzone[off] == -1 ? '.' : '!');
1654             }
1655         }
1656         putchar('\n');
1657     }
1658 }
1659
1660 /*
1661  * Print a map to help visualize closest[].
1662  * This is for debugging.
1663  */
1664 void
1665 print_closest_map(void)
1666 {
1667     int sx, sy, x, y, off;
1668
1669     for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1670         y = YNORM(sy);
1671         printf("%4d ", sy);
1672         for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1673             x = XNORM(sx);
1674             off = XYOFFSET(x, y);
1675             if ((x + y) & 1)
1676                 putchar(' ');
1677             else if (closest[off] == (natid)-1)
1678                 putchar('.');
1679             else if (!distance[off]) {
1680                 assert(closest[off] == own[x][y]);
1681                 putchar('-');
1682             } else {
1683                 putchar(numletter[closest[off] % 62]);
1684             }
1685         }
1686         printf("\n");
1687     }
1688 }
1689
1690 void
1691 print_distance_map(void)
1692 {
1693     int sx, sy, x, y, off;
1694
1695     for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1696         y = YNORM(sy);
1697         printf("%4d ", sy);
1698         for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1699             x = XNORM(sx);
1700             off = XYOFFSET(x, y);
1701             if ((x + y) & 1)
1702                 putchar(' ');
1703             else if (closest[off] == (natid)-1)
1704                 putchar('.');
1705             else if (!distance[off]) {
1706                 assert(closest[off] == own[x][y]);
1707                 putchar('-');
1708             } else {
1709                 putchar(numletter[distance[off] % 62]);
1710             }
1711         }
1712         printf("\n");
1713     }
1714 }
1715
1716
1717 /***************************************************************************
1718   WRITE A SCRIPT FOR PLACING CAPITALS
1719 ****************************************************************************/
1720 static int
1721 write_newcap_script(void)
1722 {
1723     int c;
1724     FILE *script = fopen(outfile, "w");
1725
1726     if (!script) {
1727         fprintf(stderr, "%s: unable to write to %s (%s)\n",
1728                 program_name, outfile, strerror(errno));
1729         return 0;
1730     }
1731
1732     for (c = 0; c < nc; ++c) {
1733         fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1734         fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1735     }
1736     fprintf(script, "add %d visitor visitor v\n", c + 1);
1737     fclose(script);
1738     return 1;
1739 }
1740
1741 static void
1742 qprint(const char *const fmt, ...)
1743 {
1744     va_list ap;
1745
1746     if (!quiet) {
1747         va_start(ap, fmt);
1748         vfprintf(stdout, fmt, ap);
1749         va_end(ap);
1750     }
1751 }
1752
1753 static void
1754 set_coastal_flags(void)
1755 {
1756     int i, j;
1757     struct sctstr *sp;
1758
1759     for (i = 0; i < nc + ni; ++i) {
1760         for (j = 0; j < isecs[i]; j++) {
1761             sp = getsectp(sectx[i][j], secty[i][j]);
1762             sp->sct_coastal = sectc[i][j];
1763         }
1764     }
1765 }