]> git.pond.sub.org Git - empserver/blobdiff - src/util/fairland.c
fairland: Report missing and stunted islands
[empserver] / src / util / fairland.c
index c48f1f5f83ad2e19f7d5c818d78734b35f413352..c42fbbb3d3ddd928bdae3c3955373e5275387e07 100644 (file)
 #include "version.h"
 #include "xy.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;
-static int quiet = 0;
-
-/* If you don't specify these command line arguments, then these are the
-   defaults */
-#define DEFAULT_SPIKE 10
-#define DEFAULT_MOUNTAIN 0
-#define DEFAULT_CONTDIST 2
-#define DEFAULT_ISLDIST 1
-
 /* The following five numbers refer to elevation under which (in the case of
    fertility or oil) or over which (in the case of iron, gold, and uranium)
    sectors with that elevation will contain that resource.  Elevation ranges
@@ -150,17 +138,26 @@ static int quiet = 0;
 static void qprint(const char * const fmt, ...)
     ATTRIBUTE((format (printf, 1, 2)));
 
-#define DEFAULT_OUTFILE_NAME "newcap_script"
-static const char *outfile = DEFAULT_OUTFILE_NAME;
-/* mark the continents with a * so you can tell them
-   from the islands 1 = mark, 0 = don't mark. */
-static int AIRPORT_MARKER = 0;
-
+/*
+ * Program arguments and options
+ */
+static char *program_name;
+static int nc, sc;             /* number and size of continents */
+static int ni, is;             /* number and size of islands */
+#define DEFAULT_SPIKE 10
+static int sp = DEFAULT_SPIKE; /* spike percentage */
+#define DEFAULT_MOUNTAIN 0
+static int pm = DEFAULT_MOUNTAIN; /* mountain percentage */
+#define DEFAULT_CONTDIST 2
+static int di = DEFAULT_CONTDIST; /* min. distance between continents */
+#define DEFAULT_ISLDIST 1
+static int id = DEFAULT_ISLDIST;  /* ... continents and islands */
 /* don't let the islands crash into each other.
    1 = don't merge, 0 = merge. */
 static int DISTINCT_ISLANDS = 1;
-
-static char *program_name;
+static int quiet;
+#define DEFAULT_OUTFILE_NAME "newcap_script"
+static const char *outfile = DEFAULT_OUTFILE_NAME;
 
 #define STABLE_CYCLE 4         /* stability required for perterbed capitals */
 #define INFINITY       999     /* a number which means "BIG" */
@@ -180,17 +177,10 @@ static char *program_name;
 #define new_x(newx) (((newx) + WORLD_X) % WORLD_X)
 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
 
-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 int *capx, *capy;       /* location of the nc capitals */
-static int *mc, mcc;           /* array and counter used for stability
-                                  check when perturbing */
-static int spike;              /* are we spiking? */
-static int mind;               /* the final distance between capitals that
-                                  we achieved */
 static int dirx[] = { -2, -1, 1, 2, 1, -1 }; /* gyujnb */
 static int diry[] = { 0, -1, -1, 0, 1, 1 };
 
@@ -201,8 +191,7 @@ 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 */
 
 static const char *numletter =
@@ -214,15 +203,14 @@ static void parse_args(int argc, char *argv[]);
 static void allocate_memory(void);
 static void init(void);
 static int drift(void);
-static void grow_continents(void);
+static int grow_continents(void);
 static void create_elevations(void);
 static void write_sects(void);
 static void output(void);
 static int write_newcap_script(void);
-static int stable(void);
+static int stable(int);
 static void elevate_land(void);
 static void elevate_sea(void);
-static int map_symbol(int x, int y);
 static void set_coastal_flags(void);
 
 static void print_vars(void);
