]> git.pond.sub.org Git - empserver/blobdiff - src/util/fairland.c
Fix PRNG seeding to resist guessing
[empserver] / src / util / fairland.c
index b6f0d7a13057952a3fc0c54535ec92fc030c4de0..d95282f2c60e82ee872f093ba680e1dbe47ee670 100644 (file)
@@ -1,11 +1,11 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
- *                           Ken Stevens, Steve McClure
+ *  Copyright (C) 1986-2013, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                Ken Stevens, Steve McClure, Markus Armbruster
  *
- *  This program is free software; you can redistribute it and/or modify
+ *  Empire is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation, either version 3 of the License, or
  *  (at your option) any later version.
  *
  *  This program is distributed in the hope that it will be useful,
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *
  *  ---
  *
- *  See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
- *  related information and legal notices. It is expected that any future
- *  projects/authors will amend these files as needed.
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
  *
  *  ---
  *
  *  fairland.c: Create a nice, new world
- * 
+ *
  *  Known contributors to this file:
  *     Ken Stevens, 1995
  *     Steve McClure, 1998
+ *     Markus Armbruster, 2004-2012
  */
 
+#include <config.h>
+
 /* define ORE 1 to add resources, define ORE 0 if you want to use another
    program to add the resources */
 static int ORE = 1;
@@ -53,7 +55,7 @@ static int quiet = 0;
 #define FERT_MAX   56
 
 /* raise OIL_MAX for more oil */
-#define OIL_MAX    33
+#define OIL_MAX           33
 
 /* lower IRON_MIN for more iron */
 #define IRON_MIN   22
@@ -64,24 +66,18 @@ static int quiet = 0;
 /* lower URAN_MIN for more uranium */
 #define URAN_MIN   56
 
-#if defined(_WIN32)
-#include "../lib/gen/getopt.h"
-#endif
-
+#include <assert.h>
 #include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include "misc.h"
-#include "power.h"
-#include "nat.h"
-#include "sect.h"
-#include "gamesdef.h"
+#include <unistd.h>
+#include "chance.h"
 #include "file.h"
-#include "xy.h"
 #include "optlist.h"
 #include "prototypes.h"
+#include "sect.h"
+#include "version.h"
+#include "xy.h"
 
 /* do not change these 4 defines */
 #define LANDMIN                1       /* plate altitude for normal land */
@@ -104,10 +100,8 @@ static int DISTINCT_ISLANDS = 1;
 
 static char *program_name;
 
-#define XSIZE           ((WORLD_X) / 2)        /* basically world x-y size */
-#define YSIZE           (WORLD_Y)
 #define STABLE_CYCLE 4         /* stability required for perterbed capitals */
-#define INFINITY        999    /* a number which means "BIG" */
+#define INFINITY       999     /* a number which means "BIG" */
 
 /* these defines prevent infinite loops:
 */
@@ -123,61 +117,52 @@ static char *program_name;
 
 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
-#if !defined(_WIN32)
-#define max(a,b) (a>b?a:b)
-#endif
-#define rnd(x) (random() % (x))
-
-int secs;                      /* number of sectors grown */
-int ctot;                      /* total number of continents and islands grown */
-int *isecs;                    /* array of how large each island is */
-
-int nc, sc, di, sp, pm, ni, is, id;    /* the 8 arguments to this program */
-unsigned long rnd_seed;                /* optional seed can be passed as an argument */
-int *capx, *capy;              /* location of the nc capitals */
-int *mc, mcc;                  /* array and counter used for stability
+
+static int secs;               /* number of sectors grown */
+static int ctot;               /* total number of continents and islands grown */
+static int *isecs;             /* array of how large each island is */
+
+static int nc, sc, di, sp, pm, ni, is, id; /* the 8 args to this program */
+static unsigned long rnd_seed; /* optional seed argument */
+static int *capx, *capy;       /* location of the nc capitals */
+static int *mc, mcc;           /* array and counter used for stability
                                   check when perturbing */
