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
70 * Place and grow islands in spheres in turn. Place the first sector
71 * randomly, pick an island size, then grow the island to that size.
73 * If placement fails due to lack of room, start over, just like for
76 * Growing works as for continents, except the minimum distance for
77 * additional islands applies, and growing simply stops when there is
80 * 4. Compute elevation
82 * Elevate islands one after the other.
84 * First, place the specified number of mountains randomly.
85 * Probability increases with distance to sea.
87 * Last, elevate mountains and the capitals. Pick coastal mountain
88 * elevation randomly from an interval of medium elevations reserved
89 * for them. Pick non-coastal mountain elevation randomly from an
90 * interval of high elevation reserved for them. Set capital
91 * elevation to a fixed, medium value.
93 * In between, elevate the remaining land one by one, working from
94 * mountains towards the sea, and from the elevation just below the
95 * non-coastal mountains' interval linearly down to 1, avoiding the
96 * coastal mountains' interval.
98 * This gives islands of the same size the same set of elevations,
99 * except for mountains.
101 * Elevate sea: pick a random depth from an interval that deepens with
102 * the distance to land.
106 * Sector resources are simple functions of elevation. You can alter
107 * macros OIL_MAX, IRON_MIN, GOLD_MIN, FERT_MAX, and URAN_MIN to
122 #include "prototypes.h"
127 /* The following five numbers refer to elevation under which (in the case of
128 fertility or oil) or over which (in the case of iron, gold, and uranium)
129 sectors with that elevation will contain that resource. Elevation ranges
132 /* raise FERT_MAX for more fertility */
135 /* raise OIL_MAX for more oil */
138 /* lower IRON_MIN for more iron */
141 /* lower GOLD_MIN for more gold */
144 /* lower URAN_MIN for more uranium */
147 /* do not change these 4 defines */
148 #define LANDMIN 1 /* plate altitude for normal land */
149 #define HILLMIN 34 /* plate altitude for hills */
150 #define PLATMIN 36 /* plate altitude for plateau */
151 #define HIGHMIN 98 /* plate altitude for mountains */
153 static void qprint(const char * const fmt, ...)
154 ATTRIBUTE((format (printf, 1, 2)));
157 * Program arguments and options
159 static char *program_name;
160 static int nc, sc; /* number and size of continents */
161 static int ni, is; /* number and size of islands */
162 #define DEFAULT_SPIKE 10
163 static int sp = DEFAULT_SPIKE; /* spike percentage */
164 #define DEFAULT_MOUNTAIN 0
165 static int pm = DEFAULT_MOUNTAIN; /* mountain percentage */
166 #define DEFAULT_CONTDIST 2
167 static int di = DEFAULT_CONTDIST; /* min. distance between continents */
168 #define DEFAULT_ISLDIST 1
169 static int id = DEFAULT_ISLDIST; /* ... continents and islands */
170 /* don't let the islands crash into each other.
171 1 = don't merge, 0 = merge. */
172 static int DISTINCT_ISLANDS = 1;
174 #define DEFAULT_OUTFILE_NAME "newcap_script"
175 static const char *outfile = DEFAULT_OUTFILE_NAME;
177 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
178 #define INFINITE_ELEVATION 999
180 /* these defines prevent infinite loops:
182 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
183 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
184 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
189 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
190 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
194 * isecs[i] is the size of the i-th island.
198 static int *capx, *capy; /* location of the nc capitals */
200 static int **own; /* owner of the sector. -1 means water */
203 * Adjacent land sectors
204 * adj_land[XYOFFSET(x, y)] bit d is set exactly when the sector next
205 * to x, y in direction d is land.
207 static unsigned char *adj_land;
211 * Each island is surrounded by an exclusive zone where only it may
212 * grow. The width of the zone depends on minimum distances.
213 * While growing continents, it is @di sectors wide.
214 * While growing additional islands, it is @id sectors wide.
215 * DISTINCT_ISLANDS nullifies the exclusive zone then.
216 * xzone[XYOFFSET(x, y)] is -1 when the sector is in no exclusive
217 * zone, a (non-negative) island number when it is in that island's
218 * exclusive zone and no other, and -2 when it is in multiple
224 * Set of sectors seen already
225 * Increment @cur_seen to empty the set of sectors seen, set
226 * seen[XYOFFSET(x, y)] to @cur_seen to add x,y to the set.
228 static unsigned *seen;
229 static unsigned cur_seen;
232 * Closest continent and "distance"
233 * closest[XYOFFSET(x, y)] is the closest continent's number.
234 * distance[] is complicated; see init_spheres_of_influence().
236 static natid *closest;
237 static unsigned short *distance;
240 * Queue for breadth-first search
242 static int *bfs_queue;
243 static int bfs_queue_head, bfs_queue_tail;
245 static int **elev; /* elevation of the sectors */
246 static int **sectx, **secty; /* the sectors for each continent */
247 static int **sectc; /* which sectors are on the coast? */
248 static int *weight; /* used for placing mountains */
249 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
251 #define NUMTRIES 10 /* keep trying to grow this many times */
253 static const char *numletter =
254 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
256 static void help(char *);
257 static void usage(void);
258 static void parse_args(int argc, char *argv[]);
259 static void allocate_memory(void);
260 static void init(void);
261 static int drift(void);
262 static int grow_continents(void);
263 static void create_elevations(void);
264 static void write_sects(void);
265 static void output(void);
266 static int write_newcap_script(void);
267 static int stable(int);
268 static void elevate_land(void);
269 static void elevate_sea(void);
270 static void set_coastal_flags(void);
272 static void print_vars(void);
273 static void fl_move(int);
274 static int grow_islands(void);
276 /* Debugging aids: */
277 void print_own_map(void);
278 void print_xzone_map(void);
279 void print_closest_map(void);
280 void print_distance_map(void);
281 void print_elev_map(void);
283 /****************************************************************************
285 ****************************************************************************/
288 main(int argc, char *argv[])
291 char *config_file = NULL;
293 unsigned rnd_seed = 0;
296 program_name = argv[0];
298 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
301 config_file = optarg;
304 DISTINCT_ISLANDS = 0;
310 rnd_seed = strtoul(optarg, NULL, 10);
320 printf("%s\n\n%s", version, legal);
329 rnd_seed = pick_seed();
332 if (emp_config(config_file) < 0)
336 parse_args(argc - optind, argv + optind);
341 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
342 qprint("seed is %u\n", rnd_seed);
347 qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
348 qprint("placing capitals...\n");
350 qprint("unstable drift\n");
351 qprint("growing continents...\n");
352 done = grow_continents();
355 qprint("growing islands:");
356 done = grow_islands();
357 } while (!done && ++try < NUMTRIES);
359 fprintf(stderr, "%s: world not large enough for this much land\n",
363 qprint("elevating land...\n");
366 qprint("writing to sectors file...\n");
367 if (!write_newcap_script())
369 if (chdir(gamedir)) {
370 fprintf(stderr, "%s: can't chdir to %s (%s)\n",
371 program_name, gamedir, strerror(errno));
374 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
377 if (!ef_close(EF_SECTOR))
381 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
391 puts("Creating a planet with:\n");
392 printf("%d continents\n", nc);
393 printf("continent size: %d\n", sc);
394 printf("number of islands: %d\n", ni);
395 printf("average size of islands: %d\n", is);
396 printf("spike: %d%%\n", sp);
397 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
398 pm, (pm * sc) / 100);
399 printf("minimum distance between continents: %d\n", di);
400 printf("minimum distance from islands to continents: %d\n", id);
401 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
405 help(char *complaint)
408 fprintf(stderr, "%s: %s\n", program_name, complaint);
409 fprintf(stderr, "Try -h for help.\n");
415 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
416 " -e CONFIG-FILE configuration file\n"
418 " -i islands may merge\n"
420 " -R SEED seed for random number generator\n"
421 " -s SCRIPT name of script to create (default %s)\n"
422 " -h display this help and exit\n"
423 " -v display version information and exit\n"
424 " NC number of continents\n"
425 " SC continent size\n"
426 " NI number of islands (default NC)\n"
427 " IS average island size (default SC/2)\n"
428 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
429 " PM percentage of land that is mountain (default %d)\n"
430 " DI minimum distance between continents (default %d)\n"
431 " ID minimum distance from islands to continents (default %d)\n",
432 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
433 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
437 parse_args(int argc, char *argv[])
439 int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
442 help("missing arguments");
446 help("too many arguments");
451 fprintf(stderr, "%s: number of continents must be > 0\n",
458 fprintf(stderr, "%s: size of continents must be > 1\n",
469 fprintf(stderr, "%s: number of islands must be >= 0\n",
474 fprintf(stderr, "%s: number of islands must be a multiple of"
475 " the number of continents\n",
483 fprintf(stderr, "%s: size of islands must be > 0\n",
490 if (sp < 0 || sp > 100) {
492 "%s: spike percentage must be between 0 and 100\n",
499 if (pm < 0 || pm > 100) {
501 "%s: mountain percentage must be between 0 and 100\n",
509 fprintf(stderr, "%s: distance between continents must be >= 0\n",
514 fprintf(stderr, "%s: distance between continents too large\n",
523 "%s: distance from islands to continents must be >= 0\n",
529 "%s: distance from islands to continents too large\n",
535 /****************************************************************************
536 VARIABLE INITIALIZATION
537 ****************************************************************************/
540 allocate_memory(void)
544 capx = calloc(nc, sizeof(int));
545 capy = calloc(nc, sizeof(int));
546 own = calloc(WORLD_X, sizeof(int *));
547 adj_land = malloc(WORLD_SZ() * sizeof(*adj_land));
548 xzone = malloc(WORLD_SZ() * sizeof(*xzone));
549 seen = calloc(WORLD_SZ(), sizeof(*seen));
550 closest = malloc(WORLD_SZ() * sizeof(*closest));
551 distance = malloc(WORLD_SZ() * sizeof(*distance));
552 bfs_queue = malloc(WORLD_SZ() * sizeof(*bfs_queue));
553 elev = calloc(WORLD_X, sizeof(int *));
554 for (i = 0; i < WORLD_X; ++i) {
555 own[i] = calloc(WORLD_Y, sizeof(int));
556 elev[i] = calloc(WORLD_Y, sizeof(int));
558 sectx = calloc(nc + ni, sizeof(int *));
559 secty = calloc(nc + ni, sizeof(int *));
560 sectc = calloc(nc + ni, sizeof(int *));
561 isecs = calloc(nc + ni, sizeof(int));
562 weight = calloc(MAX(sc, is * 2), sizeof(int));
563 dsea = calloc(MAX(sc, is * 2), sizeof(int));
564 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
565 for (i = 0; i < nc; ++i) {
566 sectx[i] = calloc(sc, sizeof(int));
567 secty[i] = calloc(sc, sizeof(int));
568 sectc[i] = calloc(sc, sizeof(int));
570 for (i = nc; i < nc + ni; ++i) {
571 sectx[i] = calloc(is * 2, sizeof(int));
572 secty[i] = calloc(is * 2, sizeof(int));
573 sectc[i] = calloc(is * 2, sizeof(int));
583 for (i = 0; i < WORLD_X; ++i) {
584 for (j = 0; j < WORLD_Y; ++j) {
588 memset(adj_land, 0, WORLD_SZ() * sizeof(*adj_land));
591 /****************************************************************************
592 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
593 ****************************************************************************/
596 * How isolated is capital @j at @newx,@newy?
597 * Return the distance to the closest other capital.
600 iso(int j, int newx, int newy)
605 for (i = 0; i < nc; ++i) {
608 md = mapdist(capx[i], capy[i], newx, newy);
618 * Return 1 for a stable drift, 0 for an unstable one.
625 for (i = 0; i < nc; i++) {
626 capy[i] = (2 * i) / WORLD_X;
627 capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
628 if (capy[i] >= WORLD_Y) {
630 "%s: world not big enough for all the continents\n",
636 for (turns = 0; turns < DRIFT_MAX; ++turns) {
639 for (i = 0; i < nc; ++i)
646 * Has the drift stabilized?
647 * @turns is the number of turns so far.
652 static int mc[STABLE_CYCLE];
653 int i, isod, d = 0, stab = 1;
656 for (i = 0; i < STABLE_CYCLE; i++)
660 if (turns <= DRIFT_BEFORE_CHECK)
663 for (i = 0; i < nc; ++i) {
664 isod = iso(i, capx[i], capy[i]);
669 for (i = 0; i < STABLE_CYCLE; ++i)
673 mc[turns % STABLE_CYCLE] = d;
677 /* This routine does the actual drifting
683 int dir, i, newx, newy;
685 dir = DIR_L + roll0(6);
686 for (i = 0; i < 6; i++) {
689 newx = new_x(capx[j] + diroff[dir][0]);
690 newy = new_y(capy[j] + diroff[dir][1]);
692 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
700 /****************************************************************************
702 ****************************************************************************/
704 /* Look for a coastal sector of continent c
712 for (i = 0; i < isecs[c]; ++i) {
714 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
715 nx = new_x(sectx[c][i] + diroff[dir][0]);
716 ny = new_y(secty[c][i] + diroff[dir][1]);
717 if (own[nx][ny] == -1)
723 struct hexagon_iter {
728 * Start iterating around @x0,@y0 at distance @d.
729 * Set *x,*y to coordinates of the first sector.
732 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
735 *x = new_x(x0 - 2 * n);
737 iter->dir = DIR_FIRST;
743 * Continue iteration started with hexagon_first().
744 * Set *x,*y to coordinates of the next sector.
745 * Return whether we're back at the first sector, i.e. iteration is
749 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
751 *x = new_x(*x + diroff[iter->dir][0]);
752 *y = new_y(*y + diroff[iter->dir][1]);
754 if (iter->i == iter->n) {
758 return iter->dir <= DIR_LAST;
762 * Is @x,@y in no exclusive zone other than perhaps @c's?
765 xzone_ok(int c, int x, int y)
767 int off = XYOFFSET(x, y);
769 return xzone[off] == c || xzone[off] == -1;
773 * Add sectors within distance @dist of @x,@y to @c's exclusive zone.
776 xzone_around_sector(int c, int x, int y, int dist)
779 struct hexagon_iter hexit;
781 assert(xzone_ok(c, x, y));
783 xzone[XYOFFSET(x, y)] = c;
784 for (d = 1; d <= dist; d++) {
785 hexagon_first(&hexit, x, y, d, &x1, &y1);
787 off = XYOFFSET(x1, y1);
788 if (xzone[off] == -1)
790 else if (xzone[off] != c)
792 } while (hexagon_next(&hexit, &x1, &y1));
797 * Add sectors within distance @dist to island @c's exclusive zone.
800 xzone_around_island(int c, int dist)
804 for (i = 0; i < isecs[c]; i++)
805 xzone_around_sector(c, sectx[c][i], secty[c][i], dist);
809 * Initialize exclusive zones around @n islands.
816 for (i = 0; i < WORLD_SZ(); i++)
819 for (c = 0; c < n; c++)
820 xzone_around_island(c, id);
824 * Initialize breadth-first search.
831 for (i = 0; i < WORLD_SZ(); i++) {
833 distance[i] = USHRT_MAX;
836 bfs_queue_head = bfs_queue_tail = 0;
840 * Add sector @x,@y to the BFS queue.
841 * It's closest to @c, with distance @dist.
844 bfs_enqueue(int c, int x, int y, int dist)
846 int off = XYOFFSET(x, y);
848 assert(dist < distance[off]);
850 distance[off] = dist;
851 bfs_queue[bfs_queue_tail] = off;
853 if (bfs_queue_tail >= WORLD_SZ())
855 assert(bfs_queue_tail != bfs_queue_head);
859 * Search breadth-first until the queue is empty.
864 int off, dist, i, noff, nx, ny;
867 while (bfs_queue_head != bfs_queue_tail) {
868 off = bfs_queue[bfs_queue_head];
870 if (bfs_queue_head >= WORLD_SZ())
872 dist = distance[off] + 1;
873 sctoff2xy(&x, &y, off);
874 for (i = DIR_FIRST; i <= DIR_LAST; i++) {
875 nx = new_x(x + diroff[i][0]);
876 ny = new_y(y + diroff[i][1]);
877 noff = XYOFFSET(nx, ny);
878 if (dist < distance[noff]) {
879 bfs_enqueue(closest[off], nx, ny, dist);
880 } else if (distance[noff] == dist) {
881 if (closest[off] != closest[noff])
882 closest[noff] = (natid)-1;
884 assert(distance[noff] < dist);
890 * Add island @c's coastal sectors to the BFS queue, with distance 0.
893 bfs_enqueue_island(int c)
897 for (i = 0; i < isecs[c]; i++) {
899 bfs_enqueue(c, sectx[c][i], secty[c][i], 0);
904 * Compute spheres of influence
905 * A continent's sphere of influence is the set of sectors closer to
906 * it than to any other continent.
907 * Set closest[XYOFFSET(x, y)] to the closest continent's number,
908 * -1 if no single continent is closest.
909 * Set distance[XYOFFSET(x, y)] to the distance to the closest coastal
913 init_spheres_of_influence(void)
918 for (c = 0; c < nc; c++)
919 bfs_enqueue_island(c);
924 * Is @x,@y in the same sphere of influence as island @c?
925 * Always true when @c is a continent.
928 is_in_sphere(int c, int x, int y)
930 return c < nc || closest[XYOFFSET(x, y)] == c % nc;
934 * Can island @c grow at @x,@y?
937 can_grow_at(int c, int x, int y)
939 return own[x][y] == -1 && xzone_ok(c, x, y) && is_in_sphere(c, x, y);
943 adj_land_update(int x, int y)
945 int dir, nx, ny, noff;
947 assert(own[x][y] != -1);
949 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
950 nx = new_x(x + diroff[dir][0]);
951 ny = new_y(y + diroff[dir][1]);
952 noff = XYOFFSET(nx, ny);
953 adj_land[noff] |= 1u << DIR_BACK(dir);
958 add_sector(int c, int x, int y)
960 assert(own[x][y] == -1);
961 xzone_around_sector(c, x, y, c < nc ? di : DISTINCT_ISLANDS ? id : 0);
962 sectx[c][isecs[c]] = x;
963 secty[c][isecs[c]] = y;
966 adj_land_update(x, y);
970 grow_weight(int c, int x, int y, int spike)
975 * #Land neighbors is #bits set in adj_land[].
976 * Count them Brian Kernighan's way.
979 for (b = adj_land[XYOFFSET(x, y)]; b; b &= b - 1)
981 assert(n > 0 && n < 7);
984 return (6 - n) * (6 - n);
990 grow_one_sector(int c)
992 int spike = roll0(100) < sp;
993 int wsum, newx, newy, i, x, y, off, dir, nx, ny, noff, w;
995 assert(cur_seen < UINT_MAX);
1000 for (i = 0; i < isecs[c]; i++) {
1003 off = XYOFFSET(x, y);
1005 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
1006 if (adj_land[off] & (1u << dir))
1008 nx = new_x(x + diroff[dir][0]);
1009 ny = new_y(y + diroff[dir][1]);
1010 noff = XYOFFSET(nx, ny);
1011 if (seen[noff] == cur_seen)
1013 assert(seen[noff] < cur_seen);
1014 seen[noff] = cur_seen;
1015 if (!can_grow_at(c, nx, ny))
1017 w = grow_weight(c, nx, ny, spike);
1018 assert(wsum < INT_MAX - w);
1020 if (roll0(wsum) < w) {
1030 add_sector(c, newx, newy);
1035 * Grow the continents.
1036 * Return 1 on success, 0 on error.
1039 grow_continents(void)
1046 for (c = 0; c < nc; ++c) {
1048 if (!can_grow_at(c, capx[c], capy[c])
1049 || !can_grow_at(c, new_x(capx[c] + 2), capy[c])) {
1053 add_sector(c, capx[c], capy[c]);
1054 add_sector(c, new_x(capx[c] + 2), capy[c]);
1058 qprint("No room for continents\n");
1062 for (secs = 2; secs < sc && done; secs++) {
1063 for (c = 0; c < nc; ++c) {
1064 if (!grow_one_sector(c))
1069 for (c = 0; c < nc; ++c)
1073 qprint("Only managed to grow %d out of %d sectors.\n",
1078 /****************************************************************************
1080 ****************************************************************************/
1083 * Place additional island @c's first sector.
1084 * Return 1 on success, 0 on error.
1089 int n, x, y, newx, newy;
1093 for (y = 0; y < WORLD_Y; y++) {
1094 for (x = y % 2; x < WORLD_X; x += 2) {
1095 if (can_grow_at(c, x, y)) {
1106 add_sector(c, newx, newy);
1111 * Grow the additional islands.
1112 * Return 1 on success, 0 on error.
1117 int stunted_islands = 0;
1121 init_spheres_of_influence();
1123 for (c = nc; c < nc + ni; ++c) {
1126 if (!place_island(c)) {
1127 qprint("\nNo room for island #%d", c - nc + 1);
1131 isiz = roll(is) + roll0(is);
1132 for (secs = 1; secs < isiz; secs++) {
1133 if (!grow_one_sector(c)) {
1140 qprint(" %d(%d)", c - nc + 1, secs);
1148 if (stunted_islands)
1149 qprint("%d stunted island%s\n",
1150 stunted_islands, splur(stunted_islands));
1154 /****************************************************************************
1156 ****************************************************************************/
1158 create_elevations(void)
1162 for (i = 0; i < WORLD_X; i++) {
1163 for (j = 0; j < WORLD_Y; j++)
1164 elev[i][j] = -INFINITE_ELEVATION;
1170 /* Generic function for finding the distance to the closest sea, land, or
1174 distance_to_what(int x, int y, int flag)
1177 struct hexagon_iter hexit;
1179 for (d = 1; d < 5; ++d) {
1180 hexagon_first(&hexit, x, y, d, &px, &py);
1183 case 0: /* distance to sea */
1184 if (own[px][py] == -1)
1187 case 1: /* distance to land */
1188 if (own[px][py] != -1)
1191 case 2: /* distance to mountain */
1192 if (elev[px][py] == INFINITE_ELEVATION)
1196 } while (hexagon_next(&hexit, &px, &py));
1201 #define ELEV elev[sectx[c][i]][secty[c][i]]
1202 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1203 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1205 /* Decide where the mountains go
1210 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
1213 for (c = 0; c < nc + ni; ++c) {
1216 nm = (pm * ns) / 100;
1218 /* Place the mountains */
1220 for (i = 0; i < ns; ++i) {
1221 dsea[i] = distance_to_sea();
1222 weight[i] = (total += (dsea[i] * dsea[i]));
1225 for (k = nm, mountain_search = 0;
1226 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1227 ++mountain_search) {
1229 for (i = 0; i < ns; ++i)
1230 if (r < weight[i] && ELEV == -INFINITE_ELEVATION &&
1232 ((!(capx[c] == sectx[c][i] &&
1233 capy[c] == secty[c][i])) &&
1234 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1235 capy[c] == secty[c][i]))))) {
1236 ELEV = INFINITE_ELEVATION;
1242 /* Elevate land that is not mountain and not capital */
1244 for (i = 0; i < ns; ++i)
1245 dmoun[i] = distance_to_mountain();
1246 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1247 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1248 100 * INFINITE_ELEVATION;
1249 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1252 for (i = 0; i < ns; ++i) {
1253 if (ELEV == -INFINITE_ELEVATION &&
1254 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1255 capy[c] == secty[c][i])) &&
1256 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1257 capy[c] == secty[c][i]))))) {
1258 h = 3 * (5 - dmoun[i]) + dsea[i];
1269 if (newk >= HILLMIN && newk < PLATMIN)
1273 elev[sectx[c][where]][secty[c][where]] = newk;
1276 /* Elevate the mountains and capitals */
1278 for (i = 0; i < ns; ++i) {
1279 if (ELEV == INFINITE_ELEVATION) {
1281 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1283 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1284 roll0((256 - HIGHMIN) / 2);
1285 } else if (c < nc &&
1286 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1287 ((new_x(capx[c] + 2) == sectx[c][i] &&
1288 capy[c] == secty[c][i]))))
1294 #define distance_to_land() distance_to_what(x, y, 1)
1301 for (y = 0; y < WORLD_Y; ++y) {
1302 for (x = y % 2; x < WORLD_X; x += 2) {
1303 if (elev[x][y] == -INFINITE_ELEVATION)
1304 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1310 elev_to_sct_type(int elevation)
1312 if (elevation < LANDMIN)
1314 if (elevation < HILLMIN)
1316 if (elevation < PLATMIN)
1318 if (elevation < HIGHMIN)
1323 /****************************************************************************
1325 ****************************************************************************/
1332 fert = LANDMIN - e + 40;
1333 else if (e < FERT_MAX)
1334 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1345 oil = (LANDMIN - e) * 2 + roll0(2);
1346 else if (e <= OIL_MAX)
1347 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1357 if (e >= IRON_MIN && e < HIGHMIN)
1358 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1368 if (e >= GOLD_MIN) {
1370 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1372 gold = 100 - 20 * HIGHMIN / e;
1383 if (e >= URAN_MIN && e < HIGHMIN)
1384 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1391 add_resources(struct sctstr *sct)
1393 sct->sct_fertil = set_fert(sct->sct_elev);
1394 sct->sct_oil = set_oil(sct->sct_elev);
1395 sct->sct_min = set_iron(sct->sct_elev);
1396 sct->sct_gmin = set_gold(sct->sct_elev);
1397 sct->sct_uran = set_uran(sct->sct_elev);
1400 /****************************************************************************
1401 DESIGNATE THE SECTORS
1402 ****************************************************************************/
1410 for (y = 0; y < WORLD_Y; y++) {
1411 for (x = y % 2; x < WORLD_X; x += 2) {
1412 sct = getsectp(x, y);
1413 sct->sct_elev = elev[x][y];
1414 sct->sct_type = elev_to_sct_type(elev[x][y]);
1415 sct->sct_newtype = sct->sct_type;
1416 sct->sct_dterr = own[sct->sct_x][y] + 1;
1420 set_coastal_flags();
1423 /****************************************************************************
1424 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1425 ****************************************************************************/
1429 int sx, sy, x, y, c, type;
1432 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1437 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1440 type = elev_to_sct_type(elev[x][y]);
1441 if (type == SCT_WATER)
1443 else if (type == SCT_MOUNT)
1448 assert(0 <= c && c < nc);
1449 if ((x == capx[c] || x == new_x(capx[c] + 2))
1451 printf("%c ", numletter[c % 62]);
1461 * Print a map to help visualize own[][].
1462 * This is for debugging.
1469 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1472 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1476 else if (own[x][y] == -1)
1479 putchar(numletter[own[x][y] % 62]);
1486 * Print a map to help visualize elev[][].
1487 * This is for debugging. It expects the terminal to understand
1488 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1491 print_elev_map(void)
1493 int sx, sy, x, y, sat;
1495 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1498 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1502 else if (!elev[x][y])
1504 else if (elev[x][y] < 0) {
1505 sat = 256 + elev[x][y] * 2;
1506 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1507 } else if (elev[x][y] < HIGHMIN / 2) {
1508 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1509 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1510 } else if (elev[x][y] < HIGHMIN) {
1511 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1512 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1514 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1515 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1523 * Print a map to help visualize xzone[].
1524 * This is for debugging.
1527 print_xzone_map(void)
1529 int sx, sy, x, y, off;
1531 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1534 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1536 off = XYOFFSET(x, y);
1539 else if (own[x][y] >= 0)
1541 else if (xzone[off] >= 0)
1542 putchar(numletter[xzone[off] % 62]);
1544 assert(own[x][y] == -1);
1545 putchar(xzone[off] == -1 ? '.' : '!');
1553 * Print a map to help visualize closest[].
1554 * This is for debugging.
1557 print_closest_map(void)
1559 int sx, sy, x, y, off;
1561 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1564 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1566 off = XYOFFSET(x, y);
1569 else if (closest[off] == (natid)-1)
1571 else if (!distance[off]) {
1572 assert(closest[off] == own[x][y]);
1575 putchar(numletter[closest[off] % 62]);
1583 print_distance_map(void)
1585 int sx, sy, x, y, off;
1587 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1590 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1592 off = XYOFFSET(x, y);
1595 else if (closest[off] == (natid)-1)
1597 else if (!distance[off]) {
1598 assert(closest[off] == own[x][y]);
1601 putchar(numletter[distance[off] % 62]);
1609 /***************************************************************************
1610 WRITE A SCRIPT FOR PLACING CAPITALS
1611 ****************************************************************************/
1613 write_newcap_script(void)
1616 FILE *script = fopen(outfile, "w");
1619 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1620 program_name, outfile, strerror(errno));
1624 for (c = 0; c < nc; ++c) {
1625 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1626 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1628 fprintf(script, "add %d visitor visitor v\n", c + 1);
1634 qprint(const char *const fmt, ...)
1640 vfprintf(stdout, fmt, ap);
1646 set_coastal_flags(void)
1651 for (i = 0; i < nc + ni; ++i) {
1652 for (j = 0; j < isecs[i]; j++) {
1653 sp = getsectp(sectx[i][j], secty[i][j]);
1654 sp->sct_coastal = sectc[i][j];