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 */
71 #include "../lib/gen/getopt.h"
86 #include "prototypes.h"
88 /* do not change these 4 defines */
89 #define LANDMIN 1 /* plate altitude for normal land */
90 #define HILLMIN 34 /* plate altitude for hills */
91 #define PLATMIN 36 /* plate altitude for plateau */
92 #define HIGHMIN 98 /* plate altitude for mountains */
94 static void qprint(const char * const fmt, ...)
95 ATTRIBUTE((format (printf, 1, 2)));
97 static const char *outfile = "newcap_script";
98 /* mark the continents with a * so you can tell them
99 from the islands 1 = mark, 0 = don't mark. */
100 static int AIRPORT_MARKER = 0;
102 /* don't let the islands crash into each other.
103 1 = don't merge, 0 = merge. */
104 static int DISTINCT_ISLANDS = 1;
106 #define XSIZE ((WORLD_X) / 2) /* basically world x-y size */
107 #define YSIZE (WORLD_Y)
108 #define STABLE_CYCLE 4 /* stability required for perterbed capitals */
109 #define INFINITY 999 /* a number which means "BIG" */
111 /* these defines prevent infinite loops:
114 #define COAST_SEARCH_MAX 200 /* how many times do we look for a coast sector
115 when growing continents and islands */
116 #define DRIFT_BEFORE_CHECK ((WORLD_X + WORLD_Y)/2)
117 #define DRIFT_MAX ((WORLD_X + WORLD_Y)*2)
118 #define MOUNTAIN_SEARCH_MAX 1000 /* how long do we try to place mountains */
123 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
124 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
126 #define max(a,b) (a>b?a:b)
129 #define SRANDOM srandom
132 #define RANDOM random
134 #define rnd(x) (RANDOM() % (x))
136 int secs; /* number of sectors grown */
137 int ctot; /* total number of continents and islands grown */
138 int *isecs; /* array of how large each island is */
140 int nc, sc, di, sp, pm, ni, is, id; /* the 8 arguments to this program */
141 unsigned long rnd_seed; /* optional seed can be passed as an argument */
142 int *capx, *capy; /* location of the nc capitals */
143 int *mc, mcc; /* array and counter used for stability
144 check when perturbing */
145 int spike; /* are we spiking? */
146 int mind; /* the final distance between capitals that
148 int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
149 int diry[] = { 0, -1, -1, 0, 1, 1 };
151 int **own; /* owner of the sector. -1 means water */
152 int **elev; /* elevation of the sectors */
153 int **sectx, **secty; /* the sectors for each continent */
154 int **sectc; /* which sectors are on the coast? */
155 int *vector; /* used for measuring distances */
156 int *weight; /* used for placing mountains */
157 int *dsea, *dmoun; /* the dist to the ocean and mountain */
158 int the_file; /* the file we write everything to */
159 struct sctstr **sects;
160 struct sctstr *sectsbuf;
161 int fl_status; /* is anything wrong? */
162 #define STATUS_NO_ROOM (1) /* there was no room to grow */
163 #define NUMTRIES 10 /* keep trying to grow this many times */
165 const char *numletter =
166 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
168 static void parse_args(int argc, char *argv[]);
169 static int allocate_memory(void);
170 static void init(void);
171 static int drift(void);
172 static void grow_continents(void);
173 static void create_elevations(void);
174 static void write_sects(void);
175 static int write_file(void);
176 static void output(void);
177 static int write_newcap_script(void);
178 static int stable(void);
179 static void elevate_land(void);
180 static void elevate_sea(void);
181 static void translate_continents(void);
182 static int map_symbol(int x, int y);
183 static void fl_sct_init(coord x, coord y, s_char *ptr);
185 static void print_vars(void);
186 static void fl_move(int);
187 static void next_coast(int c, int x, int y, int *xp, int *yp);
188 static void grow_islands(void);
190 /****************************************************************************
192 ****************************************************************************/
195 main(int argc, char *argv[])
198 char *config_file = NULL;
202 rnd_seed = time(NULL);
204 rnd_seed += getpid();
207 while ((opt = getopt(argc, argv, "ae:ioqs:R:")) != EOF) {
213 DISTINCT_ISLANDS = 0;
216 config_file = optarg;
228 rnd_seed = strtoul(optarg, NULL, 10);
233 if (config_file == NULL) {
234 sprintf(tbuf, "%s/econfig", datadir);
237 emp_config(config_file);
239 parse_args(argc - optind, argv + optind);
240 if (allocate_memory() == -1)
247 qprint("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
248 qprint("\n\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
249 qprint("seed is %lu\n", rnd_seed);
250 qprint("placing capitals...\n");
252 qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
253 qprint("growing continents...\n");
255 } while (fl_status && ++i < NUMTRIES);
257 fputs("ERROR: World not large enough to hold continents\n",
261 qprint("growing islands:");
263 qprint("\nelevating land...\n");
265 qprint("designating sectors...\n");
267 qprint("adding resources...\n");
269 qprint("writing to sectors file...\n");
270 if (write_file() == -1)
273 write_newcap_script();
275 qprint("\t*** Resources have not been added ***\n");
284 puts("Creating a planet with:\n");
285 printf("%d continents\n", nc);
286 printf("continent size: %d\n", sc);
287 printf("number of islands: %d\n", ni);
288 printf("average size of islands: %d\n", is);
289 printf("spike: %d%%\n", sp);
290 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
291 pm, (pm * sc) / 100);
292 printf("minimum distance between continents: %d\n", di);
293 printf("minimum distance from islands to continents: %d\n", id);
294 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
302 for (i = 1; i * i < n * 10000; ++i) ;
303 return (i + 50) / 100;
306 /****************************************************************************
307 PARSE COMMAND LINE ARGUMENTS
308 ****************************************************************************/
311 parse_args(int argc, char *argv[])
313 if (argc < 2 || argc > 8) {
314 puts("fairland syntax:\n");
315 puts("fairland [-e config] [-aiqo] [-s script] [-R seed] <nc> <sc> [<ni>] [<is>] [<sp>] [<pm>] [<di>] [<id>]");
316 puts("-q = quiet, -o = no ore produced");
317 puts("-a = Airport marker for continents, -i = islands not distinct");
318 puts("-R = seed to use for random, -e = read config file");
319 printf("-s = name of script (default %s)\n",
321 puts("nc = number of continents [MANDATORY]");
322 puts("sc = continent size [MANDATORY]");
323 puts("ni = number of islands (default = nc)");
324 puts("is = average size of islands (default = sc/2)");
325 printf("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n",
327 printf("pm = the percentage of land that is mountain (default = %d)\n",
329 printf("di = the minimum distance between continents (default = %d)\n",
331 printf("id = minimum distance from islands to continents (default = %d)\n",
337 puts("fairland: error -- number of continents must be > 0");
343 puts("fairland: error -- size of continents must be > 0");
371 pm = DEFAULT_MOUNTAIN;
378 di = DEFAULT_CONTDIST;
381 puts("fairland: error -- distance between continents must be >= 0");
384 if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
385 puts("fairland: error -- distance between continents too large");
392 id = DEFAULT_ISLDIST;
394 puts("fairland: error -- distance from islands to continents must be >= 0");
397 if (id > WORLD_X || id > WORLD_Y) {
398 puts("fairland: error -- distance from islands to continents too large");
401 if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
402 puts("fairland: error -- world not big enough to fit continents.");
403 puts("arguments must satisfy:");
404 puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
409 /****************************************************************************
410 VARIABLE INITIALIZATION
411 ****************************************************************************/
414 allocate_memory(void)
420 open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC, 0660);
423 open(empfile[EF_SECTOR].file,
424 O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0660);
427 perror(empfile[EF_SECTOR].file);
431 (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
432 sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
433 for (i = 0; i < YSIZE; i++)
434 sects[i] = §sbuf[XSIZE * i];
435 capx = (int *)calloc(nc, sizeof(int));
436 capy = (int *)calloc(nc, sizeof(int));
437 vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
438 mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
439 own = (int **)calloc(WORLD_X, sizeof(int *));
440 elev = (int **)calloc(WORLD_X, sizeof(int *));
441 for (i = 0; i < WORLD_X; ++i) {
442 own[i] = (int *)calloc(WORLD_Y, sizeof(int));
443 elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
445 sectx = (int **)calloc(nc + ni, sizeof(int *));
446 secty = (int **)calloc(nc + ni, sizeof(int *));
447 sectc = (int **)calloc(nc + ni, sizeof(int *));
448 isecs = (int *)calloc(nc + ni, sizeof(int));
449 weight = (int *)calloc(max(sc, is * 2), sizeof(int));
450 dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
451 dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
452 for (i = 0; i < nc; ++i) {
453 sectx[i] = (int *)calloc(sc, sizeof(int));
454 secty[i] = (int *)calloc(sc, sizeof(int));
455 sectc[i] = (int *)calloc(sc, sizeof(int));
457 for (i = nc; i < nc + ni; ++i) {
458 sectx[i] = (int *)calloc(is * 2, sizeof(int));
459 secty[i] = (int *)calloc(is * 2, sizeof(int));
460 sectc[i] = (int *)calloc(is * 2, sizeof(int));
469 int i, j, xx = 0, yy = 0;
474 for (i = 0; i < WORLD_X; ++i) {
475 for (j = 0; j < WORLD_Y; ++j) {
477 elev[i][j] = -INFINITY;
481 for (i = 0; i < nc; ++i, xx += 2) {
486 puts("fairland error: world not big enough for all the continents.\n");
493 for (i = 0; i < STABLE_CYCLE; ++i)
497 /****************************************************************************
498 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
499 ****************************************************************************/
501 /* How isolated is capital j?
504 iso(int j, int newx, int newy)
506 int i, md, d = WORLD_X + WORLD_Y;
508 for (i = 0; i < nc; ++i) {
511 md = mapdist(capx[i], capy[i], newx, newy);
519 /* Drift all the capitals
526 for (turns = 0; turns < DRIFT_MAX; ++turns) {
527 if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
529 for (i = 0; i < nc; ++i)
535 /* Check to see if we have stabilized--can we stop drifting the capitals?
541 int i, isod, d = 0, stab = 1;
543 for (i = 0; i < nc; ++i) {
544 isod = iso(i, capx[i], capy[i]);
548 for (i = 0; i < STABLE_CYCLE; ++i)
552 mcc = (mcc + 1) % STABLE_CYCLE;
556 /* This routine does the actual drifting
562 int i, n, newx, newy;
564 for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
565 newx = new_x(capx[j] + dirx[i]);
566 newy = new_y(capy[j] + diry[i]);
567 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
575 /****************************************************************************
577 ****************************************************************************/
579 /* Look for a coastal sector of continent c
587 for (i = 0; i < secs; ++i) {
589 for (j = 0; j < 6; ++j)
590 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
595 /* Used for measuring distances
607 for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
610 return i > 1 || vector[0] > 0;
613 /* Test to see if we're allowed to grow there: the arguments di and id
616 try_to_grow(int c, int newx, int newy, int d)
620 for (i = 1; i <= d; ++i) {
621 for (j = 0; j < i; ++j)
626 for (j = 0; j < i; ++j) {
627 px = new_x(px + dirx[vector[j]]);
628 py = new_y(py + diry[vector[j]]);
630 if (own[px][py] != -1 &&
632 (DISTINCT_ISLANDS || own[px][py] < nc))
634 } while (next_vector(i));
636 sectx[c][secs] = newx;
637 secty[c][secs] = newy;
642 /* Move along the coast in a clockwise direction.
646 next_coast(int c, int x, int y, int *xp, int *yp)
648 int i, nx, ny, wat = 0;
656 for (i = 0; i < 12; ++i) {
657 nx = new_x(x + dirx[i % 6]);
658 ny = new_y(y + diry[i % 6]);
659 if (own[nx][ny] == -1)
661 if (wat && own[nx][ny] == c) {
669 /* Choose a sector to grow from
681 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
686 } while (i != starti);
688 printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
697 /* Grow continent c by 1 sector
701 grow_one_sector(int c)
703 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
705 spike = rnd(100) < sp;
706 if ((try1 = new_try(c)) == -1)
708 x = sx = sectx[c][try1];
709 y = sy = secty[c][try1];
714 for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
715 newx = new_x(x + dirx[i]);
716 newy = new_y(y + diry[i]);
717 if (own[newx][newy] == -1 &&
719 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
720 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
721 if (try_to_grow(c, newx, newy, c < nc ? di : id))
725 for (i = rnd(6), n = 0; n < 6 && !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)
729 if (try_to_grow(c, newx, newy, c < nc ? di : id))
732 next_coast(c, x, y, &x, &y);
734 } while (!done && coast_search < COAST_SEARCH_MAX &&
735 (secs == 1 || x != sx || y != sy));
736 if (!done && c < nc) {
737 qprint("fairland: error -- continent %c had no room to grow!\n",
739 fl_status |= STATUS_NO_ROOM;
744 /* Grow all the continents
747 grow_continents(void)
751 for (c = 0; c < nc; ++c) {
752 sectx[c][0] = capx[c];
753 secty[c][0] = capy[c];
754 own[sectx[c][0]][secty[c][0]] = c;
755 sectx[c][1] = new_x(capx[c] + 2);
756 secty[c][1] = capy[c];
757 own[sectx[c][1]][secty[c][1]] = c;
760 for (secs = 2; secs < sc && !fl_status; ++secs) {
761 for (c = 0; c < nc; ++c) {
767 qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
771 /****************************************************************************
773 ****************************************************************************/
775 /* Choose a place to start growing an island from
778 place_island(int c, int *xp, int *yp)
781 int ssy = rnd(WORLD_Y);
782 int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
784 if (ssx > WORLD_X - 2)
785 ssx = new_x(ssx + 2);
786 for (d = di + id; d >= id; --d) {
790 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
791 if (*xp >= WORLD_X) {
792 *yp = new_y(*yp + 1);
794 if (*xp == sx && *yp == sy)
797 if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
804 /* Grow all the islands
812 for (c = nc; c < nc + ni; ++c) {
814 if (!place_island(c, &x, &y))
816 isiz = 1 + rnd(2 * is - 1);
820 } while (secs < isiz && grow_one_sector(c));
821 qprint(" %d(%d)", c - nc + 1, secs);
827 /****************************************************************************
829 ****************************************************************************/
831 create_elevations(void)
837 /* Generic function for finding the distance to the closest sea, land, or
841 distance_to_what(int x, int y, int flag)
845 for (d = 1; d < 5; ++d) {
846 for (j = 0; j < d; ++j)
851 for (j = 0; j < d; ++j) {
852 px = new_x(px + dirx[vector[j]]);
853 py = new_y(py + diry[vector[j]]);
856 case 0: /* distance to sea */
857 if (own[px][py] == -1)
860 case 1: /* distance to land */
861 if (own[px][py] != -1)
864 case 2: /* distance to mountain */
865 if (elev[px][py] == INFINITY)
869 } while (next_vector(d));
874 #define ELEV elev[sectx[c][i]][secty[c][i]]
875 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
876 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
878 /* Decide where the mountains go
883 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
886 for (c = 0; c < ctot; ++c) {
888 ns = (c < nc) ? sc : isecs[c];
889 nm = (pm * ns) / 100;
891 /* Place the mountains */
893 for (i = 0; i < ns; ++i) {
894 dsea[i] = distance_to_sea();
895 weight[i] = (total += (dsea[i] * dsea[i]));
898 for (k = nm, mountain_search = 0;
899 k && mountain_search < MOUNTAIN_SEARCH_MAX;
902 for (i = 0; i < ns; ++i)
903 if (r < weight[i] && ELEV == -INFINITY &&
905 ((!(capx[c] == sectx[c][i] &&
906 capy[c] == secty[c][i])) &&
907 (!(new_x(capx[c] + 2) == sectx[c][i] &&
908 capy[c] == secty[c][i]))))) {
915 /* Elevate land that is not mountain and not capital */
917 for (i = 0; i < ns; ++i)
918 dmoun[i] = distance_to_mountain();
919 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
920 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
922 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
925 for (i = 0; i < ns; ++i) {
926 if (ELEV != INFINITY &&
927 (c >= nc || ((!(capx[c] == sectx[c][i] &&
928 capy[c] == secty[c][i])) &&
929 (!(new_x(capx[c] + 2) == sectx[c][i] &&
930 capy[c] == secty[c][i]))))) {
931 h = 3 * (5 - dmoun[i]) + dsea[i];
941 if (newk >= HILLMIN && newk < PLATMIN)
945 elev[sectx[c][where]][secty[c][where]] = newk;
946 dsea[where] = -INFINITY;
947 dmoun[where] = INFINITY;
950 /* Elevate the mountains and capitals */
952 for (i = 0; i < ns; ++i) {
953 if (ELEV == INFINITY) {
955 ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
957 ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
958 rnd((256 - HIGHMIN) / 2);
959 } else if ((c < nc &&
960 ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
961 ((new_x(capx[c] + 2) == sectx[c][i] &&
962 capy[c] == secty[c][i])))
968 #define distance_to_land() distance_to_what(x, y, 1)
975 for (y = 0; y < WORLD_Y; ++y) {
976 for (x = y % 2; x < WORLD_X; x += 2) {
977 if (elev[x][y] == -INFINITY)
978 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
983 /****************************************************************************
985 ****************************************************************************/
992 fert = LANDMIN - e + 40;
993 else if (e < FERT_MAX)
994 fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1005 oil = (LANDMIN - e) * 2 + rnd(2);
1006 else if (e <= OIL_MAX)
1007 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1017 if (e >= IRON_MIN && e < HIGHMIN)
1018 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1028 if (e >= GOLD_MIN) {
1030 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1032 gold = 100 - 20 * HIGHMIN / e;
1043 if (e >= URAN_MIN && e < HIGHMIN)
1044 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1051 add_resources(struct sctstr *sct)
1053 sct->sct_fertil = set_fert(sct->sct_elev);
1054 sct->sct_oil = set_oil(sct->sct_elev);
1055 sct->sct_min = set_iron(sct->sct_elev);
1056 sct->sct_gmin = set_gold(sct->sct_elev);
1057 sct->sct_uran = set_uran(sct->sct_elev);
1060 /****************************************************************************
1061 DESIGNATE THE SECTORS
1062 ****************************************************************************/
1070 /* sct = §s[0][0]; */
1072 for (y = 0; y < YSIZE; y++) {
1073 for (x = 0; x < XSIZE; x++, sct++) {
1074 fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1075 total = elev[sct->sct_x][y];
1076 if (total < LANDMIN) {
1077 sct->sct_type = SCT_WATER;
1078 } else if (total < HILLMIN)
1079 sct->sct_type = SCT_RURAL;
1080 else if (total < PLATMIN)
1081 sct->sct_type = SCT_MOUNT;
1082 else if (total < HIGHMIN)
1083 sct->sct_type = SCT_RURAL;
1085 sct->sct_type = SCT_MOUNT;
1086 sct->sct_elev = total;
1087 sct->sct_newtype = sct->sct_type;
1093 for (c = 0; c < nc; ++c) {
1094 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1095 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1099 /****************************************************************************
1100 WRITE ALL THIS STUFF TO THE FILE
1101 ****************************************************************************/
1107 /* if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1108 if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1109 perror(empfile[EF_SECTOR].file);
1112 if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1113 printf("%s:partial write\n", empfile[EF_SECTOR].file);
1120 /****************************************************************************
1121 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1122 ****************************************************************************/
1128 translate_continents();
1130 for (i = 0; i < WORLD_Y; ++i) {
1134 for (j = i % 2; j < WORLD_X; j += 2) {
1135 if (own[j][i] == -1)
1138 printf("%c ", map_symbol(j, i));
1144 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");
1147 /* Reorder the continents from top left to bottom right */
1149 translate_continents(void)
1151 int i, j, n = 0, k, gotit, c;
1152 int *trans, *trans_cont, *oldcapx, *oldcapy;
1154 trans = (int *)calloc(nc, sizeof(int));
1155 trans_cont = (int *)calloc(nc, sizeof(int));
1156 oldcapx = (int *)calloc(nc, sizeof(int));
1157 oldcapy = (int *)calloc(nc, sizeof(int));
1159 for (i = 0; i < WORLD_Y; ++i) {
1160 for (j = i % 2; j < WORLD_X; j += 2) {
1161 if (own[j][i] > -1 && own[j][i] < nc) {
1163 for (k = 0; k < n; ++k) {
1164 if (trans[k] == own[j][i])
1169 printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n");
1172 trans[n] = own[j][i];
1173 trans_cont[own[j][i]] = n;
1179 for (i = 0; i < WORLD_Y; ++i) {
1180 for (j = i % 2; j < WORLD_X; j += 2) {
1181 if (own[j][i] > -1 && own[j][i] < nc) {
1182 own[j][i] = trans_cont[own[j][i]];
1186 for (c = 0; c < nc; ++c) {
1187 oldcapx[c] = capx[c];
1188 oldcapy[c] = capy[c];
1190 for (c = 0; c < nc; ++c) {
1191 capx[c] = oldcapx[trans[c]];
1192 capy[c] = oldcapy[trans[c]];
1197 map_symbol(int x, int y)
1201 for (c = 0; c < nc; ++c)
1202 if ((x == capx[c] && y == capy[c])
1203 || (x == new_x(capx[c] + 2) && y == capy[c]))
1205 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1206 || elev[x][y] >= HIGHMIN)
1208 return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1211 /***************************************************************************
1212 WRITE A SCRIPT FOR PLACING CAPITALS
1213 ****************************************************************************/
1215 write_newcap_script(void)
1218 FILE *script = fopen(outfile, "w");
1221 printf("fairland: error, unable to write to %s.\n", outfile);
1225 for (c = 0; c < nc; ++c) {
1226 fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1228 fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1229 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1231 fprintf(script, "add %d visitor visitor v i\n", c + 1);
1234 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1240 qprint(const char * const fmt, ...)
1246 vfprintf(stdout, fmt, ap);
1252 fl_sct_init(coord x, coord y, s_char *ptr)
1254 struct sctstr *sp = (struct sctstr *)ptr;
1256 sp->ef_type = EF_SECTOR;
1263 sp->sct_defense = 0;