-int spike;                     /* are we spiking? */
-int mind;                      /* the final distance between capitals that
+static int spike;              /* are we spiking? */
+static int mind;               /* the final distance between capitals that
                                   we achieved */
-int dirx[] = { -2, -1, 1, 2, 1, -1 };  /* gyujnb */
-int diry[] = { 0, -1, -1, 0, 1, 1 };
-
-int **own;                     /* owner of the sector.  -1 means water */
-int **elev;                    /* elevation of the sectors */
-int **sectx, **secty;          /* the sectors for each continent */
-int **sectc;                   /* which sectors are on the coast? */
-int *vector;                   /* used for measuring distances */
-int *weight;                   /* used for placing mountains */
-int *dsea, *dmoun;             /* the dist to the ocean and mountain */
-FILE *sect_fptr;                       /* the file we write everything to */
-struct sctstr **sects;
-struct sctstr *sectsbuf;
-int fl_status;                 /* is anything wrong? */
-#define STATUS_NO_ROOM (1)     /* there was no room to grow */
+static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
+static int diry[] = { 0, -1, -1, 0, 1, 1 };
+
+static int **own;              /* owner of the sector.  -1 means water */
+static int **elev;             /* elevation of the sectors */
+static int **sectx, **secty;   /* the sectors for each continent */
+static int **sectc;            /* which sectors are on the coast? */
+static int *vector;            /* used for measuring distances */
+static int *weight;            /* used for placing mountains */
+static int *dsea, *dmoun;      /* the dist to the ocean and mountain */
+static int fl_status;          /* is anything wrong? */
+#define STATUS_NO_ROOM 1       /* there was no room to grow */
 #define NUMTRIES 10            /* keep trying to grow this many times */
 
-const char *numletter =
+static const char *numletter =
     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 
 static void help(char *);
 static void usage(void);
 static void parse_args(int argc, char *argv[]);
-static int allocate_memory(void);
+static void allocate_memory(void);
 static void init(void);
 static int drift(void);
 static void grow_continents(void);
 static void create_elevations(void);
 static void write_sects(void);
-static int write_file(void);
 static void output(void);
 static int write_newcap_script(void);
 static int stable(void);
 static void elevate_land(void);
 static void elevate_sea(void);
-static void translate_continents(void);
 static int map_symbol(int x, int y);
-static void fl_sct_init(coord x, coord y, s_char *ptr);
+static void set_coastal_flags(void);
 
 static void print_vars(void);
 static void fl_move(int);
@@ -194,48 +179,57 @@ main(int argc, char *argv[])
     int opt;
     char *config_file = NULL;
     int i = 0;
+    int seed_set = 0;
 
     program_name = argv[0];
-    rnd_seed = time(NULL);
+    rnd_seed = 0;
 
