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