2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2004, 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 */
67 #if defined(aix) || defined(linux) || defined(solaris)
69 #endif /* aix or linux */
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 static const char *outfile = "newcap_script";
95 /* mark the continents with a * so you can tell them
96 from the islands 1 = mark, 0 = don't mark. */
97 static int AIRPORT_MARKER = 0;
99 /* don't let the islands crash into each other.
100 1 = don't merge, 0 = merge. */
101 static int DISTINCT_ISLANDS = 1;
103 #define XSIZE ((WORLD_X) / 2) /* basically world x-y size */
104 #define YSIZE (WORLD_Y)
105 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
106 #define INFINITY 999 /* a number which means "BIG" */
108 /* these defines prevent infinite loops:
111 #define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector
112 when growing continents and islands */
113 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
114 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
115 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
120 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
121 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
123 #define max(a,b) (a>b?a:b)
126 #define SRANDOM srandom
129 #define RANDOM random
131 #define rnd(x) (RANDOM() % (x))
133 int secs; /* number of sectors grown */
134 int ctot; /* total number of continents and islands grown */
135 int *isecs; /* array of how large each island is */
137 int nc, sc, di, sp, pm, ni, is, id; /* the 8 arguments to this program */
138 unsigned long rnd_seed; /* optional seed can be passed as an argument */
139 int *capx, *capy; /* location of the nc capitals */
140 int *mc, mcc; /* array and counter used for stability
141 check when perturbing */
142 int spike; /* are we spiking? */
143 int mind; /* the final distance between capitals that
145 int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
146 int diry[] = { 0, -1, -1, 0, 1, 1 };
148 int **own; /* owner of the sector. -1 means water */
149 int **elev; /* elevation of the sectors */
150 int **sectx, **secty; /* the sectors for each continent */
151 int **sectc; /* which sectors are on the coast? */
152 int *vector; /* used for measuring distances */
153 int *weight; /* used for placing mountains */
154 int *dsea, *dmoun; /* the dist to the ocean and mountain */
155 int the_file; /* the file we write everything to */
156 struct sctstr **sects;
157 struct sctstr *sectsbuf;
158 int fl_status; /* is anything wrong? */
159 #define STATUS_NO_ROOM (1) /* there was no room to grow */
160 #define NUMTRIES 10 /* keep trying to grow this many times */
162 const char *numletter =
163 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
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[])
197 char *config_file = NULL;
201 rnd_seed = time(NULL);
203 rnd_seed += getpid();
205 while ((opt = getopt(argc, argv, "ae:ioqs:R:")) != EOF) {
211 DISTINCT_ISLANDS = 0;
214 config_file = optarg;
226 rnd_seed = strtoul(optarg, NULL, 10);
232 if (config_file == NULL) {
233 sprintf(tbuf, "%s/econfig", datadir);
236 emp_config(config_file);
239 parse_args(argc - optind, argv + optind);
241 parse_args(argc - 1, argv + 1);
243 if (allocate_memory() == -1)
250 qprint("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
251 qprint("\n\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
252 qprint("seed is %lu\n", rnd_seed);
253 qprint("placing capitals...\n");
255 qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
256 qprint("growing continents...\n");
258 } while (fl_status && ++i < NUMTRIES);
260 fputs("ERROR: World not large enough to hold continents\n",
264 qprint("growing islands:");
266 qprint("\nelevating land...\n");
268 qprint("designating sectors...\n");
270 qprint("adding resources...\n");
272 qprint("writing to sectors file...\n");
273 if (write_file() == -1)
276 write_newcap_script();
278 qprint("\t*** Resources have not been added ***\n");
287 puts("Creating a planet with:\n");
288 printf("%d continents\n", nc);
289 printf("continent size: %d\n", sc);
290 printf("number of islands: %d\n", ni);
291 printf("average size of islands: %d\n", is);
292 printf("spike: %d%%\n", sp);
293 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
294 pm, (pm * sc) / 100);
295 printf("minimum distance between continents: %d\n", di);
296 printf("minimum distance from islands to continents: %d\n", id);
297 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
305 for (i = 1; i * i < n * 10000; ++i) ;
306 return (i + 50) / 100;
309 /****************************************************************************
310 PARSE COMMAND LINE ARGUMENTS
311 ****************************************************************************/
314 parse_args(int argc, char *argv[])
316 if (argc < 2 || argc > 8) {
317 puts("fairland syntax:\n");
318 puts("fairland [-e config] [-aiqo] [-s script] [-R seed] <nc> <sc> [<ni>] [<is>] [<sp>] [<pm>] [<di>] [<id>]");
319 puts("-q = quiet, -o = no ore produced");
320 puts("-a = Airport marker for continents, -i = islands not distinct");
321 puts("-R = seed to use for random, -e = read config file");
322 printf("-s = name of script (default %s)\n",
324 puts("nc = number of continents [MANDATORY]");
325 puts("sc = continent size [MANDATORY]");
326 puts("ni = number of islands (default = nc)");
327 puts("is = average size of islands (default = sc/2)");
328 printf("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n",
330 printf("pm = the percentage of land that is mountain (default = %d)\n",
332 printf("di = the minimum distance between continents (default = %d)\n",
334 printf("id = minimum distance from islands to continents (default = %d)\n",
340 puts("fairland: error -- number of continents must be > 0");
346 puts("fairland: error -- size of continents must be > 0");
374 pm = DEFAULT_MOUNTAIN;
381 di = DEFAULT_CONTDIST;
384 puts("fairland: error -- distance between continents must be >= 0");
387 if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
388 puts("fairland: error -- distance between continents too large");
395 id = DEFAULT_ISLDIST;
397 puts("fairland: error -- distance from islands to continents must be >= 0");
400 if (id > WORLD_X || id > WORLD_Y) {
401 puts("fairland: error -- distance from islands to continents too large");
404 if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
405 puts("fairland: error -- world not big enough to fit continents.");
406 puts("arguments must satisfy:");
407 puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
412 /****************************************************************************
413 VARIABLE INITIALIZATION
414 ****************************************************************************/
417 allocate_memory(void)
423 open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC, 0660);
426 open(empfile[EF_SECTOR].file,
427 O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0660);
430 perror(empfile[EF_SECTOR].file);
434 (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
435 sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
436 for (i = 0; i < YSIZE; i++)
437 sects[i] = §sbuf[XSIZE * i];
438 capx = (int *)calloc(nc, sizeof(int));
439 capy = (int *)calloc(nc, sizeof(int));
440 vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
441 mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
442 own = (int **)calloc(WORLD_X, sizeof(int *));
443 elev = (int **)calloc(WORLD_X, sizeof(int *));
444 for (i = 0; i < WORLD_X; ++i) {
445 own[i] = (int *)calloc(WORLD_Y, sizeof(int));
446 elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
448 sectx = (int **)calloc(nc + ni, sizeof(int *));
449 secty = (int **)calloc(nc + ni, sizeof(int *));
450 sectc = (int **)calloc(nc + ni, sizeof(int *));
451 isecs = (int *)calloc(nc + ni, sizeof(int));
452 weight = (int *)calloc(max(sc, is * 2), sizeof(int));
453 dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
454 dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
455 for (i = 0; i < nc; ++i) {
456 sectx[i] = (int *)calloc(sc, sizeof(int));
457 secty[i] = (int *)calloc(sc, sizeof(int));
458 sectc[i] = (int *)calloc(sc, sizeof(int));
460 for (i = nc; i < nc + ni; ++i) {
461 sectx[i] = (int *)calloc(is * 2, sizeof(int));
462 secty[i] = (int *)calloc(is * 2, sizeof(int));
463 sectc[i] = (int *)calloc(is * 2, sizeof(int));
472 int i, j, xx = 0, yy = 0;
477 for (i = 0; i < WORLD_X; ++i) {
478 for (j = 0; j < WORLD_Y; ++j) {
480 elev[i][j] = -INFINITY;
484 for (i = 0; i < nc; ++i, xx += 2) {
489 puts("fairland error: world not big enough for all the continents.\n");
496 for (i = 0; i < STABLE_CYCLE; ++i)
500 /****************************************************************************
501 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
502 ****************************************************************************/
504 /* How isolated is capital j?
507 iso(int j, int newx, int newy)
509 int i, md, d = WORLD_X + WORLD_Y;
511 for (i = 0; i < nc; ++i) {
514 md = mapdist(capx[i], capy[i], newx, newy);
522 /* Drift all the capitals
529 for (turns = 0; turns < DRIFT_MAX; ++turns) {
530 if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
532 for (i = 0; i < nc; ++i)
538 /* Check to see if we have stabilized--can we stop drifting the capitals?
544 int i, isod, d = 0, stab = 1;
546 for (i = 0; i < nc; ++i) {
547 isod = iso(i, capx[i], capy[i]);
551 for (i = 0; i < STABLE_CYCLE; ++i)
555 mcc = (mcc + 1) % STABLE_CYCLE;
559 /* This routine does the actual drifting
565 int i, n, newx, newy;
567 for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
568 newx = new_x(capx[j] + dirx[i]);
569 newy = new_y(capy[j] + diry[i]);
570 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
578 /****************************************************************************
580 ****************************************************************************/
582 /* Look for a coastal sector of continent c
590 for (i = 0; i < secs; ++i) {
592 for (j = 0; j < 6; ++j)
593 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
598 /* Used for measuring distances
610 for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
613 return i > 1 || vector[0] > 0;
616 /* Test to see if we're allowed to grow there: the arguments di and id
619 try_to_grow(int c, int newx, int newy, int d)
623 for (i = 1; i <= d; ++i) {
624 for (j = 0; j < i; ++j)
629 for (j = 0; j < i; ++j) {
630 px = new_x(px + dirx[vector[j]]);
631 py = new_y(py + diry[vector[j]]);
633 if (own[px][py] != -1 &&
635 (DISTINCT_ISLANDS || own[px][py] < nc))
637 } while (next_vector(i));
639 sectx[c][secs] = newx;
640 secty[c][secs] = newy;
645 /* Move along the coast in a clockwise direction.
649 next_coast(int c, int x, int y, int *xp, int *yp)
651 int i, nx, ny, wat = 0;
659 for (i = 0; i < 12; ++i) {
660 nx = new_x(x + dirx[i % 6]);
661 ny = new_y(y + diry[i % 6]);
662 if (own[nx][ny] == -1)
664 if (wat && own[nx][ny] == c) {
672 /* Choose a sector to grow from
684 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
689 } while (i != starti);
691 printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
700 /* Grow continent c by 1 sector
704 grow_one_sector(int c)
706 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
708 spike = rnd(100) < sp;
709 if ((try1 = new_try(c)) == -1)
711 x = sx = sectx[c][try1];
712 y = sy = secty[c][try1];
717 for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
718 newx = new_x(x + dirx[i]);
719 newy = new_y(y + diry[i]);
720 if (own[newx][newy] == -1 &&
722 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
723 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
724 if (try_to_grow(c, newx, newy, c < nc ? di : id))
728 for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
729 newx = new_x(x + dirx[i]);
730 newy = new_y(y + diry[i]);
731 if (own[newx][newy] == -1)
732 if (try_to_grow(c, newx, newy, c < nc ? di : id))
735 next_coast(c, x, y, &x, &y);
737 } while (!done && coast_search < COAST_SEARCH_MAX &&
738 (secs == 1 || x != sx || y != sy));
739 if (!done && c < nc) {
740 qprint("fairland: error -- continent %c had no room to grow!\n",
742 fl_status |= STATUS_NO_ROOM;
747 /* Grow all the continents
750 grow_continents(void)
754 for (c = 0; c < nc; ++c) {
755 sectx[c][0] = capx[c];
756 secty[c][0] = capy[c];
757 own[sectx[c][0]][secty[c][0]] = c;
758 sectx[c][1] = new_x(capx[c] + 2);
759 secty[c][1] = capy[c];
760 own[sectx[c][1]][secty[c][1]] = c;
763 for (secs = 2; secs < sc && !fl_status; ++secs) {
764 for (c = 0; c < nc; ++c) {
770 qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
774 /****************************************************************************
776 ****************************************************************************/
778 /* Choose a place to start growing an island from
781 place_island(int c, int *xp, int *yp)
784 int ssy = rnd(WORLD_Y);
785 int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
787 if (ssx > WORLD_X - 2)
788 ssx = new_x(ssx + 2);
789 for (d = di + id; d >= id; --d) {
793 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
794 if (*xp >= WORLD_X) {
795 *yp = new_y(*yp + 1);
797 if (*xp == sx && *yp == sy)
800 if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
807 /* Grow all the islands
815 for (c = nc; c < nc + ni; ++c) {
817 if (!place_island(c, &x, &y))
819 isiz = 1 + rnd(2 * is - 1);
823 } while (secs < isiz && grow_one_sector(c));
824 qprint(" %d(%d)", c - nc + 1, secs);
830 /****************************************************************************
832 ****************************************************************************/
834 create_elevations(void)
840 /* Generic function for finding the distance to the closest sea, land, or
844 distance_to_what(int x, int y, int flag)
848 for (d = 1; d < 5; ++d) {
849 for (j = 0; j < d; ++j)
854 for (j = 0; j < d; ++j) {
855 px = new_x(px + dirx[vector[j]]);
856 py = new_y(py + diry[vector[j]]);
859 case 0: /* distance to sea */
860 if (own[px][py] == -1)
863 case 1: /* distance to land */
864 if (own[px][py] != -1)
867 case 2: /* distance to mountain */
868 if (elev[px][py] == INFINITY)
872 } while (next_vector(d));
877 #define ELEV elev[sectx[c][i]][secty[c][i]]
878 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
879 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
881 /* Decide where the mountains go
886 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
889 for (c = 0; c < ctot; ++c) {
891 ns = (c < nc) ? sc : isecs[c];
892 nm = (pm * ns) / 100;
894 /* Place the mountains */
896 for (i = 0; i < ns; ++i) {
897 dsea[i] = distance_to_sea();
898 weight[i] = (total += (dsea[i] * dsea[i]));
901 for (k = nm, mountain_search = 0;
902 k && mountain_search < MOUNTAIN_SEARCH_MAX;
905 for (i = 0; i < ns; ++i)
906 if (r < weight[i] && ELEV == -INFINITY &&
908 ((!(capx[c] == sectx[c][i] &&
909 capy[c] == secty[c][i])) &&
910 (!(new_x(capx[c] + 2) == sectx[c][i] &&
911 capy[c] == secty[c][i]))))) {
918 /* Elevate land that is not mountain and not capital */
920 for (i = 0; i < ns; ++i)
921 dmoun[i] = distance_to_mountain();
922 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
923 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
925 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
928 for (i = 0; i < ns; ++i) {
929 if (ELEV != INFINITY &&
930 (c >= nc || ((!(capx[c] == sectx[c][i] &&
931 capy[c] == secty[c][i])) &&
932 (!(new_x(capx[c] + 2) == sectx[c][i] &&
933 capy[c] == secty[c][i]))))) {
934 h = 3 * (5 - dmoun[i]) + dsea[i];
944 if (newk >= HILLMIN && newk < PLATMIN)
948 elev[sectx[c][where]][secty[c][where]] = newk;
949 dsea[where] = -INFINITY;
950 dmoun[where] = INFINITY;
953 /* Elevate the mountains and capitals */
955 for (i = 0; i < ns; ++i) {
956 if (ELEV == INFINITY) {
958 ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
960 ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
961 rnd((256 - HIGHMIN) / 2);
962 } else if ((c < nc &&
963 ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
964 ((new_x(capx[c] + 2) == sectx[c][i] &&
965 capy[c] == secty[c][i])))
971 #define distance_to_land() distance_to_what(x, y, 1)
978 for (y = 0; y < WORLD_Y; ++y) {
979 for (x = y % 2; x < WORLD_X; x += 2) {
980 if (elev[x][y] == -INFINITY)
981 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
986 /****************************************************************************
988 ****************************************************************************/
995 fert = LANDMIN - e + 40;
996 else if (e < FERT_MAX)
997 fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1008 oil = (LANDMIN - e) * 2 + rnd(2);
1009 else if (e <= OIL_MAX)
1010 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1020 if (e >= IRON_MIN && e < HIGHMIN)
1021 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1031 if (e >= GOLD_MIN) {
1033 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1035 gold = 100 - 20 * HIGHMIN / e;
1046 if (e >= URAN_MIN && e < HIGHMIN)
1047 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1054 add_resources(struct sctstr *sct)
1056 sct->sct_fertil = set_fert(sct->sct_elev);
1057 sct->sct_oil = set_oil(sct->sct_elev);
1058 sct->sct_min = set_iron(sct->sct_elev);
1059 sct->sct_gmin = set_gold(sct->sct_elev);
1060 sct->sct_uran = set_uran(sct->sct_elev);
1063 /****************************************************************************
1064 DESIGNATE THE SECTORS
1065 ****************************************************************************/
1073 /* sct = §s[0][0]; */
1075 for (y = 0; y < YSIZE; y++) {
1076 for (x = 0; x < XSIZE; x++, sct++) {
1077 fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1078 total = elev[sct->sct_x][y];
1079 if (total < LANDMIN) {
1080 sct->sct_type = SCT_WATER;
1081 } else if (total < HILLMIN)
1082 sct->sct_type = SCT_RURAL;
1083 else if (total < PLATMIN)
1084 sct->sct_type = SCT_MOUNT;
1085 else if (total < HIGHMIN)
1086 sct->sct_type = SCT_RURAL;
1088 sct->sct_type = SCT_MOUNT;
1089 sct->sct_elev = total;
1090 sct->sct_newtype = sct->sct_type;
1096 for (c = 0; c < nc; ++c) {
1097 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1098 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1102 /****************************************************************************
1103 WRITE ALL THIS STUFF TO THE FILE
1104 ****************************************************************************/
1110 /* if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1111 if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1112 perror(empfile[EF_SECTOR].file);
1115 if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1116 printf("%s:partial write\n", empfile[EF_SECTOR].file);
1123 /****************************************************************************
1124 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1125 ****************************************************************************/
1131 translate_continents();
1133 for (i = 0; i < WORLD_Y; ++i) {
1137 for (j = i % 2; j < WORLD_X; j += 2) {
1138 if (own[j][i] == -1)
1141 printf("%c ", map_symbol(j, i));
1147 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");
1150 /* Reorder the continents from top left to bottom right */
1152 translate_continents(void)
1154 int i, j, n = 0, k, gotit, c;
1155 int *trans, *trans_cont, *oldcapx, *oldcapy;
1157 trans = (int *)calloc(nc, sizeof(int));
1158 trans_cont = (int *)calloc(nc, sizeof(int));
1159 oldcapx = (int *)calloc(nc, sizeof(int));
1160 oldcapy = (int *)calloc(nc, sizeof(int));
1162 for (i = 0; i < WORLD_Y; ++i) {
1163 for (j = i % 2; j < WORLD_X; j += 2) {
1164 if (own[j][i] > -1 && own[j][i] < nc) {
1166 for (k = 0; k < n; ++k) {
1167 if (trans[k] == own[j][i])
1172 printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n");
1175 trans[n] = own[j][i];
1176 trans_cont[own[j][i]] = n;
1182 for (i = 0; i < WORLD_Y; ++i) {
1183 for (j = i % 2; j < WORLD_X; j += 2) {
1184 if (own[j][i] > -1 && own[j][i] < nc) {
1185 own[j][i] = trans_cont[own[j][i]];
1189 for (c = 0; c < nc; ++c) {
1190 oldcapx[c] = capx[c];
1191 oldcapy[c] = capy[c];
1193 for (c = 0; c < nc; ++c) {
1194 capx[c] = oldcapx[trans[c]];
1195 capy[c] = oldcapy[trans[c]];
1200 map_symbol(int x, int y)
1204 for (c = 0; c < nc; ++c)
1205 if ((x == capx[c] && y == capy[c])
1206 || (x == new_x(capx[c] + 2) && y == capy[c]))
1208 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1209 || elev[x][y] >= HIGHMIN)
1211 return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1214 /***************************************************************************
1215 WRITE A SCRIPT FOR PLACING CAPITALS
1216 ****************************************************************************/
1218 write_newcap_script(void)
1221 FILE *script = fopen(outfile, "w");
1224 printf("fairland: error, unable to write to %s.\n", outfile);
1228 for (c = 0; c < nc; ++c) {
1229 fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1231 fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1232 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1234 fprintf(script, "add %d visitor visitor v i\n", c + 1);
1237 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1243 qprint(const char * const fmt, ...)
1249 vfprintf(stdout, fmt, ap);
1255 fl_sct_init(coord x, coord y, s_char *ptr)
1257 struct sctstr *sp = (struct sctstr *)ptr;
1259 sp->ef_type = EF_SECTOR;
1266 sp->sct_defense = 0;