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