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"
84 #include "prototypes.h"
86 /* do not change these 4 defines */
87 #define LANDMIN 1 /* plate altitude for normal land */
88 #define HILLMIN 34 /* plate altitude for hills */
89 #define PLATMIN 36 /* plate altitude for plateau */
90 #define HIGHMIN 98 /* plate altitude for mountains */
92 static void qprint(const char * const fmt, ...)
93 ATTRIBUTE((format (printf, 1, 2)));
95 #define DEFAULT_OUTFILE_NAME "newcap_script"
96 static const char *outfile = DEFAULT_OUTFILE_NAME;
97 /* mark the continents with a * so you can tell them
98 from the islands 1 = mark, 0 = don't mark. */
99 static int AIRPORT_MARKER = 0;
101 /* don't let the islands crash into each other.
102 1 = don't merge, 0 = merge. */
103 static int DISTINCT_ISLANDS = 1;
105 static char *program_name;
107 #define XSIZE ((WORLD_X) / 2) /* basically world x-y size */
108 #define YSIZE (WORLD_Y)
109 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
110 #define INFINITY 999 /* a number which means "BIG" */
112 /* these defines prevent infinite loops:
115 #define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector
116 when growing continents and islands */
117 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
118 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
119 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
124 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
125 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
127 #define max(a,b) (a>b?a:b)
129 #define rnd(x) (random() % (x))
131 int secs; /* number of sectors grown */
132 int ctot; /* total number of continents and islands grown */
133 int *isecs; /* array of how large each island is */
135 int nc, sc, di, sp, pm, ni, is, id; /* the 8 arguments to this program */
136 unsigned long rnd_seed; /* optional seed can be passed as an argument */
137 int *capx, *capy; /* location of the nc capitals */
138 int *mc, mcc; /* array and counter used for stability
139 check when perturbing */
140 int spike; /* are we spiking? */
141 int mind; /* the final distance between capitals that
143 int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
144 int diry[] = { 0, -1, -1, 0, 1, 1 };
146 int **own; /* owner of the sector. -1 means water */
147 int **elev; /* elevation of the sectors */
148 int **sectx, **secty; /* the sectors for each continent */
149 int **sectc; /* which sectors are on the coast? */
150 int *vector; /* used for measuring distances */
151 int *weight; /* used for placing mountains */
152 int *dsea, *dmoun; /* the dist to the ocean and mountain */
153 FILE *sect_fptr; /* the file we write everything to */
154 struct sctstr **sects;
155 struct sctstr *sectsbuf;
156 int fl_status; /* is anything wrong? */
157 #define STATUS_NO_ROOM 1 /* there was no room to grow */
158 #define NUMTRIES 10 /* keep trying to grow this many times */
160 const char *numletter =
161 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
163 static void help(char *);
164 static void usage(void);
165 static void parse_args(int argc, char *argv[]);
166 static int allocate_memory(void);
167 static void init(void);
168 static int drift(void);
169 static void grow_continents(void);
170 static void create_elevations(void);
171 static void write_sects(void);
172 static int write_file(void);
173 static void output(void);
174 static int write_newcap_script(void);
175 static int stable(void);
176 static void elevate_land(void);
177 static void elevate_sea(void);
178 static void translate_continents(void);
179 static int map_symbol(int x, int y);
180 static void fl_sct_init(coord x, coord y, s_char *ptr,
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) {
779 qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
783 /****************************************************************************
785 ****************************************************************************/
787 /* Choose a place to start growing an island from
790 place_island(int c, int *xp, int *yp)
793 int ssy = rnd(WORLD_Y);
794 int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
796 if (ssx > WORLD_X - 2)
797 ssx = new_x(ssx + 2);
798 for (d = di + id; d >= id; --d) {
802 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
803 if (*xp >= WORLD_X) {
804 *yp = new_y(*yp + 1);
806 if (*xp == sx && *yp == sy)
809 if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
816 /* Grow all the islands
824 for (c = nc; c < nc + ni; ++c) {
826 if (!place_island(c, &x, &y))
828 isiz = 1 + rnd(2 * is - 1);
832 } while (secs < isiz && grow_one_sector(c));
833 qprint(" %d(%d)", c - nc + 1, secs);
839 /****************************************************************************
841 ****************************************************************************/
843 create_elevations(void)
849 /* Generic function for finding the distance to the closest sea, land, or
853 distance_to_what(int x, int y, int flag)
857 for (d = 1; d < 5; ++d) {
858 for (j = 0; j < d; ++j)
863 for (j = 0; j < d; ++j) {
864 px = new_x(px + dirx[vector[j]]);
865 py = new_y(py + diry[vector[j]]);
868 case 0: /* distance to sea */
869 if (own[px][py] == -1)
872 case 1: /* distance to land */
873 if (own[px][py] != -1)
876 case 2: /* distance to mountain */
877 if (elev[px][py] == INFINITY)
881 } while (next_vector(d));
886 #define ELEV elev[sectx[c][i]][secty[c][i]]
887 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
888 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
890 /* Decide where the mountains go
895 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
898 for (c = 0; c < ctot; ++c) {
900 ns = (c < nc) ? sc : isecs[c];
901 nm = (pm * ns) / 100;
903 /* Place the mountains */
905 for (i = 0; i < ns; ++i) {
906 dsea[i] = distance_to_sea();
907 weight[i] = (total += (dsea[i] * dsea[i]));
910 for (k = nm, mountain_search = 0;
911 k && mountain_search < MOUNTAIN_SEARCH_MAX;
914 for (i = 0; i < ns; ++i)
915 if (r < weight[i] && ELEV == -INFINITY &&
917 ((!(capx[c] == sectx[c][i] &&
918 capy[c] == secty[c][i])) &&
919 (!(new_x(capx[c] + 2) == sectx[c][i] &&
920 capy[c] == secty[c][i]))))) {
927 /* Elevate land that is not mountain and not capital */
929 for (i = 0; i < ns; ++i)
930 dmoun[i] = distance_to_mountain();
931 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
932 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
934 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
937 for (i = 0; i < ns; ++i) {
938 if (ELEV != INFINITY &&
939 (c >= nc || ((!(capx[c] == sectx[c][i] &&
940 capy[c] == secty[c][i])) &&
941 (!(new_x(capx[c] + 2) == sectx[c][i] &&
942 capy[c] == secty[c][i]))))) {
943 h = 3 * (5 - dmoun[i]) + dsea[i];
953 if (newk >= HILLMIN && newk < PLATMIN)
957 elev[sectx[c][where]][secty[c][where]] = newk;
958 dsea[where] = -INFINITY;
959 dmoun[where] = INFINITY;
962 /* Elevate the mountains and capitals */
964 for (i = 0; i < ns; ++i) {
965 if (ELEV == INFINITY) {
967 ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
969 ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
970 rnd((256 - HIGHMIN) / 2);
971 } else if ((c < nc &&
972 ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
973 ((new_x(capx[c] + 2) == sectx[c][i] &&
974 capy[c] == secty[c][i])))
980 #define distance_to_land() distance_to_what(x, y, 1)
987 for (y = 0; y < WORLD_Y; ++y) {
988 for (x = y % 2; x < WORLD_X; x += 2) {
989 if (elev[x][y] == -INFINITY)
990 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
995 /****************************************************************************
997 ****************************************************************************/
1004 fert = LANDMIN - e + 40;
1005 else if (e < FERT_MAX)
1006 fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1017 oil = (LANDMIN - e) * 2 + rnd(2);
1018 else if (e <= OIL_MAX)
1019 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1029 if (e >= IRON_MIN && e < HIGHMIN)
1030 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1040 if (e >= GOLD_MIN) {
1042 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1044 gold = 100 - 20 * HIGHMIN / e;
1055 if (e >= URAN_MIN && e < HIGHMIN)
1056 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1063 add_resources(struct sctstr *sct)
1065 sct->sct_fertil = set_fert(sct->sct_elev);
1066 sct->sct_oil = set_oil(sct->sct_elev);
1067 sct->sct_min = set_iron(sct->sct_elev);
1068 sct->sct_gmin = set_gold(sct->sct_elev);
1069 sct->sct_uran = set_uran(sct->sct_elev);
1072 /****************************************************************************
1073 DESIGNATE THE SECTORS
1074 ****************************************************************************/
1081 time_t current_time = time(NULL);
1083 /* sct = §s[0][0]; */
1085 for (y = 0; y < YSIZE; y++) {
1086 for (x = 0; x < XSIZE; x++, sct++) {
1087 fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct, current_time);
1088 total = elev[sct->sct_x][y];
1089 if (total < LANDMIN) {
1090 sct->sct_type = SCT_WATER;
1091 } else if (total < HILLMIN)
1092 sct->sct_type = SCT_RURAL;
1093 else if (total < PLATMIN)
1094 sct->sct_type = SCT_MOUNT;
1095 else if (total < HIGHMIN)
1096 sct->sct_type = SCT_RURAL;
1098 sct->sct_type = SCT_MOUNT;
1099 sct->sct_elev = total;
1100 sct->sct_newtype = sct->sct_type;
1106 for (c = 0; c < nc; ++c) {
1107 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1108 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1112 /****************************************************************************
1113 WRITE ALL THIS STUFF TO THE FILE
1114 ****************************************************************************/
1120 n = fwrite(sectsbuf, sizeof(struct sctstr), YSIZE * XSIZE, sect_fptr);
1122 perror(empfile[EF_SECTOR].file);
1125 if (n != YSIZE * XSIZE) {
1126 printf("%s:partial write\n", empfile[EF_SECTOR].file);
1133 /****************************************************************************
1134 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1135 ****************************************************************************/
1141 translate_continents();
1143 for (i = 0; i < WORLD_Y; ++i) {
1147 for (j = i % 2; j < WORLD_X; j += 2) {
1148 if (own[j][i] == -1)
1151 printf("%c ", map_symbol(j, i));
1157 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");
1160 /* Reorder the continents from top left to bottom right */
1162 translate_continents(void)
1164 int i, j, n = 0, k, gotit, c;
1165 int *trans, *trans_cont, *oldcapx, *oldcapy;
1167 trans = calloc(nc, sizeof(int));
1168 trans_cont = calloc(nc, sizeof(int));
1169 oldcapx = calloc(nc, sizeof(int));
1170 oldcapy = calloc(nc, sizeof(int));
1172 for (i = 0; i < WORLD_Y; ++i) {
1173 for (j = i % 2; j < WORLD_X; j += 2) {
1174 if (own[j][i] > -1 && own[j][i] < nc) {
1176 for (k = 0; k < n; ++k) {
1177 if (trans[k] == own[j][i])
1182 printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n");
1185 trans[n] = own[j][i];
1186 trans_cont[own[j][i]] = n;
1192 for (i = 0; i < WORLD_Y; ++i) {
1193 for (j = i % 2; j < WORLD_X; j += 2) {
1194 if (own[j][i] > -1 && own[j][i] < nc) {
1195 own[j][i] = trans_cont[own[j][i]];
1199 for (c = 0; c < nc; ++c) {
1200 oldcapx[c] = capx[c];
1201 oldcapy[c] = capy[c];
1203 for (c = 0; c < nc; ++c) {
1204 capx[c] = oldcapx[trans[c]];
1205 capy[c] = oldcapy[trans[c]];
1210 map_symbol(int x, int y)
1214 for (c = 0; c < nc; ++c)
1215 if ((x == capx[c] && y == capy[c])
1216 || (x == new_x(capx[c] + 2) && y == capy[c]))
1218 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1219 || elev[x][y] >= HIGHMIN)
1221 return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1224 /***************************************************************************
1225 WRITE A SCRIPT FOR PLACING CAPITALS
1226 ****************************************************************************/
1228 write_newcap_script(void)
1231 FILE *script = fopen(outfile, "w");
1234 printf("fairland: error, unable to write to %s.\n", outfile);
1238 for (c = 0; c < nc; ++c) {
1239 fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1241 fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1242 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1244 fprintf(script, "add %d visitor visitor v i\n", c + 1);
1247 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1253 qprint(const char * const fmt, ...)
1259 vfprintf(stdout, fmt, ap);
1265 fl_sct_init(coord x, coord y, s_char *ptr, time_t timestamp)
1267 struct sctstr *sp = (struct sctstr *)ptr;
1269 sp->ef_type = EF_SECTOR;
1276 sp->sct_defense = 0;
1277 sp->sct_timestamp = timestamp;