@@ -242,26 +230,20 @@ main(int argc, char *argv[])
 {
     int opt;
     char *config_file = NULL;
-    int i = 0;
+    int try, done;
     unsigned rnd_seed = 0;
     int seed_set = 0;
 
     program_name = argv[0];
 
-    while ((opt = getopt(argc, argv, "ae:hioqR:s:v")) != EOF) {
+    while ((opt = getopt(argc, argv, "e:hiqR:s:v")) != EOF) {
        switch (opt) {
-       case 'a':
-           AIRPORT_MARKER = 1;
-           break;
        case 'e':
            config_file = optarg;
            break;
        case 'i':
            DISTINCT_ISLANDS = 0;
            break;
-       case 'o':
-           ORE = 0;
-           break;
        case 'q':
            quiet = 1;
            break;
@@ -283,7 +265,6 @@ main(int argc, char *argv[])
            exit(1);
        }
     }
-    parse_args(argc - optind, argv + optind);
 
     if (!seed_set)
        rnd_seed = pick_seed();
@@ -293,51 +274,51 @@ main(int argc, char *argv[])
        exit(1);
     empfile_fixup();
 
+    parse_args(argc - optind, argv + optind);
+
     allocate_memory();
     print_vars();
 
     qprint("\n        #*# ...fairland rips open a rift in the datumplane... #*#\n\n");
     qprint("seed is %u\n", rnd_seed);
+    try = 0;
     do {
        init();
-       if (i)
-           qprint("\ntry #%d (out of %d)...\n", i + 1, NUMTRIES);
+       if (try)
+           qprint("\ntry #%d (out of %d)...\n", try + 1, NUMTRIES);
        qprint("placing capitals...\n");
        if (!drift())
-           qprint("fairland: unstable drift -- try increasing DRIFT_MAX\n");
+           qprint("unstable drift\n");
        qprint("growing continents...\n");
-       grow_continents();
-    } while (fl_status && ++i < NUMTRIES);
-    if (fl_status) {
-       fputs("ERROR: World not large enough to hold continents\n",
-             stderr);
+       done = grow_continents();
+    } while (!done && ++try < NUMTRIES);
+    if (!done) {
+       fprintf(stderr, "%s: world not large enough to hold continents\n",
+               program_name);
        exit(1);
     }
     qprint("growing islands:");
     grow_islands();
     qprint("\nelevating land...\n");
     create_elevations();
-    qprint("designating sectors...\n");
-    if (ORE)
-       qprint("adding resources...\n");
-    write_newcap_script();
 
+    qprint("writing to sectors file...\n");
+    if (!write_newcap_script())
+       exit(1);
     if (chdir(gamedir)) {
-       fprintf(stderr, "Can't chdir to %s (%s)\n", gamedir, strerror(errno));
-       exit(EXIT_FAILURE);
+       fprintf(stderr, "%s: can't chdir to %s (%s)\n",
+               program_name, gamedir, strerror(errno));
+       exit(1);
     }
     if (!ef_open(EF_SECTOR, EFF_MEM | EFF_NOTIME))
        exit(1);
     write_sects();
-    qprint("writing to sectors file...\n");
     if (!ef_close(EF_SECTOR))
        exit(1);
 
     output();
     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);
 }
 
@@ -359,19 +340,6 @@ print_vars(void)
     printf("World dimensions: %dx%d\n", WORLD_X, WORLD_Y);
 }
 
