X-Git-Url: http://git.pond.sub.org/?p=empserver;a=blobdiff_plain;f=src%2Futil%2Ffairland.c;h=d95282f2c60e82ee872f093ba680e1dbe47ee670;hp=58ad7c563791eff5c005143820c6880aab088864;hb=9102ecce5;hpb=63bdc89835765a6163fe06e194fb3fbcc5dce083 diff --git a/src/util/fairland.c b/src/util/fairland.c index 58ad7c563..d95282f2c 100644 --- a/src/util/fairland.c +++ b/src/util/fairland.c @@ -1,11 +1,11 @@ /* * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2007, 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, @@ -14,8 +14,7 @@ * 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 . * * --- * @@ -26,10 +25,11 @@ * --- * * fairland.c: Create a nice, new world - * + * * Known contributors to this file: * Ken Stevens, 1995 * Steve McClure, 1998 + * Markus Armbruster, 2004-2012 */ #include @@ -55,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 @@ -66,21 +66,14 @@ static int quiet = 0; /* lower URAN_MIN for more uranium */ #define URAN_MIN 56 -#if defined(_WIN32) -#include "../lib/gen/getopt.h" -#else -#include -#endif - +#include #include #include #include -#include +#include +#include "chance.h" #include "file.h" -#include "misc.h" -#include "nat.h" #include "optlist.h" -#include "power.h" #include "prototypes.h" #include "sect.h" #include "version.h" @@ -107,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: */ @@ -126,57 +117,51 @@ static char *program_name; #define new_x(newx) (((newx) + WORLD_X) % WORLD_X) #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 *); 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 int map_symbol(int x, int y); -static void fl_sct_init(coord, coord, struct sctstr *, time_t timestamp); static void set_coastal_flags(void); static void print_vars(void); @@ -194,9 +179,10 @@ 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:hioqR:s:v")) != EOF) { switch (opt) { @@ -217,6 +203,7 @@ main(int argc, char *argv[]) break; case 'R': rnd_seed = strtoul(optarg, NULL, 10); + seed_set = 1; break; case 's': outfile = optarg; @@ -232,13 +219,17 @@ main(int argc, char *argv[]) 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 { @@ -265,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); @@ -372,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]); @@ -418,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); } } @@ -429,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(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] = §sbuf[XSIZE * i]; capx = calloc(nc, sizeof(int)); capy = calloc(nc, sizeof(int)); vector = calloc(WORLD_X + WORLD_Y, sizeof(int)); @@ -475,7 +462,6 @@ allocate_memory(void) sectc[i] = calloc(is * 2, sizeof(int)); } - return 0; } static void @@ -493,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; @@ -504,6 +490,7 @@ init(void) } capx[i] = xx; capy[i] = yy; + xx += 2; } for (i = 0; i < STABLE_CYCLE; ++i) mc[i] = i; @@ -576,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])) { @@ -693,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; } @@ -717,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]; @@ -726,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 && @@ -737,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) @@ -796,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); @@ -831,7 +814,7 @@ 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); @@ -839,7 +822,7 @@ grow_islands(void) find_coast(c); qprint(" %d(%d)", c - nc + 1, secs); isecs[c] = secs; - ctot = c; + ctot++; } } @@ -917,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 || @@ -971,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; } } @@ -994,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); } } } @@ -1010,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; } @@ -1021,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) @@ -1085,14 +1068,11 @@ write_sects(void) { struct sctstr *sct; int c, x, y, total; - time_t current_time = time(NULL); - - /* sct = §s[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, current_time); - 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) @@ -1111,33 +1091,13 @@ 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; } 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 ****************************************************************************/ @@ -1160,7 +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"); + 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 @@ -1193,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; @@ -1218,31 +1177,23 @@ qprint(const char * const fmt, ...) } } -static void -fl_sct_init(coord x, coord y, struct sctstr *sp, time_t timestamp) -{ - 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; - sp->sct_timestamp = timestamp; - 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]; + } + } }