]> git.pond.sub.org Git - empserver/blobdiff - src/util/fairland.c
Update copyright notice.
[empserver] / src / util / fairland.c
index e4b80ffda3121c0ea77f60f8236e79b17882635f..58ad7c563791eff5c005143820c6880aab088864 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2005, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -19,9 +19,9 @@
  *
  *  ---
  *
- *  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.
  *
  *  ---
  *
@@ -32,6 +32,8 @@
  *     Steve McClure, 1998
  */
 
+#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;
@@ -66,22 +68,23 @@ static int quiet = 0;
 
 #if defined(_WIN32)
 #include "../lib/gen/getopt.h"
+#else
+#include <unistd.h>
 #endif
 
 #include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <fcntl.h>
+#include "file.h"
 #include "misc.h"
-#include "power.h"
 #include "nat.h"
-#include "sect.h"
-#include "gamesdef.h"
-#include "file.h"
-#include "xy.h"
 #include "optlist.h"
+#include "power.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 */
@@ -123,9 +126,6 @@ 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 */
@@ -154,7 +154,7 @@ 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 */
+#define STATUS_NO_ROOM 1       /* there was no room to grow */
 #define NUMTRIES 10            /* keep trying to grow this many times */
 
 const char *numletter =
@@ -175,9 +175,9 @@ 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 fl_sct_init(coord, coord, struct sctstr *, time_t timestamp);
+static void set_coastal_flags(void);
 
 static void print_vars(void);
 static void fl_move(int);
@@ -198,32 +198,35 @@ main(int argc, char *argv[])
     program_name = argv[0];
     rnd_seed = time(NULL);
 
-    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);
            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);
@@ -315,24 +318,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);
 }
 
@@ -431,45 +435,44 @@ 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);
+    fname = malloc(strlen(gamedir) + 1 + strlen(empfile[EF_SECTOR].file) + 1);
+    sprintf(fname, "%s/%s", gamedir, empfile[EF_SECTOR].file);
     sect_fptr = fopen(fname, "wb");
     if (sect_fptr == NULL) {
        perror(fname);
        return -1;
     }
     free(fname);
-    sectsbuf =
-       (struct sctstr *)calloc((YSIZE * XSIZE), sizeof(struct sctstr));
-    sects = (struct sctstr **)calloc(YSIZE, sizeof(struct sctstr *));
+    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 = (int *)calloc(nc, sizeof(int));
-    capy = (int *)calloc(nc, sizeof(int));
-    vector = (int *)calloc(WORLD_X + WORLD_Y, sizeof(int));
-    mc = (int *)calloc(STABLE_CYCLE, sizeof(int));
-    own = (int **)calloc(WORLD_X, sizeof(int *));
-    elev = (int **)calloc(WORLD_X, sizeof(int *));
+    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) {
-       own[i] = (int *)calloc(WORLD_Y, sizeof(int));
-       elev[i] = (int *)calloc(WORLD_Y, sizeof(int));
+       own[i] = calloc(WORLD_Y, sizeof(int));
+       elev[i] = calloc(WORLD_Y, sizeof(int));
     }
-    sectx = (int **)calloc(nc + ni, sizeof(int *));
-    secty = (int **)calloc(nc + ni, sizeof(int *));
-    sectc = (int **)calloc(nc + ni, sizeof(int *));
-    isecs = (int *)calloc(nc + ni, sizeof(int));
-    weight = (int *)calloc(max(sc, is * 2), sizeof(int));
-    dsea = (int *)calloc(max(sc, is * 2), sizeof(int));
-    dmoun = (int *)calloc(max(sc, is * 2), sizeof(int));
+    sectx = calloc(nc + ni, sizeof(int *));
+    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));
     for (i = 0; i < nc; ++i) {
-       sectx[i] = (int *)calloc(sc, sizeof(int));
-       secty[i] = (int *)calloc(sc, sizeof(int));
-       sectc[i] = (int *)calloc(sc, sizeof(int));
+       sectx[i] = calloc(sc, sizeof(int));
+       secty[i] = calloc(sc, sizeof(int));
+       sectc[i] = calloc(sc, sizeof(int));
     }
     for (i = nc; i < nc + ni; ++i) {
-       sectx[i] = (int *)calloc(is * 2, sizeof(int));
-       secty[i] = (int *)calloc(is * 2, sizeof(int));
-       sectc[i] = (int *)calloc(is * 2, sizeof(int));
+       sectx[i] = calloc(is * 2, sizeof(int));
+       secty[i] = calloc(is * 2, sizeof(int));
+       sectc[i] = calloc(is * 2, sizeof(int));
     }
 
     return 0;