-static int
-my_sqrt(int n)
-{
-    int i;
-
-    for (i = 1; i * i < n * 10000; ++i) ;
-    return (i + 50) / 100;
-}
-
-/****************************************************************************
-  PARSE COMMAND LINE ARGUMENTS
-****************************************************************************/
-
 static void
 help(char *complaint)
 {
@@ -384,11 +352,9 @@ static void
 usage(void)
 {
     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"
           "  -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"
@@ -409,6 +375,8 @@ usage(void)
 static void
 parse_args(int argc, char *argv[])
 {
+    int dist_max = mapdist(0, 0, WORLD_X / 2, WORLD_Y / 2);
+
     if (argc < 2) {
        help("missing arguments");
        exit(1);
@@ -419,72 +387,82 @@ parse_args(int argc, char *argv[])
     }
     nc = atoi(argv[0]);
     if (nc < 1) {
-       puts("fairland: error -- number of continents must be > 0");
+       fprintf(stderr, "%s: number of continents must be > 0\n",
+               program_name);
        exit(1);
     }
 
     sc = atoi(argv[1]);
-    if (sc < 1) {
-       puts("fairland: error -- size of continents must be > 0");
+    if (sc < 2) {
+       fprintf(stderr, "%s: size of continents must be > 1\n",
+               program_name);
        exit(1);
     }
 
+    ni = nc;
+    is = sc / 2;
+
     if (argc > 2)
        ni = atoi(argv[2]);
-    else
-       ni = nc;
+    if (ni < 0) {
+       fprintf(stderr, "%s: number of islands must be >= 0\n",
+               program_name);
+       exit(1);
+    }
 
     if (argc > 3)
        is = atoi(argv[3]);
-    else
-       is = sc / 2;
-    if (is < 1)
-       is = 1;
+    if (is < 1) {
+       fprintf(stderr, "%s: size of islands must be > 0\n",
+               program_name);
+       exit(1);
+    }
 
     if (argc > 4)
        sp = atoi(argv[4]);
-    else
-       sp = DEFAULT_SPIKE;
-    sp = LIMIT_TO(sp, 0, 100);
+    if (sp < 0 || sp > 100) {
+       fprintf(stderr,
+               "%s: spike percentage must be between 0 and 100\n",
+               program_name);
+       exit(1);
+    }
 
     if (argc > 5)
        pm = atoi(argv[5]);
-    else
-       pm = DEFAULT_MOUNTAIN;
-    if (pm < 0)
-       pm = 0;
+    if (pm < 0 || pm > 100) {
+       fprintf(stderr,
+               "%s: mountain percentage must be between 0 and 100\n",
+               program_name);
+       exit(1);
+    }
 
     if (argc > 6)
        di = atoi(argv[6]);
-    else
-       di = DEFAULT_CONTDIST;
-
     if (di < 0) {
-       puts("fairland: error -- distance between continents must be >= 0");
+       fprintf(stderr, "%s: distance between continents must be >= 0\n",
+               program_name);
        exit(1);
     }
-    if (di > WORLD_X / 2 || di > WORLD_Y / 2) {
-       puts("fairland: error -- distance between continents too large");
+    if (di > dist_max) {
+       fprintf(stderr, "%s: distance between continents too large\n",
+               program_name);
        exit(1);
     }
 
     if (argc > 7)
        id = atoi(argv[7]);
-    else
-       id = DEFAULT_ISLDIST;
     if (id < 0) {
-       puts("fairland: error -- distance from islands to continents must be >= 0");
+       fprintf(stderr,
+               "%s: distance from islands to continents must be >= 0\n",
+               program_name);
        exit(1);
     }
-    if (id > WORLD_X || id > WORLD_Y) {
-       puts("fairland: error -- distance from islands to continents too large");
+    if (id > dist_max) {
+       fprintf(stderr,
+               "%s: distance from islands to continents too large\n",
+               program_name);
        exit(1);
     }
-    if (nc * sc + nc * my_sqrt(sc) * 2 * (di + 1) > WORLD_X * WORLD_Y) {
-       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");
-    }
 }
 
 /****************************************************************************
@@ -499,7 +477,6 @@ allocate_memory(void)
     capx = calloc(nc, sizeof(int));
     capy = calloc(nc, sizeof(int));
     vector = calloc(WORLD_X + WORLD_Y, sizeof(int));
-    mc = calloc(STABLE_CYCLE, sizeof(int));
     own = calloc(WORLD_X, sizeof(int *));
     elev = calloc(WORLD_X, sizeof(int *));
     for (i = 0; i < WORLD_X; ++i) {
@@ -529,33 +506,13 @@ allocate_memory(void)
 static void
 init(void)
 {
-    int i, j, xx = 0, yy = 0;
-
-    mcc = 0;
-    fl_status = 0;
+    int i, j;
 
     for (i = 0; i < WORLD_X; ++i) {
        for (j = 0; j < WORLD_Y; ++j) {
            own[i][j] = -1;
-           elev[i][j] = -INFINITY;
        }
     }
-
-    for (i = 0; i < nc; ++i) {
-       if (xx >= WORLD_X) {
-           ++yy;
-           xx = yy % 2;
-           if (yy == WORLD_Y) {
-               puts("fairland error: world not big enough for all the continents.\n");
-               exit(1);
-           }
-       }
-       capx[i] = xx;
-       capy[i] = yy;
-       xx += 2;
-    }
-    for (i = 0; i < STABLE_CYCLE; ++i)
-       mc[i] = i;
 }
 
 /****************************************************************************
@@ -580,15 +537,28 @@ iso(int j, int newx, int newy)
     return d;
 }
 
-/* Drift all the capitals
-*/
+/*
+ * Drift the capitals
+ * Return 1 for a stable drift, 0 for an unstable one.
+ */
 static int
 drift(void)
 {
-    int i, turns;
+    int turns, i;
+
+    for (i = 0; i < nc; i++) {
+       capy[i] = (2 * i) / WORLD_X;
+       capx[i] = (2 * i) % WORLD_X + capy[i] % 2;
+       if (capy[i] >= WORLD_Y) {
+           fprintf(stderr,
+                   "%s: world not big enough for all the continents\n",
+                   program_name);
+           exit(1);
+       }
+    }
 
     for (turns = 0; turns < DRIFT_MAX; ++turns) {
-       if (turns > DRIFT_BEFORE_CHECK && (mind = stable()))
+       if (stable(turns))
            return 1;
        for (i = 0; i < nc; ++i)
            fl_move(i);
@@ -596,25 +566,36 @@ drift(void)
     return 0;
 }
 
-/* Check to see if we have stabilized--can we stop drifting the capitals?
-*/
-
+/*
+ * Has the drift stabilized?
+ * @turns is the number of turns so far.
+ */
 static int
-stable(void)
+stable(int turns)
 {
+    static int mc[STABLE_CYCLE];
     int i, isod, d = 0, stab = 1;
 
+    if (!turns) {
+       for (i = 0; i < STABLE_CYCLE; i++)
+           mc[i] = i;
+    }
+
+    if (turns <= DRIFT_BEFORE_CHECK)
+       return 0;
+
     for (i = 0; i < nc; ++i) {
        isod = iso(i, capx[i], capy[i]);
        if (isod > d)
            d = isod;
     }
+
     for (i = 0; i < STABLE_CYCLE; ++i)
        if (d != mc[i])
            stab = 0;
-    mc[mcc] = d;
-    mcc = (mcc + 1) % STABLE_CYCLE;
-    return stab ? d : 0;
+
+    mc[turns % STABLE_CYCLE] = d;
+    return stab;
 }
 
 /* This routine does the actual drifting
@@ -648,7 +629,7 @@ find_coast(int c)
 {
     int i, j;
 
-    for (i = 0; i < secs; ++i) {
+    for (i = 0; i < isecs[c]; ++i) {
        sectc[c][i] = 0;
        for (j = 0; j < 6; ++j)
            if (own[new_x(sectx[c][i] + dirx[j])][new_y(secty[c][i] + diry[j])] == -1)
@@ -681,6 +662,9 @@ try_to_grow(int c, int newx, int newy, int d)
 {
     int i, j, px, py;
 
+    if (own[newx][newy] != -1)
+       return 0;
+
     for (i = 1; i <= d; ++i) {
        for (j = 0; j < i; ++j)
            vector[j] = 0;
@@ -697,8 +681,9 @@ try_to_grow(int c, int newx, int newy, int d)
                return 0;
        } while (next_vector(i));
     }
-    sectx[c][secs] = newx;
-    secty[c][secs] = newy;
+    sectx[c][isecs[c]] = newx;
+    secty[c][isecs[c]] = newy;
+    isecs[c]++;
     own[newx][newy] = c;
     return 1;
 }
@@ -711,7 +696,7 @@ next_coast(int c, int x, int y, int *xp, int *yp)
 {
     int i, nx, ny, wat = 0;
 
-    if (secs == 1) {
+    if (isecs[c] == 1) {
        *xp = x;
        *yp = y;
        return;
@@ -734,8 +719,9 @@ next_coast(int c, int x, int y, int *xp, int *yp)
 */
 
 static int
-new_try(int c)
+new_try(int c, int spike)
 {
+    int secs = isecs[c];
     int i, starti;
 
     if (secs == 1) {
@@ -760,10 +746,10 @@ new_try(int c)
 static int
 grow_one_sector(int c)
 {
+    int spike = roll0(100) < sp;
     int done, coast_search, try1, x, y, newx, newy, i, n, sx, sy;
 
-    spike = roll0(100) < sp;
-    if ((try1 = new_try(c)) == -1)
+    if ((try1 = new_try(c, spike)) == -1)
        return 0;
     x = sx = sectx[c][try1];
     y = sy = secty[c][try1];
@@ -774,10 +760,9 @@ grow_one_sector(int c)
            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 &&
-                   (n > 5 ||
-                    (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
-                     own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1)))
+               if (n > 5 ||
+                   (own[new_x(x+dirx[(i+5)%6])][new_y(y+diry[(i+5)%6])] == -1 &&
+                    own[new_x(x+dirx[(i+1)%6])][new_y(y+diry[(i+1)%6])] == -1))
                    if (try_to_grow(c, newx, newy, c < nc ? di : id))
                        done = 1;
            }
@@ -785,50 +770,56 @@ grow_one_sector(int c)
            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)
-                   if (try_to_grow(c, newx, newy, c < nc ? di : id))
-                       done = 1;
+               if (try_to_grow(c, newx, newy, c < nc ? di : id))
+                   done = 1;
            }
        next_coast(c, x, y, &x, &y);
        ++coast_search;
     } while (!done && coast_search < COAST_SEARCH_MAX &&
-            (secs == 1 || x != sx || y != sy));
-    if (!done && c < nc) {
-       qprint("fairland: error -- continent %c had no room to grow!\n",
-              numletter[c % 62]);
-       fl_status |= STATUS_NO_ROOM;
-    }
+            (isecs[c] == 1 || x != sx || y != sy));
     return done;
 }
 
-/* Grow all the continents
-*/
-static void
+/*
+ * Grow the continents.
+ * Return 1 on success, 0 on error.
+ */
+static int
 grow_continents(void)
 {
-    int c;
+    int done = 1;
+    int c, secs;
 
     for (c = 0; c < nc; ++c) {
-       sectx[c][0] = capx[c];
-       secty[c][0] = capy[c];
-       own[sectx[c][0]][secty[c][0]] = c;
-       sectx[c][1] = new_x(capx[c] + 2);
-       secty[c][1] = capy[c];
-       own[sectx[c][1]][secty[c][1]] = c;
+       isecs[c] = 0;
+       if (!try_to_grow(c, capx[c], capy[c], di)
+           || !try_to_grow(c, new_x(capx[c] + 2), capy[c], di)) {
+           done = 0;
+           continue;
+       }
     }
 
-    for (secs = 2; secs < sc && !fl_status; ++secs) {
+    if (!done) {
+       qprint("No room for continents\n");
+       return 0;
+    }
+
+    for (secs = 2; secs < sc && done; secs++) {
        for (c = 0; c < nc; ++c) {
            find_coast(c);
-           grow_one_sector(c);
+           if (!grow_one_sector(c))
+               done = 0;
        }
     }
+
     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);
+    if (!done)
+       qprint("Only managed to grow %d out of %d sectors.\n",
+              secs - 1, sc);
     ctot = nc;
+    return done;
 }
 
 /****************************************************************************
@@ -857,7 +848,7 @@ place_island(int c, int *xp, int *yp)
                if (*xp == sx && *yp == sy)
                    break;
            }
-           if (own[*xp][*yp] == -1 && try_to_grow(c, *xp, *yp, d))
+           if (try_to_grow(c, *xp, *yp, d))
                return 1;
        }
     }
@@ -870,22 +861,32 @@ place_island(int c, int *xp, int *yp)
 static void
 grow_islands(void)
 {
-    int c, x, y, isiz;
+    int stunted_islands = 0;
+    int c, secs, x, y, isiz;
 
     for (c = nc; c < nc + ni; ++c) {
-       secs = 0;
-       if (!place_island(c, &x, &y))
-           return;
+       if (!place_island(c, &x, &y)) {
+           qprint("\nNo room for island #%d", c - nc + 1);
+           break;
+       }
+
        isiz = roll(is) + roll0(is);
-       do {
-           ++secs;
+       for (secs = 1; secs < isiz; secs++) {
            find_coast(c);
-       } while (secs < isiz && grow_one_sector(c));
+           if (!grow_one_sector(c)) {
+               stunted_islands++;
+               break;
+           }
+       }
+
        find_coast(c);
        qprint(" %d(%d)", c - nc + 1, secs);
-       isecs[c] = secs;
        ctot++;
     }
+
+    if (stunted_islands)
+       qprint("\n%d stunted island%s",
+              stunted_islands, splur(stunted_islands));
 }
 
 /****************************************************************************
@@ -894,6 +895,12 @@ grow_islands(void)
 static void
 create_elevations(void)
 {
+    int i, j;
+
+    for (i = 0; i < WORLD_X; i++) {
+       for (j = 0; j < WORLD_Y; j++)
+           elev[i][j] = -INFINITY;
+    }
     elevate_land();
     elevate_sea();
 }
@@ -949,7 +956,7 @@ elevate_land(void)
 
     for (c = 0; c < ctot; ++c) {
        total = 0;
-       ns = (c < nc) ? sc : isecs[c];
+       ns = isecs[c];
        nm = (pm * ns) / 100;
 
 /* Place the mountains */
@@ -1044,6 +1051,20 @@ elevate_sea(void)
     }
 }
 
