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
108 #include "prototypes.h"
113 /* The following five numbers refer to elevation under which (in the case of
114 fertility or oil) or over which (in the case of iron, gold, and uranium)
115 sectors with that elevation will contain that resource. Elevation ranges
118 /* raise FERT_MAX for more fertility */
121 /* raise OIL_MAX for more oil */
124 /* lower IRON_MIN for more iron */
127 /* lower GOLD_MIN for more gold */
130 /* lower URAN_MIN for more uranium */
133 /* do not change these 4 defines */
134 #define LANDMIN 1 /* plate altitude for normal land */
135 #define HILLMIN 34 /* plate altitude for hills */
136 #define PLATMIN 36 /* plate altitude for plateau */
137 #define HIGHMIN 98 /* plate altitude for mountains */
139 static void qprint(const char * const fmt, ...)
140 ATTRIBUTE((format (printf, 1, 2)));
143 * Program arguments and options
145 static char *program_name;
146 static int nc, sc; /* number and size of continents */
147 static int ni, is; /* number and size of islands */
148 #define DEFAULT_SPIKE 10
149 static int sp = DEFAULT_SPIKE; /* spike percentage */
150 #define DEFAULT_MOUNTAIN 0
151 static int pm = DEFAULT_MOUNTAIN; /* mountain percentage */
152 #define DEFAULT_CONTDIST 2
153 static int di = DEFAULT_CONTDIST; /* min. distance between continents */
154 #define DEFAULT_ISLDIST 1
155 static int id = DEFAULT_ISLDIST; /* ... continents and islands */
156 /* don't let the islands crash into each other.
157 1 = don't merge, 0 = merge. */
158 static int DISTINCT_ISLANDS = 1;
160 #define DEFAULT_OUTFILE_NAME "newcap_script"
161 static const char *outfile = DEFAULT_OUTFILE_NAME;
163 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
164 #define INFINITY 999 /* a number which means "BIG" */
166 /* these defines prevent infinite loops:
169 #define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector
170 when growing continents and islands */
171 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
172 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
173 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
178 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
179 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
181 static int ctot; /* total number of continents and islands grown */
182 static int *isecs; /* array of how large each island is */
184 static int *capx, *capy; /* location of the nc capitals */
185 static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
186 static int diry[] = { 0, -1, -1, 0, 1, 1 };
188 static int **own; /* owner of the sector. -1 means water */
189 static int **elev; /* elevation of the sectors */
190 static int **sectx, **secty; /* the sectors for each continent */
191 static int **sectc; /* which sectors are on the coast? */
192 static int *weight; /* used for placing mountains */
193 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
195 #define NUMTRIES 10 /* keep trying to grow this many times */
197 static const char *numletter =
198 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
200 static void help(char *);
201 static void usage(void);
202 static void parse_args(int argc, char *argv[]);
203 static void allocate_memory(void);
204 static void init(void);
205 static int drift(void);
206 static int grow_continents(void);
207 static void create_elevations(void);
208 static void write_sects(void);
209 static void output(void);
210 static int write_newcap_script(void);
211 static int stable(int);
212 static void elevate_land(void);
213 static void elevate_sea(void);
214 static void set_coastal_flags(void);
216 static void print_vars(void);
217 static void fl_move(int);
218 static void grow_islands(void);
220 /* Debugging aids: */
221 void print_own_map(void);
222 void print_elev_map(void);
224 /****************************************************************************
226 ****************************************************************************/
229 main(int argc, char *argv[])
232 char *config_file = NULL;
234 unsigned rnd_seed = 0;
237 program_name = argv[0];
239 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
242 config_file = optarg;
245 DISTINCT_ISLANDS = 0;
251 rnd_seed = strtoul(optarg, NULL, 10);
261 printf("%s\n\n%s", version, legal);
270 rnd_seed = pick_seed();
273 if (emp_config(config_file) < 0)
277 parse_args(argc - optind, argv + optind);
282 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
283 qprint("seed is %u\n", rnd_seed);
288 qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
289 qprint("placing capitals...\n");
291 qprint("unstable drift\n");
292 qprint("growing continents...\n");
293 done = grow_continents();
294 } while (!done && ++try < NUMTRIES);
296 fprintf(stderr, "%s: world not large enough to hold continents\n",
300 qprint("growing islands:");
302 qprint("\nelevating land...\n");
305 qprint("writing to sectors file...\n");
306 if (!write_newcap_script())
308 if (chdir(gamedir)) {
309 fprintf(stderr, "%s: can't chdir to %s (%s)\n",
310 program_name, gamedir, strerror(errno));
313 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
316 if (!ef_close(EF_SECTOR))
320 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
330 puts("Creating a planet with:\n");
331 printf("%d continents\n", nc);
332 printf("continent size: %d\n", sc);
333 printf("number of islands: %d\n", ni);
334 printf("average size of islands: %d\n", is);
335 printf("spike: %d%%\n", sp);
336 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
337 pm, (pm * sc) / 100);
338 printf("minimum distance between continents: %d\n", di);
339 printf("minimum distance from islands to continents: %d\n", id);
340 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
344 help(char *complaint)
347 fprintf(stderr, "%s: %s\n", program_name, complaint);
348 fprintf(stderr, "Try -h for help.\n");
354 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
355 " -e CONFIG-FILE configuration file\n"
357 " -i islands may merge\n"
359 " -R SEED seed for random number generator\n"
360 " -s SCRIPT name of script to create (default %s)\n"
361 " -h display this help and exit\n"
362 " -v display version information and exit\n"
363 " NC number of continents\n"
364 " SC continent size\n"
365 " NI number of islands (default NC)\n"
366 " IS average island size (default SC/2)\n"
367 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
368 " PM percentage of land that is mountain (default %d)\n"
369 " DI minimum distance between continents (default %d)\n"
370 " ID minimum distance from islands to continents (default %d)\n",
371 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
372 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
376 parse_args(int argc, char *argv[])
378 int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
381 help("missing arguments");
385 help("too many arguments");
390 fprintf(stderr, "%s: number of continents must be > 0\n",
397 fprintf(stderr, "%s: size of continents must be > 1\n",
408 fprintf(stderr, "%s: number of islands must be >= 0\n",
416 fprintf(stderr, "%s: size of islands must be > 0\n",
423 if (sp < 0 || sp > 100) {
425 "%s: spike percentage must be between 0 and 100\n",
432 if (pm < 0 || pm > 100) {
434 "%s: mountain percentage must be between 0 and 100\n",
442 fprintf(stderr, "%s: distance between continents must be >= 0\n",
447 fprintf(stderr, "%s: distance between continents too large\n",
456 "%s: distance from islands to continents must be >= 0\n",
462 "%s: distance from islands to continents too large\n",
468 /****************************************************************************
469 VARIABLE INITIALIZATION
470 ****************************************************************************/
473 allocate_memory(void)
477 capx = calloc(nc, sizeof(int));
478 capy = calloc(nc, sizeof(int));
479 own = calloc(WORLD_X, sizeof(int *));
480 elev = calloc(WORLD_X, sizeof(int *));
481 for (i = 0; i < WORLD_X; ++i) {
482 own[i] = calloc(WORLD_Y, sizeof(int));
483 elev[i] = calloc(WORLD_Y, sizeof(int));
485 sectx = calloc(nc + ni, sizeof(int *));
486 secty = calloc(nc + ni, sizeof(int *));
487 sectc = calloc(nc + ni, sizeof(int *));
488 isecs = calloc(nc + ni, sizeof(int));
489 weight = calloc(MAX(sc, is * 2), sizeof(int));
490 dsea = calloc(MAX(sc, is * 2), sizeof(int));
491 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
492 for (i = 0; i < nc; ++i) {
493 sectx[i] = calloc(sc, sizeof(int));
494 secty[i] = calloc(sc, sizeof(int));
495 sectc[i] = calloc(sc, sizeof(int));
497 for (i = nc; i < nc + ni; ++i) {
498 sectx[i] = calloc(is * 2, sizeof(int));
499 secty[i] = calloc(is * 2, sizeof(int));
500 sectc[i] = calloc(is * 2, sizeof(int));
510 for (i = 0; i < WORLD_X; ++i) {
511 for (j = 0; j < WORLD_Y; ++j) {
517 /****************************************************************************
518 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
519 ****************************************************************************/
521 /* How isolated is capital j?
524 iso(int j, int newx, int newy)
526 int i, md, d = WORLD_X + WORLD_Y;
528 for (i = 0; i < nc; ++i) {
531 md = mapdist(capx[i], capy[i], newx, newy);
541 * Return 1 for a stable drift, 0 for an unstable one.
548 for (i = 0; i < nc; i++) {
549 capy[i] = (2 * i) / WORLD_X;
550 capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
551 if (capy[i] >= WORLD_Y) {
553 "%s: world not big enough for all the continents\n",
559 for (turns = 0; turns < DRIFT_MAX; ++turns) {
562 for (i = 0; i < nc; ++i)
569 * Has the drift stabilized?
570 * @turns is the number of turns so far.
575 static int mc[STABLE_CYCLE];
576 int i, isod, d = 0, stab = 1;
579 for (i = 0; i < STABLE_CYCLE; i++)
583 if (turns <= DRIFT_BEFORE_CHECK)
586 for (i = 0; i < nc; ++i) {
587 isod = iso(i, capx[i], capy[i]);
592 for (i = 0; i < STABLE_CYCLE; ++i)
596 mc[turns % STABLE_CYCLE] = d;
600 /* This routine does the actual drifting
606 int i, n, newx, newy;
608 for (i = roll0(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
609 newx = new_x(capx[j] + dirx[i]);
610 newy = new_y(capy[j] + diry[i]);
611 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
619 /****************************************************************************
621 ****************************************************************************/
623 /* Look for a coastal sector of continent c
631 for (i = 0; i < isecs[c]; ++i) {
633 for (j = 0; j < 6; ++j)
634 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
639 struct hexagon_iter {
644 * Start iterating around @x0,@y0 at distance @d.
645 * Set *x,*y to coordinates of the first sector.
648 hexagon_first(struct hexagon_iter *iter, int x0, int y0, int n,
651 *x = new_x(x0 - 2 * n);
653 iter->dir = DIR_FIRST;
659 * Continue iteration started with hexagon_first().
660 * Set *x,*y to coordinates of the next sector.
661 * Return whether we're back at the first sector, i.e. iteration is
665 hexagon_next(struct hexagon_iter *iter, int *x, int *y)
667 *x = new_x(*x + diroff[iter->dir][0]);
668 *y = new_y(*y + diroff[iter->dir][1]);
670 if (iter->i == iter->n) {
674 return iter->dir <= DIR_LAST;
677 /* Test to see if we're allowed to grow there: the arguments di and id
680 try_to_grow(int c, int newx, int newy, int d)
683 struct hexagon_iter hexit;
685 if (own[newx][newy] != -1)
688 for (i = 1; i <= d; ++i) {
689 hexagon_first(&hexit, newx, newy, i, &px, &py);
691 if (own[px][py] != -1 &&
693 (DISTINCT_ISLANDS || own[px][py] < nc))
695 } while (hexagon_next(&hexit, &px, &py));
697 sectx[c][isecs[c]] = newx;
698 secty[c][isecs[c]] = newy;
704 /* Move along the coast in a clockwise direction.
708 next_coast(int c, int x, int y, int *xp, int *yp)
710 int i, nx, ny, wat = 0;
718 for (i = 0; i < 12; ++i) {
719 nx = new_x(x + dirx[i % 6]);
720 ny = new_y(y + diry[i % 6]);
721 if (own[nx][ny] == -1)
723 if (wat && own[nx][ny] == c) {
731 /* Choose a sector to grow from
735 new_try(int c, int spike)
744 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : roll0(secs);
749 } while (i != starti);
756 /* Grow continent c by 1 sector
760 grow_one_sector(int c)
762 int spike = roll0(100) < sp;
763 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
765 if ((try1 = new_try(c, spike)) == -1)
767 x = sx = sectx[c][try1];
768 y = sy = secty[c][try1];
773 for (i = roll0(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
774 newx = new_x(x + dirx[i]);
775 newy = new_y(y + diry[i]);
777 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
778 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1))
779 if (try_to_grow(c, newx, newy, c < nc ? di : id))
783 for (i = roll0(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
784 newx = new_x(x + dirx[i]);
785 newy = new_y(y + diry[i]);
786 if (try_to_grow(c, newx, newy, c < nc ? di : id))
789 next_coast(c, x, y, &x, &y);
791 } while (!done && coast_search < COAST_SEARCH_MAX &&
792 (isecs[c] == 1 || x != sx || y != sy));
797 * Grow the continents.
798 * Return 1 on success, 0 on error.
801 grow_continents(void)
806 for (c = 0; c < nc; ++c) {
808 if (!try_to_grow(c, capx[c], capy[c], di)
809 || !try_to_grow(c, new_x(capx[c] + 2), capy[c], di)) {
816 qprint("No room for continents\n");
820 for (secs = 2; secs < sc && done; secs++) {
821 for (c = 0; c < nc; ++c) {
823 if (!grow_one_sector(c))
828 for (c = 0; c < nc; ++c)
832 qprint("Only managed to grow %d out of %d sectors.\n",
838 /****************************************************************************
840 ****************************************************************************/
842 /* Choose a place to start growing an island from
845 place_island(int c, int *xp, int *yp)
848 int ssy = roll0(WORLD_Y);
849 int ssx = new_x(roll0(WORLD_X / 2) * 2 + ssy % 2);
851 if (ssx > WORLD_X - 2)
852 ssx = new_x(ssx + 2);
853 for (d = di + id; d >= id; --d) {
857 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
858 if (*xp >= WORLD_X) {
859 *yp = new_y(*yp + 1);
861 if (*xp == sx && *yp == sy)
864 if (try_to_grow(c, *xp, *yp, d))
871 /* Grow all the islands
877 int stunted_islands = 0;
878 int c, secs, x, y, isiz;
880 for (c = nc; c < nc + ni; ++c) {
881 if (!place_island(c, &x, &y)) {
882 qprint("\nNo room for island #%d", c - nc + 1);
886 isiz = roll(is) + roll0(is);
887 for (secs = 1; secs < isiz; secs++) {
889 if (!grow_one_sector(c)) {
896 qprint(" %d(%d)", c - nc + 1, secs);
901 qprint("\n%d stunted island%s",
902 stunted_islands, splur(stunted_islands));
905 /****************************************************************************
907 ****************************************************************************/
909 create_elevations(void)
913 for (i = 0; i < WORLD_X; i++) {
914 for (j = 0; j < WORLD_Y; j++)
915 elev[i][j] = -INFINITY;
921 /* Generic function for finding the distance to the closest sea, land, or
925 distance_to_what(int x, int y, int flag)
928 struct hexagon_iter hexit;
930 for (d = 1; d < 5; ++d) {
931 hexagon_first(&hexit, x, y, d, &px, &py);
934 case 0: /* distance to sea */
935 if (own[px][py] == -1)
938 case 1: /* distance to land */
939 if (own[px][py] != -1)
942 case 2: /* distance to mountain */
943 if (elev[px][py] == INFINITY)
947 } while (hexagon_next(&hexit, &px, &py));
952 #define ELEV elev[sectx[c][i]][secty[c][i]]
953 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
954 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
956 /* Decide where the mountains go
961 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
964 for (c = 0; c < ctot; ++c) {
967 nm = (pm * ns) / 100;
969 /* Place the mountains */
971 for (i = 0; i < ns; ++i) {
972 dsea[i] = distance_to_sea();
973 weight[i] = (total += (dsea[i] * dsea[i]));
976 for (k = nm, mountain_search = 0;
977 k && mountain_search < MOUNTAIN_SEARCH_MAX;
980 for (i = 0; i < ns; ++i)
981 if (r < weight[i] && ELEV == -INFINITY &&
983 ((!(capx[c] == sectx[c][i] &&
984 capy[c] == secty[c][i])) &&
985 (!(new_x(capx[c] + 2) == sectx[c][i] &&
986 capy[c] == secty[c][i]))))) {
993 /* Elevate land that is not mountain and not capital */
995 for (i = 0; i < ns; ++i)
996 dmoun[i] = distance_to_mountain();
997 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
998 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
1000 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
1001 highest = -INFINITY;
1003 for (i = 0; i < ns; ++i) {
1004 if (ELEV != INFINITY &&
1005 (c >= nc || ((!(capx[c] == sectx[c][i] &&
1006 capy[c] == secty[c][i])) &&
1007 (!(new_x(capx[c] + 2) == sectx[c][i] &&
1008 capy[c] == secty[c][i]))))) {
1009 h = 3 * (5 - dmoun[i]) + dsea[i];
1019 if (newk >= HILLMIN && newk < PLATMIN)
1023 elev[sectx[c][where]][secty[c][where]] = newk;
1024 dsea[where] = -INFINITY;
1025 dmoun[where] = INFINITY;
1028 /* Elevate the mountains and capitals */
1030 for (i = 0; i < ns; ++i) {
1031 if (ELEV == INFINITY) {
1033 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
1035 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
1036 roll0((256 - HIGHMIN) / 2);
1037 } else if (c < nc &&
1038 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
1039 ((new_x(capx[c] + 2) == sectx[c][i] &&
1040 capy[c] == secty[c][i]))))
1046 #define distance_to_land() distance_to_what(x, y, 1)
1053 for (y = 0; y < WORLD_Y; ++y) {
1054 for (x = y % 2; x < WORLD_X; x += 2) {
1055 if (elev[x][y] == -INFINITY)
1056 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1062 elev_to_sct_type(int elevation)
1064 if (elevation < LANDMIN)
1066 if (elevation < HILLMIN)
1068 if (elevation < PLATMIN)
1070 if (elevation < HIGHMIN)
1075 /****************************************************************************
1077 ****************************************************************************/
1084 fert = LANDMIN - e + 40;
1085 else if (e < FERT_MAX)
1086 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1097 oil = (LANDMIN - e) * 2 + roll0(2);
1098 else if (e <= OIL_MAX)
1099 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1109 if (e >= IRON_MIN && e < HIGHMIN)
1110 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1120 if (e >= GOLD_MIN) {
1122 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1124 gold = 100 - 20 * HIGHMIN / e;
1135 if (e >= URAN_MIN && e < HIGHMIN)
1136 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1143 add_resources(struct sctstr *sct)
1145 sct->sct_fertil = set_fert(sct->sct_elev);
1146 sct->sct_oil = set_oil(sct->sct_elev);
1147 sct->sct_min = set_iron(sct->sct_elev);
1148 sct->sct_gmin = set_gold(sct->sct_elev);
1149 sct->sct_uran = set_uran(sct->sct_elev);
1152 /****************************************************************************
1153 DESIGNATE THE SECTORS
1154 ****************************************************************************/
1162 for (y = 0; y < WORLD_Y; y++) {
1163 for (x = y % 2; x < WORLD_X; x += 2) {
1164 sct = getsectp(x, y);
1165 sct->sct_elev = elev[x][y];
1166 sct->sct_type = elev_to_sct_type(elev[x][y]);
1167 sct->sct_newtype = sct->sct_type;
1168 sct->sct_dterr = own[sct->sct_x][y] + 1;
1172 set_coastal_flags();
1175 /****************************************************************************
1176 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1177 ****************************************************************************/
1181 int sx, sy, x, y, c, type;
1184 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1189 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1192 type = elev_to_sct_type(elev[x][y]);
1193 if (type == SCT_WATER)
1195 else if (type == SCT_MOUNT)
1200 assert(0 <= c && c < nc);
1201 if ((x == capx[c] || x == new_x(capx[c] + 2))
1203 printf("%c ", numletter[c % 62]);
1213 * Print a map to help visualize own[][].
1214 * This is for debugging.
1221 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1224 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1228 else if (own[x][y] == -1)
1231 putchar(numletter[own[x][y] % 62]);
1238 * Print a map to help visualize elev[][].
1239 * This is for debugging. It expects the terminal to understand
1240 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1243 print_elev_map(void)
1245 int sx, sy, x, y, sat;
1247 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1250 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1254 else if (!elev[x][y])
1256 else if (elev[x][y] < 0) {
1257 sat = 256 + elev[x][y] * 2;
1258 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1259 } else if (elev[x][y] < HIGHMIN / 2) {
1260 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1261 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1262 } else if (elev[x][y] < HIGHMIN) {
1263 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1264 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1266 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1267 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1274 /***************************************************************************
1275 WRITE A SCRIPT FOR PLACING CAPITALS
1276 ****************************************************************************/
1278 write_newcap_script(void)
1281 FILE *script = fopen(outfile, "w");
1284 fprintf(stderr, "%s: unable to write to %s (%s)\n",
1285 program_name, outfile, strerror(errno));
1289 for (c = 0; c < nc; ++c) {
1290 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1291 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1293 fprintf(script, "add %d visitor visitor v\n", c + 1);
1299 qprint(const char *const fmt, ...)
1305 vfprintf(stdout, fmt, ap);
1311 set_coastal_flags(void)
1316 for (i = 0; i < nc + ni; ++i) {
1317 for (j = 0; j < isecs[i]; j++) {
1318 sp = getsectp(sectx[i][j], secty[i][j]);
1319 sp->sct_coastal = sectc[i][j];