@@ -775,6 +778,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;
@@ -802,7 +808,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;
            }
@@ -830,6 +836,7 @@ grow_islands(void)
            ++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;
@@ -1078,12 +1085,13 @@ write_sects(void)
 {
     struct sctstr *sct;
     int c, x, y, total;
+    time_t current_time = time(NULL);
 
     /*  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);
+           fl_sct_init(x * 2 + (y & 1), y, sct, current_time);
            total = elev[sct->sct_x][y];
            if (total < LANDMIN) {
                sct->sct_type = SCT_WATER;
@@ -1106,6 +1114,7 @@ write_sects(void)
            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;
        }
+    set_coastal_flags();
 }
 
 /****************************************************************************
@@ -1116,8 +1125,8 @@ write_file(void)
 {
     int n;
 
-    if ((n = fwrite((void *)sectsbuf, sizeof(struct sctstr),
-                    YSIZE * XSIZE, sect_fptr)) <= 0) {
+    n = fwrite(sectsbuf, sizeof(struct sctstr), YSIZE * XSIZE, sect_fptr);
+    if (n <= 0) {
        perror(empfile[EF_SECTOR].file);
        return -1;
     }
@@ -1136,8 +1145,6 @@ static void
 output(void)
 {
     int i, j;
-    if (opt_BLITZ)
-       translate_continents();
     if (quiet == 0) {
        for (i = 0; i < WORLD_Y; ++i) {
            puts("");
@@ -1156,55 +1163,6 @@ output(void)
        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 = (int *)calloc(nc, sizeof(int));
-    trans_cont = (int *)calloc(nc, sizeof(int));
-    oldcapx = (int *)calloc(nc, sizeof(int));
-    oldcapy = (int *)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]];
-    }
-}
-
 static int
 map_symbol(int x, int y)
 {
@@ -1261,10 +1219,8 @@ qprint(const char * const fmt, ...)
 }
 
 static void
-fl_sct_init(coord x, coord y, s_char *ptr)
+fl_sct_init(coord x, coord y, struct sctstr *sp, time_t timestamp)
 {
-    struct sctstr *sp = (struct sctstr *)ptr;
-
     sp->ef_type = EF_SECTOR;
     sp->sct_x = x;
     sp->sct_y = y;
@@ -1273,4 +1229,20 @@ fl_sct_init(coord x, coord y, s_char *ptr)
     sp->sct_road = 0;
     sp->sct_rail = 0;
     sp->sct_defense = 0;
+    sp->sct_timestamp = timestamp;
+    sp->sct_coastal = 1;
+}
+
+static void
+set_coastal_flags(void)
+{
+    int i, j;
+
+    qprint("setting coastal flags...\n");
+    for (i = 0; i < nc; ++i)
+       for (j = 0; j < sc; j++)
+           sects[secty[i][j]][sectx[i][j] / 2].sct_coastal = sectc[i][j];
+    for (i = nc; i < nc + ni; ++i)
+       for (j = 0; j < isecs[i]; j++)
+           sects[secty[i][j]][sectx[i][j] / 2].sct_coastal = sectc[i][j];
 }