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
107 #include "prototypes.h"
112 /* The following five numbers refer to elevation under which (in the case of
113 fertility or oil) or over which (in the case of iron, gold, and uranium)
114 sectors with that elevation will contain that resource. Elevation ranges
117 /* raise FERT_MAX for more fertility */
120 /* raise OIL_MAX for more oil */
123 /* lower IRON_MIN for more iron */
126 /* lower GOLD_MIN for more gold */
129 /* lower URAN_MIN for more uranium */
132 /* do not change these 4 defines */
133 #define LANDMIN 1 /* plate altitude for normal land */
134 #define HILLMIN 34 /* plate altitude for hills */
135 #define PLATMIN 36 /* plate altitude for plateau */
136 #define HIGHMIN 98 /* plate altitude for mountains */
138 static void qprint(const char * const fmt, ...)
139 ATTRIBUTE((format (printf, 1, 2)));
142 * Program arguments and options
144 static char *program_name;
145 static int nc, sc; /* number and size of continents */
146 static int ni, is; /* number and size of islands */
147 #define DEFAULT_SPIKE 10
148 static int sp; /* spike percentage */
149 #define DEFAULT_MOUNTAIN 0
150 static int pm; /* mountain percentage */
151 #define DEFAULT_CONTDIST 2
152 static int di; /* min. distance between continents */
153 #define DEFAULT_ISLDIST 1
154 static int id; /* ... continents and islands */
155 /* don't let the islands crash into each other.
156 1 = don't merge, 0 = merge. */
157 static int DISTINCT_ISLANDS = 1;
159 #define DEFAULT_OUTFILE_NAME "newcap_script"
160 static const char *outfile = DEFAULT_OUTFILE_NAME;
162 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
163 #define INFINITY 999 /* a number which means "BIG" */
165 /* these defines prevent infinite loops:
168 #define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector
169 when growing continents and islands */
170 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
171 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
172 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
177 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
178 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
180 static int secs; /* number of sectors grown */
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 *mc, mcc; /* array and counter used for stability
186 check when perturbing */
187 static int spike; /* are we spiking? */
188 static int mind; /* the final distance between capitals that
190 static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
191 static int diry[] = { 0, -1, -1, 0, 1, 1 };
193 static int **own; /* owner of the sector. -1 means water */
194 static int **elev; /* elevation of the sectors */
195 static int **sectx, **secty; /* the sectors for each continent */
196 static int **sectc; /* which sectors are on the coast? */
197 static int *vector; /* used for measuring distances */
198 static int *weight; /* used for placing mountains */
199 static int *dsea, *dmoun; /* the dist to the ocean and mountain */
200 static int fl_status; /* is anything wrong? */
201 #define STATUS_NO_ROOM 1 /* there was no room to grow */
202 #define NUMTRIES 10 /* keep trying to grow this many times */
204 static const char *numletter =
205 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
207 static void help(char *);
208 static void usage(void);
209 static void parse_args(int argc, char *argv[]);
210 static void allocate_memory(void);
211 static void init(void);
212 static int drift(void);
213 static void grow_continents(void);
214 static void create_elevations(void);
215 static void write_sects(void);
216 static void output(void);
217 static int write_newcap_script(void);
218 static int stable(void);
219 static void elevate_land(void);
220 static void elevate_sea(void);
221 static int map_symbol(int x, int y);
222 static void set_coastal_flags(void);
224 static void print_vars(void);
225 static void fl_move(int);
226 static void grow_islands(void);
228 /* Debugging aids: */
229 void print_own_map(void);
230 void print_elev_map(void);
232 /****************************************************************************
234 ****************************************************************************/
237 main(int argc, char *argv[])
240 char *config_file = NULL;
242 unsigned rnd_seed = 0;
245 program_name = argv[0];
247 while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
250 config_file = optarg;
253 DISTINCT_ISLANDS = 0;
259 rnd_seed = strtoul(optarg, NULL, 10);
269 printf("%s\n\n%s", version, legal);
276 parse_args(argc - optind, argv + optind);
279 rnd_seed = pick_seed();
282 if (emp_config(config_file) < 0)
289 qprint("\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
290 qprint("seed is %u\n", rnd_seed);
294 qprint("\ntry #%d (out of %d)...\n", i + 1, NUMTRIES);
295 qprint("placing capitals...\n");
297 qprint("unstable drift\n");
298 qprint("growing continents...\n");
300 } while (fl_status && ++i < NUMTRIES);
302 fputs("ERROR: World not large enough to hold continents\n",
306 qprint("growing islands:");
308 qprint("\nelevating land...\n");
311 qprint("writing to sectors file...\n");
312 if (!write_newcap_script())
314 if (chdir(gamedir)) {
315 fprintf(stderr, "Can't chdir to %s (%s)\n", gamedir, strerror(errno));
318 if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
321 if (!ef_close(EF_SECTOR))
325 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
335 puts("Creating a planet with:\n");
336 printf("%d continents\n", nc);
337 printf("continent size: %d\n", sc);
338 printf("number of islands: %d\n", ni);
339 printf("average size of islands: %d\n", is);
340 printf("spike: %d%%\n", sp);
341 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
342 pm, (pm * sc) / 100);
343 printf("minimum distance between continents: %d\n", di);
344 printf("minimum distance from islands to continents: %d\n", id);
345 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
349 help(char *complaint)
352 fprintf(stderr, "%s: %s\n", program_name, complaint);
353 fprintf(stderr, "Try -h for help.\n");
359 printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
360 " -e CONFIG-FILE configuration file\n"
362 " -i islands may merge\n"
364 " -R SEED seed for random number generator\n"
365 " -s SCRIPT name of script to create (default %s)\n"
366 " -h display this help and exit\n"
367 " -v display version information and exit\n"
368 " NC number of continents\n"
369 " SC continent size\n"
370 " NI number of islands (default NC)\n"
371 " IS average island size (default SC/2)\n"
372 " SP spike percentage: 0 = round, 100 = snake (default %d)\n"
373 " PM percentage of land that is mountain (default %d)\n"
374 " DI minimum distance between continents (default %d)\n"
375 " ID minimum distance from islands to continents (default %d)\n",
376 program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
377 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
381 parse_args(int argc, char *argv[])
384 help("missing arguments");
388 help("too many arguments");
393 puts("fairland: error -- number of continents must be > 0");
399 puts("fairland: error -- size of continents must be > 0");
419 sp = LIMIT_TO(sp, 0, 100);
424 pm = DEFAULT_MOUNTAIN;
431 di = DEFAULT_CONTDIST;
434 puts("fairland: error -- distance between continents must be >= 0");
437 if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
438 puts("fairland: error -- distance between continents too large");
445 id = DEFAULT_ISLDIST;
447 puts("fairland: error -- distance from islands to continents must be >= 0");
450 if (id > WORLD_X || id > WORLD_Y) {
451 puts("fairland: error -- distance from islands to continents too large");
456 /****************************************************************************
457 VARIABLE INITIALIZATION
458 ****************************************************************************/
461 allocate_memory(void)
465 capx = calloc(nc, sizeof(int));
466 capy = calloc(nc, sizeof(int));
467 vector = calloc(WORLD_X + WORLD_Y, sizeof(int));
468 mc = calloc(STABLE_CYCLE, sizeof(int));
469 own = calloc(WORLD_X, sizeof(int *));
470 elev = calloc(WORLD_X, sizeof(int *));
471 for (i = 0; i < WORLD_X; ++i) {
472 own[i] = calloc(WORLD_Y, sizeof(int));
473 elev[i] = calloc(WORLD_Y, sizeof(int));
475 sectx = calloc(nc + ni, sizeof(int *));
476 secty = calloc(nc + ni, sizeof(int *));
477 sectc = calloc(nc + ni, sizeof(int *));
478 isecs = calloc(nc + ni, sizeof(int));
479 weight = calloc(MAX(sc, is * 2), sizeof(int));
480 dsea = calloc(MAX(sc, is * 2), sizeof(int));
481 dmoun = calloc(MAX(sc, is * 2), sizeof(int));
482 for (i = 0; i < nc; ++i) {
483 sectx[i] = calloc(sc, sizeof(int));
484 secty[i] = calloc(sc, sizeof(int));
485 sectc[i] = calloc(sc, sizeof(int));
487 for (i = nc; i < nc + ni; ++i) {
488 sectx[i] = calloc(is * 2, sizeof(int));
489 secty[i] = calloc(is * 2, sizeof(int));
490 sectc[i] = calloc(is * 2, sizeof(int));
498 int i, j, xx = 0, yy = 0;
503 for (i = 0; i < WORLD_X; ++i) {
504 for (j = 0; j < WORLD_Y; ++j) {
506 elev[i][j] = -INFINITY;
510 for (i = 0; i < nc; ++i) {
515 puts("fairland error: world not big enough for all the continents.\n");
523 for (i = 0; i < STABLE_CYCLE; ++i)
527 /****************************************************************************
528 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
529 ****************************************************************************/
531 /* How isolated is capital j?
534 iso(int j, int newx, int newy)
536 int i, md, d = WORLD_X + WORLD_Y;
538 for (i = 0; i < nc; ++i) {
541 md = mapdist(capx[i], capy[i], newx, newy);
549 /* Drift all the capitals
556 for (turns = 0; turns < DRIFT_MAX; ++turns) {
557 if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
559 for (i = 0; i < nc; ++i)
565 /* Check to see if we have stabilized--can we stop drifting the capitals?
571 int i, isod, d = 0, stab = 1;
573 for (i = 0; i < nc; ++i) {
574 isod = iso(i, capx[i], capy[i]);
578 for (i = 0; i < STABLE_CYCLE; ++i)
582 mcc = (mcc + 1) % STABLE_CYCLE;
586 /* This routine does the actual drifting
592 int i, n, newx, newy;
594 for (i = roll0(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
595 newx = new_x(capx[j] + dirx[i]);
596 newy = new_y(capy[j] + diry[i]);
597 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
605 /****************************************************************************
607 ****************************************************************************/
609 /* Look for a coastal sector of continent c
617 for (i = 0; i < secs; ++i) {
619 for (j = 0; j < 6; ++j)
620 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
625 /* Used for measuring distances
637 for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
640 return i > 1 || vector[0] > 0;
643 /* Test to see if we're allowed to grow there: the arguments di and id
646 try_to_grow(int c, int newx, int newy, int d)
650 for (i = 1; i <= d; ++i) {
651 for (j = 0; j < i; ++j)
656 for (j = 0; j < i; ++j) {
657 px = new_x(px + dirx[vector[j]]);
658 py = new_y(py + diry[vector[j]]);
660 if (own[px][py] != -1 &&
662 (DISTINCT_ISLANDS || own[px][py] < nc))
664 } while (next_vector(i));
666 sectx[c][secs] = newx;
667 secty[c][secs] = newy;
672 /* Move along the coast in a clockwise direction.
676 next_coast(int c, int x, int y, int *xp, int *yp)
678 int i, nx, ny, wat = 0;
686 for (i = 0; i < 12; ++i) {
687 nx = new_x(x + dirx[i % 6]);
688 ny = new_y(y + diry[i % 6]);
689 if (own[nx][ny] == -1)
691 if (wat && own[nx][ny] == c) {
699 /* Choose a sector to grow from
711 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : roll0(secs);
716 } while (i != starti);
723 /* Grow continent c by 1 sector
727 grow_one_sector(int c)
729 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
731 spike = roll0(100) < sp;
732 if ((try1 = new_try(c)) == -1)
734 x = sx = sectx[c][try1];
735 y = sy = secty[c][try1];
740 for (i = roll0(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
741 newx = new_x(x + dirx[i]);
742 newy = new_y(y + diry[i]);
743 if (own[newx][newy] == -1 &&
745 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
746 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
747 if (try_to_grow(c, newx, newy, c < nc ? di : id))
751 for (i = roll0(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
752 newx = new_x(x + dirx[i]);
753 newy = new_y(y + diry[i]);
754 if (own[newx][newy] == -1)
755 if (try_to_grow(c, newx, newy, c < nc ? di : id))
758 next_coast(c, x, y, &x, &y);
760 } while (!done && coast_search < COAST_SEARCH_MAX &&
761 (secs == 1 || x != sx || y != sy));
763 fl_status |= STATUS_NO_ROOM;
767 /* Grow all the continents
770 grow_continents(void)
774 for (c = 0; c < nc; ++c) {
775 sectx[c][0] = capx[c];
776 secty[c][0] = capy[c];
777 own[sectx[c][0]][secty[c][0]] = c;
778 sectx[c][1] = new_x(capx[c] + 2);
779 secty[c][1] = capy[c];
780 own[sectx[c][1]][secty[c][1]] = c;
783 for (secs = 2; secs < sc && !fl_status; ++secs) {
784 for (c = 0; c < nc; ++c) {
789 for (c = 0; c < nc; ++c)
793 qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
797 /****************************************************************************
799 ****************************************************************************/
801 /* Choose a place to start growing an island from
804 place_island(int c, int *xp, int *yp)
807 int ssy = roll0(WORLD_Y);
808 int ssx = new_x(roll0(WORLD_X / 2) * 2 + ssy % 2);
810 if (ssx > WORLD_X - 2)
811 ssx = new_x(ssx + 2);
812 for (d = di + id; d >= id; --d) {
816 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
817 if (*xp >= WORLD_X) {
818 *yp = new_y(*yp + 1);
820 if (*xp == sx && *yp == sy)
823 if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
830 /* Grow all the islands
838 for (c = nc; c < nc + ni; ++c) {
840 if (!place_island(c, &x, &y))
842 isiz = roll(is) + roll0(is);
846 } while (secs < isiz && grow_one_sector(c));
848 qprint(" %d(%d)", c - nc + 1, secs);
854 /****************************************************************************
856 ****************************************************************************/
858 create_elevations(void)
864 /* Generic function for finding the distance to the closest sea, land, or
868 distance_to_what(int x, int y, int flag)
872 for (d = 1; d < 5; ++d) {
873 for (j = 0; j < d; ++j)
878 for (j = 0; j < d; ++j) {
879 px = new_x(px + dirx[vector[j]]);
880 py = new_y(py + diry[vector[j]]);
883 case 0: /* distance to sea */
884 if (own[px][py] == -1)
887 case 1: /* distance to land */
888 if (own[px][py] != -1)
891 case 2: /* distance to mountain */
892 if (elev[px][py] == INFINITY)
896 } while (next_vector(d));
901 #define ELEV elev[sectx[c][i]][secty[c][i]]
902 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
903 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
905 /* Decide where the mountains go
910 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
913 for (c = 0; c < ctot; ++c) {
915 ns = (c < nc) ? sc : isecs[c];
916 nm = (pm * ns) / 100;
918 /* Place the mountains */
920 for (i = 0; i < ns; ++i) {
921 dsea[i] = distance_to_sea();
922 weight[i] = (total += (dsea[i] * dsea[i]));
925 for (k = nm, mountain_search = 0;
926 k && mountain_search < MOUNTAIN_SEARCH_MAX;
929 for (i = 0; i < ns; ++i)
930 if (r < weight[i] && ELEV == -INFINITY &&
932 ((!(capx[c] == sectx[c][i] &&
933 capy[c] == secty[c][i])) &&
934 (!(new_x(capx[c] + 2) == sectx[c][i] &&
935 capy[c] == secty[c][i]))))) {
942 /* Elevate land that is not mountain and not capital */
944 for (i = 0; i < ns; ++i)
945 dmoun[i] = distance_to_mountain();
946 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
947 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
949 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
952 for (i = 0; i < ns; ++i) {
953 if (ELEV != INFINITY &&
954 (c >= nc || ((!(capx[c] == sectx[c][i] &&
955 capy[c] == secty[c][i])) &&
956 (!(new_x(capx[c] + 2) == sectx[c][i] &&
957 capy[c] == secty[c][i]))))) {
958 h = 3 * (5 - dmoun[i]) + dsea[i];
968 if (newk >= HILLMIN && newk < PLATMIN)
972 elev[sectx[c][where]][secty[c][where]] = newk;
973 dsea[where] = -INFINITY;
974 dmoun[where] = INFINITY;
977 /* Elevate the mountains and capitals */
979 for (i = 0; i < ns; ++i) {
980 if (ELEV == INFINITY) {
982 ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
984 ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
985 roll0((256 - HIGHMIN) / 2);
987 (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
988 ((new_x(capx[c] + 2) == sectx[c][i] &&
989 capy[c] == secty[c][i]))))
995 #define distance_to_land() distance_to_what(x, y, 1)
1002 for (y = 0; y < WORLD_Y; ++y) {
1003 for (x = y % 2; x < WORLD_X; x += 2) {
1004 if (elev[x][y] == -INFINITY)
1005 elev[x][y] = -roll(distance_to_land() * 20 + 27);
1010 /****************************************************************************
1012 ****************************************************************************/
1019 fert = LANDMIN - e + 40;
1020 else if (e < FERT_MAX)
1021 fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1032 oil = (LANDMIN - e) * 2 + roll0(2);
1033 else if (e <= OIL_MAX)
1034 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1044 if (e >= IRON_MIN && e < HIGHMIN)
1045 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1055 if (e >= GOLD_MIN) {
1057 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1059 gold = 100 - 20 * HIGHMIN / e;
1070 if (e >= URAN_MIN && e < HIGHMIN)
1071 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1078 add_resources(struct sctstr *sct)
1080 sct->sct_fertil = set_fert(sct->sct_elev);
1081 sct->sct_oil = set_oil(sct->sct_elev);
1082 sct->sct_min = set_iron(sct->sct_elev);
1083 sct->sct_gmin = set_gold(sct->sct_elev);
1084 sct->sct_uran = set_uran(sct->sct_elev);
1087 /****************************************************************************
1088 DESIGNATE THE SECTORS
1089 ****************************************************************************/
1097 for (y = 0; y < WORLD_Y; y++) {
1098 for (x = y % 2; x < WORLD_X; x += 2) {
1099 sct = getsectp(x, y);
1101 if (total < LANDMIN) {
1102 sct->sct_type = SCT_WATER;
1103 } else if (total < HILLMIN)
1104 sct->sct_type = SCT_RURAL;
1105 else if (total < PLATMIN)
1106 sct->sct_type = SCT_MOUNT;
1107 else if (total < HIGHMIN)
1108 sct->sct_type = SCT_RURAL;
1110 sct->sct_type = SCT_MOUNT;
1111 sct->sct_elev = total;
1112 sct->sct_newtype = sct->sct_type;
1113 sct->sct_dterr = own[sct->sct_x][y] + 1;
1117 set_coastal_flags();
1120 /****************************************************************************
1121 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1122 ****************************************************************************/
1129 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1134 for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
1136 if (own[x][y] == -1)
1139 printf("%c ", map_symbol(x, y));
1147 map_symbol(int x, int y)
1151 for (c = 0; c < nc; ++c)
1152 if ((x == capx[c] && y == capy[c])
1153 || (x == new_x(capx[c] + 2) && y == capy[c]))
1154 return numletter[own[x][y] % 62];
1155 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1156 || elev[x][y] >= HIGHMIN)
1158 return own[x][y] >= nc ? '%' : '#';
1162 * Print a map to help visualize own[][].
1163 * This is for debugging.
1170 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1173 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1177 else if (own[x][y] == -1)
1180 putchar(numletter[own[x][y] % 62]);
1187 * Print a map to help visualize elev[][].
1188 * This is for debugging. It expects the terminal to understand
1189 * 24-bit color escape sequences \e[48;2;$red;$green;$blue;m.
1192 print_elev_map(void)
1194 int sx, sy, x, y, sat;
1196 for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
1199 for (sx = -WORLD_X / 2; sx < WORLD_X / 2; sx++) {
1203 else if (!elev[x][y])
1205 else if (elev[x][y] < 0) {
1206 sat = 256 + elev[x][y] * 2;
1207 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat, 255);
1208 } else if (elev[x][y] < HIGHMIN / 2) {
1209 sat = (HIGHMIN / 2 - elev[x][y]) * 4;
1210 printf("\033[48;2;%d;%d;%dm \033[0m", sat, 255, sat);
1211 } else if (elev[x][y] < HIGHMIN) {
1212 sat = 128 + (HIGHMIN - elev[x][y]) * 2;
1213 printf("\033[48;2;%d;%d;%dm \033[0m", sat, sat / 2, sat / 4);
1215 sat = 128 + (elev[x][y] - HIGHMIN) * 4 / 5;
1216 printf("\033[48;2;%d;%d;%dm^\033[0m", sat, sat, sat);
1223 /***************************************************************************
1224 WRITE A SCRIPT FOR PLACING CAPITALS
1225 ****************************************************************************/
1227 write_newcap_script(void)
1230 FILE *script = fopen(outfile, "w");
1233 printf("fairland: error, unable to write to %s.\n", outfile);
1237 for (c = 0; c < nc; ++c) {
1238 fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
1239 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1241 fprintf(script, "add %d visitor visitor v\n", c + 1);
1247 qprint(const char *const fmt, ...)
1253 vfprintf(stdout, fmt, ap);
1259 set_coastal_flags(void)
1264 for (i = 0; i < nc; ++i) {
1265 for (j = 0; j < sc; j++) {
1266 sp = getsectp(sectx[i][j], secty[i][j]);
1267 sp->sct_coastal = sectc[i][j];
1270 for (i = nc; i < nc + ni; ++i) {
1271 for (j = 0; j < isecs[i]; j++) {
1272 sp = getsectp(sectx[i][j], secty[i][j]);
1273 sp->sct_coastal = sectc[i][j];