-    while ((opt = getopt(argc, argv, "ae:hioqs:R:")) != EOF) {
+    while ((opt = getopt(argc, argv, "ae:hioqR:s:v")) != EOF) {
        switch (opt) {
        case 'a':
            AIRPORT_MARKER = 1;
            break;
-       case 'i':
-           DISTINCT_ISLANDS = 0;
-           break;
        case 'e':
            config_file = optarg;
            break;
+       case 'i':
+           DISTINCT_ISLANDS = 0;
+           break;
        case 'o':
            ORE = 0;
            break;
        case 'q':
            quiet = 1;
            break;
-       case 's':
-           outfile = optarg;
-           break;
        case 'R':
            rnd_seed = strtoul(optarg, NULL, 10);
+           seed_set = 1;
+           break;
+       case 's':
+           outfile = optarg;
            break;
        case 'h':
            usage();
-           return 0;
+           exit(0);
+       case 'v':
+           printf("%s\n\n%s", version, legal);
+           exit(0);
        default:
            help(NULL);
            exit(1);
        }
     }
-    srandom(rnd_seed);
-    if (emp_config(config_file))
+    parse_args(argc - optind, argv + optind);
+
+    if (!seed_set)
+       rnd_seed = pick_seed();
+    seed_prng(rnd_seed);
+    empfile_init();
+    if (emp_config(config_file) < 0)
        exit(1);
+    empfile_fixup();
 
-    parse_args(argc - optind, argv + optind);
-    if (allocate_memory() == -1)
-       exit(-1);
+    allocate_memory();
     print_vars();
 
     do {
@@ -262,12 +256,22 @@ main(int argc, char *argv[])
     qprint("designating sectors...\n");
     if (ORE)
        qprint("adding resources...\n");
+    write_newcap_script();
+
+    if (chdir(gamedir)) {
+       fprintf(stderr, "Can't chdir to %s (%s)\n", gamedir, strerror(errno));
+       exit(EXIT_FAILURE);
+    }
+    if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
+       exit(1);
     write_sects();
     qprint("writing to sectors file...\n");
-    if (write_file() == -1)
-       exit(-1);
+    if (!ef_close(EF_SECTOR))
+       exit(1);
+
     output();
-    write_newcap_script();
+    qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
+          outfile);
     if (!ORE)
        qprint("\t*** Resources have not been added ***\n");
     exit(0);
@@ -315,24 +319,25 @@ help(char *complaint)
 static void
 usage(void)
 {
-    printf("Usage: %s [-e CONFIG] [-aiqo] [-s SCRIPT] [-R SEED] NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
-          "  -q            quiet\n"
-          "  -o            don't set resources\n"
-          "  -a            airport marker for continents\n"
-          "  -i            islands may merge\n"
-          "  -R SEED       seed for random number generator\n"
-          "  -e CONFIG     configuration file\n"
-          "  -s SCRIPT     name of script to create (default %s)\n"
-          "  NC            number of continents\n"
-          "  SC            continent size\n"
-          "  NI            number of islands (default NC)\n"
-          "  IS            average island size (default SC/2)\n"
-          "  SP            spike percentage: 0 = round, 100 = snake\n"
-          "                (default = %d)\n"
-          "  PM            percentage of land that is mountain (default %d)\n"
-          "  DI            minimum distance between continents (default %d)\n"
-          "  ID            minimum distance from islands to continents (default %d)\n",
-          program_name, DEFAULT_OUTFILE_NAME,
+    printf("Usage: %s [OPTION]... NC SC [NI] [IS] [SP] [PM] [DI] [ID]\n"
+          "  -a              airport marker for continents\n"
+          "  -e CONFIG-FILE  configuration file\n"
+          "                  (default %s)\n"
+          "  -h              display this help and exit\n"
+          "  -i              islands may merge\n"
+          "  -o              don't set resources\n"
+          "  -q              quiet\n"
+          "  -R SEED         seed for random number generator\n"
+          "  -s SCRIPT       name of script to create (default %s)\n"
+          "  NC              number of continents\n"
+          "  SC              continent size\n"
+          "  NI              number of islands (default NC)\n"
+          "  IS              average island size (default SC/2)\n"
+          "  SP              spike percentage: 0 = round, 100 = snake (default %d)\n"
+          "  PM              percentage of land that is mountain (default %d)\n"
+          "  DI              minimum distance between continents (default %d)\n"
+          "  ID              minimum distance from islands to continents (default %d)\n",
+          program_name, dflt_econfig, DEFAULT_OUTFILE_NAME,
           DEFAULT_SPIKE, DEFAULT_MOUNTAIN, DEFAULT_CONTDIST, DEFAULT_ISLDIST);
 }
 
@@ -368,8 +373,8 @@ parse_args(int argc, char *argv[])
        is = atoi(argv[3]);
     else
        is = sc / 2;
-    if (is < 0)
-       is = 0;
+    if (is < 1)
+       is = 1;
 
     if (argc > 4)
        sp = atoi(argv[4]);
@@ -414,10 +419,9 @@ parse_args(int argc, char *argv[])
        exit(1);
     }
     if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
-       puts("fairland: error -- world not big enough to fit continents.");
-       puts("arguments must satisfy:");
+       puts("fairland: warning -- world might be too small to fit continents.");
+       puts("arguments should satisfy:");
        puts("nc*sc*sc + nc*sqrt(sc)*2*(di+1) < WORLD_X * WORLD_Y");
-       exit(1);
     }
 }
 
