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);
821 static int grow_weight(int c, int x, int y, int spike)
826 * #Land neighbors is #bits set in adj_land[].
827 * Count them Brian Kernighan's way.
830 for (b = adj_land[XYOFFSET(x, y)]; b; b &= b - 1)
832 assert(n > 0 && n < 7);
835 return (6 - n) * (6 - n);
841 grow_one_sector(int c)
843 int spike = roll0(100) < sp;
844 int wsum, newx, newy, i, x, y, off, dir, nx, ny, noff, w;
846 assert(cur_seen < UINT_MAX);
851 for (i = 0; i < isecs[c]; i++) {
854 off = XYOFFSET(x, y);
856 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
857 if (adj_land[off] & (1u << dir))
859 nx = new_x(x + diroff[dir][0]);
860 ny = new_y(y + diroff[dir][1]);
861 noff = XYOFFSET(nx, ny);
862 if (seen[noff] == cur_seen)
864 assert(seen[noff] < cur_seen);
865 seen[noff] = cur_seen;
866 if (!can_grow_at(c, nx, ny))
868 w = grow_weight(c, nx, ny, spike);
869 assert(wsum < INT_MAX - w);
871 if (roll0(wsum) < w) {
881 add_sector(c, newx, newy);
886 * Grow the continents.
887 * Return 1 on success, 0 on error.
890 grow_continents(void)
898 for (c = 0; c < nc; ++c) {
900 if (!can_grow_at(c, capx[c], capy[c])
901 || !can_grow_at(c, new_x(capx[c] + 2), capy[c])) {
905 add_sector(c, capx[c], capy[c]);
906 add_sector(c, new_x(capx[c] + 2), capy[c]);
910 qprint("No room for continents\n");
914 for (secs = 2; secs < sc && done; secs++) {
915 for (c = 0; c < nc; ++c) {
916 if (!grow_one_sector(c))
921 for (c = 0; c < nc; ++c)
925 qprint("Only managed to grow %d out of %d sectors.\n",
931 /****************************************************************************
933 ****************************************************************************/
936 * Place additional island @c's first sector.
937 * Return 1 on success, 0 on error.
942 int n, x, y, newx, newy;
946 for (y = 0; y < WORLD_Y; y++) {
947 for (x = y % 2; x < WORLD_X; x += 2) {
948 if (can_grow_at(c, x, y)) {
959 add_sector(c, newx, newy);
963 /* Grow all the islands
969 int stunted_islands = 0;
974 for (c = nc; c < nc + ni; ++c) {
975 if (!place_island(c)) {
976 qprint("\nNo room for island #%d", c - nc + 1);
980 isiz = roll(is) + roll0(is);
981 for (secs = 1; secs < isiz; secs++) {
982 if (!grow_one_sector(c)) {
989 qprint(" %d(%d)", c - nc + 1, secs);
994 qprint("\n%d stunted island%s",
995 stunted_islands, splur(stunted_islands));
998 /****************************************************************************
1000 ****************************************************************************/
1002 create_elevations(void)
1006 for (i = 0; i < WORLD_X; i++) {
1007 for (j = 0; j < WORLD_Y; j++)
1008 elev[i][j] = -INFINITE_ELEVATION;
1014 /* Generic function for finding the distance to the closest sea, land, or
1018 distance_to_what(int x, int y, int flag)
1021 struct hexagon_iter hexit;
1023 for (d = 1; d < 5; ++d) {
1024 hexagon_first(&hexit, x, y, d, &px, &py);
1027 case 0: /* distance to sea */
1028 if (own[px][py] == -1)
1031 case 1: /* distance to land */
1032 if (own[px][py] != -1)
1035 case 2: /* distance to mountain */
1036 if (elev[px][py] == INFINITE_ELEVATION)
1040 } while (hexagon_next(&hexit, &px, &py));
1045 #define ELEV elev[sectx[c][i]][secty[c][i]]
1046 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1047 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1049 /* Decide where the mountains go
1054 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
1057 for (c = 0; c < ctot; ++c) {
1060 nm = (pm * ns) / 100;
1062 /* Place the mountains */
1064 for (i = 0; i < ns; ++i) {
1065 dsea[i] = distance_to_sea();
1066 weight[i] = (total += (dsea[i] * dsea[i]));
1069 for (k = nm, mountain_search = 0;
1070 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1071 ++mountain_search) {
1073 for (i = 0; i < ns; ++i)
1074 if (r < weight[i] && ELEV == -INFINITE_ELEVATION &&
1076 ((!(capx[c] == sectx[c][i] &&
1077 capy[c] == secty[c][i])) &&
1078 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1079 capy[c] == secty[c][i]))))) {
1080 ELEV = INFINITE_ELEVATION;
1086 /* Elevate land that is not mountain and not capital */
1088 for (i = 0; i < ns; ++i)
1089 dmoun[i] = distance_to_mountain();
1090 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1091 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1092 100 * INFINITE_ELEVATION;
1093 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1096 for (i = 0; i < ns; ++i) {
1097 if (ELEV == -INFINITE_ELEVATION &&
1098 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1099 capy[c] == secty[c][i])) &&
1100 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1101 capy[c] == secty[c][i]))))) {
1102 h = 3 * (5 - dmoun[i]) + dsea[i];
1113 if (newk >= HILLMIN && newk < PLATMIN)
1117 elev[sectx[c][where]][secty[c][where]] = newk;
1120 /* Elevate the mountains and capitals */
1122 for (i = 0; i < ns; ++i) {
1123 if (ELEV == INFINITE_ELEVATION) {
1125 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1127 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1128 roll0((256 - HIGHMIN) / 2);
1129 } else if (c < nc &&
1130 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1131 ((new_x(capx[c] + 2) == sectx[c][i] &&
1132 capy[c] == secty[c][i]))))
1138 #define distance_to_land() distance_to_what(x, y, 1)
1145 for (y = 0; y < WORLD_Y; ++y) {
1146 for (x = y % 2; x < WORLD_X; x += 2) {
1147 if (elev[x][y] == -INFINITE_ELEVATION)
1148 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1154 elev_to_sct_type(int elevation)
1156 if (elevation < LANDMIN)
1158 if (elevation < HILLMIN)
1160 if (elevation < PLATMIN)
1162 if (elevation < HIGHMIN)
1167 /****************************************************************************
1169 ****************************************************************************/
1176 fert = LANDMIN - e + 40;
1177 else if (e < FERT_MAX)
1178 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1189 oil = (LANDMIN - e) * 2 + roll0(2);
1190 else if (e <= OIL_MAX)
1191 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1201 if (e >= IRON_MIN && e < HIGHMIN)
1202 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1212 if (e >= GOLD_MIN) {
1214 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1216 gold = 100 - 20 * HIGHMIN / e;
1227 if (e >= URAN_MIN && e < HIGHMIN)
1228 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1235 add_resources(struct sctstr *sct)
1237 sct->sct_fertil = set_fert(sct->sct_elev);
1238 sct->sct_oil = set_oil(sct->sct_elev);
1239 sct->sct_min = set_iron(sct->sct_elev);
1240 sct->sct_gmin = set_gold(sct->sct_elev);
1241 sct->sct_uran = set_uran(sct->sct_elev);
1244 /****************************************************************************
1245 DESIGNATE THE SECTORS
1246 ****************************************************************************/
1254 for (y = 0; y < WORLD_Y; y++) {
1255 for (x = y % 2; x < WORLD_X; x += 2) {
1256 sct = getsectp(x, y);
1257 sct->sct_elev = elev[x][y];
1258 sct->sct_type = elev_to_sct_type(elev[x][y]);
1259 sct->sct_newtype = sct->sct_type;
1260 sct->sct_dterr = own[sct->sct_x][y] + 1;
1264 set_coastal_flags();
1267 /****************************************************************************
1268 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1269 ****************************************************************************/
1273 int sx, sy, x, y, c, type;
1276 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1281 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1284 type = elev_to_sct_type(elev[x][y]);
1285 if (type == SCT_WATER)
1287 else if (type == SCT_MOUNT)
1292 assert(0 <= c && c < nc);
1293 if ((x == capx[c] || x == new_x(capx[c] + 2))
1295 printf("%c ", numletter[c % 62]);
1305 * Print a map to help visualize own[][].
1306 * This is for debugging.
1313 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1316 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1320 else if (own[x][y] == -1)
1323 putchar(numletter[own[x][y] % 62]);
1330 * Print a map to help visualize elev[][].
1331 * This is for debugging. It expects the terminal to understand
1332 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1335 print_elev_map(void)
1337 int sx, sy, x, y, sat;
1339 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1342 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1346 else if (!elev[x][y])
1348 else if (elev[x][y] < 0) {
1349 sat = 256 + elev[x][y] * 2;
1350 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1351 } else if (elev[x][y] < HIGHMIN / 2) {
1352 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1353 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1354 } else if (elev[x][y] < HIGHMIN) {
1355 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1356 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1358 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1359 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1367 * Print a map to help visualize xzone[].
1368 * This is for debugging.
1371 print_xzone_map(void)
1373 int sx, sy, x, y, off;
1375 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1378 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1380 off = XYOFFSET(x, y);
1383 else if (own[x][y] >= 0)
1385 else if (xzone[off] >= 0)
1386 putchar(numletter[xzone[off] % 62]);
1388 assert(own[x][y] == -1);
1389 putchar(xzone[off] == -1 ? '.' : '!');
1397 /***************************************************************************
1398 WRITE A SCRIPT FOR PLACING CAPITALS
1399 ****************************************************************************/
1401 write_newcap_script(void)
1404 FILE *script = fopen(outfile, "w");
1407 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1408 program_name, outfile, strerror(errno));
1412 for (c = 0; c < nc; ++c) {
1413 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1414 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1416 fprintf(script, "add %d visitor visitor v\n", c + 1);
1422 qprint(const char *const fmt, ...)
1428 vfprintf(stdout, fmt, ap);
1434 set_coastal_flags(void)
1439 for (i = 0; i < nc + ni; ++i) {
1440 for (j = 0; j < isecs[i]; j++) {
1441 sp = getsectp(sectx[i][j], secty[i][j]);
1442 sp->sct_coastal = sectc[i][j];