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