@@ -425,24 +429,11 @@ parse_args(int argc, char *argv[])
   VARIABLE INITIALIZATION
 ****************************************************************************/
 
-static int
+static void
 allocate_memory(void)
 {
     int i;
-    char *fname;
 
-    fname = malloc(strlen(datadir) + 1 + strlen(empfile[EF_SECTOR].file) + 1);
-    sprintf(fname, "%s/%s", datadir, empfile[EF_SECTOR].file);
-    sect_fptr = fopen(fname, "wb");
-    if (sect_fptr == NULL) {
-       perror(fname);
-       return -1;
-    }
-    free(fname);
-    sectsbuf = calloc((YSIZE * XSIZE), sizeof(struct sctstr));
-    sects = calloc(YSIZE, sizeof(struct sctstr *));
-    for (i = 0; i < YSIZE; i++)
-       sects[i] = &sectsbuf[XSIZE * i];
     capx = calloc(nc, sizeof(int));
     capy = calloc(nc, sizeof(int));
     vector = calloc(WORLD_X + WORLD_Y, sizeof(int));
@@ -457,9 +448,9 @@ allocate_memory(void)
     secty = calloc(nc + ni, sizeof(int *));
     sectc = calloc(nc + ni, sizeof(int *));
     isecs = calloc(nc + ni, sizeof(int));
-    weight = calloc(max(sc, is * 2), sizeof(int));
-    dsea = calloc(max(sc, is * 2), sizeof(int));
-    dmoun = calloc(max(sc, is * 2), sizeof(int));
+    weight = calloc(MAX(sc, is * 2), sizeof(int));
+    dsea = calloc(MAX(sc, is * 2), sizeof(int));
+    dmoun = calloc(MAX(sc, is * 2), sizeof(int));
     for (i = 0; i < nc; ++i) {
        sectx[i] = calloc(sc, sizeof(int));
        secty[i] = calloc(sc, sizeof(int));
@@ -471,7 +462,6 @@ allocate_memory(void)
        sectc[i] = calloc(is * 2, sizeof(int));
     }
 
-    return 0;
 }
 
 static void
@@ -489,7 +479,7 @@ init(void)
        }
     }
 
