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, obeying the minimum
49 * distance between continents, until they have the specified size.
51 * The kind of shape they grow into is determined by the "spike
52 * percentage" --- the higher the spike, the more spindly they will
53 * be. If you lower the spike, the continents will be more round.
55 * If growing fails due to lack of room, start over. If it fails too
56 * many times, give up and terminate unsuccessfully.
58 * 3. Place and grow additional islands
60 * Place and grow islands one after the other. Place the first sector
61 * randomly, pick an island size, then grow the island to that size.
63 * Growing works as for continents, except the minimum distance for
64 * additional islands applies, and growing simply stops when there is
67 * 4. Compute elevation
69 * Elevate islands one after the other.
71 * First, place the specified number of mountains randomly.
72 * Probability increases with distance to sea.
74 * Last, elevate mountains and the capitals. Pick coastal mountain
75 * elevation randomly from an interval of medium elevations reserved
76 * for them. Pick non-coastal mountain elevation randomly from an
77 * interval of high elevation reserved for them. Set capital
78 * elevation to a fixed, medium value.
80 * In between, elevate the remaining land one by one, working from
81 * mountains towards the sea, and from the elevation just below the
82 * non-coastal mountains' interval linearly down to 1, avoiding the
83 * coastal mountains' interval.
85 * This gives islands of the same size the same set of elevations,
86 * except for mountains.
88 * Elevate sea: pick a random depth from an interval that deepens with
89 * the distance to land.
93 * Sector resources are simple functions of elevation. You can alter
94 * macros OIL_MAX, IRON_MIN, GOLD_MIN, FERT_MAX, and URAN_MIN to
109 #include "prototypes.h"
114 /* The following five numbers refer to elevation under which (in the case of
115 fertility or oil) or over which (in the case of iron, gold, and uranium)
116 sectors with that elevation will contain that resource. Elevation ranges
119 /* raise FERT_MAX for more fertility */
122 /* raise OIL_MAX for more oil */
125 /* lower IRON_MIN for more iron */
128 /* lower GOLD_MIN for more gold */
131 /* lower URAN_MIN for more uranium */
134 /* do not change these 4 defines */
135 #define LANDMIN 1 /* plate altitude for normal land */
136 #define HILLMIN 34 /* plate altitude for hills */
137 #define PLATMIN 36 /* plate altitude for plateau */
138 #define HIGHMIN 98 /* plate altitude for mountains */
140 static void qprint(const char * const fmt, ...)
141 ATTRIBUTE((format (printf, 1, 2)));
144 * Program arguments and options
146 static char *program_name;
147 static int nc, sc; /* number and size of continents */
148 static int ni, is; /* number and size of islands */
149 #define DEFAULT_SPIKE 10
150 static int sp = DEFAULT_SPIKE; /* spike percentage */
151 #define DEFAULT_MOUNTAIN 0
152 static int pm = DEFAULT_MOUNTAIN; /* mountain percentage */
153 #define DEFAULT_CONTDIST 2
154 static int di = DEFAULT_CONTDIST; /* min. distance between continents */
155 #define DEFAULT_ISLDIST 1
156 static int id = DEFAULT_ISLDIST; /* ... continents and islands */
157 /* don't let the islands crash into each other.
158 1 = don't merge, 0 = merge. */
159 static int DISTINCT_ISLANDS = 1;
161 #define DEFAULT_OUTFILE_NAME "newcap_script"
162 static const char *outfile = DEFAULT_OUTFILE_NAME;
164 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
165 #define INFINITE_ELEVATION 999
167 /* these defines prevent infinite loops:
170 #define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector
171 when growing continents and islands */
172 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
173 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
174 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
179 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
180 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
182 static int ctot; /* total number of continents and islands grown */
183 static int *isecs; /* array of how large each island is */
185 static int *capx, *capy; /* location of the nc capitals */
186 static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
187 static int diry[] = { 0, -1, -1, 0, 1, 1 };
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
212 static int **elev; /* elevation of the sectors */
213 static int **sectx, **secty; /* the sectors for each continent */
214 static int **sectc; /* which sectors are on the coast? */
215 static int *weight; /* used for placing mountains */
216 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
218 #define NUMTRIES 10 /* keep trying to grow this many times */
220 static const char *numletter =
221 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
223 static void help(char *);
224 static void usage(void);
225 static void parse_args(int argc, char *argv[]);
226 static void allocate_memory(void);
227 static void init(void);
228 static int drift(void);
229 static int grow_continents(void);
230 static void create_elevations(void);
231 static void write_sects(void);
232 static void output(void);
233 static int write_newcap_script(void);
234 static int stable(int);
235 static void elevate_land(void);
236 static void elevate_sea(void);
237 static void set_coastal_flags(void);
239 static void print_vars(void);
240 static void fl_move(int);
241 static void grow_islands(void);
243 /* Debugging aids: */
244 void print_own_map(void);
245 void print_xzone_map(void);
246 void print_elev_map(void);
248 /****************************************************************************
250 ****************************************************************************/
253 main(int argc, char *argv[])
256 char *config_file = NULL;
258 unsigned rnd_seed = 0;
261 program_name = argv[0];
263 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
266 config_file = optarg;
269 DISTINCT_ISLANDS = 0;
275 rnd_seed = strtoul(optarg, NULL, 10);
285 printf("%s\n\n%s", version, legal);
294 rnd_seed = pick_seed();
297 if (emp_config(config_file) < 0)
301 parse_args(argc - optind, argv + optind);
306 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
307 qprint("seed is %u\n", rnd_seed);
312 qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
313 qprint("placing capitals...\n");
315 qprint("unstable drift\n");
316 qprint("growing continents...\n");
317 done = grow_continents();
318 } while (!done && ++try < NUMTRIES);
320 fprintf(stderr, "%s: world not large enough to hold continents\n",
324 qprint("growing islands:");
326 qprint("\nelevating land...\n");
329 qprint("writing to sectors file...\n");
330 if (!write_newcap_script())
332 if (chdir(gamedir)) {
333 fprintf(stderr, "%s: can't chdir to %s (%s)\n",
334 program_name, gamedir, strerror(errno));
337 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
340 if (!ef_close(EF_SECTOR))
344 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
354 puts("Creating a planet with:\n");
355 printf("%d continents\n", nc);
356 printf("continent size: %d\n", sc);
357 printf("number of islands: %d\n", ni);
358 printf("average size of islands: %d\n", is);
359 printf("spike: %d%%\n", sp);
360 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
361 pm, (pm * sc) / 100);
362 printf("minimum distance between continents: %d\n", di);
363 printf("minimum distance from islands to continents: %d\n", id);
364 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
368 help(char *complaint)
371 fprintf(stderr, "%s: %s\n", program_name, complaint);
372 fprintf(stderr, "Try -h for help.\n");
378 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
379 " -e CONFIG-FILE configuration file\n"
381 " -i islands may merge\n"
383 " -R SEED seed for random number generator\n"
384 " -s SCRIPT name of script to create (default %s)\n"
385 " -h display this help and exit\n"
386 " -v display version information and exit\n"
387 " NC number of continents\n"
388 " SC continent size\n"
389 " NI number of islands (default NC)\n"
390 " IS average island size (default SC/2)\n"
391 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
392 " PM percentage of land that is mountain (default %d)\n"
393 " DI minimum distance between continents (default %d)\n"
394 " ID minimum distance from islands to continents (default %d)\n",
395 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
396 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
400 parse_args(int argc, char *argv[])
402 int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
405 help("missing arguments");
409 help("too many arguments");
414 fprintf(stderr, "%s: number of continents must be > 0\n",
421 fprintf(stderr, "%s: size of continents must be > 1\n",
432 fprintf(stderr, "%s: number of islands must be >= 0\n",
440 fprintf(stderr, "%s: size of islands must be > 0\n",
447 if (sp < 0 || sp > 100) {
449 "%s: spike percentage must be between 0 and 100\n",
456 if (pm < 0 || pm > 100) {
458 "%s: mountain percentage must be between 0 and 100\n",
466 fprintf(stderr, "%s: distance between continents must be >= 0\n",
471 fprintf(stderr, "%s: distance between continents too large\n",
480 "%s: distance from islands to continents must be >= 0\n",
486 "%s: distance from islands to continents too large\n",
492 /****************************************************************************
493 VARIABLE INITIALIZATION
494 ****************************************************************************/
497 allocate_memory(void)
501 capx = calloc(nc, sizeof(int));
502 capy = calloc(nc, sizeof(int));
503 own = calloc(WORLD_X, sizeof(int *));
504 adj_land = malloc(WORLD_SZ() * sizeof(*adj_land));
505 xzone = malloc(WORLD_SZ() * sizeof(*xzone));
506 elev = calloc(WORLD_X, sizeof(int *));
507 for (i = 0; i < WORLD_X; ++i) {
508 own[i] = calloc(WORLD_Y, sizeof(int));
509 elev[i] = calloc(WORLD_Y, sizeof(int));
511 sectx = calloc(nc + ni, sizeof(int *));
512 secty = calloc(nc + ni, sizeof(int *));
513 sectc = calloc(nc + ni, sizeof(int *));
514 isecs = calloc(nc + ni, sizeof(int));
515 weight = calloc(MAX(sc, is * 2), sizeof(int));
516 dsea = calloc(MAX(sc, is * 2), sizeof(int));
517 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
518 for (i = 0; i < nc; ++i) {
519 sectx[i] = calloc(sc, sizeof(int));
520 secty[i] = calloc(sc, sizeof(int));
521 sectc[i] = calloc(sc, sizeof(int));
523 for (i = nc; i < nc + ni; ++i) {
524 sectx[i] = calloc(is * 2, sizeof(int));
525 secty[i] = calloc(is * 2, sizeof(int));
526 sectc[i] = calloc(is * 2, sizeof(int));
536 for (i = 0; i < WORLD_X; ++i) {
537 for (j = 0; j < WORLD_Y; ++j) {
541 memset(adj_land, 0, WORLD_SZ() * sizeof(*adj_land));
544 /****************************************************************************
545 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
546 ****************************************************************************/
549 * How isolated is capital @j at @newx,@newy?
550 * Return the distance to the closest other capital.
553 iso(int j, int newx, int newy)
558 for (i = 0; i < nc; ++i) {
561 md = mapdist(capx[i], capy[i], newx, newy);
571 * Return 1 for a stable drift, 0 for an unstable one.
578 for (i = 0; i < nc; i++) {
579 capy[i] = (2 * i) / WORLD_X;
580 capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
581 if (capy[i] >= WORLD_Y) {
583 "%s: world not big enough for all the continents\n",
589 for (turns = 0; turns < DRIFT_MAX; ++turns) {
592 for (i = 0; i < nc; ++i)
599 * Has the drift stabilized?
600 * @turns is the number of turns so far.
605 static int mc[STABLE_CYCLE];
606 int i, isod, d = 0, stab = 1;
609 for (i = 0; i < STABLE_CYCLE; i++)
613 if (turns <= DRIFT_BEFORE_CHECK)
616 for (i = 0; i < nc; ++i) {
617 isod = iso(i, capx[i], capy[i]);
622 for (i = 0; i < STABLE_CYCLE; ++i)
626 mc[turns % STABLE_CYCLE] = d;
630 /* This routine does the actual drifting
636 int i, n, newx, newy;
638 for (i = roll0(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
639 newx = new_x(capx[j] + dirx[i]);
640 newy = new_y(capy[j] + diry[i]);
641 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
649 /****************************************************************************
651 ****************************************************************************/
653 /* Look for a coastal sector of continent c
661 for (i = 0; i < isecs[c]; ++i) {
663 for (j = 0; j < 6; ++j)
664 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
669 struct hexagon_iter {
674 * Start iterating around @x0,@y0 at distance @d.
675 * Set *x,*y to coordinates of the first sector.
678 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
681 *x = new_x(x0 - 2 * n);
683 iter->dir = DIR_FIRST;
689 * Continue iteration started with hexagon_first().
690 * Set *x,*y to coordinates of the next sector.
691 * Return whether we're back at the first sector, i.e. iteration is
695 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
697 *x = new_x(*x + diroff[iter->dir][0]);
698 *y = new_y(*y + diroff[iter->dir][1]);
700 if (iter->i == iter->n) {
704 return iter->dir <= DIR_LAST;
708 * Is @x,@y in no exclusive zone other than perhaps @c's?
711 xzone_ok(int c, int x, int y)
713 int off = XYOFFSET(x, y);
715 return xzone[off] == c || xzone[off] == -1;
719 * Add sectors within distance @dist of @x,@y to @c's exclusive zone.
722 xzone_around_sector(int c, int x, int y, int dist)
725 struct hexagon_iter hexit;
727 assert(xzone_ok(c, x, y));
729 xzone[XYOFFSET(x, y)] = c;
730 for (d = 1; d <= dist; d++) {
731 hexagon_first(&hexit, x, y, d, &x1, &y1);
733 off = XYOFFSET(x1, y1);
734 if (xzone[off] == -1)
736 else if (xzone[off] != c)
738 } while (hexagon_next(&hexit, &x1, &y1));
743 * Add sectors within distance @dist to island @c's exclusive zone.
746 xzone_around_island(int c, int dist)
750 for (i = 0; i < isecs[c]; i++)
751 xzone_around_sector(c, sectx[c][i], secty[c][i], dist);
755 * Initialize exclusive zones around @n islands.
762 for (i = 0; i < WORLD_SZ(); i++)
765 for (c = 0; c < n; c++)
766 xzone_around_island(c, id);
770 * Can island @c grow at @x,@y?
773 can_grow_at(int c, int x, int y)
775 return own[x][y] == -1 && xzone_ok(c, x, y);
779 adj_land_update(int x, int y)
781 int dir, nx, ny, noff;
783 assert(own[x][y] != -1);
785 for (dir = DIR_FIRST; dir <= DIR_LAST; dir++) {
786 nx = new_x(x + diroff[dir][0]);
787 ny = new_y(y + diroff[dir][1]);
788 noff = XYOFFSET(nx, ny);
789 adj_land[noff] |= 1u << DIR_BACK(dir);
794 add_sector(int c, int x, int y)
796 assert(own[x][y] == -1);
797 xzone_around_sector(c, x, y, c < nc ? di : DISTINCT_ISLANDS ? id : 0);
798 sectx[c][isecs[c]] = x;
799 secty[c][isecs[c]] = y;
802 adj_land_update(x, y);
806 try_to_grow(int c, int newx, int newy)
808 if (!can_grow_at(c, newx, newy))
811 add_sector(c, newx, newy);
815 /* Move along the coast in a clockwise direction.
819 next_coast(int c, int x, int y, int *xp, int *yp)
821 int i, nx, ny, wat = 0;
829 for (i = 0; i < 12; ++i) {
830 nx = new_x(x + dirx[i % 6]);
831 ny = new_y(y + diry[i % 6]);
832 if (own[nx][ny] == -1)
834 if (wat && own[nx][ny] == c) {
842 /* Choose a sector to grow from
846 new_try(int c, int spike)
855 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : roll0(secs);
860 } while (i != starti);
867 /* Grow continent c by 1 sector
871 grow_one_sector(int c)
873 int spike = roll0(100) < sp;
874 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
876 if ((try1 = new_try(c, spike)) == -1)
878 x = sx = sectx[c][try1];
879 y = sy = secty[c][try1];
884 for (i = roll0(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
885 newx = new_x(x + dirx[i]);
886 newy = new_y(y + diry[i]);
888 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
889 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1))
890 if (try_to_grow(c, newx, newy))
894 for (i = roll0(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
895 newx = new_x(x + dirx[i]);
896 newy = new_y(y + diry[i]);
897 if (try_to_grow(c, newx, newy))
900 next_coast(c, x, y, &x, &y);
902 } while (!done && coast_search < COAST_SEARCH_MAX &&
903 (isecs[c] == 1 || x != sx || y != sy));
908 * Grow the continents.
909 * Return 1 on success, 0 on error.
912 grow_continents(void)
920 for (c = 0; c < nc; ++c) {
922 if (!try_to_grow(c, capx[c], capy[c])
923 || !try_to_grow(c, new_x(capx[c] + 2), capy[c])) {
930 qprint("No room for continents\n");
934 for (secs = 2; secs < sc && done; secs++) {
935 for (c = 0; c < nc; ++c) {
937 if (!grow_one_sector(c))
942 for (c = 0; c < nc; ++c)
946 qprint("Only managed to grow %d out of %d sectors.\n",
952 /****************************************************************************
954 ****************************************************************************/
957 * Place additional island @c's first sector.
958 * Return 1 on success, 0 on error.
963 int n, x, y, newx, newy;
967 for (y = 0; y < WORLD_Y; y++) {
968 for (x = y % 2; x < WORLD_X; x += 2) {
969 if (can_grow_at(c, x, y)) {
980 add_sector(c, newx, newy);
984 /* Grow all the islands
990 int stunted_islands = 0;
995 for (c = nc; c < nc + ni; ++c) {
996 if (!place_island(c)) {
997 qprint("\nNo room for island #%d", c - nc + 1);
1001 isiz = roll(is) + roll0(is);
1002 for (secs = 1; secs < isiz; secs++) {
1004 if (!grow_one_sector(c)) {
1011 qprint(" %d(%d)", c - nc + 1, secs);
1015 if (stunted_islands)
1016 qprint("\n%d stunted island%s",
1017 stunted_islands, splur(stunted_islands));
1020 /****************************************************************************
1022 ****************************************************************************/
1024 create_elevations(void)
1028 for (i = 0; i < WORLD_X; i++) {
1029 for (j = 0; j < WORLD_Y; j++)
1030 elev[i][j] = -INFINITE_ELEVATION;
1036 /* Generic function for finding the distance to the closest sea, land, or
1040 distance_to_what(int x, int y, int flag)
1043 struct hexagon_iter hexit;
1045 for (d = 1; d < 5; ++d) {
1046 hexagon_first(&hexit, x, y, d, &px, &py);
1049 case 0: /* distance to sea */
1050 if (own[px][py] == -1)
1053 case 1: /* distance to land */
1054 if (own[px][py] != -1)
1057 case 2: /* distance to mountain */
1058 if (elev[px][py] == INFINITE_ELEVATION)
1062 } while (hexagon_next(&hexit, &px, &py));
1067 #define ELEV elev[sectx[c][i]][secty[c][i]]
1068 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1069 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1071 /* Decide where the mountains go
1076 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
1079 for (c = 0; c < ctot; ++c) {
1082 nm = (pm * ns) / 100;
1084 /* Place the mountains */
1086 for (i = 0; i < ns; ++i) {
1087 dsea[i] = distance_to_sea();
1088 weight[i] = (total += (dsea[i] * dsea[i]));
1091 for (k = nm, mountain_search = 0;
1092 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1093 ++mountain_search) {
1095 for (i = 0; i < ns; ++i)
1096 if (r < weight[i] && ELEV == -INFINITE_ELEVATION &&
1098 ((!(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 ELEV = INFINITE_ELEVATION;
1108 /* Elevate land that is not mountain and not capital */
1110 for (i = 0; i < ns; ++i)
1111 dmoun[i] = distance_to_mountain();
1112 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1113 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1114 100 * INFINITE_ELEVATION;
1115 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1118 for (i = 0; i < ns; ++i) {
1119 if (ELEV == -INFINITE_ELEVATION &&
1120 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1121 capy[c] == secty[c][i])) &&
1122 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1123 capy[c] == secty[c][i]))))) {
1124 h = 3 * (5 - dmoun[i]) + dsea[i];
1135 if (newk >= HILLMIN && newk < PLATMIN)
1139 elev[sectx[c][where]][secty[c][where]] = newk;
1142 /* Elevate the mountains and capitals */
1144 for (i = 0; i < ns; ++i) {
1145 if (ELEV == INFINITE_ELEVATION) {
1147 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1149 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1150 roll0((256 - HIGHMIN) / 2);
1151 } else if (c < nc &&
1152 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1153 ((new_x(capx[c] + 2) == sectx[c][i] &&
1154 capy[c] == secty[c][i]))))
1160 #define distance_to_land() distance_to_what(x, y, 1)
1167 for (y = 0; y < WORLD_Y; ++y) {
1168 for (x = y % 2; x < WORLD_X; x += 2) {
1169 if (elev[x][y] == -INFINITE_ELEVATION)
1170 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1176 elev_to_sct_type(int elevation)
1178 if (elevation < LANDMIN)
1180 if (elevation < HILLMIN)
1182 if (elevation < PLATMIN)
1184 if (elevation < HIGHMIN)
1189 /****************************************************************************
1191 ****************************************************************************/
1198 fert = LANDMIN - e + 40;
1199 else if (e < FERT_MAX)
1200 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1211 oil = (LANDMIN - e) * 2 + roll0(2);
1212 else if (e <= OIL_MAX)
1213 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1223 if (e >= IRON_MIN && e < HIGHMIN)
1224 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1234 if (e >= GOLD_MIN) {
1236 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1238 gold = 100 - 20 * HIGHMIN / e;
1249 if (e >= URAN_MIN && e < HIGHMIN)
1250 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1257 add_resources(struct sctstr *sct)
1259 sct->sct_fertil = set_fert(sct->sct_elev);
1260 sct->sct_oil = set_oil(sct->sct_elev);
1261 sct->sct_min = set_iron(sct->sct_elev);
1262 sct->sct_gmin = set_gold(sct->sct_elev);
1263 sct->sct_uran = set_uran(sct->sct_elev);
1266 /****************************************************************************
1267 DESIGNATE THE SECTORS
1268 ****************************************************************************/
1276 for (y = 0; y < WORLD_Y; y++) {
1277 for (x = y % 2; x < WORLD_X; x += 2) {
1278 sct = getsectp(x, y);
1279 sct->sct_elev = elev[x][y];
1280 sct->sct_type = elev_to_sct_type(elev[x][y]);
1281 sct->sct_newtype = sct->sct_type;
1282 sct->sct_dterr = own[sct->sct_x][y] + 1;
1286 set_coastal_flags();
1289 /****************************************************************************
1290 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1291 ****************************************************************************/
1295 int sx, sy, x, y, c, type;
1298 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1303 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1306 type = elev_to_sct_type(elev[x][y]);
1307 if (type == SCT_WATER)
1309 else if (type == SCT_MOUNT)
1314 assert(0 <= c && c < nc);
1315 if ((x == capx[c] || x == new_x(capx[c] + 2))
1317 printf("%c ", numletter[c % 62]);
1327 * Print a map to help visualize own[][].
1328 * This is for debugging.
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 (own[x][y] == -1)
1345 putchar(numletter[own[x][y] % 62]);
1352 * Print a map to help visualize elev[][].
1353 * This is for debugging. It expects the terminal to understand
1354 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1357 print_elev_map(void)
1359 int sx, sy, x, y, sat;
1361 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1364 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1368 else if (!elev[x][y])
1370 else if (elev[x][y] < 0) {
1371 sat = 256 + elev[x][y] * 2;
1372 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1373 } else if (elev[x][y] < HIGHMIN / 2) {
1374 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1375 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1376 } else if (elev[x][y] < HIGHMIN) {
1377 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1378 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1380 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1381 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1389 * Print a map to help visualize xzone[].
1390 * This is for debugging.
1393 print_xzone_map(void)
1395 int sx, sy, x, y, off;
1397 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1400 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1402 off = XYOFFSET(x, y);
1405 else if (own[x][y] >= 0)
1407 else if (xzone[off] >= 0)
1408 putchar(numletter[xzone[off] % 62]);
1410 assert(own[x][y] == -1);
1411 putchar(xzone[off] == -1 ? '.' : '!');
1419 /***************************************************************************
1420 WRITE A SCRIPT FOR PLACING CAPITALS
1421 ****************************************************************************/
1423 write_newcap_script(void)
1426 FILE *script = fopen(outfile, "w");
1429 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1430 program_name, outfile, strerror(errno));
1434 for (c = 0; c < nc; ++c) {
1435 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1436 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1438 fprintf(script, "add %d visitor visitor v\n", c + 1);
1444 qprint(const char *const fmt, ...)
1450 vfprintf(stdout, fmt, ap);
1456 set_coastal_flags(void)
1461 for (i = 0; i < nc + ni; ++i) {
1462 for (j = 0; j < isecs[i]; j++) {
1463 sp = getsectp(sectx[i][j], secty[i][j]);
1464 sp->sct_coastal = sectc[i][j];