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 */
193 * Each island is surrounded by an exclusive zone where only it may
194 * grow. The width of the zone depends on minimum distances.
195 * While growing continents, it is @di sectors wide.
196 * While growing additional islands, it is @id sectors wide.
197 * DISTINCT_ISLANDS nullifies the exclusive zone then.
198 * xzone[XYOFFSET(x, y)] is -1 when the sector is in no exclusive
199 * zone, a (non-negative) island number when it is in that island's
200 * exclusive zone and no other, and -2 when it is in multiple
205 static int **elev; /* elevation of the sectors */
206 static int **sectx, **secty; /* the sectors for each continent */
207 static int **sectc; /* which sectors are on the coast? */
208 static int *weight; /* used for placing mountains */
209 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
211 #define NUMTRIES 10 /* keep trying to grow this many times */
213 static const char *numletter =
214 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
216 static void help(char *);
217 static void usage(void);
218 static void parse_args(int argc, char *argv[]);
219 static void allocate_memory(void);
220 static void init(void);
221 static int drift(void);
222 static int grow_continents(void);
223 static void create_elevations(void);
224 static void write_sects(void);
225 static void output(void);
226 static int write_newcap_script(void);
227 static int stable(int);
228 static void elevate_land(void);
229 static void elevate_sea(void);
230 static void set_coastal_flags(void);
232 static void print_vars(void);
233 static void fl_move(int);
234 static void grow_islands(void);
236 /* Debugging aids: */
237 void print_own_map(void);
238 void print_xzone_map(void);
239 void print_elev_map(void);
241 /****************************************************************************
243 ****************************************************************************/
246 main(int argc, char *argv[])
249 char *config_file = NULL;
251 unsigned rnd_seed = 0;
254 program_name = argv[0];
256 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
259 config_file = optarg;
262 DISTINCT_ISLANDS = 0;
268 rnd_seed = strtoul(optarg, NULL, 10);
278 printf("%s\n\n%s", version, legal);
287 rnd_seed = pick_seed();
290 if (emp_config(config_file) < 0)
294 parse_args(argc - optind, argv + optind);
299 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
300 qprint("seed is %u\n", rnd_seed);
305 qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
306 qprint("placing capitals...\n");
308 qprint("unstable drift\n");
309 qprint("growing continents...\n");
310 done = grow_continents();
311 } while (!done && ++try < NUMTRIES);
313 fprintf(stderr, "%s: world not large enough to hold continents\n",
317 qprint("growing islands:");
319 qprint("\nelevating land...\n");
322 qprint("writing to sectors file...\n");
323 if (!write_newcap_script())
325 if (chdir(gamedir)) {
326 fprintf(stderr, "%s: can't chdir to %s (%s)\n",
327 program_name, gamedir, strerror(errno));
330 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
333 if (!ef_close(EF_SECTOR))
337 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
347 puts("Creating a planet with:\n");
348 printf("%d continents\n", nc);
349 printf("continent size: %d\n", sc);
350 printf("number of islands: %d\n", ni);
351 printf("average size of islands: %d\n", is);
352 printf("spike: %d%%\n", sp);
353 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
354 pm, (pm * sc) / 100);
355 printf("minimum distance between continents: %d\n", di);
356 printf("minimum distance from islands to continents: %d\n", id);
357 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
361 help(char *complaint)
364 fprintf(stderr, "%s: %s\n", program_name, complaint);
365 fprintf(stderr, "Try -h for help.\n");
371 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
372 " -e CONFIG-FILE configuration file\n"
374 " -i islands may merge\n"
376 " -R SEED seed for random number generator\n"
377 " -s SCRIPT name of script to create (default %s)\n"
378 " -h display this help and exit\n"
379 " -v display version information and exit\n"
380 " NC number of continents\n"
381 " SC continent size\n"
382 " NI number of islands (default NC)\n"
383 " IS average island size (default SC/2)\n"
384 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
385 " PM percentage of land that is mountain (default %d)\n"
386 " DI minimum distance between continents (default %d)\n"
387 " ID minimum distance from islands to continents (default %d)\n",
388 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
389 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
393 parse_args(int argc, char *argv[])
395 int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
398 help("missing arguments");
402 help("too many arguments");
407 fprintf(stderr, "%s: number of continents must be > 0\n",
414 fprintf(stderr, "%s: size of continents must be > 1\n",
425 fprintf(stderr, "%s: number of islands must be >= 0\n",
433 fprintf(stderr, "%s: size of islands must be > 0\n",
440 if (sp < 0 || sp > 100) {
442 "%s: spike percentage must be between 0 and 100\n",
449 if (pm < 0 || pm > 100) {
451 "%s: mountain percentage must be between 0 and 100\n",
459 fprintf(stderr, "%s: distance between continents must be >= 0\n",
464 fprintf(stderr, "%s: distance between continents too large\n",
473 "%s: distance from islands to continents must be >= 0\n",
479 "%s: distance from islands to continents too large\n",
485 /****************************************************************************
486 VARIABLE INITIALIZATION
487 ****************************************************************************/
490 allocate_memory(void)
494 capx = calloc(nc, sizeof(int));
495 capy = calloc(nc, sizeof(int));
496 own = calloc(WORLD_X, sizeof(int *));
497 xzone = malloc(WORLD_SZ() * sizeof(*xzone));
498 elev = calloc(WORLD_X, sizeof(int *));
499 for (i = 0; i < WORLD_X; ++i) {
500 own[i] = calloc(WORLD_Y, sizeof(int));
501 elev[i] = calloc(WORLD_Y, sizeof(int));
503 sectx = calloc(nc + ni, sizeof(int *));
504 secty = calloc(nc + ni, sizeof(int *));
505 sectc = calloc(nc + ni, sizeof(int *));
506 isecs = calloc(nc + ni, sizeof(int));
507 weight = calloc(MAX(sc, is * 2), sizeof(int));
508 dsea = calloc(MAX(sc, is * 2), sizeof(int));
509 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
510 for (i = 0; i < nc; ++i) {
511 sectx[i] = calloc(sc, sizeof(int));
512 secty[i] = calloc(sc, sizeof(int));
513 sectc[i] = calloc(sc, sizeof(int));
515 for (i = nc; i < nc + ni; ++i) {
516 sectx[i] = calloc(is * 2, sizeof(int));
517 secty[i] = calloc(is * 2, sizeof(int));
518 sectc[i] = calloc(is * 2, sizeof(int));
528 for (i = 0; i < WORLD_X; ++i) {
529 for (j = 0; j < WORLD_Y; ++j) {
535 /****************************************************************************
536 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
537 ****************************************************************************/
540 * How isolated is capital @j at @newx,@newy?
541 * Return the distance to the closest other capital.
544 iso(int j, int newx, int newy)
549 for (i = 0; i < nc; ++i) {
552 md = mapdist(capx[i], capy[i], newx, newy);
562 * Return 1 for a stable drift, 0 for an unstable one.
569 for (i = 0; i < nc; i++) {
570 capy[i] = (2 * i) / WORLD_X;
571 capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
572 if (capy[i] >= WORLD_Y) {
574 "%s: world not big enough for all the continents\n",
580 for (turns = 0; turns < DRIFT_MAX; ++turns) {
583 for (i = 0; i < nc; ++i)
590 * Has the drift stabilized?
591 * @turns is the number of turns so far.
596 static int mc[STABLE_CYCLE];
597 int i, isod, d = 0, stab = 1;
600 for (i = 0; i < STABLE_CYCLE; i++)
604 if (turns <= DRIFT_BEFORE_CHECK)
607 for (i = 0; i < nc; ++i) {
608 isod = iso(i, capx[i], capy[i]);
613 for (i = 0; i < STABLE_CYCLE; ++i)
617 mc[turns % STABLE_CYCLE] = d;
621 /* This routine does the actual drifting
627 int i, n, newx, newy;
629 for (i = roll0(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
630 newx = new_x(capx[j] + dirx[i]);
631 newy = new_y(capy[j] + diry[i]);
632 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
640 /****************************************************************************
642 ****************************************************************************/
644 /* Look for a coastal sector of continent c
652 for (i = 0; i < isecs[c]; ++i) {
654 for (j = 0; j < 6; ++j)
655 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
660 struct hexagon_iter {
665 * Start iterating around @x0,@y0 at distance @d.
666 * Set *x,*y to coordinates of the first sector.
669 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
672 *x = new_x(x0 - 2 * n);
674 iter->dir = DIR_FIRST;
680 * Continue iteration started with hexagon_first().
681 * Set *x,*y to coordinates of the next sector.
682 * Return whether we're back at the first sector, i.e. iteration is
686 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
688 *x = new_x(*x + diroff[iter->dir][0]);
689 *y = new_y(*y + diroff[iter->dir][1]);
691 if (iter->i == iter->n) {
695 return iter->dir <= DIR_LAST;
699 * Is @x,@y in no exclusive zone other than perhaps @c's?
702 xzone_ok(int c, int x, int y)
704 int off = XYOFFSET(x, y);
706 return xzone[off] == c || xzone[off] == -1;
710 * Add sectors within distance @dist of @x,@y to @c's exclusive zone.
713 xzone_around_sector(int c, int x, int y, int dist)
716 struct hexagon_iter hexit;
718 assert(xzone_ok(c, x, y));
720 xzone[XYOFFSET(x, y)] = c;
721 for (d = 1; d <= dist; d++) {
722 hexagon_first(&hexit, x, y, d, &x1, &y1);
724 off = XYOFFSET(x1, y1);
725 if (xzone[off] == -1)
727 else if (xzone[off] != c)
729 } while (hexagon_next(&hexit, &x1, &y1));
734 * Add sectors within distance @dist to island @c's exclusive zone.
737 xzone_around_island(int c, int dist)
741 for (i = 0; i < isecs[c]; i++)
742 xzone_around_sector(c, sectx[c][i], secty[c][i], dist);
746 * Initialize exclusive zones around @n islands.
753 for (i = 0; i < WORLD_SZ(); i++)
756 for (c = 0; c < n; c++)
757 xzone_around_island(c, id);
761 * Can island @c grow at @x,@y?
764 can_grow_at(int c, int x, int y)
766 return own[x][y] == -1 && xzone_ok(c, x, y);
770 try_to_grow(int c, int newx, int newy, int extra_dist)
772 int d = c < nc ? di : id;
774 struct hexagon_iter hexit;
776 if (!can_grow_at(c, newx, newy))
779 for (i = 1; i <= extra_dist; i++) {
780 hexagon_first(&hexit, newx, newy, d + i, &px, &py);
782 if (own[px][py] != -1 &&
784 (DISTINCT_ISLANDS || own[px][py] < nc))
786 } while (hexagon_next(&hexit, &px, &py));
789 xzone_around_sector(c, newx, newy,
790 c < nc ? di : DISTINCT_ISLANDS ? id : 0);
791 sectx[c][isecs[c]] = newx;
792 secty[c][isecs[c]] = newy;
798 /* Move along the coast in a clockwise direction.
802 next_coast(int c, int x, int y, int *xp, int *yp)
804 int i, nx, ny, wat = 0;
812 for (i = 0; i < 12; ++i) {
813 nx = new_x(x + dirx[i % 6]);
814 ny = new_y(y + diry[i % 6]);
815 if (own[nx][ny] == -1)
817 if (wat && own[nx][ny] == c) {
825 /* Choose a sector to grow from
829 new_try(int c, int spike)
838 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : roll0(secs);
843 } while (i != starti);
850 /* Grow continent c by 1 sector
854 grow_one_sector(int c)
856 int spike = roll0(100) < sp;
857 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
859 if ((try1 = new_try(c, spike)) == -1)
861 x = sx = sectx[c][try1];
862 y = sy = secty[c][try1];
867 for (i = roll0(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
868 newx = new_x(x + dirx[i]);
869 newy = new_y(y + diry[i]);
871 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
872 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1))
873 if (try_to_grow(c, newx, newy, 0))
877 for (i = roll0(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
878 newx = new_x(x + dirx[i]);
879 newy = new_y(y + diry[i]);
880 if (try_to_grow(c, newx, newy, 0))
883 next_coast(c, x, y, &x, &y);
885 } while (!done && coast_search < COAST_SEARCH_MAX &&
886 (isecs[c] == 1 || x != sx || y != sy));
891 * Grow the continents.
892 * Return 1 on success, 0 on error.
895 grow_continents(void)
903 for (c = 0; c < nc; ++c) {
905 if (!try_to_grow(c, capx[c], capy[c], 0)
906 || !try_to_grow(c, new_x(capx[c] + 2), capy[c], 0)) {
913 qprint("No room for continents\n");
917 for (secs = 2; secs < sc && done; secs++) {
918 for (c = 0; c < nc; ++c) {
920 if (!grow_one_sector(c))
925 for (c = 0; c < nc; ++c)
929 qprint("Only managed to grow %d out of %d sectors.\n",
935 /****************************************************************************
937 ****************************************************************************/
939 /* Choose a place to start growing an island from
942 place_island(int c, int *xp, int *yp)
945 int ssy = roll0(WORLD_Y);
946 int ssx = new_x(roll0(WORLD_X / 2) * 2 + ssy % 2);
948 if (ssx > WORLD_X - 2)
949 ssx = new_x(ssx + 2);
950 for (d = di; d >= 0; --d) {
954 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
955 if (*xp >= WORLD_X) {
956 *yp = new_y(*yp + 1);
958 if (*xp == sx && *yp == sy)
961 if (try_to_grow(c, *xp, *yp, d))
968 /* Grow all the islands
974 int stunted_islands = 0;
975 int c, secs, x, y, isiz;
979 for (c = nc; c < nc + ni; ++c) {
980 if (!place_island(c, &x, &y)) {
981 qprint("\nNo room for island #%d", c - nc + 1);
985 isiz = roll(is) + roll0(is);
986 for (secs = 1; secs < isiz; secs++) {
988 if (!grow_one_sector(c)) {
995 qprint(" %d(%d)", c - nc + 1, secs);
1000 qprint("\n%d stunted island%s",
1001 stunted_islands, splur(stunted_islands));
1004 /****************************************************************************
1006 ****************************************************************************/
1008 create_elevations(void)
1012 for (i = 0; i < WORLD_X; i++) {
1013 for (j = 0; j < WORLD_Y; j++)
1014 elev[i][j] = -INFINITE_ELEVATION;
1020 /* Generic function for finding the distance to the closest sea, land, or
1024 distance_to_what(int x, int y, int flag)
1027 struct hexagon_iter hexit;
1029 for (d = 1; d < 5; ++d) {
1030 hexagon_first(&hexit, x, y, d, &px, &py);
1033 case 0: /* distance to sea */
1034 if (own[px][py] == -1)
1037 case 1: /* distance to land */
1038 if (own[px][py] != -1)
1041 case 2: /* distance to mountain */
1042 if (elev[px][py] == INFINITE_ELEVATION)
1046 } while (hexagon_next(&hexit, &px, &py));
1051 #define ELEV elev[sectx[c][i]][secty[c][i]]
1052 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
1053 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
1055 /* Decide where the mountains go
1060 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
1063 for (c = 0; c < ctot; ++c) {
1066 nm = (pm * ns) / 100;
1068 /* Place the mountains */
1070 for (i = 0; i < ns; ++i) {
1071 dsea[i] = distance_to_sea();
1072 weight[i] = (total += (dsea[i] * dsea[i]));
1075 for (k = nm, mountain_search = 0;
1076 k && mountain_search < MOUNTAIN_SEARCH_MAX;
1077 ++mountain_search) {
1079 for (i = 0; i < ns; ++i)
1080 if (r < weight[i] && ELEV == -INFINITE_ELEVATION &&
1082 ((!(capx[c] == sectx[c][i] &&
1083 capy[c] == secty[c][i])) &&
1084 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1085 capy[c] == secty[c][i]))))) {
1086 ELEV = INFINITE_ELEVATION;
1092 /* Elevate land that is not mountain and not capital */
1094 for (i = 0; i < ns; ++i)
1095 dmoun[i] = distance_to_mountain();
1096 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
1097 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1098 100 * INFINITE_ELEVATION;
1099 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1102 for (i = 0; i < ns; ++i) {
1103 if (ELEV == -INFINITE_ELEVATION &&
1104 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1105 capy[c] == secty[c][i])) &&
1106 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1107 capy[c] == secty[c][i]))))) {
1108 h = 3 * (5 - dmoun[i]) + dsea[i];
1119 if (newk >= HILLMIN && newk < PLATMIN)
1123 elev[sectx[c][where]][secty[c][where]] = newk;
1126 /* Elevate the mountains and capitals */
1128 for (i = 0; i < ns; ++i) {
1129 if (ELEV == INFINITE_ELEVATION) {
1131 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1133 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1134 roll0((256 - HIGHMIN) / 2);
1135 } else if (c < nc &&
1136 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1137 ((new_x(capx[c] + 2) == sectx[c][i] &&
1138 capy[c] == secty[c][i]))))
1144 #define distance_to_land() distance_to_what(x, y, 1)
1151 for (y = 0; y < WORLD_Y; ++y) {
1152 for (x = y % 2; x < WORLD_X; x += 2) {
1153 if (elev[x][y] == -INFINITE_ELEVATION)
1154 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1160 elev_to_sct_type(int elevation)
1162 if (elevation < LANDMIN)
1164 if (elevation < HILLMIN)
1166 if (elevation < PLATMIN)
1168 if (elevation < HIGHMIN)
1173 /****************************************************************************
1175 ****************************************************************************/
1182 fert = LANDMIN - e + 40;
1183 else if (e < FERT_MAX)
1184 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1195 oil = (LANDMIN - e) * 2 + roll0(2);
1196 else if (e <= OIL_MAX)
1197 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1207 if (e >= IRON_MIN && e < HIGHMIN)
1208 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1218 if (e >= GOLD_MIN) {
1220 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1222 gold = 100 - 20 * HIGHMIN / e;
1233 if (e >= URAN_MIN && e < HIGHMIN)
1234 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1241 add_resources(struct sctstr *sct)
1243 sct->sct_fertil = set_fert(sct->sct_elev);
1244 sct->sct_oil = set_oil(sct->sct_elev);
1245 sct->sct_min = set_iron(sct->sct_elev);
1246 sct->sct_gmin = set_gold(sct->sct_elev);
1247 sct->sct_uran = set_uran(sct->sct_elev);
1250 /****************************************************************************
1251 DESIGNATE THE SECTORS
1252 ****************************************************************************/
1260 for (y = 0; y < WORLD_Y; y++) {
1261 for (x = y % 2; x < WORLD_X; x += 2) {
1262 sct = getsectp(x, y);
1263 sct->sct_elev = elev[x][y];
1264 sct->sct_type = elev_to_sct_type(elev[x][y]);
1265 sct->sct_newtype = sct->sct_type;
1266 sct->sct_dterr = own[sct->sct_x][y] + 1;
1270 set_coastal_flags();
1273 /****************************************************************************
1274 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1275 ****************************************************************************/
1279 int sx, sy, x, y, c, type;
1282 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1287 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1290 type = elev_to_sct_type(elev[x][y]);
1291 if (type == SCT_WATER)
1293 else if (type == SCT_MOUNT)
1298 assert(0 <= c && c < nc);
1299 if ((x == capx[c] || x == new_x(capx[c] + 2))
1301 printf("%c ", numletter[c % 62]);
1311 * Print a map to help visualize own[][].
1312 * This is for debugging.
1319 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1322 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1326 else if (own[x][y] == -1)
1329 putchar(numletter[own[x][y] % 62]);
1336 * Print a map to help visualize elev[][].
1337 * This is for debugging. It expects the terminal to understand
1338 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1341 print_elev_map(void)
1343 int sx, sy, x, y, sat;
1345 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1348 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1352 else if (!elev[x][y])
1354 else if (elev[x][y] < 0) {
1355 sat = 256 + elev[x][y] * 2;
1356 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1357 } else if (elev[x][y] < HIGHMIN / 2) {
1358 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1359 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1360 } else if (elev[x][y] < HIGHMIN) {
1361 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1362 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1364 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1365 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1373 * Print a map to help visualize xzone[].
1374 * This is for debugging.
1377 print_xzone_map(void)
1379 int sx, sy, x, y, off;
1381 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1384 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1386 off = XYOFFSET(x, y);
1389 else if (own[x][y] >= 0)
1391 else if (xzone[off] >= 0)
1392 putchar(numletter[xzone[off] % 62]);
1394 assert(own[x][y] == -1);
1395 putchar(xzone[off] == -1 ? '.' : '!');
1403 /***************************************************************************
1404 WRITE A SCRIPT FOR PLACING CAPITALS
1405 ****************************************************************************/
1407 write_newcap_script(void)
1410 FILE *script = fopen(outfile, "w");
1413 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1414 program_name, outfile, strerror(errno));
1418 for (c = 0; c < nc; ++c) {
1419 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1420 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1422 fprintf(script, "add %d visitor visitor v\n", c + 1);
1428 qprint(const char *const fmt, ...)
1434 vfprintf(stdout, fmt, ap);
1440 set_coastal_flags(void)
1445 for (i = 0; i < nc + ni; ++i) {
1446 for (j = 0; j < isecs[i]; j++) {
1447 sp = getsectp(sectx[i][j], secty[i][j]);
1448 sp->sct_coastal = sectc[i][j];