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);
816 static int grow_weight(int c, int x, int y, int spike)
821 * #Land neighbors is #bits set in adj_land[].
822 * Count them Brian Kernighan's way.
825 for (b = adj_land[XYOFFSET(x, y)]; b; b &= b - 1)
827 assert(n > 0 && n < 7);
830 return (6 - n) * (6 - n);
836 grow_one_sector(int c)
838 int spike = roll0(100) < sp;
839 int wsum, newx, newy, i, x, y, off, dir, nx, ny, noff, w;
841 assert(cur_seen < UINT_MAX);
846 for (i = 0; i < isecs[c]; i++) {
849 off = XYOFFSET(x, y);
851 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
852 if (adj_land[off] & (1u << dir))
854 nx = new_x(x + diroff[dir][0]);
855 ny = new_y(y + diroff[dir][1]);
856 noff = XYOFFSET(nx, ny);
857 if (seen[noff] == cur_seen)
859 assert(seen[noff] < cur_seen);
860 seen[noff] = cur_seen;
861 if (!can_grow_at(c, nx, ny))
863 w = grow_weight(c, nx, ny, spike);
864 assert(wsum < INT_MAX - w);
866 if (roll0(wsum) < w) {
876 add_sector(c, newx, newy);
881 * Grow the continents.
882 * Return 1 on success, 0 on error.
885 grow_continents(void)
893 for (c = 0; c < nc; ++c) {
895 if (!can_grow_at(c, capx[c], capy[c])
896 || !can_grow_at(c, new_x(capx[c] + 2), capy[c])) {
900 add_sector(c, capx[c], capy[c]);
901 add_sector(c, new_x(capx[c] + 2), capy[c]);
905 qprint("No room for continents\n");
909 for (secs = 2; secs < sc && done; secs++) {
910 for (c = 0; c < nc; ++c) {
911 if (!grow_one_sector(c))
916 for (c = 0; c < nc; ++c)
920 qprint("Only managed to grow %d out of %d sectors.\n",
926 /****************************************************************************
928 ****************************************************************************/
931 * Place additional island @c's first sector.
932 * Return 1 on success, 0 on error.
937 int n, x, y, newx, newy;
941 for (y = 0; y < WORLD_Y; y++) {
942 for (x = y % 2; x < WORLD_X; x += 2) {
943 if (can_grow_at(c, x, y)) {
954 add_sector(c, newx, newy);
958 /* Grow all the islands
964 int stunted_islands = 0;
969 for (c = nc; c < nc + ni; ++c) {
970 if (!place_island(c)) {
971 qprint("\nNo room for island #%d", c - nc + 1);
975 isiz = roll(is) + roll0(is);
976 for (secs = 1; secs < isiz; secs++) {
977 if (!grow_one_sector(c)) {
984 qprint(" %d(%d)", c - nc + 1, secs);
989 qprint("\n%d stunted island%s",
990 stunted_islands, splur(stunted_islands));
993 /****************************************************************************
995 ****************************************************************************/
997 create_elevations(void)
1001 for (i = 0; i < WORLD_X; i++) {
1002 for (j = 0; j < WORLD_Y; j++)
1003 elev[i][j] = -INFINITE_ELEVATION;
1009 /* Generic function for finding the distance to the closest sea, land, or
1013 distance_to_what(int x, int y, int flag)
1016 struct hexagon_iter hexit;
1018 for (d = 1; d < 5; ++d) {
1019 hexagon_first(&hexit, x, y, d, &px, &py);
1022 case 0: /* distance to sea */
1023 if (own[px][py] == -1)
1026 case 1: /* distance to land */
1027 if (own[px][py] != -1)
1030 case 2: /* distance to mountain */
1031 if (elev[px][py] == INFINITE_ELEVATION)
1035 } while (hexagon_next(&hexit, &px, &py));
1040 #define ELEV elev[sectx[c][i]][secty[c][i]]
1041 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1042 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1044 /* Decide where the mountains go
1049 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
1052 for (c = 0; c < ctot; ++c) {
1055 nm = (pm * ns) / 100;
1057 /* Place the mountains */
1059 for (i = 0; i < ns; ++i) {
1060 dsea[i] = distance_to_sea();
1061 weight[i] = (total += (dsea[i] * dsea[i]));
1064 for (k = nm, mountain_search = 0;
1065 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1066 ++mountain_search) {
1068 for (i = 0; i < ns; ++i)
1069 if (r < weight[i] && ELEV == -INFINITE_ELEVATION &&
1071 ((!(capx[c] == sectx[c][i] &&
1072 capy[c] == secty[c][i])) &&
1073 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1074 capy[c] == secty[c][i]))))) {
1075 ELEV = INFINITE_ELEVATION;
1081 /* Elevate land that is not mountain and not capital */
1083 for (i = 0; i < ns; ++i)
1084 dmoun[i] = distance_to_mountain();
1085 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1086 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1087 100 * INFINITE_ELEVATION;
1088 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1091 for (i = 0; i < ns; ++i) {
1092 if (ELEV == -INFINITE_ELEVATION &&
1093 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1094 capy[c] == secty[c][i])) &&
1095 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1096 capy[c] == secty[c][i]))))) {
1097 h = 3 * (5 - dmoun[i]) + dsea[i];
1108 if (newk >= HILLMIN && newk < PLATMIN)
1112 elev[sectx[c][where]][secty[c][where]] = newk;
1115 /* Elevate the mountains and capitals */
1117 for (i = 0; i < ns; ++i) {
1118 if (ELEV == INFINITE_ELEVATION) {
1120 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1122 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1123 roll0((256 - HIGHMIN) / 2);
1124 } else if (c < nc &&
1125 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1126 ((new_x(capx[c] + 2) == sectx[c][i] &&
1127 capy[c] == secty[c][i]))))
1133 #define distance_to_land() distance_to_what(x, y, 1)
1140 for (y = 0; y < WORLD_Y; ++y) {
1141 for (x = y % 2; x < WORLD_X; x += 2) {
1142 if (elev[x][y] == -INFINITE_ELEVATION)
1143 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1149 elev_to_sct_type(int elevation)
1151 if (elevation < LANDMIN)
1153 if (elevation < HILLMIN)
1155 if (elevation < PLATMIN)
1157 if (elevation < HIGHMIN)
1162 /****************************************************************************
1164 ****************************************************************************/
1171 fert = LANDMIN - e + 40;
1172 else if (e < FERT_MAX)
1173 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1184 oil = (LANDMIN - e) * 2 + roll0(2);
1185 else if (e <= OIL_MAX)
1186 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1196 if (e >= IRON_MIN && e < HIGHMIN)
1197 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1207 if (e >= GOLD_MIN) {
1209 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1211 gold = 100 - 20 * HIGHMIN / e;
1222 if (e >= URAN_MIN && e < HIGHMIN)
1223 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1230 add_resources(struct sctstr *sct)
1232 sct->sct_fertil = set_fert(sct->sct_elev);
1233 sct->sct_oil = set_oil(sct->sct_elev);
1234 sct->sct_min = set_iron(sct->sct_elev);
1235 sct->sct_gmin = set_gold(sct->sct_elev);
1236 sct->sct_uran = set_uran(sct->sct_elev);
1239 /****************************************************************************
1240 DESIGNATE THE SECTORS
1241 ****************************************************************************/
1249 for (y = 0; y < WORLD_Y; y++) {
1250 for (x = y % 2; x < WORLD_X; x += 2) {
1251 sct = getsectp(x, y);
1252 sct->sct_elev = elev[x][y];
1253 sct->sct_type = elev_to_sct_type(elev[x][y]);
1254 sct->sct_newtype = sct->sct_type;
1255 sct->sct_dterr = own[sct->sct_x][y] + 1;
1259 set_coastal_flags();
1262 /****************************************************************************
1263 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1264 ****************************************************************************/
1268 int sx, sy, x, y, c, type;
1271 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1276 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1279 type = elev_to_sct_type(elev[x][y]);
1280 if (type == SCT_WATER)
1282 else if (type == SCT_MOUNT)
1287 assert(0 <= c && c < nc);
1288 if ((x == capx[c] || x == new_x(capx[c] + 2))
1290 printf("%c ", numletter[c % 62]);
1300 * Print a map to help visualize own[][].
1301 * This is for debugging.
1308 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1311 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1315 else if (own[x][y] == -1)
1318 putchar(numletter[own[x][y] % 62]);
1325 * Print a map to help visualize elev[][].
1326 * This is for debugging. It expects the terminal to understand
1327 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1330 print_elev_map(void)
1332 int sx, sy, x, y, sat;
1334 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1337 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1341 else if (!elev[x][y])
1343 else if (elev[x][y] < 0) {
1344 sat = 256 + elev[x][y] * 2;
1345 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1346 } else if (elev[x][y] < HIGHMIN / 2) {
1347 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1348 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1349 } else if (elev[x][y] < HIGHMIN) {
1350 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1351 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1353 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1354 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1362 * Print a map to help visualize xzone[].
1363 * This is for debugging.
1366 print_xzone_map(void)
1368 int sx, sy, x, y, off;
1370 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1373 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1375 off = XYOFFSET(x, y);
1378 else if (own[x][y] >= 0)
1380 else if (xzone[off] >= 0)
1381 putchar(numletter[xzone[off] % 62]);
1383 assert(own[x][y] == -1);
1384 putchar(xzone[off] == -1 ? '.' : '!');
1392 /***************************************************************************
1393 WRITE A SCRIPT FOR PLACING CAPITALS
1394 ****************************************************************************/
1396 write_newcap_script(void)
1399 FILE *script = fopen(outfile, "w");
1402 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1403 program_name, outfile, strerror(errno));
1407 for (c = 0; c < nc; ++c) {
1408 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1409 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1411 fprintf(script, "add %d visitor visitor v\n", c + 1);
1417 qprint(const char *const fmt, ...)
1423 vfprintf(stdout, fmt, ap);
1429 set_coastal_flags(void)
1434 for (i = 0; i < nc + ni; ++i) {
1435 for (j = 0; j < isecs[i]; j++) {
1436 sp = getsectp(sectx[i][j], secty[i][j]);
1437 sp->sct_coastal = sectc[i][j];