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
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.
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.
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/>.
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.
27 * fairland.c: Create a nice, new world
29 * Known contributors to this file:
32 * Markus Armbruster, 2004-2020
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.
44 * 2. Grow start islands ("continents")
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
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.
60 * If growing fails due to lack of room, start over. If it fails too
61 * many times, give up and terminate unsuccessfully.
63 * 3. Place and grow additional islands
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.
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.
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.
81 * If placement fails due to lack of room, start over, just like for
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.
89 * 4. Compute elevation
91 * Elevate islands one after the other.
93 * First, place the specified number of mountains randomly.
94 * Probability increases with distance to sea.
96 * Last, elevate mountains and the capitals. Pick coastal mountain
97 * elevation randomly from an interval of medium elevations reserved
98 * for them. Pick non-coastal mountain elevation randomly from an
99 * interval of high elevation reserved for them. Set capital
100 * elevation to a fixed, medium value.
102 * In between, elevate the remaining land one by one, working from
103 * mountains towards the sea, and from the elevation just below the
104 * non-coastal mountains' interval linearly down to 1, avoiding the
105 * coastal mountains' interval.
107 * This gives islands of the same size the same set of elevations,
108 * except for mountains.
110 * Elevate sea: pick a random depth from an interval that deepens with
111 * the distance to land.
115 * Sector resources are simple functions of elevation. You can alter
116 * macros OIL_MAX, IRON_MIN, GOLD_MIN, FERT_MAX, and URAN_MIN to
131 #include "prototypes.h"
136 /* The following five numbers refer to elevation under which (in the case of
137 fertility or oil) or over which (in the case of iron, gold, and uranium)
138 sectors with that elevation will contain that resource. Elevation ranges
141 /* raise FERT_MAX for more fertility */
144 /* raise OIL_MAX for more oil */
147 /* lower IRON_MIN for more iron */
150 /* lower GOLD_MIN for more gold */
153 /* lower URAN_MIN for more uranium */
156 /* do not change these 4 defines */
157 #define LANDMIN 1 /* plate altitude for normal land */
158 #define HILLMIN 34 /* plate altitude for hills */
159 #define PLATMIN 36 /* plate altitude for plateau */
160 #define HIGHMIN 98 /* plate altitude for mountains */
162 static void qprint(const char * const fmt, ...)
163 ATTRIBUTE((format (printf, 1, 2)));
166 * Program arguments and options
168 static char *program_name;
169 static int nc, sc; /* number and size of continents */
170 static int ni, is; /* number and size of islands */
171 #define DEFAULT_SPIKE 10
172 static int sp = DEFAULT_SPIKE; /* spike percentage */
173 #define DEFAULT_MOUNTAIN 0
174 static int pm = DEFAULT_MOUNTAIN; /* mountain percentage */
175 #define DEFAULT_CONTDIST 2
176 static int di = DEFAULT_CONTDIST; /* min. distance between continents */
177 #define DEFAULT_ISLDIST 1
178 static int id = DEFAULT_ISLDIST; /* ... continents and islands */
179 /* don't let the islands crash into each other.
180 1 = don't merge, 0 = merge. */
181 static int DISTINCT_ISLANDS = 1;
183 #define DEFAULT_OUTFILE_NAME "newcap_script"
184 static const char *outfile = DEFAULT_OUTFILE_NAME;
186 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
187 #define INFINITE_ELEVATION 999
189 /* these defines prevent infinite loops:
191 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
192 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
193 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
198 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
199 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
203 * isecs[i] is the size of the i-th island.
207 static int *capx, *capy; /* location of the nc capitals */
209 static int **own; /* owner of the sector. -1 means water */
212 * Adjacent land sectors
213 * adj_land[XYOFFSET(x, y)] bit d is set exactly when the sector next
214 * to x, y in direction d is land.
216 static unsigned char *adj_land;
220 * Each island is surrounded by an exclusive zone where only it may
221 * grow. The width of the zone depends on minimum distances.
222 * While growing continents, it is @di sectors wide.
223 * While growing additional islands, it is @id sectors wide.
224 * DISTINCT_ISLANDS nullifies the exclusive zone then.
225 * xzone[XYOFFSET(x, y)] is -1 when the sector is in no exclusive
226 * zone, a (non-negative) island number when it is in that island's
227 * exclusive zone and no other, and -2 when it is in multiple
233 * Set of sectors seen already
234 * Increment @cur_seen to empty the set of sectors seen, set
235 * seen[XYOFFSET(x, y)] to @cur_seen to add x,y to the set.
237 static unsigned *seen;
238 static unsigned cur_seen;
241 * Closest continent and "distance"
242 * closest[XYOFFSET(x, y)] is the closest continent's number.
243 * distance[] is complicated; see init_spheres_of_influence() and
244 * init_distance_to_coast().
246 static natid *closest;
247 static unsigned short *distance;
250 * Queue for breadth-first search
252 static int *bfs_queue;
253 static int bfs_queue_head, bfs_queue_tail;
255 static int **elev; /* elevation of the sectors */
256 static int **sectx, **secty; /* the sectors for each continent */
257 static int **sectc; /* which sectors are on the coast? */
258 static int *weight; /* used for placing mountains */
259 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
261 #define NUMTRIES 10 /* keep trying to grow this many times */
263 static const char *numletter =
264 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
266 static void help(char *);
267 static void usage(void);
268 static void parse_args(int argc, char *argv[]);
269 static void allocate_memory(void);
270 static void init(void);
271 static int drift(void);
272 static int grow_continents(void);
273 static void create_elevations(void);
274 static void write_sects(void);
275 static void output(void);
276 static int write_newcap_script(void);
277 static int stable(int);
278 static void elevate_land(void);
279 static void elevate_sea(void);
280 static void set_coastal_flags(void);
282 static void print_vars(void);
283 static void fl_move(int);
284 static int grow_islands(void);
286 /* Debugging aids: */
287 void print_own_map(void);
288 void print_xzone_map(void);
289 void print_closest_map(void);
290 void print_distance_map(void);
291 void print_elev_map(void);
293 /****************************************************************************
295 ****************************************************************************/
298 main(int argc, char *argv[])
301 char *config_file = NULL;
303 unsigned rnd_seed = 0;
306 program_name = argv[0];
308 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
311 config_file = optarg;
314 DISTINCT_ISLANDS = 0;
320 rnd_seed = strtoul(optarg, NULL, 10);
330 printf("%s\n\n%s", version, legal);
339 rnd_seed = pick_seed();
342 if (emp_config(config_file) < 0)
346 parse_args(argc - optind, argv + optind);
351 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
352 qprint("seed is %u\n", rnd_seed);
357 qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
358 qprint("placing capitals...\n");
360 qprint("unstable drift\n");
361 qprint("growing continents...\n");
362 done = grow_continents();
365 qprint("growing islands:");
366 done = grow_islands();
367 } while (!done && ++try < NUMTRIES);
369 fprintf(stderr, "%s: world not large enough for this much land\n",
373 qprint("elevating land...\n");
376 qprint("writing to sectors file...\n");
377 if (!write_newcap_script())
379 if (chdir(gamedir)) {
380 fprintf(stderr, "%s: can't chdir to %s (%s)\n",
381 program_name, gamedir, strerror(errno));
384 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
387 if (!ef_close(EF_SECTOR))
391 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
401 puts("Creating a planet with:\n");
402 printf("%d continents\n", nc);
403 printf("continent size: %d\n", sc);
404 printf("number of islands: %d\n", ni);
405 printf("average size of islands: %d\n", is);
406 printf("spike: %d%%\n", sp);
407 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
408 pm, (pm * sc) / 100);
409 printf("minimum distance between continents: %d\n", di);
410 printf("minimum distance from islands to continents: %d\n", id);
411 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
415 help(char *complaint)
418 fprintf(stderr, "%s: %s\n", program_name, complaint);
419 fprintf(stderr, "Try -h for help.\n");
425 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
426 " -e CONFIG-FILE configuration file\n"
428 " -i islands may merge\n"
430 " -R SEED seed for random number generator\n"
431 " -s SCRIPT name of script to create (default %s)\n"
432 " -h display this help and exit\n"
433 " -v display version information and exit\n"
434 " NC number of continents\n"
435 " SC continent size\n"
436 " NI number of islands (default NC)\n"
437 " IS average island size (default SC/2)\n"
438 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
439 " PM percentage of land that is mountain (default %d)\n"
440 " DI minimum distance between continents (default %d)\n"
441 " ID minimum distance from islands to continents (default %d)\n",
442 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
443 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
447 parse_args(int argc, char *argv[])
449 int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
452 help("missing arguments");
456 help("too many arguments");
461 fprintf(stderr, "%s: number of continents must be > 0\n",
468 fprintf(stderr, "%s: size of continents must be > 1\n",
479 fprintf(stderr, "%s: number of islands must be >= 0\n",
484 fprintf(stderr, "%s: number of islands must be a multiple of"
485 " the number of continents\n",
493 fprintf(stderr, "%s: size of islands must be > 0\n",
500 if (sp < 0 || sp > 100) {
502 "%s: spike percentage must be between 0 and 100\n",
509 if (pm < 0 || pm > 100) {
511 "%s: mountain percentage must be between 0 and 100\n",
519 fprintf(stderr, "%s: distance between continents must be >= 0\n",
524 fprintf(stderr, "%s: distance between continents too large\n",
533 "%s: distance from islands to continents must be >= 0\n",
539 "%s: distance from islands to continents too large\n",
545 /****************************************************************************
546 VARIABLE INITIALIZATION
547 ****************************************************************************/
550 allocate_memory(void)
554 capx = calloc(nc, sizeof(int));
555 capy = calloc(nc, sizeof(int));
556 own = calloc(WORLD_X, sizeof(int *));
557 adj_land = malloc(WORLD_SZ() * sizeof(*adj_land));
558 xzone = malloc(WORLD_SZ() * sizeof(*xzone));
559 seen = calloc(WORLD_SZ(), sizeof(*seen));
560 closest = malloc(WORLD_SZ() * sizeof(*closest));
561 distance = malloc(WORLD_SZ() * sizeof(*distance));
562 bfs_queue = malloc(WORLD_SZ() * sizeof(*bfs_queue));
563 elev = calloc(WORLD_X, sizeof(int *));
564 for (i = 0; i < WORLD_X; ++i) {
565 own[i] = calloc(WORLD_Y, sizeof(int));
566 elev[i] = calloc(WORLD_Y, sizeof(int));
568 sectx = calloc(nc + ni, sizeof(int *));
569 secty = calloc(nc + ni, sizeof(int *));
570 sectc = calloc(nc + ni, sizeof(int *));
571 isecs = calloc(nc + ni, sizeof(int));
572 weight = calloc(MAX(sc, is * 2), sizeof(int));
573 dsea = calloc(MAX(sc, is * 2), sizeof(int));
574 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
575 for (i = 0; i < nc; ++i) {
576 sectx[i] = calloc(sc, sizeof(int));
577 secty[i] = calloc(sc, sizeof(int));
578 sectc[i] = calloc(sc, sizeof(int));
580 for (i = nc; i < nc + ni; ++i) {
581 sectx[i] = calloc(is * 2, sizeof(int));
582 secty[i] = calloc(is * 2, sizeof(int));
583 sectc[i] = calloc(is * 2, sizeof(int));
593 for (i = 0; i < WORLD_X; ++i) {
594 for (j = 0; j < WORLD_Y; ++j) {
598 memset(adj_land, 0, WORLD_SZ() * sizeof(*adj_land));
601 /****************************************************************************
602 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
603 ****************************************************************************/
606 * How isolated is capital @j at @newx,@newy?
607 * Return the distance to the closest other capital.
610 iso(int j, int newx, int newy)
615 for (i = 0; i < nc; ++i) {
618 md = mapdist(capx[i], capy[i], newx, newy);
628 * Return 1 for a stable drift, 0 for an unstable one.
635 for (i = 0; i < nc; i++) {
636 capy[i] = (2 * i) / WORLD_X;
637 capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
638 if (capy[i] >= WORLD_Y) {
640 "%s: world not big enough for all the continents\n",
646 for (turns = 0; turns < DRIFT_MAX; ++turns) {
649 for (i = 0; i < nc; ++i)
656 * Has the drift stabilized?
657 * @turns is the number of turns so far.
662 static int mc[STABLE_CYCLE];
663 int i, isod, d = 0, stab = 1;
666 for (i = 0; i < STABLE_CYCLE; i++)
670 if (turns <= DRIFT_BEFORE_CHECK)
673 for (i = 0; i < nc; ++i) {
674 isod = iso(i, capx[i], capy[i]);
679 for (i = 0; i < STABLE_CYCLE; ++i)
683 mc[turns % STABLE_CYCLE] = d;
687 /* This routine does the actual drifting
693 int dir, i, newx, newy;
695 dir = DIR_L + roll0(6);
696 for (i = 0; i < 6; i++) {
699 newx = new_x(capx[j] + diroff[dir][0]);
700 newy = new_y(capy[j] + diroff[dir][1]);
702 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
710 /****************************************************************************
712 ****************************************************************************/
714 /* Look for a coastal sector of continent c
722 for (i = 0; i < isecs[c]; ++i) {
724 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
725 nx = new_x(sectx[c][i] + diroff[dir][0]);
726 ny = new_y(secty[c][i] + diroff[dir][1]);
727 if (own[nx][ny] == -1)
733 struct hexagon_iter {
738 * Start iterating around @x0,@y0 at distance @d.
739 * Set *x,*y to coordinates of the first sector.
742 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
745 *x = new_x(x0 - 2 * n);
747 iter->dir = DIR_FIRST;
753 * Continue iteration started with hexagon_first().
754 * Set *x,*y to coordinates of the next sector.
755 * Return whether we're back at the first sector, i.e. iteration is
759 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
761 *x = new_x(*x + diroff[iter->dir][0]);
762 *y = new_y(*y + diroff[iter->dir][1]);
764 if (iter->i == iter->n) {
768 return iter->dir <= DIR_LAST;
772 * Is @x,@y in no exclusive zone other than perhaps @c's?
775 xzone_ok(int c, int x, int y)
777 int off = XYOFFSET(x, y);
779 return xzone[off] == c || xzone[off] == -1;
783 * Add sectors within distance @dist of @x,@y to @c's exclusive zone.
786 xzone_around_sector(int c, int x, int y, int dist)
789 struct hexagon_iter hexit;
791 assert(xzone_ok(c, x, y));
793 xzone[XYOFFSET(x, y)] = c;
794 for (d = 1; d <= dist; d++) {
795 hexagon_first(&hexit, x, y, d, &x1, &y1);
797 off = XYOFFSET(x1, y1);
798 if (xzone[off] == -1)
800 else if (xzone[off] != c)
802 } while (hexagon_next(&hexit, &x1, &y1));
807 * Add sectors within distance @dist to island @c's exclusive zone.
810 xzone_around_island(int c, int dist)
814 for (i = 0; i < isecs[c]; i++)
815 xzone_around_sector(c, sectx[c][i], secty[c][i], dist);
819 * Initialize exclusive zones around @n islands.
826 for (i = 0; i < WORLD_SZ(); i++)
829 for (c = 0; c < n; c++)
830 xzone_around_island(c, id);
834 * Initialize breadth-first search.
841 for (i = 0; i < WORLD_SZ(); i++) {
843 distance[i] = USHRT_MAX;
846 bfs_queue_head = bfs_queue_tail = 0;
850 * Add sector @x,@y to the BFS queue.
851 * It's closest to @c, with distance @dist.
854 bfs_enqueue(int c, int x, int y, int dist)
856 int off = XYOFFSET(x, y);
858 assert(dist < distance[off]);
860 distance[off] = dist;
861 bfs_queue[bfs_queue_tail] = off;
863 if (bfs_queue_tail >= WORLD_SZ())
865 assert(bfs_queue_tail != bfs_queue_head);
869 * Search breadth-first until the queue is empty.
874 int off, dist, i, noff, nx, ny;
877 while (bfs_queue_head != bfs_queue_tail) {
878 off = bfs_queue[bfs_queue_head];
880 if (bfs_queue_head >= WORLD_SZ())
882 dist = distance[off] + 1;
883 sctoff2xy(&x, &y, off);
884 for (i = DIR_FIRST; i <= DIR_LAST; i++) {
885 nx = new_x(x + diroff[i][0]);
886 ny = new_y(y + diroff[i][1]);
887 noff = XYOFFSET(nx, ny);
888 if (dist < distance[noff]) {
889 bfs_enqueue(closest[off], nx, ny, dist);
890 } else if (distance[noff] == dist) {
891 if (closest[off] != closest[noff])
892 closest[noff] = (natid)-1;
894 assert(distance[noff] < dist);
900 * Add island @c's coastal sectors to the BFS queue, with distance 0.
903 bfs_enqueue_island(int c)
907 for (i = 0; i < isecs[c]; i++) {
909 bfs_enqueue(c, sectx[c][i], secty[c][i], 0);
914 * Enqueue spheres of influence borders for breadth-first search.
917 bfs_enqueue_border(void)
919 int x, y, off, dir, nx, ny, noff;
921 for (y = 0; y < WORLD_Y; y++) {
922 for (x = y % 2; x < WORLD_X; x += 2) {
923 off = XYOFFSET(x, y);
924 if (distance[off] <= id + 1)
926 if (closest[off] == (natid)-1)
928 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
929 nx = new_x(x + diroff[dir][0]);
930 ny = new_y(y + diroff[dir][1]);
931 noff = XYOFFSET(nx, ny);
932 if (closest[noff] != closest[off]) {
933 bfs_enqueue(closest[off], x, y, id + 1);
942 * Compute spheres of influence
943 * A continent's sphere of influence is the set of sectors closer to
944 * it than to any other continent.
945 * Set closest[XYOFFSET(x, y)] to the closest continent's number,
946 * -1 if no single continent is closest.
947 * Set distance[XYOFFSET(x, y)] to the minimum of the distance to the
948 * closest coastal land sector and the distance to just outside the
949 * sphere of influence plus @id. For sea sectors within a continent's
950 * sphere of influence, distance[off] - id is the distance to the
951 * border of the area where additional islands can be placed.
954 init_spheres_of_influence(void)
959 for (c = 0; c < nc; c++)
960 bfs_enqueue_island(c);
962 bfs_enqueue_border();
967 * Precompute distance to coast
968 * Set distance[XYOFFSET(x, y)] to the distance to the closest coastal
970 * Set closest[XYOFFSET(x, y)] to the closest continent's number,
971 * -1 if no single continent is closest.
974 init_distance_to_coast(void)
979 for (c = 0; c < nc + ni; c++)
980 bfs_enqueue_island(c);
985 * Is @x,@y in the same sphere of influence as island @c?
986 * Always true when @c is a continent.
989 is_in_sphere(int c, int x, int y)
991 return c < nc || closest[XYOFFSET(x, y)] == c % nc;
995 * Can island @c grow at @x,@y?
998 can_grow_at(int c, int x, int y)
1000 return own[x][y] == -1 && xzone_ok(c, x, y) && is_in_sphere(c, x, y);
1004 adj_land_update(int x, int y)
1006 int is_land = own[x][y] != -1;
1007 int dir, nx, ny, noff;
1009 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
1010 nx = new_x(x + diroff[dir][0]);
1011 ny = new_y(y + diroff[dir][1]);
1012 noff = XYOFFSET(nx, ny);
1014 adj_land[noff] |= 1u << DIR_BACK(dir);
1016 adj_land[noff] &= ~(1u << DIR_BACK(dir));
1021 add_sector(int c, int x, int y)
1023 assert(own[x][y] == -1);
1024 xzone_around_sector(c, x, y, c < nc ? di : DISTINCT_ISLANDS ? id : 0);
1025 sectx[c][isecs[c]] = x;
1026 secty[c][isecs[c]] = y;
1029 adj_land_update(x, y);
1032 static int grow_weight(int c, int x, int y, int spike)
1037 * #Land neighbors is #bits set in adj_land[].
1038 * Count them Brian Kernighan's way.
1041 for (b = adj_land[XYOFFSET(x, y)]; b; b &= b - 1)
1043 assert(n > 0 && n < 7);
1046 return (6 - n) * (6 - n);
1052 grow_one_sector(int c)
1054 int spike = roll0(100) < sp;
1055 int wsum, newx, newy, i, x, y, off, dir, nx, ny, noff, w;
1057 assert(cur_seen < UINT_MAX);
1062 for (i = 0; i < isecs[c]; i++) {
1065 off = XYOFFSET(x, y);
1067 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
1068 if (adj_land[off] & (1u << dir))
1070 nx = new_x(x + diroff[dir][0]);
1071 ny = new_y(y + diroff[dir][1]);
1072 noff = XYOFFSET(nx, ny);
1073 if (seen[noff] == cur_seen)
1075 assert(seen[noff] < cur_seen);
1076 seen[noff] = cur_seen;
1077 if (!can_grow_at(c, nx, ny))
1079 w = grow_weight(c, nx, ny, spike);
1080 assert(wsum < INT_MAX - w);
1082 if (roll0(wsum) < w) {
1092 add_sector(c, newx, newy);
1097 * Grow the continents.
1098 * Return 1 on success, 0 on error.
1101 grow_continents(void)
1108 for (c = 0; c < nc; ++c) {
1110 if (!can_grow_at(c, capx[c], capy[c])
1111 || !can_grow_at(c, new_x(capx[c] + 2), capy[c])) {
1115 add_sector(c, capx[c], capy[c]);
1116 add_sector(c, new_x(capx[c] + 2), capy[c]);
1120 qprint("No room for continents\n");
1124 for (secs = 2; secs < sc && done; secs++) {
1125 for (c = 0; c < nc; ++c) {
1126 if (!grow_one_sector(c))
1131 for (c = 0; c < nc; ++c)
1135 qprint("Only managed to grow %d out of %d sectors.\n",
1140 /****************************************************************************
1142 ****************************************************************************/
1145 * Place additional island @c's first sector.
1146 * Return 1 on success, 0 on error.
1149 place_island(int c, int isiz)
1151 int n, x, y, d, w, newx, newy;
1155 for (y = 0; y < WORLD_Y; y++) {
1156 for (x = y % 2; x < WORLD_X; x += 2) {
1157 if (can_grow_at(c, x, y)) {
1158 d = distance[XYOFFSET(x, y)];
1160 w = (d - id) * (d - id);
1161 n += MIN(w, (isiz + 2) / 3);
1171 add_sector(c, newx, newy);
1176 int_cmp(const void *a, const void *b)
1178 return *(int *)b - *(int *)a;
1185 int *isiz = malloc(n * sizeof(*isiz));
1190 for (i = 1; i < n; i++) {
1193 isiz[i] = is + r1 - r0;
1197 qsort(isiz, n, sizeof(*isiz), int_cmp);
1202 * Grow the additional islands.
1203 * Return 1 on success, 0 on error.
1208 int *island_size = size_islands();
1209 int xzone_valid = 0;
1211 int i, j, c, done, secs, isiz, x, y;
1213 init_spheres_of_influence();
1215 for (i = 0; i < ni / nc; i++) {
1221 carry += island_size[i];
1222 isiz = MIN(2 * is, carry);
1224 for (j = 0; j < nc; j++) {
1226 if (!place_island(c + j, isiz)) {
1227 qprint("\nNo room for island #%d\n", c - nc + j + 1);
1234 for (secs = 1; secs < isiz && done; secs++) {
1235 for (j = 0; j < nc; j++) {
1236 if (!grow_one_sector(c + j))
1243 for (j = 0; j < nc; j++) {
1244 if (isecs[c + j] != secs) {
1246 assert(isecs[c + j] == secs);
1247 x = sectx[c + j][secs];
1248 y = secty[c + j][secs];
1250 adj_land_update(x, y);
1256 for (j = 0; j < nc; j++)
1257 qprint(" %d(%d)", c - nc + j + 1, isecs[c + j]);
1266 qprint("Only managed to grow %d out of %d island sectors.\n",
1267 is * ni - carry * nc, is * ni);
1269 for (c = nc; c < nc + ni; c++)
1275 /****************************************************************************
1277 ****************************************************************************/
1279 create_elevations(void)
1283 for (i = 0; i < WORLD_X; i++) {
1284 for (j = 0; j < WORLD_Y; j++)
1285 elev[i][j] = -INFINITE_ELEVATION;
1287 init_distance_to_coast();
1292 /* Generic function for finding the distance to the closest sea, land, or
1296 distance_to_what(int x, int y, int flag)
1299 struct hexagon_iter hexit;
1301 for (d = 1; d < 5; ++d) {
1302 hexagon_first(&hexit, x, y, d, &px, &py);
1305 case 0: /* distance to sea */
1306 if (own[px][py] == -1)
1309 case 1: /* distance to land */
1310 if (own[px][py] != -1)
1313 case 2: /* distance to mountain */
1314 if (elev[px][py] == INFINITE_ELEVATION)
1318 } while (hexagon_next(&hexit, &px, &py));
1323 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1325 /* Decide where the mountains go
1330 int i, off, mountain_search, k, c, total, ns, nm, r, x, y;
1331 int highest, where, h, newk, dk;
1333 for (c = 0; c < nc + ni; ++c) {
1336 nm = (pm * ns) / 100;
1338 /* Place the mountains */
1340 for (i = 0; i < ns; ++i) {
1341 off = XYOFFSET(sectx[c][i], secty[c][i]);
1342 dsea[i] = MIN(5, distance[off] + 1);
1343 weight[i] = (total += (dsea[i] * dsea[i]));
1346 for (k = nm, mountain_search = 0;
1347 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1348 ++mountain_search) {
1350 for (i = 0; i < ns; ++i) {
1353 if (r < weight[i] && elev[x][y] == -INFINITE_ELEVATION &&
1355 ((!(capx[c] == sectx[c][i] &&
1356 capy[c] == secty[c][i])) &&
1357 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1358 capy[c] == secty[c][i]))))) {
1359 elev[x][y] = INFINITE_ELEVATION;
1366 /* Elevate land that is not mountain and not capital */
1368 for (i = 0; i < ns; ++i)
1369 dmoun[i] = distance_to_mountain();
1370 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1371 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1372 100 * INFINITE_ELEVATION;
1373 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1376 for (i = 0; i < ns; ++i) {
1379 if (elev[x][y] == -INFINITE_ELEVATION &&
1380 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1381 capy[c] == secty[c][i])) &&
1382 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1383 capy[c] == secty[c][i]))))) {
1384 h = 3 * (5 - dmoun[i]) + dsea[i];
1395 if (newk >= HILLMIN && newk < PLATMIN)
1399 elev[sectx[c][where]][secty[c][where]] = newk;
1402 /* Elevate the mountains and capitals */
1404 for (i = 0; i < ns; ++i) {
1407 if (elev[x][y] == INFINITE_ELEVATION) {
1409 elev[x][y] = HILLMIN + roll0(PLATMIN - HILLMIN);
1411 elev[x][y] = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1412 roll0((256 - HIGHMIN) / 2);
1413 } else if (c < nc &&
1414 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1415 ((new_x(capx[c] + 2) == sectx[c][i] &&
1416 capy[c] == secty[c][i]))))
1417 elev[x][y] = PLATMIN;
1427 for (y = 0; y < WORLD_Y; ++y) {
1428 for (x = y % 2; x < WORLD_X; x += 2) {
1429 off = XYOFFSET(x, y);
1430 if (elev[x][y] == -INFINITE_ELEVATION)
1431 elev[x][y] = -roll(MIN(5, distance[off]) * 20 + 27);
1437 elev_to_sct_type(int elevation)
1439 if (elevation < LANDMIN)
1441 if (elevation < HILLMIN)
1443 if (elevation < PLATMIN)
1445 if (elevation < HIGHMIN)
1450 /****************************************************************************
1452 ****************************************************************************/
1459 fert = LANDMIN - e + 40;
1460 else if (e < FERT_MAX)
1461 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1472 oil = (LANDMIN - e) * 2 + roll0(2);
1473 else if (e <= OIL_MAX)
1474 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1484 if (e >= IRON_MIN && e < HIGHMIN)
1485 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1495 if (e >= GOLD_MIN) {
1497 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1499 gold = 100 - 20 * HIGHMIN / e;
1510 if (e >= URAN_MIN && e < HIGHMIN)
1511 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1518 add_resources(struct sctstr *sct)
1520 sct->sct_fertil = set_fert(sct->sct_elev);
1521 sct->sct_oil = set_oil(sct->sct_elev);
1522 sct->sct_min = set_iron(sct->sct_elev);
1523 sct->sct_gmin = set_gold(sct->sct_elev);
1524 sct->sct_uran = set_uran(sct->sct_elev);
1527 /****************************************************************************
1528 DESIGNATE THE SECTORS
1529 ****************************************************************************/
1537 for (y = 0; y < WORLD_Y; y++) {
1538 for (x = y % 2; x < WORLD_X; x += 2) {
1539 sct = getsectp(x, y);
1540 sct->sct_elev = elev[x][y];
1541 sct->sct_type = elev_to_sct_type(elev[x][y]);
1542 sct->sct_newtype = sct->sct_type;
1543 sct->sct_dterr = own[sct->sct_x][y] + 1;
1547 set_coastal_flags();
1550 /****************************************************************************
1551 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1552 ****************************************************************************/
1556 int sx, sy, x, y, c, type;
1559 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1564 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1567 type = elev_to_sct_type(elev[x][y]);
1568 if (type == SCT_WATER)
1570 else if (type == SCT_MOUNT)
1575 assert(0 <= c && c < nc);
1576 if ((x == capx[c] || x == new_x(capx[c] + 2))
1578 printf("%c ", numletter[c % 62]);
1588 * Print a map to help visualize own[][].
1589 * This is for debugging.
1596 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1599 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1603 else if (own[x][y] == -1)
1606 putchar(numletter[own[x][y] % 62]);
1613 * Print a map to help visualize elev[][].
1614 * This is for debugging. It expects the terminal to understand
1615 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1618 print_elev_map(void)
1620 int sx, sy, x, y, sat;
1622 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1625 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1629 else if (!elev[x][y])
1631 else if (elev[x][y] < 0) {
1632 sat = 256 + elev[x][y] * 2;
1633 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1634 } else if (elev[x][y] < HIGHMIN / 2) {
1635 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1636 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1637 } else if (elev[x][y] < HIGHMIN) {
1638 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1639 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1641 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1642 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1650 * Print a map to help visualize xzone[].
1651 * This is for debugging.
1654 print_xzone_map(void)
1656 int sx, sy, x, y, off;
1658 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1661 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1663 off = XYOFFSET(x, y);
1666 else if (own[x][y] >= 0)
1668 else if (xzone[off] >= 0)
1669 putchar(numletter[xzone[off] % 62]);
1671 assert(own[x][y] == -1);
1672 putchar(xzone[off] == -1 ? '.' : '!');
1680 * Print a map to help visualize closest[].
1681 * This is for debugging.
1684 print_closest_map(void)
1686 int sx, sy, x, y, off;
1688 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1691 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1693 off = XYOFFSET(x, y);
1696 else if (closest[off] == (natid)-1)
1698 else if (!distance[off]) {
1699 assert(closest[off] == own[x][y]);
1702 putchar(numletter[closest[off] % 62]);
1710 print_distance_map(void)
1712 int sx, sy, x, y, off;
1714 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1717 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1719 off = XYOFFSET(x, y);
1722 else if (closest[off] == (natid)-1)
1724 else if (!distance[off]) {
1725 assert(closest[off] == own[x][y]);
1728 putchar(numletter[distance[off] % 62]);
1736 /***************************************************************************
1737 WRITE A SCRIPT FOR PLACING CAPITALS
1738 ****************************************************************************/
1740 write_newcap_script(void)
1743 FILE *script = fopen(outfile, "w");
1746 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1747 program_name, outfile, strerror(errno));
1751 for (c = 0; c < nc; ++c) {
1752 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1753 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1755 fprintf(script, "add %d visitor visitor v\n", c + 1);
1761 qprint(const char *const fmt, ...)
1767 vfprintf(stdout, fmt, ap);
1773 set_coastal_flags(void)
1778 for (i = 0; i < nc + ni; ++i) {
1779 for (j = 0; j < isecs[i]; j++) {
1780 sp = getsectp(sectx[i][j], secty[i][j]);
1781 sp->sct_coastal = sectc[i][j];