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 #define DEFAULT_OUTFILE_NAME "newcap_script"
98 static const char *outfile = DEFAULT_OUTFILE_NAME;
99 /* mark the continents with a * so you can tell them
100 from the islands 1 = mark, 0 = don't mark. */
101 static int AIRPORT_MARKER = 0;
103 /* don't let the islands crash into each other.
104 1 = don't merge, 0 = merge. */
105 static int DISTINCT_ISLANDS = 1;
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 int the_file; /* 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 parse_args(int argc, char *argv[]);
164 static int allocate_memory(void);
165 static void init(void);
166 static int drift(void);
167 static void grow_continents(void);
168 static void create_elevations(void);
169 static void write_sects(void);
170 static int write_file(void);
171 static void output(void);
172 static int write_newcap_script(void);
173 static int stable(void);
174 static void elevate_land(void);
175 static void elevate_sea(void);
176 static void translate_continents(void);
177 static int map_symbol(int x, int y);
178 static void fl_sct_init(coord x, coord y, s_char *ptr);
180 static void print_vars(void);
181 static void fl_move(int);
182 static void next_coast(int c, int x, int y, int *xp, int *yp);
183 static void grow_islands(void);
185 /****************************************************************************
187 ****************************************************************************/
190 main(int argc, char *argv[])
193 char *config_file = NULL;
197 rnd_seed = time(NULL);
199 rnd_seed += getpid();
202 while ((opt = getopt(argc, argv, "ae:ioqs:R:")) != EOF) {
208 DISTINCT_ISLANDS = 0;
211 config_file = optarg;
223 rnd_seed = strtoul(optarg, NULL, 10);
228 if (config_file == NULL) {
229 sprintf(tbuf, "%s/econfig", datadir);
232 emp_config(config_file);
234 parse_args(argc - optind, argv + optind);
235 if (allocate_memory() == -1)
242 qprint("\ntry #%d (out of %d)...", i + 1, NUMTRIES);
243 qprint("\n\n #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
244 qprint("seed is %lu\n", rnd_seed);
245 qprint("placing capitals...\n");
247 qprint("fairland: unstable drift -- try increasisg DRIFT_MAX\n");
248 qprint("growing continents...\n");
250 } while (fl_status && ++i < NUMTRIES);
252 fputs("ERROR: World not large enough to hold continents\n",
256 qprint("growing islands:");
258 qprint("\nelevating land...\n");
260 qprint("designating sectors...\n");
262 qprint("adding resources...\n");
264 qprint("writing to sectors file...\n");
265 if (write_file() == -1)
268 write_newcap_script();
270 qprint("\t*** Resources have not been added ***\n");
279 puts("Creating a planet with:\n");
280 printf("%d continents\n", nc);
281 printf("continent size: %d\n", sc);
282 printf("number of islands: %d\n", ni);
283 printf("average size of islands: %d\n", is);
284 printf("spike: %d%%\n", sp);
285 printf("%d%% of land is mountain (each continent will have %d mountains)\n",
286 pm, (pm * sc) / 100);
287 printf("minimum distance between continents: %d\n", di);
288 printf("minimum distance from islands to continents: %d\n", id);
289 printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
297 for (i = 1; i * i < n * 10000; ++i) ;
298 return (i + 50) / 100;
301 /****************************************************************************
302 PARSE COMMAND LINE ARGUMENTS
303 ****************************************************************************/
306 parse_args(int argc, char *argv[])
308 if (argc < 2 || argc > 8) {
309 puts("fairland syntax:\n");
310 puts("fairland [-e config] [-aiqo] [-s script] [-R seed] <nc> <sc> [<ni>] [<is>] [<sp>] [<pm>] [<di>] [<id>]");
311 puts("-q = quiet, -o = no ore produced");
312 puts("-a = Airport marker for continents, -i = islands not distinct");
313 puts("-R = seed to use for random, -e = read config file");
314 printf("-s = name of script (default = %s)\n",
315 DEFAULT_OUTFILE_NAME);
316 puts("nc = number of continents [MANDATORY]");
317 puts("sc = continent size [MANDATORY]");
318 puts("ni = number of islands (default = nc)");
319 puts("is = average size of islands (default = sc/2)");
320 printf("sp = spike percentage: 0 = round, 100 = snake (default = %d)\n",
322 printf("pm = the percentage of land that is mountain (default = %d)\n",
324 printf("di = the minimum distance between continents (default = %d)\n",
326 printf("id = minimum distance from islands to continents (default = %d)\n",
332 puts("fairland: error -- number of continents must be > 0");
338 puts("fairland: error -- size of continents must be > 0");
366 pm = DEFAULT_MOUNTAIN;
373 di = DEFAULT_CONTDIST;
376 puts("fairland: error -- distance between continents must be >= 0");
379 if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
380 puts("fairland: error -- distance between continents too large");
387 id = DEFAULT_ISLDIST;
389 puts("fairland: error -- distance from islands to continents must be >= 0");
392 if (id > WORLD_X || id > WORLD_Y) {
393 puts("fairland: error -- distance from islands to continents too large");
396 if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
397 puts("fairland: error -- world not big enough to fit continents.");
398 puts("arguments must satisfy:");
399 puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
404 /****************************************************************************
405 VARIABLE INITIALIZATION
406 ****************************************************************************/
409 allocate_memory(void)
415 open(empfile[EF_SECTOR].file, O_RDWR | O_CREAT | O_TRUNC, 0660);
418 open(empfile[EF_SECTOR].file,
419 O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0660);
422 perror(empfile[EF_SECTOR].file);
426 (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
427 sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
428 for (i = 0; i < YSIZE; i++)
429 sects[i] = §sbuf[XSIZE * i];
430 capx = (int *)calloc(nc, sizeof(int));
431 capy = (int *)calloc(nc, sizeof(int));
432 vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
433 mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
434 own = (int **)calloc(WORLD_X, sizeof(int *));
435 elev = (int **)calloc(WORLD_X, sizeof(int *));
436 for (i = 0; i < WORLD_X; ++i) {
437 own[i] = (int *)calloc(WORLD_Y, sizeof(int));
438 elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
440 sectx = (int **)calloc(nc + ni, sizeof(int *));
441 secty = (int **)calloc(nc + ni, sizeof(int *));
442 sectc = (int **)calloc(nc + ni, sizeof(int *));
443 isecs = (int *)calloc(nc + ni, sizeof(int));
444 weight = (int *)calloc(max(sc, is * 2), sizeof(int));
445 dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
446 dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
447 for (i = 0; i < nc; ++i) {
448 sectx[i] = (int *)calloc(sc, sizeof(int));
449 secty[i] = (int *)calloc(sc, sizeof(int));
450 sectc[i] = (int *)calloc(sc, sizeof(int));
452 for (i = nc; i < nc + ni; ++i) {
453 sectx[i] = (int *)calloc(is * 2, sizeof(int));
454 secty[i] = (int *)calloc(is * 2, sizeof(int));
455 sectc[i] = (int *)calloc(is * 2, sizeof(int));
464 int i, j, xx = 0, yy = 0;
469 for (i = 0; i < WORLD_X; ++i) {
470 for (j = 0; j < WORLD_Y; ++j) {
472 elev[i][j] = -INFINITY;
476 for (i = 0; i < nc; ++i, xx += 2) {
481 puts("fairland error: world not big enough for all the continents.\n");
488 for (i = 0; i < STABLE_CYCLE; ++i)
492 /****************************************************************************
493 DRIFT THE CAPITALS UNTIL THEY ARE AS FAR AWAY FROM EACH OTHER AS POSSIBLE
494 ****************************************************************************/
496 /* How isolated is capital j?
499 iso(int j, int newx, int newy)
501 int i, md, d = WORLD_X + WORLD_Y;
503 for (i = 0; i < nc; ++i) {
506 md = mapdist(capx[i], capy[i], newx, newy);
514 /* Drift all the capitals
521 for (turns = 0; turns < DRIFT_MAX; ++turns) {
522 if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
524 for (i = 0; i < nc; ++i)
530 /* Check to see if we have stabilized--can we stop drifting the capitals?
536 int i, isod, d = 0, stab = 1;
538 for (i = 0; i < nc; ++i) {
539 isod = iso(i, capx[i], capy[i]);
543 for (i = 0; i < STABLE_CYCLE; ++i)
547 mcc = (mcc + 1) % STABLE_CYCLE;
551 /* This routine does the actual drifting
557 int i, n, newx, newy;
559 for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
560 newx = new_x(capx[j] + dirx[i]);
561 newy = new_y(capy[j] + diry[i]);
562 if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
570 /****************************************************************************
572 ****************************************************************************/
574 /* Look for a coastal sector of continent c
582 for (i = 0; i < secs; ++i) {
584 for (j = 0; j < 6; ++j)
585 if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
590 /* Used for measuring distances
602 for (i = 1; i < n && vector[i] == vector[i - 1]; ++i) ;
605 return i > 1 || vector[0] > 0;
608 /* Test to see if we're allowed to grow there: the arguments di and id
611 try_to_grow(int c, int newx, int newy, int d)
615 for (i = 1; i <= d; ++i) {
616 for (j = 0; j < i; ++j)
621 for (j = 0; j < i; ++j) {
622 px = new_x(px + dirx[vector[j]]);
623 py = new_y(py + diry[vector[j]]);
625 if (own[px][py] != -1 &&
627 (DISTINCT_ISLANDS || own[px][py] < nc))
629 } while (next_vector(i));
631 sectx[c][secs] = newx;
632 secty[c][secs] = newy;
637 /* Move along the coast in a clockwise direction.
641 next_coast(int c, int x, int y, int *xp, int *yp)
643 int i, nx, ny, wat = 0;
651 for (i = 0; i < 12; ++i) {
652 nx = new_x(x + dirx[i % 6]);
653 ny = new_y(y + diry[i % 6]);
654 if (own[nx][ny] == -1)
656 if (wat && own[nx][ny] == c) {
664 /* Choose a sector to grow from
676 i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
681 } while (i != starti);
683 printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
692 /* Grow continent c by 1 sector
696 grow_one_sector(int c)
698 int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
700 spike = rnd(100) < sp;
701 if ((try1 = new_try(c)) == -1)
703 x = sx = sectx[c][try1];
704 y = sy = secty[c][try1];
709 for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
710 newx = new_x(x + dirx[i]);
711 newy = new_y(y + diry[i]);
712 if (own[newx][newy] == -1 &&
714 (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
715 own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
716 if (try_to_grow(c, newx, newy, c < nc ? di : id))
720 for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
721 newx = new_x(x + dirx[i]);
722 newy = new_y(y + diry[i]);
723 if (own[newx][newy] == -1)
724 if (try_to_grow(c, newx, newy, c < nc ? di : id))
727 next_coast(c, x, y, &x, &y);
729 } while (!done && coast_search < COAST_SEARCH_MAX &&
730 (secs == 1 || x != sx || y != sy));
731 if (!done && c < nc) {
732 qprint("fairland: error -- continent %c had no room to grow!\n",
734 fl_status |= STATUS_NO_ROOM;
739 /* Grow all the continents
742 grow_continents(void)
746 for (c = 0; c < nc; ++c) {
747 sectx[c][0] = capx[c];
748 secty[c][0] = capy[c];
749 own[sectx[c][0]][secty[c][0]] = c;
750 sectx[c][1] = new_x(capx[c] + 2);
751 secty[c][1] = capy[c];
752 own[sectx[c][1]][secty[c][1]] = c;
755 for (secs = 2; secs < sc && !fl_status; ++secs) {
756 for (c = 0; c < nc; ++c) {
762 qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
766 /****************************************************************************
768 ****************************************************************************/
770 /* Choose a place to start growing an island from
773 place_island(int c, int *xp, int *yp)
776 int ssy = rnd(WORLD_Y);
777 int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
779 if (ssx > WORLD_X - 2)
780 ssx = new_x(ssx + 2);
781 for (d = di + id; d >= id; --d) {
785 for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
786 if (*xp >= WORLD_X) {
787 *yp = new_y(*yp + 1);
789 if (*xp == sx && *yp == sy)
792 if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
799 /* Grow all the islands
807 for (c = nc; c < nc + ni; ++c) {
809 if (!place_island(c, &x, &y))
811 isiz = 1 + rnd(2 * is - 1);
815 } while (secs < isiz && grow_one_sector(c));
816 qprint(" %d(%d)", c - nc + 1, secs);
822 /****************************************************************************
824 ****************************************************************************/
826 create_elevations(void)
832 /* Generic function for finding the distance to the closest sea, land, or
836 distance_to_what(int x, int y, int flag)
840 for (d = 1; d < 5; ++d) {
841 for (j = 0; j < d; ++j)
846 for (j = 0; j < d; ++j) {
847 px = new_x(px + dirx[vector[j]]);
848 py = new_y(py + diry[vector[j]]);
851 case 0: /* distance to sea */
852 if (own[px][py] == -1)
855 case 1: /* distance to land */
856 if (own[px][py] != -1)
859 case 2: /* distance to mountain */
860 if (elev[px][py] == INFINITY)
864 } while (next_vector(d));
869 #define ELEV elev[sectx[c][i]][secty[c][i]]
870 #define distance_to_sea() (sectc[c][i]?1:distance_to_what(sectx[c][i], secty[c][i], 0))
871 #define distance_to_mountain() distance_to_what(sectx[c][i], secty[c][i], 2)
873 /* Decide where the mountains go
878 int i, mountain_search, k, c, total, ns, nm, highest, where, h, newk,
881 for (c = 0; c < ctot; ++c) {
883 ns = (c < nc) ? sc : isecs[c];
884 nm = (pm * ns) / 100;
886 /* Place the mountains */
888 for (i = 0; i < ns; ++i) {
889 dsea[i] = distance_to_sea();
890 weight[i] = (total += (dsea[i] * dsea[i]));
893 for (k = nm, mountain_search = 0;
894 k && mountain_search < MOUNTAIN_SEARCH_MAX;
897 for (i = 0; i < ns; ++i)
898 if (r < weight[i] && ELEV == -INFINITY &&
900 ((!(capx[c] == sectx[c][i] &&
901 capy[c] == secty[c][i])) &&
902 (!(new_x(capx[c] + 2) == sectx[c][i] &&
903 capy[c] == secty[c][i]))))) {
910 /* Elevate land that is not mountain and not capital */
912 for (i = 0; i < ns; ++i)
913 dmoun[i] = distance_to_mountain();
914 dk = (ns - nm - ((c < nc) ? 3 : 1) > 0) ?
915 (100 * (HIGHMIN - LANDMIN)) / (ns - nm - ((c < nc) ? 3 : 1)) :
917 for (k = 100 * (HIGHMIN - 1);; k -= dk) {
920 for (i = 0; i < ns; ++i) {
921 if (ELEV != INFINITY &&
922 (c >= nc || ((!(capx[c] == sectx[c][i] &&
923 capy[c] == secty[c][i])) &&
924 (!(new_x(capx[c] + 2) == sectx[c][i] &&
925 capy[c] == secty[c][i]))))) {
926 h = 3 * (5 - dmoun[i]) + dsea[i];
936 if (newk >= HILLMIN && newk < PLATMIN)
940 elev[sectx[c][where]][secty[c][where]] = newk;
941 dsea[where] = -INFINITY;
942 dmoun[where] = INFINITY;
945 /* Elevate the mountains and capitals */
947 for (i = 0; i < ns; ++i) {
948 if (ELEV == INFINITY) {
950 ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
952 ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
953 rnd((256 - HIGHMIN) / 2);
954 } else if ((c < nc &&
955 ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
956 ((new_x(capx[c] + 2) == sectx[c][i] &&
957 capy[c] == secty[c][i])))
963 #define distance_to_land() distance_to_what(x, y, 1)
970 for (y = 0; y < WORLD_Y; ++y) {
971 for (x = y % 2; x < WORLD_X; x += 2) {
972 if (elev[x][y] == -INFINITY)
973 elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
978 /****************************************************************************
980 ****************************************************************************/
987 fert = LANDMIN - e + 40;
988 else if (e < FERT_MAX)
989 fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
1000 oil = (LANDMIN - e) * 2 + rnd(2);
1001 else if (e <= OIL_MAX)
1002 oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
1012 if (e >= IRON_MIN && e < HIGHMIN)
1013 iron = (120 * (e - IRON_MIN + 1)) / (HIGHMIN - IRON_MIN);
1023 if (e >= GOLD_MIN) {
1025 gold = (80 * (e - GOLD_MIN + 1)) / (HIGHMIN - GOLD_MIN);
1027 gold = 100 - 20 * HIGHMIN / e;
1038 if (e >= URAN_MIN && e < HIGHMIN)
1039 uran = (120 * (e - URAN_MIN + 1)) / (HIGHMIN - URAN_MIN);
1046 add_resources(struct sctstr *sct)
1048 sct->sct_fertil = set_fert(sct->sct_elev);
1049 sct->sct_oil = set_oil(sct->sct_elev);
1050 sct->sct_min = set_iron(sct->sct_elev);
1051 sct->sct_gmin = set_gold(sct->sct_elev);
1052 sct->sct_uran = set_uran(sct->sct_elev);
1055 /****************************************************************************
1056 DESIGNATE THE SECTORS
1057 ****************************************************************************/
1065 /* sct = §s[0][0]; */
1067 for (y = 0; y < YSIZE; y++) {
1068 for (x = 0; x < XSIZE; x++, sct++) {
1069 fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
1070 total = elev[sct->sct_x][y];
1071 if (total < LANDMIN) {
1072 sct->sct_type = SCT_WATER;
1073 } else if (total < HILLMIN)
1074 sct->sct_type = SCT_RURAL;
1075 else if (total < PLATMIN)
1076 sct->sct_type = SCT_MOUNT;
1077 else if (total < HIGHMIN)
1078 sct->sct_type = SCT_RURAL;
1080 sct->sct_type = SCT_MOUNT;
1081 sct->sct_elev = total;
1082 sct->sct_newtype = sct->sct_type;
1088 for (c = 0; c < nc; ++c) {
1089 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
1090 sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
1094 /****************************************************************************
1095 WRITE ALL THIS STUFF TO THE FILE
1096 ****************************************************************************/
1102 /* if ((n = write(the_file, sects, sizeof(sects))) < 0) { */
1103 if ((n = write(the_file, sectsbuf, YSIZE * XSIZE * sizeof(struct sctstr))) < 0) {
1104 perror(empfile[EF_SECTOR].file);
1107 if (n != (int)(YSIZE * XSIZE * sizeof(struct sctstr))) {
1108 printf("%s:partial write\n", empfile[EF_SECTOR].file);
1115 /****************************************************************************
1116 PRINT A PICTURE OF THE MAP TO YOUR SCREEN
1117 ****************************************************************************/
1123 translate_continents();
1125 for (i = 0; i < WORLD_Y; ++i) {
1129 for (j = i % 2; j < WORLD_X; j += 2) {
1130 if (own[j][i] == -1)
1133 printf("%c ", map_symbol(j, i));
1139 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");
1142 /* Reorder the continents from top left to bottom right */
1144 translate_continents(void)
1146 int i, j, n = 0, k, gotit, c;
1147 int *trans, *trans_cont, *oldcapx, *oldcapy;
1149 trans = (int *)calloc(nc, sizeof(int));
1150 trans_cont = (int *)calloc(nc, sizeof(int));
1151 oldcapx = (int *)calloc(nc, sizeof(int));
1152 oldcapy = (int *)calloc(nc, sizeof(int));
1154 for (i = 0; i < WORLD_Y; ++i) {
1155 for (j = i % 2; j < WORLD_X; j += 2) {
1156 if (own[j][i] > -1 && own[j][i] < nc) {
1158 for (k = 0; k < n; ++k) {
1159 if (trans[k] == own[j][i])
1164 printf("fairland: BUG in translate continents! mail stevens@math.utoronto.ca\n");
1167 trans[n] = own[j][i];
1168 trans_cont[own[j][i]] = n;
1174 for (i = 0; i < WORLD_Y; ++i) {
1175 for (j = i % 2; j < WORLD_X; j += 2) {
1176 if (own[j][i] > -1 && own[j][i] < nc) {
1177 own[j][i] = trans_cont[own[j][i]];
1181 for (c = 0; c < nc; ++c) {
1182 oldcapx[c] = capx[c];
1183 oldcapy[c] = capy[c];
1185 for (c = 0; c < nc; ++c) {
1186 capx[c] = oldcapx[trans[c]];
1187 capy[c] = oldcapy[trans[c]];
1192 map_symbol(int x, int y)
1196 for (c = 0; c < nc; ++c)
1197 if ((x == capx[c] && y == capy[c])
1198 || (x == new_x(capx[c] + 2) && y == capy[c]))
1200 if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
1201 || elev[x][y] >= HIGHMIN)
1203 return own[x][y] >= nc ? '%' : iscap ? '#' : numletter[own[x][y] % 62];
1206 /***************************************************************************
1207 WRITE A SCRIPT FOR PLACING CAPITALS
1208 ****************************************************************************/
1210 write_newcap_script(void)
1213 FILE *script = fopen(outfile, "w");
1216 printf("fairland: error, unable to write to %s.\n", outfile);
1220 for (c = 0; c < nc; ++c) {
1221 fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
1223 fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
1224 fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
1226 fprintf(script, "add %d visitor visitor v i\n", c + 1);
1229 qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
1235 qprint(const char * const fmt, ...)
1241 vfprintf(stdout, fmt, ap);
1247 fl_sct_init(coord x, coord y, s_char *ptr)
1249 struct sctstr *sp = (struct sctstr *)ptr;
1251 sp->ef_type = EF_SECTOR;
1258 sp->sct_defense = 0;