+static int
+elev_to_sct_type(int elevation)
+{
+    if (elevation < LANDMIN)
+       return SCT_WATER;
+    if (elevation < HILLMIN)
+       return SCT_RURAL;
+    if (elevation < PLATMIN)
+       return SCT_MOUNT;
+    if (elevation < HIGHMIN)
+       return SCT_RURAL;
+    return SCT_MOUNT;
+}
+
 /****************************************************************************
   ADD THE RESOURCES
 ****************************************************************************/
@@ -1129,35 +1150,18 @@ static void
 write_sects(void)
 {
     struct sctstr *sct;
-    int c, x, y, total;
+    int 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)
-               sct->sct_type = SCT_RURAL;
-           else if (total < PLATMIN)
-               sct->sct_type = SCT_MOUNT;
-           else if (total < HIGHMIN)
-               sct->sct_type = SCT_RURAL;
-           else
-               sct->sct_type = SCT_MOUNT;
-           sct->sct_elev = total;
+           sct->sct_elev = elev[x][y];
+           sct->sct_type = elev_to_sct_type(elev[x][y]);
            sct->sct_newtype = sct->sct_type;
            sct->sct_dterr = own[sct->sct_x][y] + 1;
-           if (ORE)
-               add_resources(sct);
+           add_resources(sct);
        }
     }