-    for (i = 0; i < nc; ++i, xx += 2) {
+    for (i = 0; i < nc; ++i) {
        if (xx >= WORLD_X) {
            ++yy;
            xx = yy % 2;
@@ -500,6 +490,7 @@ init(void)
        }
        capx[i] = xx;
        capy[i] = yy;
+       xx += 2;
     }
     for (i = 0; i < STABLE_CYCLE; ++i)
        mc[i] = i;
@@ -572,7 +563,7 @@ fl_move(int j)
 {
     int i, n, newx, newy;
 
-    for (i = rnd(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
+    for (i = roll0(6), n = 0; n < 6; i = (i + 1) % 6, ++n) {
        newx = new_x(capx[j] + dirx[i]);
        newy = new_y(capy[j] + diry[i]);
        if (iso(j, newx, newy) >= iso(j, capx[j], capy[j])) {
@@ -689,18 +680,14 @@ new_try(int c)
        if (sectc[c][0])
            return 0;
     } else {
-       i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : rnd(secs);
+       i = starti = (spike && sectc[c][secs - 1]) ? secs - 1 : roll0(secs);
        do {
            if (sectc[c][i])
                return i;
            i = (i + 1) % secs;
        } while (i != starti);
-       if (c < nc) {
-           printf("fairland: BUG -- couldn't find coast for continent %c, sector %d.\nPlease mail stevens@math.utoronto.ca.\n",
-                  c + 'a', secs);
-           exit(1);
-       } else
-           return -1;
+       assert(c >= nc);
+       return -1;
     }
     return -1;
 }
@@ -713,7 +700,7 @@ grow_one_sector(int c)
 {
     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
 
-    spike = rnd(100) < sp;
+    spike = roll0(100) < sp;
     if ((try1 = new_try(c)) == -1)
        return 0;
     x = sx = sectx[c][try1];
@@ -722,7 +709,7 @@ grow_one_sector(int c)
     done = 0;
     do {
        if (spike) {
-           for (i = rnd(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
+           for (i = roll0(6), n = 0; n < 12 && !done; i = (i + 1) % 6, ++n) {
                newx = new_x(x + dirx[i]);
                newy = new_y(y + diry[i]);
                if (own[newx][newy] == -1 &&
@@ -733,7 +720,7 @@ grow_one_sector(int c)
                        done = 1;
            }
        } else
-           for (i = rnd(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
+           for (i = roll0(6), n = 0; n < 6 && !done; i = (i + 1) % 6, ++n) {
                newx = new_x(x + dirx[i]);
                newy = new_y(y + diry[i]);
                if (own[newx][newy] == -1)
@@ -774,6 +761,9 @@ grow_continents(void)
            grow_one_sector(c);
        }
     }
+    for (c = 0; c < nc; ++c)
+       find_coast(c);
+
     if (fl_status)
        qprint("Only managed to grow %d out of %d sectors.\n", secs, sc);
     ctot = nc;
@@ -789,8 +779,8 @@ static int
 place_island(int c, int *xp, int *yp)
 {
     int d, sx, sy;
-    int ssy = rnd(WORLD_Y);
-    int ssx = new_x(rnd(WORLD_X / 2) * 2 + ssy % 2);
+    int ssy = roll0(WORLD_Y);
+    int ssx = new_x(roll0(WORLD_X / 2) * 2 + ssy % 2);
 
     if (ssx > WORLD_X - 2)
        ssx = new_x(ssx + 2);
@@ -801,7 +791,7 @@ place_island(int c, int *xp, int *yp)
        for (*yp = sy; *xp != sx || *yp != sy; *xp += 2) {
            if (*xp >= WORLD_X) {
                *yp = new_y(*yp + 1);
-               *xp = (*yp) % 2;
+               *xp = *yp % 2;
                if (*xp == sx && *yp == sy)
                    break;
            }
@@ -824,14 +814,15 @@ grow_islands(void)
        secs = 0;
        if (!place_island(c, &x, &y))
            return;
-       isiz = 1 + rnd(2 * is - 1);
+       isiz = roll(2 * is - 1);
        do {
            ++secs;
            find_coast(c);
        } while (secs < isiz && grow_one_sector(c));
+       find_coast(c);
        qprint(" %d(%d)", c - nc + 1, secs);
        isecs[c] = secs;
-       ctot = c;
+       ctot++;
     }
 }
 
@@ -909,7 +900,7 @@ elevate_land(void)
        for (k = nm, mountain_search = 0;
             k && mountain_search < MOUNTAIN_SEARCH_MAX;
             ++mountain_search) {
-           r = rnd(total);
+           r = roll0(total);
            for (i = 0; i < ns; ++i)
                if (r < weight[i] && ELEV == -INFINITY &&
                    (c >= nc ||
@@ -963,14 +954,14 @@ elevate_land(void)
        for (i = 0; i < ns; ++i) {
            if (ELEV == INFINITY) {
                if (dsea[i] == 1)
-                   ELEV = HILLMIN + rnd(PLATMIN - HILLMIN);
+                   ELEV = HILLMIN + roll0(PLATMIN - HILLMIN);
                else
-                   ELEV = HIGHMIN + rnd((256 - HIGHMIN) / 2) +
-                     rnd((256 - HIGHMIN) / 2);
-           } else if ((c < nc &&
-                       ((capx[c] == sectx[c][i] && capy[c] == secty[c][i]))) ||
-                      ((new_x(capx[c] + 2) == sectx[c][i] &&
-                        capy[c] == secty[c][i])))
+                   ELEV = HIGHMIN + roll0((256 - HIGHMIN) / 2) +
+                     roll0((256 - HIGHMIN) / 2);
+           } else if (c < nc &&
+                      (((capx[c] == sectx[c][i] && capy[c] == secty[c][i])) ||
+                       ((new_x(capx[c] + 2) == sectx[c][i] &&
+                         capy[c] == secty[c][i]))))
                ELEV = PLATMIN;
        }
     }
@@ -986,7 +977,7 @@ elevate_sea(void)
     for (y = 0; y < WORLD_Y; ++y) {
        for (x = y % 2; x < WORLD_X; x += 2) {
            if (elev[x][y] == -INFINITY)
-               elev[x][y] = -rnd((distance_to_land() * 20 + 27)) - 1;
+               elev[x][y] = -roll(distance_to_land() * 20 + 27);
        }
     }
 }
@@ -1002,9 +993,9 @@ set_fert(int e)
     if (e < LANDMIN)
        fert = LANDMIN - e + 40;
     else if (e < FERT_MAX)
-       fert = (140 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
-    if (fert > 120)
-       fert = 120;
+       fert = (120 * (FERT_MAX - e)) / (FERT_MAX - LANDMIN);
+    if (fert > 100)
+       fert = 100;
     return fert;
 }
 
@@ -1013,7 +1004,7 @@ set_oil(int e)
 {
     int oil = 0;
     if (e < LANDMIN)
-       oil = (LANDMIN - e) * 2 + rnd(2);
+       oil = (LANDMIN - e) * 2 + roll0(2);
     else if (e <= OIL_MAX)
        oil = (120 * (OIL_MAX - e + 1)) / (OIL_MAX - LANDMIN + 1);
     if (oil > 100)
@@ -1078,12 +1069,10 @@ write_sects(void)
     struct sctstr *sct;
     int c, x, y, total;
 
-    /*  sct = &sects[0][0]; */
-    sct = sectsbuf;
-    for (y = 0; y < YSIZE; y++) {
-       for (x = 0; x < XSIZE; x++, sct++) {
-           fl_sct_init(x * 2 + (y & 01), y, (s_char *)sct);
-           total = elev[sct->sct_x][y];
+    for (y = 0; y < WORLD_Y; y++) {
+       for (x = y % 2; x < WORLD_X; x += 2) {
+           sct = getsectp(x, y);
+           total = elev[x][y];
            if (total < LANDMIN) {
                sct->sct_type = SCT_WATER;
            } else if (total < HILLMIN)
@@ -1102,30 +1091,11 @@ write_sects(void)
     }
     if (AIRPORT_MARKER)
        for (c = 0; c < nc; ++c) {
-           sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_type = SCT_AIRPT;
-           sects[capy[c]][capx[c] / 2 + capy[c] % 2].sct_newtype = SCT_AIRPT;
+           sct = getsectp(capx[c], capy[c]);
+           sct->sct_type = SCT_AIRPT;
+           sct->sct_newtype = SCT_AIRPT;
        }
-}
-
-/****************************************************************************
-  WRITE ALL THIS STUFF TO THE FILE
-****************************************************************************/
-static int
-write_file(void)
-{
-    int n;
-
-    n = fwrite(sectsbuf, sizeof(struct sctstr), YSIZE * XSIZE, sect_fptr);
-    if (n <= 0) {
-       perror(empfile[EF_SECTOR].file);
-       return -1;
-    }
-    if (n != YSIZE * XSIZE) {
-       printf("%s:partial write\n", empfile[EF_SECTOR].file);
-       return -1;
-    }
-    fclose(sect_fptr);
-    return 0;
+    set_coastal_flags();
 }
 
 /****************************************************************************
@@ -1135,8 +1105,6 @@ static void
 output(void)
 {
     int i, j;
-    if (opt_BLITZ)
-       translate_continents();
     if (quiet == 0) {
        for (i = 0; i < WORLD_Y; ++i) {
            puts("");
@@ -1152,56 +1120,9 @@ output(void)
        }
     }
     if (AIRPORT_MARKER)
-       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");
-}
-
-/* Reorder the continents from top left to bottom right */
-static void
-translate_continents(void)
-{
-    int i, j, n = 0, k, gotit, c;
-    int *trans, *trans_cont, *oldcapx, *oldcapy;
-
-    trans = calloc(nc, sizeof(int));
-    trans_cont = calloc(nc, sizeof(int));
-    oldcapx = calloc(nc, sizeof(int));
-    oldcapy = calloc(nc, sizeof(int));
-
-    for (i = 0; i < WORLD_Y; ++i) {
-       for (j = i % 2; j < WORLD_X; j += 2) {
-           if (own[j][i] > -1 && own[j][i] < nc) {
-               gotit = 0;
-               for (k = 0; k < n; ++k) {
-                   if (trans[k] == own[j][i])
-                       gotit = 1;
-               }
-               if (!gotit) {
-                   if (n > nc) {
-                       printf("fairland: BUG in translate continents!  mail stevens@math.utoronto.ca\n");
-                       exit(2);
-                   }
-                   trans[n] = own[j][i];
-                   trans_cont[own[j][i]] = n;
-                   ++n;
-               }
-           }
-       }
-    }
-    for (i = 0; i < WORLD_Y; ++i) {
-       for (j = i % 2; j < WORLD_X; j += 2) {
-           if (own[j][i] > -1 && own[j][i] < nc) {
-               own[j][i] = trans_cont[own[j][i]];
-           }
-       }
-    }
-    for (c = 0; c < nc; ++c) {
-       oldcapx[c] = capx[c];
-       oldcapy[c] = capy[c];
-    }
-    for (c = 0; c < nc; ++c) {
-       capx[c] = oldcapx[trans[c]];
-       capy[c] = oldcapy[trans[c]];
-    }
+       printf("\n\nEach continent is marked by a \"*\" on the map (to distinguish them from\n"
+              "the islands).  You can redesignate these airfields to wilderness sectors\n"
+              "one at a time, each time you add a new country to the game.\n");
 }
 
 static int
@@ -1234,21 +1155,18 @@ write_newcap_script(void)
     }
 
     for (c = 0; c < nc; ++c) {
-       fprintf(script, "add %d %d %d n i\n", c + 1, c + 1, c + 1);
+       fprintf(script, "add %d %d %d p\n", c + 1, c + 1, c + 1);
        if (AIRPORT_MARKER)
            fprintf(script, "des %d,%d -\n", capx[c], capy[c]);
        fprintf(script, "newcap %d %d,%d\n", c + 1, capx[c], capy[c]);
     }
-    fprintf(script, "add %d visitor visitor v i\n", c + 1);
-    ++c;
+    fprintf(script, "add %d visitor visitor v\n", c + 1);
     fclose(script);
-    qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
-          outfile);
     return 0;
 }
 
 static void
-qprint(const char * const fmt, ...)
+qprint(const char *const fmt, ...)
 {
     va_list ap;
 
@@ -1260,16 +1178,22 @@ qprint(const char * const fmt, ...)
 }
 
 static void
-fl_sct_init(coord x, coord y, s_char *ptr)
+set_coastal_flags(void)
 {
-    struct sctstr *sp = (struct sctstr *)ptr;
-
-    sp->ef_type = EF_SECTOR;
-    sp->sct_x = x;
-    sp->sct_y = y;
-    sp->sct_dist_x = x;
-    sp->sct_dist_y = y;
-    sp->sct_road = 0;
-    sp->sct_rail = 0;
-    sp->sct_defense = 0;
+    int i, j;
+    struct sctstr *sp;
+
+    qprint("setting coastal flags...\n");
+    for (i = 0; i < nc; ++i) {
+       for (j = 0; j < sc; j++) {
+           sp = getsectp(sectx[i][j], secty[i][j]);
+           sp->sct_coastal = sectc[i][j];
+       }
+    }
+    for (i = nc; i < nc + ni; ++i) {
+       for (j = 0; j < isecs[i]; j++) {
+           sp = getsectp(sectx[i][j], secty[i][j]);
+           sp->sct_coastal = sectc[i][j];
+       }
+    }
 }