]> git.pond.sub.org Git - empserver/blobdiff - src/util/fairland.c
Change fairland not to reject small worlds without trying
[empserver] / src / util / fairland.c
index 4598eba614b08318f526c109144bc6866dd2a90a..e95b33d33cf8366ccd572cab992bda2971045a3a 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Empire - A multi-player, client/server Internet based war game.
- *  Copyright (C) 1986-2008, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *  Copyright (C) 1986-2010, Dave Pare, Jeff Bailey, Thomas Ruschak,
  *                           Ken Stevens, Steve McClure
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
  *  ---
  *
  *  fairland.c: Create a nice, new world
- * 
+ *
  *  Known contributors to this file:
  *     Ken Stevens, 1995
  *     Steve McClure, 1998
@@ -66,6 +66,7 @@ static int quiet = 0;
 /* lower URAN_MIN for more uranium */
 #define URAN_MIN   56
 
+#include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -100,8 +101,6 @@ 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" */
 
@@ -121,36 +120,33 @@ static char *program_name;
 #define new_y(newy) (((newy) + WORLD_Y) % WORLD_Y)
 #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 */
+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 */
 
-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 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? */
+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 *);
@@ -162,14 +158,12 @@ 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 int map_symbol(int x, int y);
-static void fl_sct_init(coord, coord, struct sctstr *);
 static void set_coastal_flags(void);
 
 static void print_vars(void);
@@ -225,11 +219,14 @@ main(int argc, char *argv[])
            exit(1);
        }
     }
+    parse_args(argc - optind, argv + optind);
+
     srandom(rnd_seed);
-    if (emp_config(config_file))
+    empfile_init();
+    if (emp_config(config_file) < 0)
        exit(1);
+    empfile_fixup();
 
-    parse_args(argc - optind, argv + optind);
     if (allocate_memory() == -1)
        exit(-1);
     print_vars();
@@ -258,12 +255,24 @@ 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, WORLD_SZ())) {
+       perror("ef_open");
+       exit(1);
+    }
     write_sects();
     qprint("writing to sectors file...\n");
-    if (write_file() == -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);
@@ -411,10 +420,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);
     }
 }
 
@@ -426,20 +434,7 @@ static int
 allocate_memory(void)
 {
     int i;
-    char *fname;
 
-    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 = 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));
@@ -486,7 +481,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;
@@ -497,6 +492,7 @@ init(void)
        }
        capx[i] = xx;
        capy[i] = yy;
+       xx += 2;
     }
     for (i = 0; i < STABLE_CYCLE; ++i)
        mc[i] = i;
@@ -824,7 +820,7 @@ grow_islands(void)
        secs = 0;
        if (!place_island(c, &x, &y))
            return;
-       isiz = 1 + rnd(2 * is - 1);
+       isiz = 1 + rnd(is) + rnd(is);
        do {
            ++secs;
            find_coast(c);
@@ -1079,12 +1075,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 & 1), y, 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)
@@ -1097,39 +1091,20 @@ write_sects(void)
                sct->sct_type = SCT_MOUNT;
            sct->sct_elev = total;
            sct->sct_newtype = sct->sct_type;
+           sct->sct_dterr = own[sct->sct_x][y] + 1;
            if (ORE)
                add_resources(sct);
        }
     }
     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;
        }
     set_coastal_flags();
 }
 
-/****************************************************************************
-  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;
-}
-
 /****************************************************************************
   PRINT A PICTURE OF THE MAP TO YOUR SCREEN
 ****************************************************************************/
@@ -1191,10 +1166,7 @@ write_newcap_script(void)
        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;
     fclose(script);
-    qprint("\n\nA script for adding all the countries can be found in \"%s\".\n",
-          outfile);
     return 0;
 }
 
@@ -1210,31 +1182,23 @@ qprint(const char * const fmt, ...)
     }
 }
 
-static void
-fl_sct_init(coord x, coord y, struct sctstr *sp)
-{
-    sp->ef_type = EF_SECTOR;
-    sp->sct_uid = XYOFFSET(x, y);
-    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;
-    sp->sct_coastal = 1;
-}
-
 static void
 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++)
-           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];
+    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];
+       }
+    }
 }