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 */
189 static int **own; /* owner of the sector. -1 means water */
192 * Adjacent land sectors
193 * adj_land[XYOFFSET(x, y)] bit d is set exactly when the sector next
194 * to x, y in direction d is land.
196 static unsigned char *adj_land;
200 * Each island is surrounded by an exclusive zone where only it may
201 * grow. The width of the zone depends on minimum distances.
202 * While growing continents, it is @di sectors wide.
203 * While growing additional islands, it is @id sectors wide.
204 * DISTINCT_ISLANDS nullifies the exclusive zone then.
205 * xzone[XYOFFSET(x, y)] is -1 when the sector is in no exclusive
206 * zone, a (non-negative) island number when it is in that island's
207 * exclusive zone and no other, and -2 when it is in multiple
213 * Set of sectors seen already
214 * Increment @cur_seen to empty the set of sectors seen, set
215 * seen[XYOFFSET(x, y)] to @cur_seen to add x,y to the set.
217 static unsigned *seen;
218 static unsigned cur_seen;
220 static int **elev; /* elevation of the sectors */
221 static int **sectx, **secty; /* the sectors for each continent */
222 static int **sectc; /* which sectors are on the coast? */
223 static int *weight; /* used for placing mountains */
224 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
226 #define NUMTRIES 10 /* keep trying to grow this many times */
228 static const char *numletter =
229 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
231 static void help(char *);
232 static void usage(void);
233 static void parse_args(int argc, char *argv[]);
234 static void allocate_memory(void);
235 static void init(void);
236 static int drift(void);
237 static int grow_continents(void);
238 static void create_elevations(void);
239 static void write_sects(void);
240 static void output(void);
241 static int write_newcap_script(void);
242 static int stable(int);
243 static void elevate_land(void);
244 static void elevate_sea(void);
245 static void set_coastal_flags(void);
247 static void print_vars(void);
248 static void fl_move(int);
249 static void grow_islands(void);
251 /* Debugging aids: */
252 void print_own_map(void);
253 void print_xzone_map(void);
254 void print_elev_map(void);
256 /****************************************************************************
258 ****************************************************************************/
261 main(int argc, char *argv[])
264 char *config_file = NULL;
266 unsigned rnd_seed = 0;
269 program_name = argv[0];
271 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
274 config_file = optarg;
277 DISTINCT_ISLANDS = 0;
283 rnd_seed = strtoul(optarg, NULL, 10);
293 printf("%s\n\n%s", version, legal);
302 rnd_seed = pick_seed();
305 if (emp_config(config_file) < 0)
309 parse_args(argc - optind, argv + optind);
314 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
315 qprint("seed is %u\n", rnd_seed);
320 qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
321 qprint("placing capitals...\n");
323 qprint("unstable drift\n");
324 qprint("growing continents...\n");
325 done = grow_continents();
326 } while (!done && ++try < NUMTRIES);
328 fprintf(stderr, "%s: world not large enough to hold continents\n",
332 qprint("growing islands:");
334 qprint("\nelevating land...\n");
337 qprint("writing to sectors file...\n");
338 if (!write_newcap_script())
340 if (chdir(gamedir)) {
341 fprintf(stderr, "%s: can't chdir to %s (%s)\n",
342 program_name, gamedir, strerror(errno));
345 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
348 if (!ef_close(EF_SECTOR))
352 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
362 puts("Creating a planet with:\n");
363 printf("%d continents\n", nc);
364 printf("continent size: %d\n", sc);
365 printf("number of islands: %d\n", ni);
366 printf("average size of islands: %d\n", is);
367 printf("spike: %d%%\n", sp);
368 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
369 pm, (pm * sc) / 100);
370 printf("minimum distance between continents: %d\n", di);
371 printf("minimum distance from islands to continents: %d\n", id);
372 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
376 help(char *complaint)
379 fprintf(stderr, "%s: %s\n", program_name, complaint);
380 fprintf(stderr, "Try -h for help.\n");
386 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
387 " -e CONFIG-FILE configuration file\n"
389 " -i islands may merge\n"
391 " -R SEED seed for random number generator\n"
392 " -s SCRIPT name of script to create (default %s)\n"
393 " -h display this help and exit\n"
394 " -v display version information and exit\n"
395 " NC number of continents\n"
396 " SC continent size\n"
397 " NI number of islands (default NC)\n"
398 " IS average island size (default SC/2)\n"
399 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
400 " PM percentage of land that is mountain (default %d)\n"
401 " DI minimum distance between continents (default %d)\n"
402 " ID minimum distance from islands to continents (default %d)\n",
403 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
404 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
408 parse_args(int argc, char *argv[])
410 int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
413 help("missing arguments");
417 help("too many arguments");
422 fprintf(stderr, "%s: number of continents must be > 0\n",
429 fprintf(stderr, "%s: size of continents must be > 1\n",
440 fprintf(stderr, "%s: number of islands must be >= 0\n",
448 fprintf(stderr, "%s: size of islands must be > 0\n",
455 if (sp < 0 || sp > 100) {
457 "%s: spike percentage must be between 0 and 100\n",
464 if (pm < 0 || pm > 100) {
466 "%s: mountain percentage must be between 0 and 100\n",
474 fprintf(stderr, "%s: distance between continents must be >= 0\n",
479 fprintf(stderr, "%s: distance between continents too large\n",
488 "%s: distance from islands to continents must be >= 0\n",
494 "%s: distance from islands to continents too large\n",
500 /****************************************************************************
501 VARIABLE INITIALIZATION
502 ****************************************************************************/
505 allocate_memory(void)
509 capx = calloc(nc, sizeof(int));
510 capy = calloc(nc, sizeof(int));
511 own = calloc(WORLD_X, sizeof(int *));
512 adj_land = malloc(WORLD_SZ() * sizeof(*adj_land));
513 xzone = malloc(WORLD_SZ() * sizeof(*xzone));
514 seen = calloc(WORLD_SZ(), sizeof(*seen));
515 elev = calloc(WORLD_X, sizeof(int *));
516 for (i = 0; i < WORLD_X; ++i) {
517 own[i] = calloc(WORLD_Y, sizeof(int));
518 elev[i] = calloc(WORLD_Y, sizeof(int));
520 sectx = calloc(nc + ni, sizeof(int *));
521 secty = calloc(nc + ni, sizeof(int *));
522 sectc = calloc(nc + ni, sizeof(int *));
523 isecs = calloc(nc + ni, sizeof(int));
524 weight = calloc(MAX(sc, is * 2), sizeof(int));
525 dsea = calloc(MAX(sc, is * 2), sizeof(int));
526 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
527 for (i = 0; i < nc; ++i) {
528 sectx[i] = calloc(sc, sizeof(int));
529 secty[i] = calloc(sc, sizeof(int));
530 sectc[i] = calloc(sc, sizeof(int));
532 for (i = nc; i < nc + ni; ++i) {
533 sectx[i] = calloc(is * 2, sizeof(int));
534 secty[i] = calloc(is * 2, sizeof(int));
535 sectc[i] = calloc(is * 2, sizeof(int));
545 for (i = 0; i < WORLD_X; ++i) {
546 for (j = 0; j < WORLD_Y; ++j) {
550 memset(adj_land, 0, WORLD_SZ() * sizeof(*adj_land));
553 /****************************************************************************
554 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
555 ****************************************************************************/
558 * How isolated is capital @j at @newx,@newy?
559 * Return the distance to the closest other capital.
562 iso(int j, int newx, int newy)
567 for (i = 0; i < nc; ++i) {
570 md = mapdist(capx[i], capy[i], newx, newy);
580 * Return 1 for a stable drift, 0 for an unstable one.
587 for (i = 0; i < nc; i++) {
588 capy[i] = (2 * i) / WORLD_X;
589 capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
590 if (capy[i] >= WORLD_Y) {
592 "%s: world not big enough for all the continents\n",
598 for (turns = 0; turns < DRIFT_MAX; ++turns) {
601 for (i = 0; i < nc; ++i)
608 * Has the drift stabilized?
609 * @turns is the number of turns so far.
614 static int mc[STABLE_CYCLE];
615 int i, isod, d = 0, stab = 1;
618 for (i = 0; i < STABLE_CYCLE; i++)
622 if (turns <= DRIFT_BEFORE_CHECK)
625 for (i = 0; i < nc; ++i) {
626 isod = iso(i, capx[i], capy[i]);
631 for (i = 0; i < STABLE_CYCLE; ++i)
635 mc[turns % STABLE_CYCLE] = d;
639 /* This routine does the actual drifting
645 int dir, i, newx, newy;
647 dir = DIR_L + roll0(6);
648 for (i = 0; i < 6; i++) {
651 newx = new_x(capx[j] + diroff[dir][0]);
652 newy = new_y(capy[j] + diroff[dir][1]);
654 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
662 /****************************************************************************
664 ****************************************************************************/
666 /* Look for a coastal sector of continent c
674 for (i = 0; i < isecs[c]; ++i) {
676 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
677 nx = new_x(sectx[c][i] + diroff[dir][0]);
678 ny = new_y(secty[c][i] + diroff[dir][1]);
679 if (own[nx][ny] == -1)
685 struct hexagon_iter {
690 * Start iterating around @x0,@y0 at distance @d.
691 * Set *x,*y to coordinates of the first sector.
694 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
697 *x = new_x(x0 - 2 * n);
699 iter->dir = DIR_FIRST;
705 * Continue iteration started with hexagon_first().
706 * Set *x,*y to coordinates of the next sector.
707 * Return whether we're back at the first sector, i.e. iteration is
711 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
713 *x = new_x(*x + diroff[iter->dir][0]);
714 *y = new_y(*y + diroff[iter->dir][1]);
716 if (iter->i == iter->n) {
720 return iter->dir <= DIR_LAST;
724 * Is @x,@y in no exclusive zone other than perhaps @c's?
727 xzone_ok(int c, int x, int y)
729 int off = XYOFFSET(x, y);
731 return xzone[off] == c || xzone[off] == -1;
735 * Add sectors within distance @dist of @x,@y to @c's exclusive zone.
738 xzone_around_sector(int c, int x, int y, int dist)
741 struct hexagon_iter hexit;
743 assert(xzone_ok(c, x, y));
745 xzone[XYOFFSET(x, y)] = c;
746 for (d = 1; d <= dist; d++) {
747 hexagon_first(&hexit, x, y, d, &x1, &y1);
749 off = XYOFFSET(x1, y1);
750 if (xzone[off] == -1)
752 else if (xzone[off] != c)
754 } while (hexagon_next(&hexit, &x1, &y1));
759 * Add sectors within distance @dist to island @c's exclusive zone.
762 xzone_around_island(int c, int dist)
766 for (i = 0; i < isecs[c]; i++)
767 xzone_around_sector(c, sectx[c][i], secty[c][i], dist);
771 * Initialize exclusive zones around @n islands.
778 for (i = 0; i < WORLD_SZ(); i++)
781 for (c = 0; c < n; c++)
782 xzone_around_island(c, id);
786 * Can island @c grow at @x,@y?
789 can_grow_at(int c, int x, int y)
791 return own[x][y] == -1 && xzone_ok(c, x, y);
795 adj_land_update(int x, int y)
797 int dir, nx, ny, noff;
799 assert(own[x][y] != -1);
801 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
802 nx = new_x(x + diroff[dir][0]);
803 ny = new_y(y + diroff[dir][1]);
804 noff = XYOFFSET(nx, ny);
805 adj_land[noff] |= 1u << DIR_BACK(dir);
810 add_sector(int c, int x, int y)
812 assert(own[x][y] == -1);
813 xzone_around_sector(c, x, y, c < nc ? di : DISTINCT_ISLANDS ? id : 0);
814 sectx[c][isecs[c]] = x;
815 secty[c][isecs[c]] = y;
818 adj_land_update(x, y);
822 grow_weight(int c, int x, int y, int spike)
827 * #Land neighbors is #bits set in adj_land[].
828 * Count them Brian Kernighan's way.
831 for (b = adj_land[XYOFFSET(x, y)]; b; b &= b - 1)
833 assert(n > 0 && n < 7);
836 return (6 - n) * (6 - n);
842 grow_one_sector(int c)
844 int spike = roll0(100) < sp;
845 int wsum, newx, newy, i, x, y, off, dir, nx, ny, noff, w;
847 assert(cur_seen < UINT_MAX);
852 for (i = 0; i < isecs[c]; i++) {
855 off = XYOFFSET(x, y);
857 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
858 if (adj_land[off] & (1u << dir))
860 nx = new_x(x + diroff[dir][0]);
861 ny = new_y(y + diroff[dir][1]);
862 noff = XYOFFSET(nx, ny);
863 if (seen[noff] == cur_seen)
865 assert(seen[noff] < cur_seen);
866 seen[noff] = cur_seen;
867 if (!can_grow_at(c, nx, ny))
869 w = grow_weight(c, nx, ny, spike);
870 assert(wsum < INT_MAX - w);
872 if (roll0(wsum) < w) {
882 add_sector(c, newx, newy);
887 * Grow the continents.
888 * Return 1 on success, 0 on error.
891 grow_continents(void)
899 for (c = 0; c < nc; ++c) {
901 if (!can_grow_at(c, capx[c], capy[c])
902 || !can_grow_at(c, new_x(capx[c] + 2), capy[c])) {
906 add_sector(c, capx[c], capy[c]);
907 add_sector(c, new_x(capx[c] + 2), capy[c]);
911 qprint("No room for continents\n");
915 for (secs = 2; secs < sc && done; secs++) {
916 for (c = 0; c < nc; ++c) {
917 if (!grow_one_sector(c))
922 for (c = 0; c < nc; ++c)
926 qprint("Only managed to grow %d out of %d sectors.\n",
932 /****************************************************************************
934 ****************************************************************************/
937 * Place additional island @c's first sector.
938 * Return 1 on success, 0 on error.
943 int n, x, y, newx, newy;
947 for (y = 0; y < WORLD_Y; y++) {
948 for (x = y % 2; x < WORLD_X; x += 2) {
949 if (can_grow_at(c, x, y)) {
960 add_sector(c, newx, newy);
964 /* Grow all the islands
970 int stunted_islands = 0;
975 for (c = nc; c < nc + ni; ++c) {
976 if (!place_island(c)) {
977 qprint("\nNo room for island #%d", c - nc + 1);
981 isiz = roll(is) + roll0(is);
982 for (secs = 1; secs < isiz; secs++) {
983 if (!grow_one_sector(c)) {
990 qprint(" %d(%d)", c - nc + 1, secs);
995 qprint("\n%d stunted island%s",
996 stunted_islands, splur(stunted_islands));
999 /****************************************************************************
1001 ****************************************************************************/
1003 create_elevations(void)
1007 for (i = 0; i < WORLD_X; i++) {
1008 for (j = 0; j < WORLD_Y; j++)
1009 elev[i][j] = -INFINITE_ELEVATION;
1015 /* Generic function for finding the distance to the closest sea, land, or
1019 distance_to_what(int x, int y, int flag)
1022 struct hexagon_iter hexit;
1024 for (d = 1; d < 5; ++d) {
1025 hexagon_first(&hexit, x, y, d, &px, &py);
1028 case 0: /* distance to sea */
1029 if (own[px][py] == -1)
1032 case 1: /* distance to land */
1033 if (own[px][py] != -1)
1036 case 2: /* distance to mountain */
1037 if (elev[px][py] == INFINITE_ELEVATION)
1041 } while (hexagon_next(&hexit, &px, &py));
1046 #define ELEV elev[sectx[c][i]][secty[c][i]]
1047 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1048 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1050 /* Decide where the mountains go
1055 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
1058 for (c = 0; c < ctot; ++c) {
1061 nm = (pm * ns) / 100;
1063 /* Place the mountains */
1065 for (i = 0; i < ns; ++i) {
1066 dsea[i] = distance_to_sea();
1067 weight[i] = (total += (dsea[i] * dsea[i]));
1070 for (k = nm, mountain_search = 0;
1071 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1072 ++mountain_search) {
1074 for (i = 0; i < ns; ++i)
1075 if (r < weight[i] && ELEV == -INFINITE_ELEVATION &&
1077 ((!(capx[c] == sectx[c][i] &&
1078 capy[c] == secty[c][i])) &&
1079 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1080 capy[c] == secty[c][i]))))) {
1081 ELEV = INFINITE_ELEVATION;
1087 /* Elevate land that is not mountain and not capital */
1089 for (i = 0; i < ns; ++i)
1090 dmoun[i] = distance_to_mountain();
1091 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1092 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1093 100 * INFINITE_ELEVATION;
1094 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1097 for (i = 0; i < ns; ++i) {
1098 if (ELEV == -INFINITE_ELEVATION &&
1099 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1100 capy[c] == secty[c][i])) &&
1101 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1102 capy[c] == secty[c][i]))))) {
1103 h = 3 * (5 - dmoun[i]) + dsea[i];
1114 if (newk >= HILLMIN && newk < PLATMIN)
1118 elev[sectx[c][where]][secty[c][where]] = newk;
1121 /* Elevate the mountains and capitals */
1123 for (i = 0; i < ns; ++i) {
1124 if (ELEV == INFINITE_ELEVATION) {
1126 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1128 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1129 roll0((256 - HIGHMIN) / 2);
1130 } else if (c < nc &&
1131 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1132 ((new_x(capx[c] + 2) == sectx[c][i] &&
1133 capy[c] == secty[c][i]))))
1139 #define distance_to_land() distance_to_what(x, y, 1)
1146 for (y = 0; y < WORLD_Y; ++y) {
1147 for (x = y % 2; x < WORLD_X; x += 2) {
1148 if (elev[x][y] == -INFINITE_ELEVATION)
1149 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1155 elev_to_sct_type(int elevation)
1157 if (elevation < LANDMIN)
1159 if (elevation < HILLMIN)
1161 if (elevation < PLATMIN)
1163 if (elevation < HIGHMIN)
1168 /****************************************************************************
1170 ****************************************************************************/
1177 fert = LANDMIN - e + 40;
1178 else if (e < FERT_MAX)
1179 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1190 oil = (LANDMIN - e) * 2 + roll0(2);
1191 else if (e <= OIL_MAX)
1192 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1202 if (e >= IRON_MIN && e < HIGHMIN)
1203 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1213 if (e >= GOLD_MIN) {
1215 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1217 gold = 100 - 20 * HIGHMIN / e;
1228 if (e >= URAN_MIN && e < HIGHMIN)
1229 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1236 add_resources(struct sctstr *sct)
1238 sct->sct_fertil = set_fert(sct->sct_elev);
1239 sct->sct_oil = set_oil(sct->sct_elev);
1240 sct->sct_min = set_iron(sct->sct_elev);
1241 sct->sct_gmin = set_gold(sct->sct_elev);
1242 sct->sct_uran = set_uran(sct->sct_elev);
1245 /****************************************************************************
1246 DESIGNATE THE SECTORS
1247 ****************************************************************************/
1255 for (y = 0; y < WORLD_Y; y++) {
1256 for (x = y % 2; x < WORLD_X; x += 2) {
1257 sct = getsectp(x, y);
1258 sct->sct_elev = elev[x][y];
1259 sct->sct_type = elev_to_sct_type(elev[x][y]);
1260 sct->sct_newtype = sct->sct_type;
1261 sct->sct_dterr = own[sct->sct_x][y] + 1;
1265 set_coastal_flags();
1268 /****************************************************************************
1269 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1270 ****************************************************************************/
1274 int sx, sy, x, y, c, type;
1277 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1282 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1285 type = elev_to_sct_type(elev[x][y]);
1286 if (type == SCT_WATER)
1288 else if (type == SCT_MOUNT)
1293 assert(0 <= c && c < nc);
1294 if ((x == capx[c] || x == new_x(capx[c] + 2))
1296 printf("%c ", numletter[c % 62]);
1306 * Print a map to help visualize own[][].
1307 * This is for debugging.
1314 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1317 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1321 else if (own[x][y] == -1)
1324 putchar(numletter[own[x][y] % 62]);
1331 * Print a map to help visualize elev[][].
1332 * This is for debugging. It expects the terminal to understand
1333 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1336 print_elev_map(void)
1338 int sx, sy, x, y, sat;
1340 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1343 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1347 else if (!elev[x][y])
1349 else if (elev[x][y] < 0) {
1350 sat = 256 + elev[x][y] * 2;
1351 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1352 } else if (elev[x][y] < HIGHMIN / 2) {
1353 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1354 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1355 } else if (elev[x][y] < HIGHMIN) {
1356 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1357 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1359 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1360 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1368 * Print a map to help visualize xzone[].
1369 * This is for debugging.
1372 print_xzone_map(void)
1374 int sx, sy, x, y, off;
1376 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1379 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1381 off = XYOFFSET(x, y);
1384 else if (own[x][y] >= 0)
1386 else if (xzone[off] >= 0)
1387 putchar(numletter[xzone[off] % 62]);
1389 assert(own[x][y] == -1);
1390 putchar(xzone[off] == -1 ? '.' : '!');
1398 /***************************************************************************
1399 WRITE A SCRIPT FOR PLACING CAPITALS
1400 ****************************************************************************/
1402 write_newcap_script(void)
1405 FILE *script = fopen(outfile, "w");
1408 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1409 program_name, outfile, strerror(errno));
1413 for (c = 0; c < nc; ++c) {
1414 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1415 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1417 fprintf(script, "add %d visitor visitor v\n", c + 1);
1423 qprint(const char *const fmt, ...)
1429 vfprintf(stdout, fmt, ap);
1435 set_coastal_flags(void)
1440 for (i = 0; i < nc + ni; ++i) {
1441 for (j = 0; j < isecs[i]; j++) {
1442 sp = getsectp(sectx[i][j], secty[i][j]);
1443 sp->sct_coastal = sectc[i][j];