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 * 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.
68 * Growing works as for continents, except the minimum distance for
69 * additional islands applies, and growing simply stops when there is
72 * 4. Compute elevation
74 * Elevate islands one after the other.
76 * First, place the specified number of mountains randomly.
77 * Probability increases with distance to sea.
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.
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.
90 * This gives islands of the same size the same set of elevations,
91 * except for mountains.
93 * Elevate sea: pick a random depth from an interval that deepens with
94 * the distance to land.
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
114 #include "prototypes.h"
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
124 /* raise FERT_MAX for more fertility */
127 /* raise OIL_MAX for more oil */
130 /* lower IRON_MIN for more iron */
133 /* lower GOLD_MIN for more gold */
136 /* lower URAN_MIN for more uranium */
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 */
145 static void qprint(const char * const fmt, ...)
146 ATTRIBUTE((format (printf, 1, 2)));
149 * Program arguments and options
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;
166 #define DEFAULT_OUTFILE_NAME "newcap_script"
167 static const char *outfile = DEFAULT_OUTFILE_NAME;
169 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
170 #define INFINITE_ELEVATION 999
172 /* these defines prevent infinite loops:
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 */
181 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
182 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
184 static int ctot; /* total number of continents and islands grown */
185 static int *isecs; /* array of how large each island is */
187 static int *capx, *capy; /* location of the nc capitals */
188 static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
189 static int diry[] = { 0, -1, -1, 0, 1, 1 };
191 static int **own; /* owner of the sector. -1 means water */
194 * Adjacent land sectors
195 * adj_land[XYOFFSET(x, y)] bit d is set exactly when the sector next
196 * to x, y in direction d is land.
198 static unsigned char *adj_land;
202 * Each island is surrounded by an exclusive zone where only it may
203 * grow. The width of the zone depends on minimum distances.
204 * While growing continents, it is @di sectors wide.
205 * While growing additional islands, it is @id sectors wide.
206 * DISTINCT_ISLANDS nullifies the exclusive zone then.
207 * xzone[XYOFFSET(x, y)] is -1 when the sector is in no exclusive
208 * zone, a (non-negative) island number when it is in that island's
209 * exclusive zone and no other, and -2 when it is in multiple
215 * Set of sectors seen already
216 * Increment @cur_seen to empty the set of sectors seen, set
217 * seen[XYOFFSET(x, y)] to @cur_seen to add x,y to the set.
219 static unsigned *seen;
220 static unsigned cur_seen;
222 static int **elev; /* elevation of the sectors */
223 static int **sectx, **secty; /* the sectors for each continent */
224 static int **sectc; /* which sectors are on the coast? */
225 static int *weight; /* used for placing mountains */
226 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
228 #define NUMTRIES 10 /* keep trying to grow this many times */
230 static const char *numletter =
231 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
233 static void help(char *);
234 static void usage(void);
235 static void parse_args(int argc, char *argv[]);
236 static void allocate_memory(void);
237 static void init(void);
238 static int drift(void);
239 static int grow_continents(void);
240 static void create_elevations(void);
241 static void write_sects(void);
242 static void output(void);
243 static int write_newcap_script(void);
244 static int stable(int);
245 static void elevate_land(void);
246 static void elevate_sea(void);
247 static void set_coastal_flags(void);
249 static void print_vars(void);
250 static void fl_move(int);
251 static void grow_islands(void);
253 /* Debugging aids: */
254 void print_own_map(void);
255 void print_xzone_map(void);
256 void print_elev_map(void);
258 /****************************************************************************
260 ****************************************************************************/
263 main(int argc, char *argv[])
266 char *config_file = NULL;
268 unsigned rnd_seed = 0;
271 program_name = argv[0];
273 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
276 config_file = optarg;
279 DISTINCT_ISLANDS = 0;
285 rnd_seed = strtoul(optarg, NULL, 10);
295 printf("%s\n\n%s", version, legal);
304 rnd_seed = pick_seed();
307 if (emp_config(config_file) < 0)
311 parse_args(argc - optind, argv + optind);
316 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
317 qprint("seed is %u\n", rnd_seed);
322 qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
323 qprint("placing capitals...\n");
325 qprint("unstable drift\n");
326 qprint("growing continents...\n");
327 done = grow_continents();
328 } while (!done && ++try < NUMTRIES);
330 fprintf(stderr, "%s: world not large enough to hold continents\n",
334 qprint("growing islands:");
336 qprint("\nelevating land...\n");
339 qprint("writing to sectors file...\n");
340 if (!write_newcap_script())
342 if (chdir(gamedir)) {
343 fprintf(stderr, "%s: can't chdir to %s (%s)\n",
344 program_name, gamedir, strerror(errno));
347 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
350 if (!ef_close(EF_SECTOR))
354 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
364 puts("Creating a planet with:\n");
365 printf("%d continents\n", nc);
366 printf("continent size: %d\n", sc);
367 printf("number of islands: %d\n", ni);
368 printf("average size of islands: %d\n", is);
369 printf("spike: %d%%\n", sp);
370 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
371 pm, (pm * sc) / 100);
372 printf("minimum distance between continents: %d\n", di);
373 printf("minimum distance from islands to continents: %d\n", id);
374 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
378 help(char *complaint)
381 fprintf(stderr, "%s: %s\n", program_name, complaint);
382 fprintf(stderr, "Try -h for help.\n");
388 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
389 " -e CONFIG-FILE configuration file\n"
391 " -i islands may merge\n"
393 " -R SEED seed for random number generator\n"
394 " -s SCRIPT name of script to create (default %s)\n"
395 " -h display this help and exit\n"
396 " -v display version information and exit\n"
397 " NC number of continents\n"
398 " SC continent size\n"
399 " NI number of islands (default NC)\n"
400 " IS average island size (default SC/2)\n"
401 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
402 " PM percentage of land that is mountain (default %d)\n"
403 " DI minimum distance between continents (default %d)\n"
404 " ID minimum distance from islands to continents (default %d)\n",
405 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
406 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
410 parse_args(int argc, char *argv[])
412 int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
415 help("missing arguments");
419 help("too many arguments");
424 fprintf(stderr, "%s: number of continents must be > 0\n",
431 fprintf(stderr, "%s: size of continents must be > 1\n",
442 fprintf(stderr, "%s: number of islands must be >= 0\n",
450 fprintf(stderr, "%s: size of islands must be > 0\n",
457 if (sp < 0 || sp > 100) {
459 "%s: spike percentage must be between 0 and 100\n",
466 if (pm < 0 || pm > 100) {
468 "%s: mountain percentage must be between 0 and 100\n",
476 fprintf(stderr, "%s: distance between continents must be >= 0\n",
481 fprintf(stderr, "%s: distance between continents too large\n",
490 "%s: distance from islands to continents must be >= 0\n",
496 "%s: distance from islands to continents too large\n",
502 /****************************************************************************
503 VARIABLE INITIALIZATION
504 ****************************************************************************/
507 allocate_memory(void)
511 capx = calloc(nc, sizeof(int));
512 capy = calloc(nc, sizeof(int));
513 own = calloc(WORLD_X, sizeof(int *));
514 adj_land = malloc(WORLD_SZ() * sizeof(*adj_land));
515 xzone = malloc(WORLD_SZ() * sizeof(*xzone));
516 seen = calloc(WORLD_SZ(), sizeof(*seen));
517 elev = calloc(WORLD_X, sizeof(int *));
518 for (i = 0; i < WORLD_X; ++i) {
519 own[i] = calloc(WORLD_Y, sizeof(int));
520 elev[i] = calloc(WORLD_Y, sizeof(int));
522 sectx = calloc(nc + ni, sizeof(int *));
523 secty = calloc(nc + ni, sizeof(int *));
524 sectc = calloc(nc + ni, sizeof(int *));
525 isecs = calloc(nc + ni, sizeof(int));
526 weight = calloc(MAX(sc, is * 2), sizeof(int));
527 dsea = calloc(MAX(sc, is * 2), sizeof(int));
528 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
529 for (i = 0; i < nc; ++i) {
530 sectx[i] = calloc(sc, sizeof(int));
531 secty[i] = calloc(sc, sizeof(int));
532 sectc[i] = calloc(sc, sizeof(int));
534 for (i = nc; i < nc + ni; ++i) {
535 sectx[i] = calloc(is * 2, sizeof(int));
536 secty[i] = calloc(is * 2, sizeof(int));
537 sectc[i] = calloc(is * 2, sizeof(int));
547 for (i = 0; i < WORLD_X; ++i) {
548 for (j = 0; j < WORLD_Y; ++j) {
552 memset(adj_land, 0, WORLD_SZ() * sizeof(*adj_land));
555 /****************************************************************************
556 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
557 ****************************************************************************/
560 * How isolated is capital @j at @newx,@newy?
561 * Return the distance to the closest other capital.
564 iso(int j, int newx, int newy)
569 for (i = 0; i < nc; ++i) {
572 md = mapdist(capx[i], capy[i], newx, newy);
582 * Return 1 for a stable drift, 0 for an unstable one.
589 for (i = 0; i < nc; i++) {
590 capy[i] = (2 * i) / WORLD_X;
591 capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
592 if (capy[i] >= WORLD_Y) {
594 "%s: world not big enough for all the continents\n",
600 for (turns = 0; turns < DRIFT_MAX; ++turns) {
603 for (i = 0; i < nc; ++i)
610 * Has the drift stabilized?
611 * @turns is the number of turns so far.
616 static int mc[STABLE_CYCLE];
617 int i, isod, d = 0, stab = 1;
620 for (i = 0; i < STABLE_CYCLE; i++)
624 if (turns <= DRIFT_BEFORE_CHECK)
627 for (i = 0; i < nc; ++i) {
628 isod = iso(i, capx[i], capy[i]);
633 for (i = 0; i < STABLE_CYCLE; ++i)
637 mc[turns % STABLE_CYCLE] = d;
641 /* This routine does the actual drifting
647 int i, n, newx, newy;
649 for (i = roll0(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
650 newx = new_x(capx[j] + dirx[i]);
651 newy = new_y(capy[j] + diry[i]);
652 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
660 /****************************************************************************
662 ****************************************************************************/
664 /* Look for a coastal sector of continent c
672 for (i = 0; i < isecs[c]; ++i) {
674 for (j = 0; j < 6; ++j)
675 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
680 struct hexagon_iter {
685 * Start iterating around @x0,@y0 at distance @d.
686 * Set *x,*y to coordinates of the first sector.
689 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
692 *x = new_x(x0 - 2 * n);
694 iter->dir = DIR_FIRST;
700 * Continue iteration started with hexagon_first().
701 * Set *x,*y to coordinates of the next sector.
702 * Return whether we're back at the first sector, i.e. iteration is
706 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
708 *x = new_x(*x + diroff[iter->dir][0]);
709 *y = new_y(*y + diroff[iter->dir][1]);
711 if (iter->i == iter->n) {
715 return iter->dir <= DIR_LAST;
719 * Is @x,@y in no exclusive zone other than perhaps @c's?
722 xzone_ok(int c, int x, int y)
724 int off = XYOFFSET(x, y);
726 return xzone[off] == c || xzone[off] == -1;
730 * Add sectors within distance @dist of @x,@y to @c's exclusive zone.
733 xzone_around_sector(int c, int x, int y, int dist)
736 struct hexagon_iter hexit;
738 assert(xzone_ok(c, x, y));
740 xzone[XYOFFSET(x, y)] = c;
741 for (d = 1; d <= dist; d++) {
742 hexagon_first(&hexit, x, y, d, &x1, &y1);
744 off = XYOFFSET(x1, y1);
745 if (xzone[off] == -1)
747 else if (xzone[off] != c)
749 } while (hexagon_next(&hexit, &x1, &y1));
754 * Add sectors within distance @dist to island @c's exclusive zone.
757 xzone_around_island(int c, int dist)
761 for (i = 0; i < isecs[c]; i++)
762 xzone_around_sector(c, sectx[c][i], secty[c][i], dist);
766 * Initialize exclusive zones around @n islands.
773 for (i = 0; i < WORLD_SZ(); i++)
776 for (c = 0; c < n; c++)
777 xzone_around_island(c, id);
781 * Can island @c grow at @x,@y?
784 can_grow_at(int c, int x, int y)
786 return own[x][y] == -1 && xzone_ok(c, x, y);
790 adj_land_update(int x, int y)
792 int dir, nx, ny, noff;
794 assert(own[x][y] != -1);
796 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
797 nx = new_x(x + diroff[dir][0]);
798 ny = new_y(y + diroff[dir][1]);
799 noff = XYOFFSET(nx, ny);
800 adj_land[noff] |= 1u << DIR_BACK(dir);
805 add_sector(int c, int x, int y)
807 assert(own[x][y] == -1);
808 xzone_around_sector(c, x, y, c < nc ? di : DISTINCT_ISLANDS ? id : 0);
809 sectx[c][isecs[c]] = x;
810 secty[c][isecs[c]] = y;
813 adj_land_update(x, y);
817 grow_weight(int c, int x, int y, int spike)
822 * #Land neighbors is #bits set in adj_land[].
823 * Count them Brian Kernighan's way.
826 for (b = adj_land[XYOFFSET(x, y)]; b; b &= b - 1)
828 assert(n > 0 && n < 7);
831 return (6 - n) * (6 - n);
837 grow_one_sector(int c)
839 int spike = roll0(100) < sp;
840 int wsum, newx, newy, i, x, y, off, dir, nx, ny, noff, w;
842 assert(cur_seen < UINT_MAX);
847 for (i = 0; i < isecs[c]; i++) {
850 off = XYOFFSET(x, y);
852 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
853 if (adj_land[off] & (1u << dir))
855 nx = new_x(x + diroff[dir][0]);
856 ny = new_y(y + diroff[dir][1]);
857 noff = XYOFFSET(nx, ny);
858 if (seen[noff] == cur_seen)
860 assert(seen[noff] < cur_seen);
861 seen[noff] = cur_seen;
862 if (!can_grow_at(c, nx, ny))
864 w = grow_weight(c, nx, ny, spike);
865 assert(wsum < INT_MAX - w);
867 if (roll0(wsum) < w) {
877 add_sector(c, newx, newy);
882 * Grow the continents.
883 * Return 1 on success, 0 on error.
886 grow_continents(void)
894 for (c = 0; c < nc; ++c) {
896 if (!can_grow_at(c, capx[c], capy[c])
897 || !can_grow_at(c, new_x(capx[c] + 2), capy[c])) {
901 add_sector(c, capx[c], capy[c]);
902 add_sector(c, new_x(capx[c] + 2), capy[c]);
906 qprint("No room for continents\n");
910 for (secs = 2; secs < sc && done; secs++) {
911 for (c = 0; c < nc; ++c) {
912 if (!grow_one_sector(c))
917 for (c = 0; c < nc; ++c)
921 qprint("Only managed to grow %d out of %d sectors.\n",
927 /****************************************************************************
929 ****************************************************************************/
932 * Place additional island @c's first sector.
933 * Return 1 on success, 0 on error.
938 int n, x, y, newx, newy;
942 for (y = 0; y < WORLD_Y; y++) {
943 for (x = y % 2; x < WORLD_X; x += 2) {
944 if (can_grow_at(c, x, y)) {
955 add_sector(c, newx, newy);
959 /* Grow all the islands
965 int stunted_islands = 0;
970 for (c = nc; c < nc + ni; ++c) {
971 if (!place_island(c)) {
972 qprint("\nNo room for island #%d", c - nc + 1);
976 isiz = roll(is) + roll0(is);
977 for (secs = 1; secs < isiz; secs++) {
978 if (!grow_one_sector(c)) {
985 qprint(" %d(%d)", c - nc + 1, secs);
990 qprint("\n%d stunted island%s",
991 stunted_islands, splur(stunted_islands));
994 /****************************************************************************
996 ****************************************************************************/
998 create_elevations(void)
1002 for (i = 0; i < WORLD_X; i++) {
1003 for (j = 0; j < WORLD_Y; j++)
1004 elev[i][j] = -INFINITE_ELEVATION;
1010 /* Generic function for finding the distance to the closest sea, land, or
1014 distance_to_what(int x, int y, int flag)
1017 struct hexagon_iter hexit;
1019 for (d = 1; d < 5; ++d) {
1020 hexagon_first(&hexit, x, y, d, &px, &py);
1023 case 0: /* distance to sea */
1024 if (own[px][py] == -1)
1027 case 1: /* distance to land */
1028 if (own[px][py] != -1)
1031 case 2: /* distance to mountain */
1032 if (elev[px][py] == INFINITE_ELEVATION)
1036 } while (hexagon_next(&hexit, &px, &py));
1041 #define ELEV elev[sectx[c][i]][secty[c][i]]
1042 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1043 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1045 /* Decide where the mountains go
1050 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
1053 for (c = 0; c < ctot; ++c) {
1056 nm = (pm * ns) / 100;
1058 /* Place the mountains */
1060 for (i = 0; i < ns; ++i) {
1061 dsea[i] = distance_to_sea();
1062 weight[i] = (total += (dsea[i] * dsea[i]));
1065 for (k = nm, mountain_search = 0;
1066 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1067 ++mountain_search) {
1069 for (i = 0; i < ns; ++i)
1070 if (r < weight[i] && ELEV == -INFINITE_ELEVATION &&
1072 ((!(capx[c] == sectx[c][i] &&
1073 capy[c] == secty[c][i])) &&
1074 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1075 capy[c] == secty[c][i]))))) {
1076 ELEV = INFINITE_ELEVATION;
1082 /* Elevate land that is not mountain and not capital */
1084 for (i = 0; i < ns; ++i)
1085 dmoun[i] = distance_to_mountain();
1086 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1087 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1088 100 * INFINITE_ELEVATION;
1089 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1092 for (i = 0; i < ns; ++i) {
1093 if (ELEV == -INFINITE_ELEVATION &&
1094 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1095 capy[c] == secty[c][i])) &&
1096 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1097 capy[c] == secty[c][i]))))) {
1098 h = 3 * (5 - dmoun[i]) + dsea[i];
1109 if (newk >= HILLMIN && newk < PLATMIN)
1113 elev[sectx[c][where]][secty[c][where]] = newk;
1116 /* Elevate the mountains and capitals */
1118 for (i = 0; i < ns; ++i) {
1119 if (ELEV == INFINITE_ELEVATION) {
1121 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1123 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1124 roll0((256 - HIGHMIN) / 2);
1125 } else if (c < nc &&
1126 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1127 ((new_x(capx[c] + 2) == sectx[c][i] &&
1128 capy[c] == secty[c][i]))))
1134 #define distance_to_land() distance_to_what(x, y, 1)
1141 for (y = 0; y < WORLD_Y; ++y) {
1142 for (x = y % 2; x < WORLD_X; x += 2) {
1143 if (elev[x][y] == -INFINITE_ELEVATION)
1144 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1150 elev_to_sct_type(int elevation)
1152 if (elevation < LANDMIN)
1154 if (elevation < HILLMIN)
1156 if (elevation < PLATMIN)
1158 if (elevation < HIGHMIN)
1163 /****************************************************************************
1165 ****************************************************************************/
1172 fert = LANDMIN - e + 40;
1173 else if (e < FERT_MAX)
1174 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1185 oil = (LANDMIN - e) * 2 + roll0(2);
1186 else if (e <= OIL_MAX)
1187 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1197 if (e >= IRON_MIN && e < HIGHMIN)
1198 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1208 if (e >= GOLD_MIN) {
1210 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1212 gold = 100 - 20 * HIGHMIN / e;
1223 if (e >= URAN_MIN && e < HIGHMIN)
1224 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1231 add_resources(struct sctstr *sct)
1233 sct->sct_fertil = set_fert(sct->sct_elev);
1234 sct->sct_oil = set_oil(sct->sct_elev);
1235 sct->sct_min = set_iron(sct->sct_elev);
1236 sct->sct_gmin = set_gold(sct->sct_elev);
1237 sct->sct_uran = set_uran(sct->sct_elev);
1240 /****************************************************************************
1241 DESIGNATE THE SECTORS
1242 ****************************************************************************/
1250 for (y = 0; y < WORLD_Y; y++) {
1251 for (x = y % 2; x < WORLD_X; x += 2) {
1252 sct = getsectp(x, y);
1253 sct->sct_elev = elev[x][y];
1254 sct->sct_type = elev_to_sct_type(elev[x][y]);
1255 sct->sct_newtype = sct->sct_type;
1256 sct->sct_dterr = own[sct->sct_x][y] + 1;
1260 set_coastal_flags();
1263 /****************************************************************************
1264 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1265 ****************************************************************************/
1269 int sx, sy, x, y, c, type;
1272 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1277 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1280 type = elev_to_sct_type(elev[x][y]);
1281 if (type == SCT_WATER)
1283 else if (type == SCT_MOUNT)
1288 assert(0 <= c && c < nc);
1289 if ((x == capx[c] || x == new_x(capx[c] + 2))
1291 printf("%c ", numletter[c % 62]);
1301 * Print a map to help visualize own[][].
1302 * This is for debugging.
1309 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1312 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1316 else if (own[x][y] == -1)
1319 putchar(numletter[own[x][y] % 62]);
1326 * Print a map to help visualize elev[][].
1327 * This is for debugging. It expects the terminal to understand
1328 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1331 print_elev_map(void)
1333 int sx, sy, x, y, sat;
1335 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1338 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1342 else if (!elev[x][y])
1344 else if (elev[x][y] < 0) {
1345 sat = 256 + elev[x][y] * 2;
1346 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1347 } else if (elev[x][y] < HIGHMIN / 2) {
1348 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1349 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1350 } else if (elev[x][y] < HIGHMIN) {
1351 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1352 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1354 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1355 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1363 * Print a map to help visualize xzone[].
1364 * This is for debugging.
1367 print_xzone_map(void)
1369 int sx, sy, x, y, off;
1371 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1374 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1376 off = XYOFFSET(x, y);
1379 else if (own[x][y] >= 0)
1381 else if (xzone[off] >= 0)
1382 putchar(numletter[xzone[off] % 62]);
1384 assert(own[x][y] == -1);
1385 putchar(xzone[off] == -1 ? '.' : '!');
1393 /***************************************************************************
1394 WRITE A SCRIPT FOR PLACING CAPITALS
1395 ****************************************************************************/
1397 write_newcap_script(void)
1400 FILE *script = fopen(outfile, "w");
1403 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1404 program_name, outfile, strerror(errno));
1408 for (c = 0; c < nc; ++c) {
1409 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1410 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1412 fprintf(script, "add %d visitor visitor v\n", c + 1);
1418 qprint(const char *const fmt, ...)
1424 vfprintf(stdout, fmt, ap);
1430 set_coastal_flags(void)
1435 for (i = 0; i < nc + ni; ++i) {
1436 for (j = 0; j < isecs[i]; j++) {
1437 sp = getsectp(sectx[i][j], secty[i][j]);
1438 sp->sct_coastal = sectc[i][j];