-    if (AIRPORT_MARKER)
-       for (c = 0; c < nc; ++c) {
-           sct = getsectp(capx[c], capy[c]);
-           sct->sct_type = SCT_AIRPT;
-           sct->sct_newtype = SCT_AIRPT;
-       }
     set_coastal_flags();
 }
 
@@ -1167,7 +1171,7 @@ write_sects(void)
 static void
 output(void)
 {
-    int sx, sy, x, y;
+    int sx, sy, x, y, c, type;
 
     if (quiet == 0) {
        for (sy = -WORLD_Y / 2; sy < WORLD_Y / 2; sy++) {
@@ -1177,33 +1181,25 @@ output(void)
                printf(" ");
            for (sx = -WORLD_X / 2 + y % 2; sx < WORLD_X / 2; sx += 2) {
                x = XNORM(sx);
-               if (own[x][y] == -1)
+               c = own[x][y];
+               type = elev_to_sct_type(elev[x][y]);
+               if (type == SCT_WATER)
                    printf(". ");
+               else if (type == SCT_MOUNT)
+                   printf("^ ");
+               else if (c >= nc)
+                   printf("%% ");
                else {
-                   printf("%c ", map_symbol(x, y));
+                   assert(0 <= c && c < nc);
+                   if ((x == capx[c] || x == new_x(capx[c] + 2))
+                       && y == capy[c])
+                       printf("%c ", numletter[c % 62]);
+                   else
+                       printf("# ");
                }
            }
        }
     }
-    if (AIRPORT_MARKER)
-       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
-map_symbol(int x, int y)
-{
-    int c;
-
-    for (c = 0; c < nc; ++c)
-       if ((x == capx[c] && y == capy[c])
-           || (x == new_x(capx[c] + 2) && y == capy[c]))
-           return numletter[own[x][y] % 62];
-    if ((elev[x][y] >= HILLMIN && elev[x][y] < PLATMIN)
-       || elev[x][y] >= HIGHMIN)
-       return '^';
-    return own[x][y] >= nc ? '%' : '#';
 }
 
 /*
@@ -1278,19 +1274,18 @@ write_newcap_script(void)
     FILE *script = fopen(outfile, "w");
 
     if (!script) {
-       printf("fairland: error, unable to write to %s.\n", outfile);
-       return -1;
+       fprintf(stderr, "%s: unable to write to %s (%s)\n",
+               program_name, outfile, strerror(errno));
+       return 0;
     }
 
     for (c = 0; c < nc; ++c) {
        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\n", c + 1);
     fclose(script);
-    return 0;
+    return 1;
 }
 
 static void
@@ -1311,14 +1306,7 @@ set_coastal_flags(void)
     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 (i = 0; 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];