2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
6 * This program 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 2 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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * fairland.c: Create a nice, new world
30 * Known contributors to this file:
35 /* define ORE 1 to add resources, define ORE 0 if you want to use another
36 program to add the resources */
40 /* If you don't specify these command line arguments, then these are the
42 #define DEFAULT_SPIKE 10
43 #define DEFAULT_MOUNTAIN 0
44 #define DEFAULT_CONTDIST 2
45 #define DEFAULT_ISLDIST 1
47 /* The following five numbers refer to elevation under which (in the case of
48 fertility or oil) or over which (in the case of iron, gold, and uranium)
49 sectors with that elevation will contain that resource. Elevation ranges
52 /* raise FERT_MAX for more fertility */
55 /* raise OIL_MAX for more oil */
58 /* lower IRON_MIN for more iron */
61 /* lower GOLD_MIN for more gold */
64 /* lower URAN_MIN for more uranium */
68 #include "../lib/gen/getopt.h"
83 #include "prototypes.h"
85 /* do not change these 4 defines */
86 #define LANDMIN 1 /* plate altitude for normal land */
87 #define HILLMIN 34 /* plate altitude for hills */
88 #define PLATMIN 36 /* plate altitude for plateau */
89 #define HIGHMIN 98 /* plate altitude for mountains */
91 static void qprint(const char * const fmt, ...)
92 ATTRIBUTE((format (printf, 1, 2)));
94 #define DEFAULT_OUTFILE_NAME "newcap_script"
95 static const char *outfile = DEFAULT_OUTFILE_NAME;
96 /* mark the continents with a * so you can tell them
97 from the islands 1 = mark, 0 = don't mark. */
98 static int AIRPORT_MARKER = 0;
100 /* don't let the islands crash into each other.
101 1 = don't merge, 0 = merge. */
102 static int DISTINCT_ISLANDS = 1;
104 static char *program_name;
106 #define XSIZE ((WORLD_X) / 2) /* basically world x-y size */
107 #define YSIZE (WORLD_Y)
108 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
109 #define INFINITY 999 /* a number which means "BIG" */
111 /* these defines prevent infinite loops:
114 #define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector
115 when growing continents and islands */
116 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
117 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
118 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
123 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
124 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
126 #define max(a,b) (a>b?a:b)
128 #define rnd(x) (random() % (x))
130 int secs; /* number of sectors grown */
131 int ctot; /* total number of continents and islands grown */
132 int *isecs; /* array of how large each island is */
134 int nc, sc, di, sp, pm, ni, is, id; /* the 8 arguments to this program */
135 unsigned long rnd_seed; /* optional seed can be passed as an argument */
136 int *capx, *capy; /* location of the nc capitals */
137 int *mc, mcc; /* array and counter used for stability
138 check when perturbing */
139 int spike; /* are we spiking? */
140 int mind; /* the final distance between capitals that
142 int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
143 int diry[] = { 0, -1, -1, 0, 1, 1 };
145 int **own; /* owner of the sector. -1 means water */
146 int **elev; /* elevation of the sectors */
147 int **sectx, **secty; /* the sectors for each continent */
148 int **sectc; /* which sectors are on the coast? */
149 int *vector; /* used for measuring distances */
150 int *weight; /* used for placing mountains */
151 int *dsea, *dmoun; /* the dist to the ocean and mountain */
152 FILE *sect_fptr; /* the file we write everything to */
153 struct sctstr **sects;
154 struct sctstr *sectsbuf;
155 int fl_status; /* is anything wrong? */
156 #define STATUS_NO_ROOM 1 /* there was no room to grow */
157 #define NUMTRIES 10 /* keep trying to grow this many times */
159 const char *numletter =
160 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
162 static void help(char *);
163 static void usage(void);
164 static void parse_args(int argc, char *argv[]);
165 static int allocate_memory(void);
166 static void init(void);
167 static int drift(void);
168 static void grow_continents(void);
169 static void create_elevations(void);
170 static void write_sects(void);
171 static int write_file(void);
172 static void output(void);
173 static int write_newcap_script(void);
174 static int stable(void);
175 static void elevate_land(void);
176 static void elevate_sea(void);
177 static void translate_continents(void);
178 static int map_symbol(int x, int y);
179 static void fl_sct_init(coord x, coord y, s_char *ptr,
181 static void set_coastal_flags(void);
183 static void print_vars(void);
184 static void fl_move(int);
185 static void next_coast(int c, int x, int y, int *xp, int *yp);
186 static void grow_islands(void);
188 /****************************************************************************
190 ****************************************************************************/
193 main(int argc, char *argv[])
196 char *config_file = NULL;
199 program_name = argv[0];
200 rnd_seed = time(NULL);
202 while ((opt = getopt(argc, argv, "ae:hioqs:R:")) != EOF) {
208 DISTINCT_ISLANDS = 0;
211 config_file = optarg;
223 rnd_seed = strtoul(optarg, NULL, 10);
234 if (emp_config(config_file))
237 parse_args(argc - optind, argv + optind);
238 if (allocate_memory() == -1)
245 qprint("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
246 qprint("\n\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
247 qprint("seed is %lu\n", rnd_seed);
248 qprint("placing capitals...\n");
250 qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
251 qprint("growing continents...\n");
253 } while (fl_status && ++i < NUMTRIES);
255 fputs("ERROR: World not large enough to hold continents\n",
259 qprint("growing islands:");
261 qprint("\nelevating land...\n");
263 qprint("designating sectors...\n");
265 qprint("adding resources...\n");
267 qprint("writing to sectors file...\n");
268 if (write_file() == -1)
271 write_newcap_script();
273 qprint("\t*** Resources have not been added ***\n");
282 puts("Creating a planet with:\n");
283 printf("%d continents\n", nc);
284 printf("continent size: %d\n", sc);
285 printf("number of islands: %d\n", ni);
286 printf("average size of islands: %d\n", is);
287 printf("spike: %d%%\n", sp);
288 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
289 pm, (pm * sc) / 100);
290 printf("minimum distance between continents: %d\n", di);
291 printf("minimum distance from islands to continents: %d\n", id);
292 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
300 for (i = 1; i * i < n * 10000; ++i) ;
301 return (i + 50) / 100;
304 /****************************************************************************
305 PARSE COMMAND LINE ARGUMENTS
306 ****************************************************************************/
309 help(char *complaint)
312 fprintf(stderr, "%s: %s\n", program_name, complaint);
313 fprintf(stderr, "Try -h for help.\n");
319 printf("Usage: %s [-e CONFIG] [-aiqo] [-s SCRIPT] [-R SEED] NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
321 " -o don't set resources\n"
322 " -a airport marker for continents\n"
323 " -i islands may merge\n"
324 " -R SEED seed for random number generator\n"
325 " -e CONFIG configuration file\n"
326 " -s SCRIPT name of script to create (default %s)\n"
327 " NC number of continents\n"
328 " SC continent size\n"
329 " NI number of islands (default NC)\n"
330 " IS average island size (default SC/2)\n"
331 " SP spike percentage: 0 = round, 100 = snake\n"
333 " PM percentage of land that is mountain (default %d)\n"
334 " DI minimum distance between continents (default %d)\n"
335 " ID minimum distance from islands to continents (default %d)\n",
336 program_name, DEFAULT_OUTFILE_NAME,
337 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
341 parse_args(int argc, char *argv[])
344 help("missing arguments");
348 help("too many arguments");
353 puts("fairland: error -- number of continents must be > 0");
359 puts("fairland: error -- size of continents must be > 0");
387 pm = DEFAULT_MOUNTAIN;
394 di = DEFAULT_CONTDIST;
397 puts("fairland: error -- distance between continents must be >= 0");
400 if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
401 puts("fairland: error -- distance between continents too large");
408 id = DEFAULT_ISLDIST;
410 puts("fairland: error -- distance from islands to continents must be >= 0");
413 if (id > WORLD_X || id > WORLD_Y) {
414 puts("fairland: error -- distance from islands to continents too large");
417 if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
418 puts("fairland: error -- world not big enough to fit continents.");
419 puts("arguments must satisfy:");
420 puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
425 /****************************************************************************
426 VARIABLE INITIALIZATION
427 ****************************************************************************/
430 allocate_memory(void)
435 fname = malloc(strlen(datadir) + 1 + strlen(empfile[EF_SECTOR].file) + 1);
436 sprintf(fname, "%s/%s", datadir, empfile[EF_SECTOR].file);
437 sect_fptr = fopen(fname, "wb");
438 if (sect_fptr == NULL) {
443 sectsbuf = calloc((YSIZE * XSIZE), sizeof(struct sctstr));
444 sects = calloc(YSIZE, sizeof(struct sctstr *));
445 for (i = 0; i < YSIZE; i++)
446 sects[i] = §sbuf[XSIZE * i];
447 capx = calloc(nc, sizeof(int));
448 capy = calloc(nc, sizeof(int));
449 vector = calloc(WORLD_X + WORLD_Y, sizeof(int));
450 mc = calloc(STABLE_CYCLE, sizeof(int));
451 own = calloc(WORLD_X, sizeof(int *));
452 elev = calloc(WORLD_X, sizeof(int *));
453 for (i = 0; i < WORLD_X; ++i) {
454 own[i] = calloc(WORLD_Y, sizeof(int));
455 elev[i] = calloc(WORLD_Y, sizeof(int));
457 sectx = calloc(nc + ni, sizeof(int *));
458 secty = calloc(nc + ni, sizeof(int *));
459 sectc = calloc(nc + ni, sizeof(int *));
460 isecs = calloc(nc + ni, sizeof(int));
461 weight = calloc(max(sc, is * 2), sizeof(int));
462 dsea = calloc(max(sc, is * 2), sizeof(int));
463 dmoun = calloc(max(sc, is * 2), sizeof(int));
464 for (i = 0; i < nc; ++i) {
465 sectx[i] = calloc(sc, sizeof(int));
466 secty[i] = calloc(sc, sizeof(int));
467 sectc[i] = calloc(sc, sizeof(int));
469 for (i = nc; i < nc + ni; ++i) {
470 sectx[i] = calloc(is * 2, sizeof(int));
471 secty[i] = calloc(is * 2, sizeof(int));
472 sectc[i] = calloc(is * 2, sizeof(int));
481 int i, j, xx = 0, yy = 0;
486 for (i = 0; i < WORLD_X; ++i) {
487 for (j = 0; j < WORLD_Y; ++j) {
489 elev[i][j] = -INFINITY;
493 for (i = 0; i < nc; ++i, xx += 2) {
498 puts("fairland error: world not big enough for all the continents.\n");
505 for (i = 0; i < STABLE_CYCLE; ++i)
509 /****************************************************************************
510 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
511 ****************************************************************************/
513 /* How isolated is capital j?
516 iso(int j, int newx, int newy)
518 int i, md, d = WORLD_X + WORLD_Y;
520 for (i = 0; i < nc; ++i) {
523 md = mapdist(capx[i], capy[i], newx, newy);
531 /* Drift all the capitals
538 for (turns = 0; turns < DRIFT_MAX; ++turns) {
539 if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
541 for (i = 0; i < nc; ++i)
547 /* Check to see if we have stabilized--can we stop drifting the capitals?
553 int i, isod, d = 0, stab = 1;
555 for (i = 0; i < nc; ++i) {
556 isod = iso(i, capx[i], capy[i]);
560 for (i = 0; i < STABLE_CYCLE; ++i)
564 mcc = (mcc + 1) % STABLE_CYCLE;
568 /* This routine does the actual drifting
574 int i, n, newx, newy;
576 for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
577 newx = new_x(capx[j] + dirx[i]);
578 newy = new_y(capy[j] + diry[i]);
579 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
587 /****************************************************************************
589 ****************************************************************************/
591 /* Look for a coastal sector of continent c
599 for (i = 0; i < secs; ++i) {
601 for (j = 0; j < 6; ++j)
602 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
607 /* Used for measuring distances
619 for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
622 return i > 1 || vector[0] > 0;
625 /* Test to see if we're allowed to grow there: the arguments di and id
628 try_to_grow(int c, int newx, int newy, int d)
632 for (i = 1; i <= d; ++i) {
633 for (j = 0; j < i; ++j)
638 for (j = 0; j < i; ++j) {
639 px = new_x(px + dirx[vector[j]]);
640 py = new_y(py + diry[vector[j]]);
642 if (own[px][py] != -1 &&
644 (DISTINCT_ISLANDS || own[px][py] < nc))
646 } while (next_vector(i));
648 sectx[c][secs] = newx;
649 secty[c][secs] = newy;
654 /* Move along the coast in a clockwise direction.
658 next_coast(int c, int x, int y, int *xp, int *yp)
660 int i, nx, ny, wat = 0;
668 for (i = 0; i < 12; ++i) {
669 nx = new_x(x + dirx[i % 6]);
670 ny = new_y(y + diry[i % 6]);
671 if (own[nx][ny] == -1)
673 if (wat && own[nx][ny] == c) {
681 /* Choose a sector to grow from
693 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
698 } while (i != starti);
700 printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
709 /* Grow continent c by 1 sector
713 grow_one_sector(int c)
715 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
717 spike = rnd(100) < sp;
718 if ((try1 = new_try(c)) == -1)
720 x = sx = sectx[c][try1];
721 y = sy = secty[c][try1];
726 for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
727 newx = new_x(x + dirx[i]);
728 newy = new_y(y + diry[i]);
729 if (own[newx][newy] == -1 &&
731 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
732 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
733 if (try_to_grow(c, newx, newy, c < nc ? di : id))
737 for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
738 newx = new_x(x + dirx[i]);
739 newy = new_y(y + diry[i]);
740 if (own[newx][newy] == -1)
741 if (try_to_grow(c, newx, newy, c < nc ? di : id))
744 next_coast(c, x, y, &x, &y);
746 } while (!done && coast_search < COAST_SEARCH_MAX &&
747 (secs == 1 || x != sx || y != sy));
748 if (!done && c < nc) {
749 qprint("fairland: error -- continent %c had no room to grow!\n",
751 fl_status |= STATUS_NO_ROOM;
756 /* Grow all the continents
759 grow_continents(void)
763 for (c = 0; c < nc; ++c) {
764 sectx[c][0] = capx[c];
765 secty[c][0] = capy[c];
766 own[sectx[c][0]][secty[c][0]] = c;
767 sectx[c][1] = new_x(capx[c] + 2);
768 secty[c][1] = capy[c];
769 own[sectx[c][1]][secty[c][1]] = c;
772 for (secs = 2; secs < sc && !fl_status; ++secs) {
773 for (c = 0; c < nc; ++c) {
778 for (c = 0; c < nc; ++c)
782 qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
786 /****************************************************************************
788 ****************************************************************************/
790 /* Choose a place to start growing an island from
793 place_island(int c, int *xp, int *yp)
796 int ssy = rnd(WORLD_Y);
797 int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
799 if (ssx > WORLD_X - 2)
800 ssx = new_x(ssx + 2);
801 for (d = di + id; d >= id; --d) {
805 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
806 if (*xp >= WORLD_X) {
807 *yp = new_y(*yp + 1);
809 if (*xp == sx && *yp == sy)
812 if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
819 /* Grow all the islands
827 for (c = nc; c < nc + ni; ++c) {
829 if (!place_island(c, &x, &y))
831 isiz = 1 + rnd(2 * is - 1);
835 } while (secs < isiz && grow_one_sector(c));
837 qprint(" %d(%d)", c - nc + 1, secs);
843 /****************************************************************************
845 ****************************************************************************/
847 create_elevations(void)
853 /* Generic function for finding the distance to the closest sea, land, or
857 distance_to_what(int x, int y, int flag)
861 for (d = 1; d < 5; ++d) {
862 for (j = 0; j < d; ++j)
867 for (j = 0; j < d; ++j) {
868 px = new_x(px + dirx[vector[j]]);
869 py = new_y(py + diry[vector[j]]);
872 case 0: /* distance to sea */
873 if (own[px][py] == -1)
876 case 1: /* distance to land */
877 if (own[px][py] != -1)
880 case 2: /* distance to mountain */
881 if (elev[px][py] == INFINITY)
885 } while (next_vector(d));
890 #define ELEV elev[sectx[c][i]][secty[c][i]]
891 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
892 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
894 /* Decide where the mountains go
899 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
902 for (c = 0; c < ctot; ++c) {
904 ns = (c < nc) ? sc : isecs[c];
905 nm = (pm * ns) / 100;
907 /* Place the mountains */
909 for (i = 0; i < ns; ++i) {
910 dsea[i] = distance_to_sea();
911 weight[i] = (total += (dsea[i] * dsea[i]));
914 for (k = nm, mountain_search = 0;
915 k && mountain_search < MOUNTAIN_SEARCH_MAX;
918 for (i = 0; i < ns; ++i)
919 if (r < weight[i] && ELEV == -INFINITY &&
921 ((!(capx[c] == sectx[c][i] &&
922 capy[c] == secty[c][i])) &&
923 (!(new_x(capx[c] + 2) == sectx[c][i] &&
924 capy[c] == secty[c][i]))))) {
931 /* Elevate land that is not mountain and not capital */
933 for (i = 0; i < ns; ++i)
934 dmoun[i] = distance_to_mountain();
935 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
936 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
938 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
941 for (i = 0; i < ns; ++i) {
942 if (ELEV != INFINITY &&
943 (c >= nc || ((!(capx[c] == sectx[c][i] &&
944 capy[c] == secty[c][i])) &&
945 (!(new_x(capx[c] + 2) == sectx[c][i] &&
946 capy[c] == secty[c][i]))))) {
947 h = 3 * (5 - dmoun[i]) + dsea[i];
957 if (newk >= HILLMIN && newk < PLATMIN)
961 elev[sectx[c][where]][secty[c][where]] = newk;
962 dsea[where] = -INFINITY;
963 dmoun[where] = INFINITY;
966 /* Elevate the mountains and capitals */
968 for (i = 0; i < ns; ++i) {
969 if (ELEV == INFINITY) {
971 ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
973 ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
974 rnd((256 - HIGHMIN) / 2);
975 } else if ((c < nc &&
976 ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
977 ((new_x(capx[c] + 2) == sectx[c][i] &&
978 capy[c] == secty[c][i])))
984 #define distance_to_land() distance_to_what(x, y, 1)
991 for (y = 0; y < WORLD_Y; ++y) {
992 for (x = y % 2; x < WORLD_X; x += 2) {
993 if (elev[x][y] == -INFINITY)
994 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
999 /****************************************************************************
1001 ****************************************************************************/
1008 fert = LANDMIN - e + 40;
1009 else if (e < FERT_MAX)
1010 fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1021 oil = (LANDMIN - e) * 2 + rnd(2);
1022 else if (e <= OIL_MAX)
1023 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1033 if (e >= IRON_MIN && e < HIGHMIN)
1034 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1044 if (e >= GOLD_MIN) {
1046 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1048 gold = 100 - 20 * HIGHMIN / e;
1059 if (e >= URAN_MIN && e < HIGHMIN)
1060 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1067 add_resources(struct sctstr *sct)
1069 sct->sct_fertil = set_fert(sct->sct_elev);
1070 sct->sct_oil = set_oil(sct->sct_elev);
1071 sct->sct_min = set_iron(sct->sct_elev);
1072 sct->sct_gmin = set_gold(sct->sct_elev);
1073 sct->sct_uran = set_uran(sct->sct_elev);
1076 /****************************************************************************
1077 DESIGNATE THE SECTORS
1078 ****************************************************************************/
1085 time_t current_time = time(NULL);
1087 /* sct = §s[0][0]; */
1089 for (y = 0; y < YSIZE; y++) {
1090 for (x = 0; x < XSIZE; x++, sct++) {
1091 fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct, current_time);
1092 total = elev[sct->sct_x][y];
1093 if (total < LANDMIN) {
1094 sct->sct_type = SCT_WATER;
1095 } else if (total < HILLMIN)
1096 sct->sct_type = SCT_RURAL;
1097 else if (total < PLATMIN)
1098 sct->sct_type = SCT_MOUNT;
1099 else if (total < HIGHMIN)
1100 sct->sct_type = SCT_RURAL;
1102 sct->sct_type = SCT_MOUNT;
1103 sct->sct_elev = total;
1104 sct->sct_newtype = sct->sct_type;
1110 for (c = 0; c < nc; ++c) {
1111 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1112 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1114 set_coastal_flags();
1117 /****************************************************************************
1118 WRITE ALL THIS STUFF TO THE FILE
1119 ****************************************************************************/
1125 n = fwrite(sectsbuf, sizeof(struct sctstr), YSIZE * XSIZE, sect_fptr);
1127 perror(empfile[EF_SECTOR].file);
1130 if (n != YSIZE * XSIZE) {
1131 printf("%s:partial write\n", empfile[EF_SECTOR].file);
1138 /****************************************************************************
1139 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1140 ****************************************************************************/
1146 translate_continents();
1148 for (i = 0; i < WORLD_Y; ++i) {
1152 for (j = i % 2; j < WORLD_X; j += 2) {
1153 if (own[j][i] == -1)
1156 printf("%c ", map_symbol(j, i));
1162 printf("\n\nEach continent is marked by a \"*\" on the map (to distinguish them from\nthe islands). You can redesignate these airfields to wilderness sectors\none at a time, each time you add a new country to the game.\n");
1165 /* Reorder the continents from top left to bottom right */
1167 translate_continents(void)
1169 int i, j, n = 0, k, gotit, c;
1170 int *trans, *trans_cont, *oldcapx, *oldcapy;
1172 trans = calloc(nc, sizeof(int));
1173 trans_cont = calloc(nc, sizeof(int));
1174 oldcapx = calloc(nc, sizeof(int));
1175 oldcapy = calloc(nc, sizeof(int));
1177 for (i = 0; i < WORLD_Y; ++i) {
1178 for (j = i % 2; j < WORLD_X; j += 2) {
1179 if (own[j][i] > -1 && own[j][i] < nc) {
1181 for (k = 0; k < n; ++k) {
1182 if (trans[k] == own[j][i])
1187 printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n");
1190 trans[n] = own[j][i];
1191 trans_cont[own[j][i]] = n;
1197 for (i = 0; i < WORLD_Y; ++i) {
1198 for (j = i % 2; j < WORLD_X; j += 2) {
1199 if (own[j][i] > -1 && own[j][i] < nc) {
1200 own[j][i] = trans_cont[own[j][i]];
1204 for (c = 0; c < nc; ++c) {
1205 oldcapx[c] = capx[c];
1206 oldcapy[c] = capy[c];
1208 for (c = 0; c < nc; ++c) {
1209 capx[c] = oldcapx[trans[c]];
1210 capy[c] = oldcapy[trans[c]];
1215 map_symbol(int x, int y)
1219 for (c = 0; c < nc; ++c)
1220 if ((x == capx[c] && y == capy[c])
1221 || (x == new_x(capx[c] + 2) && y == capy[c]))
1223 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1224 || elev[x][y] >= HIGHMIN)
1226 return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1229 /***************************************************************************
1230 WRITE A SCRIPT FOR PLACING CAPITALS
1231 ****************************************************************************/
1233 write_newcap_script(void)
1236 FILE *script = fopen(outfile, "w");
1239 printf("fairland: error, unable to write to %s.\n", outfile);
1243 for (c = 0; c < nc; ++c) {
1244 fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1246 fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1247 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1249 fprintf(script, "add %d visitor visitor v i\n", c + 1);
1252 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1258 qprint(const char * const fmt, ...)
1264 vfprintf(stdout, fmt, ap);
1270 fl_sct_init(coord x, coord y, s_char *ptr, time_t timestamp)
1272 struct sctstr *sp = (struct sctstr *)ptr;
1274 sp->ef_type = EF_SECTOR;
1281 sp->sct_defense = 0;
1282 sp->sct_timestamp = timestamp;
1283 sp->sct_coastal = 1;
1287 set_coastal_flags(void)
1291 qprint("setting coastal flags...\n");
1292 for (i = 0; i < nc; ++i)
1293 for (j = 0; j < sc; j++)
1294 sects[secty[i][j]][sectx[i][j] / 2].sct_coastal = sectc[i][j];
1295 for (i = nc; i < nc + ni; ++i)
1296 for (j = 0; j < isecs[i]; j++)
1297 sects[secty[i][j]][sectx[i][j] / 2].sct_coastal = sectc[i][j];