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) {
442 sectsbuf = calloc((YSIZE * XSIZE), sizeof(struct sctstr));
443 sects = calloc(YSIZE, sizeof(struct sctstr *));
444 for (i = 0; i < YSIZE; i++)
445 sects[i] = §sbuf[XSIZE * i];
446 capx = calloc(nc, sizeof(int));
447 capy = calloc(nc, sizeof(int));
448 vector = calloc(WORLD_X + WORLD_Y, sizeof(int));
449 mc = calloc(STABLE_CYCLE, sizeof(int));
450 own = calloc(WORLD_X, sizeof(int *));
451 elev = calloc(WORLD_X, sizeof(int *));
452 for (i = 0; i < WORLD_X; ++i) {
453 own[i] = calloc(WORLD_Y, sizeof(int));
454 elev[i] = calloc(WORLD_Y, sizeof(int));
456 sectx = calloc(nc + ni, sizeof(int *));
457 secty = calloc(nc + ni, sizeof(int *));
458 sectc = calloc(nc + ni, sizeof(int *));
459 isecs = calloc(nc + ni, sizeof(int));
460 weight = calloc(max(sc, is * 2), sizeof(int));
461 dsea = calloc(max(sc, is * 2), sizeof(int));
462 dmoun = calloc(max(sc, is * 2), sizeof(int));
463 for (i = 0; i < nc; ++i) {
464 sectx[i] = calloc(sc, sizeof(int));
465 secty[i] = calloc(sc, sizeof(int));
466 sectc[i] = calloc(sc, sizeof(int));
468 for (i = nc; i < nc + ni; ++i) {
469 sectx[i] = calloc(is * 2, sizeof(int));
470 secty[i] = calloc(is * 2, sizeof(int));
471 sectc[i] = calloc(is * 2, sizeof(int));
480 int i, j, xx = 0, yy = 0;
485 for (i = 0; i < WORLD_X; ++i) {
486 for (j = 0; j < WORLD_Y; ++j) {
488 elev[i][j] = -INFINITY;
492 for (i = 0; i < nc; ++i, xx += 2) {
497 puts("fairland error: world not big enough for all the continents.\n");
504 for (i = 0; i < STABLE_CYCLE; ++i)
508 /****************************************************************************
509 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
510 ****************************************************************************/
512 /* How isolated is capital j?
515 iso(int j, int newx, int newy)
517 int i, md, d = WORLD_X + WORLD_Y;
519 for (i = 0; i < nc; ++i) {
522 md = mapdist(capx[i], capy[i], newx, newy);
530 /* Drift all the capitals
537 for (turns = 0; turns < DRIFT_MAX; ++turns) {
538 if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
540 for (i = 0; i < nc; ++i)
546 /* Check to see if we have stabilized--can we stop drifting the capitals?
552 int i, isod, d = 0, stab = 1;
554 for (i = 0; i < nc; ++i) {
555 isod = iso(i, capx[i], capy[i]);
559 for (i = 0; i < STABLE_CYCLE; ++i)
563 mcc = (mcc + 1) % STABLE_CYCLE;
567 /* This routine does the actual drifting
573 int i, n, newx, newy;
575 for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
576 newx = new_x(capx[j] + dirx[i]);
577 newy = new_y(capy[j] + diry[i]);
578 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
586 /****************************************************************************
588 ****************************************************************************/
590 /* Look for a coastal sector of continent c
598 for (i = 0; i < secs; ++i) {
600 for (j = 0; j < 6; ++j)
601 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
606 /* Used for measuring distances
618 for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
621 return i > 1 || vector[0] > 0;
624 /* Test to see if we're allowed to grow there: the arguments di and id
627 try_to_grow(int c, int newx, int newy, int d)
631 for (i = 1; i <= d; ++i) {
632 for (j = 0; j < i; ++j)
637 for (j = 0; j < i; ++j) {
638 px = new_x(px + dirx[vector[j]]);
639 py = new_y(py + diry[vector[j]]);
641 if (own[px][py] != -1 &&
643 (DISTINCT_ISLANDS || own[px][py] < nc))
645 } while (next_vector(i));
647 sectx[c][secs] = newx;
648 secty[c][secs] = newy;
653 /* Move along the coast in a clockwise direction.
657 next_coast(int c, int x, int y, int *xp, int *yp)
659 int i, nx, ny, wat = 0;
667 for (i = 0; i < 12; ++i) {
668 nx = new_x(x + dirx[i % 6]);
669 ny = new_y(y + diry[i % 6]);
670 if (own[nx][ny] == -1)
672 if (wat && own[nx][ny] == c) {
680 /* Choose a sector to grow from
692 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
697 } while (i != starti);
699 printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
708 /* Grow continent c by 1 sector
712 grow_one_sector(int c)
714 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
716 spike = rnd(100) < sp;
717 if ((try1 = new_try(c)) == -1)
719 x = sx = sectx[c][try1];
720 y = sy = secty[c][try1];
725 for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
726 newx = new_x(x + dirx[i]);
727 newy = new_y(y + diry[i]);
728 if (own[newx][newy] == -1 &&
730 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
731 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
732 if (try_to_grow(c, newx, newy, c < nc ? di : id))
736 for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
737 newx = new_x(x + dirx[i]);
738 newy = new_y(y + diry[i]);
739 if (own[newx][newy] == -1)
740 if (try_to_grow(c, newx, newy, c < nc ? di : id))
743 next_coast(c, x, y, &x, &y);
745 } while (!done && coast_search < COAST_SEARCH_MAX &&
746 (secs == 1 || x != sx || y != sy));
747 if (!done && c < nc) {
748 qprint("fairland: error -- continent %c had no room to grow!\n",
750 fl_status |= STATUS_NO_ROOM;
755 /* Grow all the continents
758 grow_continents(void)
762 for (c = 0; c < nc; ++c) {
763 sectx[c][0] = capx[c];
764 secty[c][0] = capy[c];
765 own[sectx[c][0]][secty[c][0]] = c;
766 sectx[c][1] = new_x(capx[c] + 2);
767 secty[c][1] = capy[c];
768 own[sectx[c][1]][secty[c][1]] = c;
771 for (secs = 2; secs < sc && !fl_status; ++secs) {
772 for (c = 0; c < nc; ++c) {
778 qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
782 /****************************************************************************
784 ****************************************************************************/
786 /* Choose a place to start growing an island from
789 place_island(int c, int *xp, int *yp)
792 int ssy = rnd(WORLD_Y);
793 int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
795 if (ssx > WORLD_X - 2)
796 ssx = new_x(ssx + 2);
797 for (d = di + id; d >= id; --d) {
801 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
802 if (*xp >= WORLD_X) {
803 *yp = new_y(*yp + 1);
805 if (*xp == sx && *yp == sy)
808 if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
815 /* Grow all the islands
823 for (c = nc; c < nc + ni; ++c) {
825 if (!place_island(c, &x, &y))
827 isiz = 1 + rnd(2 * is - 1);
831 } while (secs < isiz && grow_one_sector(c));
832 qprint(" %d(%d)", c - nc + 1, secs);
838 /****************************************************************************
840 ****************************************************************************/
842 create_elevations(void)
848 /* Generic function for finding the distance to the closest sea, land, or
852 distance_to_what(int x, int y, int flag)
856 for (d = 1; d < 5; ++d) {
857 for (j = 0; j < d; ++j)
862 for (j = 0; j < d; ++j) {
863 px = new_x(px + dirx[vector[j]]);
864 py = new_y(py + diry[vector[j]]);
867 case 0: /* distance to sea */
868 if (own[px][py] == -1)
871 case 1: /* distance to land */
872 if (own[px][py] != -1)
875 case 2: /* distance to mountain */
876 if (elev[px][py] == INFINITY)
880 } while (next_vector(d));
885 #define ELEV elev[sectx[c][i]][secty[c][i]]
886 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
887 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
889 /* Decide where the mountains go
894 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
897 for (c = 0; c < ctot; ++c) {
899 ns = (c < nc) ? sc : isecs[c];
900 nm = (pm * ns) / 100;
902 /* Place the mountains */
904 for (i = 0; i < ns; ++i) {
905 dsea[i] = distance_to_sea();
906 weight[i] = (total += (dsea[i] * dsea[i]));
909 for (k = nm, mountain_search = 0;
910 k && mountain_search < MOUNTAIN_SEARCH_MAX;
913 for (i = 0; i < ns; ++i)
914 if (r < weight[i] && ELEV == -INFINITY &&
916 ((!(capx[c] == sectx[c][i] &&
917 capy[c] == secty[c][i])) &&
918 (!(new_x(capx[c] + 2) == sectx[c][i] &&
919 capy[c] == secty[c][i]))))) {
926 /* Elevate land that is not mountain and not capital */
928 for (i = 0; i < ns; ++i)
929 dmoun[i] = distance_to_mountain();
930 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
931 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
933 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
936 for (i = 0; i < ns; ++i) {
937 if (ELEV != INFINITY &&
938 (c >= nc || ((!(capx[c] == sectx[c][i] &&
939 capy[c] == secty[c][i])) &&
940 (!(new_x(capx[c] + 2) == sectx[c][i] &&
941 capy[c] == secty[c][i]))))) {
942 h = 3 * (5 - dmoun[i]) + dsea[i];
952 if (newk >= HILLMIN && newk < PLATMIN)
956 elev[sectx[c][where]][secty[c][where]] = newk;
957 dsea[where] = -INFINITY;
958 dmoun[where] = INFINITY;
961 /* Elevate the mountains and capitals */
963 for (i = 0; i < ns; ++i) {
964 if (ELEV == INFINITY) {
966 ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
968 ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
969 rnd((256 - HIGHMIN) / 2);
970 } else if ((c < nc &&
971 ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
972 ((new_x(capx[c] + 2) == sectx[c][i] &&
973 capy[c] == secty[c][i])))
979 #define distance_to_land() distance_to_what(x, y, 1)
986 for (y = 0; y < WORLD_Y; ++y) {
987 for (x = y % 2; x < WORLD_X; x += 2) {
988 if (elev[x][y] == -INFINITY)
989 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
994 /****************************************************************************
996 ****************************************************************************/
1003 fert = LANDMIN - e + 40;
1004 else if (e < FERT_MAX)
1005 fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1016 oil = (LANDMIN - e) * 2 + rnd(2);
1017 else if (e <= OIL_MAX)
1018 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1028 if (e >= IRON_MIN && e < HIGHMIN)
1029 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1039 if (e >= GOLD_MIN) {
1041 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1043 gold = 100 - 20 * HIGHMIN / e;
1054 if (e >= URAN_MIN && e < HIGHMIN)
1055 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1062 add_resources(struct sctstr *sct)
1064 sct->sct_fertil = set_fert(sct->sct_elev);
1065 sct->sct_oil = set_oil(sct->sct_elev);
1066 sct->sct_min = set_iron(sct->sct_elev);
1067 sct->sct_gmin = set_gold(sct->sct_elev);
1068 sct->sct_uran = set_uran(sct->sct_elev);
1071 /****************************************************************************
1072 DESIGNATE THE SECTORS
1073 ****************************************************************************/
1081 /* sct = §s[0][0]; */
1083 for (y = 0; y < YSIZE; y++) {
1084 for (x = 0; x < XSIZE; x++, sct++) {
1085 fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1086 total = elev[sct->sct_x][y];
1087 if (total < LANDMIN) {
1088 sct->sct_type = SCT_WATER;
1089 } else if (total < HILLMIN)
1090 sct->sct_type = SCT_RURAL;
1091 else if (total < PLATMIN)
1092 sct->sct_type = SCT_MOUNT;
1093 else if (total < HIGHMIN)
1094 sct->sct_type = SCT_RURAL;
1096 sct->sct_type = SCT_MOUNT;
1097 sct->sct_elev = total;
1098 sct->sct_newtype = sct->sct_type;
1104 for (c = 0; c < nc; ++c) {
1105 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1106 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1110 /****************************************************************************
1111 WRITE ALL THIS STUFF TO THE FILE
1112 ****************************************************************************/
1118 n = fwrite(sectsbuf, sizeof(struct sctstr), YSIZE * XSIZE, sect_fptr);
1120 perror(empfile[EF_SECTOR].file);
1123 if (n != YSIZE * XSIZE) {
1124 printf("%s:partial write\n", empfile[EF_SECTOR].file);
1131 /****************************************************************************
1132 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1133 ****************************************************************************/
1139 translate_continents();
1141 for (i = 0; i < WORLD_Y; ++i) {
1145 for (j = i % 2; j < WORLD_X; j += 2) {
1146 if (own[j][i] == -1)
1149 printf("%c ", map_symbol(j, i));
1155 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");
1158 /* Reorder the continents from top left to bottom right */
1160 translate_continents(void)
1162 int i, j, n = 0, k, gotit, c;
1163 int *trans, *trans_cont, *oldcapx, *oldcapy;
1165 trans = calloc(nc, sizeof(int));
1166 trans_cont = calloc(nc, sizeof(int));
1167 oldcapx = calloc(nc, sizeof(int));
1168 oldcapy = calloc(nc, sizeof(int));
1170 for (i = 0; i < WORLD_Y; ++i) {
1171 for (j = i % 2; j < WORLD_X; j += 2) {
1172 if (own[j][i] > -1 && own[j][i] < nc) {
1174 for (k = 0; k < n; ++k) {
1175 if (trans[k] == own[j][i])
1180 printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n");
1183 trans[n] = own[j][i];
1184 trans_cont[own[j][i]] = n;
1190 for (i = 0; i < WORLD_Y; ++i) {
1191 for (j = i % 2; j < WORLD_X; j += 2) {
1192 if (own[j][i] > -1 && own[j][i] < nc) {
1193 own[j][i] = trans_cont[own[j][i]];
1197 for (c = 0; c < nc; ++c) {
1198 oldcapx[c] = capx[c];
1199 oldcapy[c] = capy[c];
1201 for (c = 0; c < nc; ++c) {
1202 capx[c] = oldcapx[trans[c]];
1203 capy[c] = oldcapy[trans[c]];
1208 map_symbol(int x, int y)
1212 for (c = 0; c < nc; ++c)
1213 if ((x == capx[c] && y == capy[c])
1214 || (x == new_x(capx[c] + 2) && y == capy[c]))
1216 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1217 || elev[x][y] >= HIGHMIN)
1219 return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1222 /***************************************************************************
1223 WRITE A SCRIPT FOR PLACING CAPITALS
1224 ****************************************************************************/
1226 write_newcap_script(void)
1229 FILE *script = fopen(outfile, "w");
1232 printf("fairland: error, unable to write to %s.\n", outfile);
1236 for (c = 0; c < nc; ++c) {
1237 fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1239 fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1240 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1242 fprintf(script, "add %d visitor visitor v i\n", c + 1);
1245 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1251 qprint(const char * const fmt, ...)
1257 vfprintf(stdout, fmt, ap);
1263 fl_sct_init(coord x, coord y, s_char *ptr)
1265 struct sctstr *sp = (struct sctstr *)ptr;
1267 sp->ef_type = EF_SECTOR;
1274 sp->sct_defense = 0;