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);
182 static void print_vars(void);
183 static void fl_move(int);
184 static void next_coast(int c, int x, int y, int *xp, int *yp);
185 static void grow_islands(void);
187 /****************************************************************************
189 ****************************************************************************/
192 main(int argc, char *argv[])
195 char *config_file = NULL;
198 program_name = argv[0];
199 rnd_seed = time(NULL);
201 while ((opt = getopt(argc, argv, "ae:hioqs:R:")) != EOF) {
207 DISTINCT_ISLANDS = 0;
210 config_file = optarg;
222 rnd_seed = strtoul(optarg, NULL, 10);
233 if (emp_config(config_file))
236 parse_args(argc - optind, argv + optind);
237 if (allocate_memory() == -1)
244 qprint("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
245 qprint("\n\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
246 qprint("seed is %lu\n", rnd_seed);
247 qprint("placing capitals...\n");
249 qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
250 qprint("growing continents...\n");
252 } while (fl_status && ++i < NUMTRIES);
254 fputs("ERROR: World not large enough to hold continents\n",
258 qprint("growing islands:");
260 qprint("\nelevating land...\n");
262 qprint("designating sectors...\n");
264 qprint("adding resources...\n");
266 qprint("writing to sectors file...\n");
267 if (write_file() == -1)
270 write_newcap_script();
272 qprint("\t*** Resources have not been added ***\n");
281 puts("Creating a planet with:\n");
282 printf("%d continents\n", nc);
283 printf("continent size: %d\n", sc);
284 printf("number of islands: %d\n", ni);
285 printf("average size of islands: %d\n", is);
286 printf("spike: %d%%\n", sp);
287 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
288 pm, (pm * sc) / 100);
289 printf("minimum distance between continents: %d\n", di);
290 printf("minimum distance from islands to continents: %d\n", id);
291 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
299 for (i = 1; i * i < n * 10000; ++i) ;
300 return (i + 50) / 100;
303 /****************************************************************************
304 PARSE COMMAND LINE ARGUMENTS
305 ****************************************************************************/
308 help(char *complaint)
311 fprintf(stderr, "%s: %s\n", program_name, complaint);
312 fprintf(stderr, "Try -h for help.\n");
318 printf("Usage: %s [-e CONFIG] [-aiqo] [-s SCRIPT] [-R SEED] NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
320 " -o don't set resources\n"
321 " -a airport marker for continents\n"
322 " -i islands may merge\n"
323 " -R SEED seed for random number generator\n"
324 " -e CONFIG configuration file\n"
325 " -s SCRIPT name of script to create (default %s)\n"
326 " NC number of continents\n"
327 " SC continent size\n"
328 " NI number of islands (default NC)\n"
329 " IS average island size (default SC/2)\n"
330 " SP spike percentage: 0 = round, 100 = snake\n"
332 " PM percentage of land that is mountain (default %d)\n"
333 " DI minimum distance between continents (default %d)\n"
334 " ID minimum distance from islands to continents (default %d)\n",
335 program_name, DEFAULT_OUTFILE_NAME,
336 DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
340 parse_args(int argc, char *argv[])
343 help("missing arguments");
347 help("too many arguments");
352 puts("fairland: error -- number of continents must be > 0");
358 puts("fairland: error -- size of continents must be > 0");
386 pm = DEFAULT_MOUNTAIN;
393 di = DEFAULT_CONTDIST;
396 puts("fairland: error -- distance between continents must be >= 0");
399 if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
400 puts("fairland: error -- distance between continents too large");
407 id = DEFAULT_ISLDIST;
409 puts("fairland: error -- distance from islands to continents must be >= 0");
412 if (id > WORLD_X || id > WORLD_Y) {
413 puts("fairland: error -- distance from islands to continents too large");
416 if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
417 puts("fairland: error -- world not big enough to fit continents.");
418 puts("arguments must satisfy:");
419 puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
424 /****************************************************************************
425 VARIABLE INITIALIZATION
426 ****************************************************************************/
429 allocate_memory(void)
434 fname = malloc(strlen(datadir) + 1 + strlen(empfile[EF_SECTOR].file) + 1);
435 sprintf(fname, "%s/%s", datadir, empfile[EF_SECTOR].file);
436 sect_fptr = fopen(fname, "wb");
437 if (sect_fptr == NULL) {
443 (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
444 sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
445 for (i = 0; i < YSIZE; i++)
446 sects[i] = §sbuf[XSIZE * i];
447 capx = (int *)calloc(nc, sizeof(int));
448 capy = (int *)calloc(nc, sizeof(int));
449 vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
450 mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
451 own = (int **)calloc(WORLD_X, sizeof(int *));
452 elev = (int **)calloc(WORLD_X, sizeof(int *));
453 for (i = 0; i < WORLD_X; ++i) {
454 own[i] = (int *)calloc(WORLD_Y, sizeof(int));
455 elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
457 sectx = (int **)calloc(nc + ni, sizeof(int *));
458 secty = (int **)calloc(nc + ni, sizeof(int *));
459 sectc = (int **)calloc(nc + ni, sizeof(int *));
460 isecs = (int *)calloc(nc + ni, sizeof(int));
461 weight = (int *)calloc(max(sc, is * 2), sizeof(int));
462 dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
463 dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
464 for (i = 0; i < nc; ++i) {
465 sectx[i] = (int *)calloc(sc, sizeof(int));
466 secty[i] = (int *)calloc(sc, sizeof(int));
467 sectc[i] = (int *)calloc(sc, sizeof(int));
469 for (i = nc; i < nc + ni; ++i) {
470 sectx[i] = (int *)calloc(is * 2, sizeof(int));
471 secty[i] = (int *)calloc(is * 2, sizeof(int));
472 sectc[i] = (int *)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 ****************************************************************************/
1082 /* sct = §s[0][0]; */
1084 for (y = 0; y < YSIZE; y++) {
1085 for (x = 0; x < XSIZE; x++, sct++) {
1086 fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1087 total = elev[sct->sct_x][y];
1088 if (total < LANDMIN) {
1089 sct->sct_type = SCT_WATER;
1090 } else if (total < HILLMIN)
1091 sct->sct_type = SCT_RURAL;
1092 else if (total < PLATMIN)
1093 sct->sct_type = SCT_MOUNT;
1094 else if (total < HIGHMIN)
1095 sct->sct_type = SCT_RURAL;
1097 sct->sct_type = SCT_MOUNT;
1098 sct->sct_elev = total;
1099 sct->sct_newtype = sct->sct_type;
1105 for (c = 0; c < nc; ++c) {
1106 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1107 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1111 /****************************************************************************
1112 WRITE ALL THIS STUFF TO THE FILE
1113 ****************************************************************************/
1119 if ((n = fwrite((void *)sectsbuf, sizeof(struct sctstr),
1120 YSIZE * XSIZE, sect_fptr)) <= 0) {
1121 perror(empfile[EF_SECTOR].file);
1124 if (n != YSIZE * XSIZE) {
1125 printf("%s:partial write\n", empfile[EF_SECTOR].file);
1132 /****************************************************************************
1133 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1134 ****************************************************************************/
1140 translate_continents();
1142 for (i = 0; i < WORLD_Y; ++i) {
1146 for (j = i % 2; j < WORLD_X; j += 2) {
1147 if (own[j][i] == -1)
1150 printf("%c ", map_symbol(j, i));
1156 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");
1159 /* Reorder the continents from top left to bottom right */
1161 translate_continents(void)
1163 int i, j, n = 0, k, gotit, c;
1164 int *trans, *trans_cont, *oldcapx, *oldcapy;
1166 trans = (int *)calloc(nc, sizeof(int));
1167 trans_cont = (int *)calloc(nc, sizeof(int));
1168 oldcapx = (int *)calloc(nc, sizeof(int));
1169 oldcapy = (int *)calloc(nc, sizeof(int));
1171 for (i = 0; i < WORLD_Y; ++i) {
1172 for (j = i % 2; j < WORLD_X; j += 2) {
1173 if (own[j][i] > -1 && own[j][i] < nc) {
1175 for (k = 0; k < n; ++k) {
1176 if (trans[k] == own[j][i])
1181 printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n");
1184 trans[n] = own[j][i];
1185 trans_cont[own[j][i]] = n;
1191 for (i = 0; i < WORLD_Y; ++i) {
1192 for (j = i % 2; j < WORLD_X; j += 2) {
1193 if (own[j][i] > -1 && own[j][i] < nc) {
1194 own[j][i] = trans_cont[own[j][i]];
1198 for (c = 0; c < nc; ++c) {
1199 oldcapx[c] = capx[c];
1200 oldcapy[c] = capy[c];
1202 for (c = 0; c < nc; ++c) {
1203 capx[c] = oldcapx[trans[c]];
1204 capy[c] = oldcapy[trans[c]];
1209 map_symbol(int x, int y)
1213 for (c = 0; c < nc; ++c)
1214 if ((x == capx[c] && y == capy[c])
1215 || (x == new_x(capx[c] + 2) && y == capy[c]))
1217 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1218 || elev[x][y] >= HIGHMIN)
1220 return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
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 n i\n", c + 1, c + 1, c + 1);
1240 fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1241 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1243 fprintf(script, "add %d visitor visitor v i\n", c + 1);
1246 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1252 qprint(const char * const fmt, ...)
1258 vfprintf(stdout, fmt, ap);
1264 fl_sct_init(coord x, coord y, s_char *ptr)
1266 struct sctstr *sp = (struct sctstr *)ptr;
1268 sp->ef_type = EF_SECTOR;
1275 sp->sct_defense = 0;