From 108a9091315aab2c2d18199da6498c82764e8228 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 25 Dec 2014 22:38:01 +0100 Subject: [PATCH] kill gc_add and gc_done, they were terrible ideas. --- src/economy.c | 23 +- src/kernel/config.c | 34 - src/kernel/config.h | 4 +- src/kernel/region.c | 1796 ++++++++++++++++++++-------------------- src/kernel/save.c | 3 +- src/kernel/xmlreader.c | 2 +- src/modules/autoseed.c | 1606 +++++++++++++++++------------------ 7 files changed, 1730 insertions(+), 1738 deletions(-) diff --git a/src/economy.c b/src/economy.c index 0fb810848..4ac4210fe 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1647,17 +1647,16 @@ static void expandbuying(region * r, request * buyorders) const luxury_type *type; int number; int multi; - } *trades, *trade; + } trades[MAXLUXURIES], *trade; static int ntrades = 0; int i, j; const luxury_type *ltype; if (ntrades == 0) { - for (ltype = luxurytypes; ltype; ltype = ltype->next) - ++ntrades; - trades = gc_add(calloc(sizeof(struct trade), ntrades)); - for (i = 0, ltype = luxurytypes; i != ntrades; ++i, ltype = ltype->next) - trades[i].type = ltype; + for (ntrades = 0, ltype = luxurytypes; ltype; ltype = ltype->next) { + assert(ntrades < MAXLUXURIES); + trades[ntrades++].type = ltype; + } } for (i = 0; i != ntrades; ++i) { trades[i].number = 0; @@ -1887,18 +1886,17 @@ static void expandselling(region * r, request * sellorders, int limit) building *b; unit *u; unit *hafenowner; - static int *counter; + static int counter[MAXLUXURIES]; static int ncounter = 0; if (ncounter == 0) { const luxury_type *ltype; - for (ltype = luxurytypes; ltype; ltype = ltype->next) + for (ltype = luxurytypes; ltype; ltype = ltype->next) { + assert(ncounter < MAXLUXURIES); ++ncounter; - counter = (int *)gc_add(calloc(sizeof(int), ncounter)); - } - else { - memset(counter, 0, sizeof(int) * ncounter); + } } + memset(counter, 0, sizeof(int) * ncounter); if (!sellorders) { /* NEIN, denn Insekten können in || !r->buildings) */ return; /* Sümpfen und Wüsten auch so handeln */ @@ -1958,6 +1956,7 @@ static void expandselling(region * r, request * sellorders, int limit) int i; int use = 0; for (i = 0, search = luxurytypes; search != ltype; search = search->next) { + // TODO: this is slow and lame! ++i; } if (counter[i] >= limit) diff --git a/src/kernel/config.c b/src/kernel/config.c index c4ed360e5..c7fa16fff 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -916,36 +916,6 @@ int maxworkingpeasants(const struct region *r) return _max(size-treespace, _min(size / 10 , 200)); } -void **blk_list[1024]; -int list_index; -int blk_index; - -static void gc_done(void) -{ - int i, k; - for (i = 0; i != list_index; ++i) { - for (k = 0; k != 1024; ++k) - free(blk_list[i][k]); - free(blk_list[i]); - } - for (k = 0; k != blk_index; ++k) - free(blk_list[list_index][k]); - free(blk_list[list_index]); - -} - -void *gc_add(void *p) -{ - if (blk_index == 0) { - blk_list[list_index] = (void **)malloc(1024 * sizeof(void *)); - } - blk_list[list_index][blk_index] = p; - blk_index = (blk_index + 1) % 1024; - if (!blk_index) - ++list_index; - return p; -} - static const char * parameter_key(int i) { assert(i < MAXPARAMS && i >= 0); @@ -1173,7 +1143,6 @@ void kernel_done(void) * calling it is optional, e.g. a release server will most likely not do it. */ translation_done(); - gc_done(); } attrib_type at_germs = { @@ -1186,9 +1155,6 @@ attrib_type at_germs = { ATF_UNIQUE }; -/*********************/ -/* at_guard */ -/*********************/ attrib_type at_guard = { "guard", DEFAULT_INIT, diff --git a/src/kernel/config.h b/src/kernel/config.h index 7eda36cca..6f6401e11 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -40,6 +40,7 @@ extern "C" { #ifndef MAXUNITS # define MAXUNITS 1048573 /* must be prime for hashing. 524287 was >90% full */ #endif +#define MAXLUXURIES 16 /* there must be no more than MAXLUXURIES kinds of luxury goods in any game */ #define TREESIZE (8) /* space used by trees (in #peasants) */ @@ -183,9 +184,6 @@ extern "C" { bool idle(struct faction *f); bool unit_has_cursed_item(const struct unit *u); - /* simple garbage collection: */ - void *gc_add(void *p); - /* grammatik-flags: */ #define GF_NONE 0 /* singular, ohne was dran */ diff --git a/src/kernel/region.c b/src/kernel/region.c index 61f10da27..be75a9098 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -1,7 +1,7 @@ /* Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -69,100 +69,101 @@ region *regions; int get_maxluxuries(void) { - static int maxluxuries = -1; - if (maxluxuries == -1) { - const luxury_type *ltype; - maxluxuries = 0; - for (ltype = luxurytypes; ltype; ltype = ltype->next) - ++maxluxuries; - } - return maxluxuries; + static int maxluxuries = -1; + if (maxluxuries == -1) { + const luxury_type *ltype; + maxluxuries = 0; + for (ltype = luxurytypes; ltype; ltype = ltype->next) + ++maxluxuries; + } + return maxluxuries; } const int delta_x[MAXDIRECTIONS] = { - -1, 0, 1, 1, 0, -1 + -1, 0, 1, 1, 0, -1 }; const int delta_y[MAXDIRECTIONS] = { - 1, 1, 0, -1, -1, 0 + 1, 1, 0, -1, -1, 0 }; static const direction_t back[MAXDIRECTIONS] = { - D_SOUTHEAST, - D_SOUTHWEST, - D_WEST, - D_NORTHWEST, - D_NORTHEAST, - D_EAST, + D_SOUTHEAST, + D_SOUTHWEST, + D_WEST, + D_NORTHWEST, + D_NORTHEAST, + D_EAST, }; direction_t dir_invert(direction_t dir) { - switch (dir) { + switch (dir) { case D_PAUSE: case D_SPECIAL: - return dir; - break; + return dir; + break; default: - if (dir >= 0 && dir < MAXDIRECTIONS) - return back[dir]; - } - assert(!"illegal direction"); - return NODIRECTION; + if (dir >= 0 && dir < MAXDIRECTIONS) + return back[dir]; + } + assert(!"illegal direction"); + return NODIRECTION; } const char *write_regionname(const region * r, const faction * f, char *buffer, - size_t size) + size_t size) { - char *buf = (char *)buffer; - const struct locale *lang = f ? f->locale : 0; - if (r == NULL) { - strlcpy(buf, "(null)", size); - } else { - plane *pl = rplane(r); - int nx = r->x, ny = r->y; - pnormalize(&nx, &ny, pl); - adjust_coordinates(f, &nx, &ny, pl, r); - slprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny); - } - return buffer; + char *buf = (char *)buffer; + const struct locale *lang = f ? f->locale : 0; + if (r == NULL) { + strlcpy(buf, "(null)", size); + } + else { + plane *pl = rplane(r); + int nx = r->x, ny = r->y; + pnormalize(&nx, &ny, pl); + adjust_coordinates(f, &nx, &ny, pl, r); + slprintf(buf, size, "%s (%d,%d)", rname(r, lang), nx, ny); + } + return buffer; } const char *regionname(const region * r, const faction * f) { - static int index = 0; - static char buf[2][NAMESIZE]; - index = 1-index; - return write_regionname(r, f, buf[index], sizeof(buf[index])); + static int index = 0; + static char buf[2][NAMESIZE]; + index = 1 - index; + return write_regionname(r, f, buf[index], sizeof(buf[index])); } int deathcount(const region * r) { - attrib *a = a_find(r->attribs, &at_deathcount); - if (!a) - return 0; - return a->data.i; + attrib *a = a_find(r->attribs, &at_deathcount); + if (!a) + return 0; + return a->data.i; } void deathcounts(region * r, int fallen) { - attrib *a; - static const curse_type *ctype = NULL; + attrib *a; + static const curse_type *ctype = NULL; - if (fallen == 0) - return; - if (!ctype) - ctype = ct_find("holyground"); - if (ctype && curse_active(get_curse(r->attribs, ctype))) - return; + if (fallen == 0) + return; + if (!ctype) + ctype = ct_find("holyground"); + if (ctype && curse_active(get_curse(r->attribs, ctype))) + return; - a = a_find(r->attribs, &at_deathcount); - if (!a) - a = a_add(&r->attribs, a_new(&at_deathcount)); - a->data.i += fallen; + a = a_find(r->attribs, &at_deathcount); + if (!a) + a = a_add(&r->attribs, a_new(&at_deathcount)); + a->data.i += fallen; - if (a->data.i <= 0) - a_remove(&r->attribs, a); + if (a->data.i <= 0) + a_remove(&r->attribs, a); } /* Moveblock wird zur Zeit nicht über Attribute, sondern ein Bitfeld @@ -174,82 +175,82 @@ void deathcounts(region * r, int fallen) /********************/ void a_initmoveblock(attrib * a) { - a->data.v = calloc(1, sizeof(moveblock)); + a->data.v = calloc(1, sizeof(moveblock)); } int a_readmoveblock(attrib * a, void *owner, struct storage *store) { - moveblock *m = (moveblock *) (a->data.v); - int i; + moveblock *m = (moveblock *)(a->data.v); + int i; - READ_INT(store, &i); - m->dir = (direction_t) i; - return AT_READ_OK; + READ_INT(store, &i); + m->dir = (direction_t)i; + return AT_READ_OK; } void a_writemoveblock(const attrib * a, const void *owner, struct storage *store) { - moveblock *m = (moveblock *) (a->data.v); - WRITE_INT(store, (int)m->dir); + moveblock *m = (moveblock *)(a->data.v); + WRITE_INT(store, (int)m->dir); } attrib_type at_moveblock = { - "moveblock", a_initmoveblock, NULL, NULL, a_writemoveblock, a_readmoveblock + "moveblock", a_initmoveblock, NULL, NULL, a_writemoveblock, a_readmoveblock }; #define coor_hashkey(x, y) (unsigned int)((x<<16) + y) #define RMAXHASH MAXREGIONS static region *regionhash[RMAXHASH]; static int dummy_data; -static region *dummy_ptr = (region *) & dummy_data; /* a funny hack */ +static region *dummy_ptr = (region *)& dummy_data; /* a funny hack */ typedef struct uidhashentry { - int uid; - region *r; + int uid; + region *r; } uidhashentry; static uidhashentry uidhash[MAXREGIONS]; struct region *findregionbyid(int uid) { - int key = uid % MAXREGIONS; - while (uidhash[key].uid != 0 && uidhash[key].uid != uid) { - if (++key==MAXREGIONS) key = 0; - } - return uidhash[key].r; + int key = uid % MAXREGIONS; + while (uidhash[key].uid != 0 && uidhash[key].uid != uid) { + if (++key == MAXREGIONS) key = 0; + } + return uidhash[key].r; } #define DELMARKER dummy_ptr static void unhash_uid(region * r) { - int key = r->uid % MAXREGIONS; - assert(r->uid); - while (uidhash[key].uid != 0 && uidhash[key].uid != r->uid) { - if (++key == MAXREGIONS) key = 0; - } - assert(uidhash[key].r == r); - uidhash[key].r = NULL; + int key = r->uid % MAXREGIONS; + assert(r->uid); + while (uidhash[key].uid != 0 && uidhash[key].uid != r->uid) { + if (++key == MAXREGIONS) key = 0; + } + assert(uidhash[key].r == r); + uidhash[key].r = NULL; } static void hash_uid(region * r) { - int uid = r->uid; - for (;;) { - if (uid != 0) { - int key = uid % MAXREGIONS; - while (uidhash[key].uid != 0 && uidhash[key].uid != uid) { - if (++key == MAXREGIONS) key = 0; - } - if (uidhash[key].uid == 0) { - uidhash[key].uid = uid; - uidhash[key].r = r; - break; - } - assert(uidhash[key].r != r || !"duplicate registration"); + int uid = r->uid; + for (;;) { + if (uid != 0) { + int key = uid % MAXREGIONS; + while (uidhash[key].uid != 0 && uidhash[key].uid != uid) { + if (++key == MAXREGIONS) key = 0; + } + if (uidhash[key].uid == 0) { + uidhash[key].uid = uid; + uidhash[key].r = r; + break; + } + assert(uidhash[key].r != r || !"duplicate registration"); + } + r->uid = uid = rng_int(); } - r->uid = uid = rng_int(); - } } #define HASH_STATISTICS 1 @@ -260,103 +261,103 @@ static int hash_misses; bool pnormalize(int *x, int *y, const plane * pl) { - if (pl) { - if (x) { - int width = pl->maxx - pl->minx + 1; - int nx = *x - pl->minx; - nx = (nx > 0) ? nx : (width - (-nx) % width); - *x = nx % width + pl->minx; + if (pl) { + if (x) { + int width = pl->maxx - pl->minx + 1; + int nx = *x - pl->minx; + nx = (nx > 0) ? nx : (width - (-nx) % width); + *x = nx % width + pl->minx; + } + if (y) { + int height = pl->maxy - pl->miny + 1; + int ny = *y - pl->miny; + ny = (ny > 0) ? ny : (height - (-ny) % height); + *y = ny % height + pl->miny; + } } - if (y) { - int height = pl->maxy - pl->miny + 1; - int ny = *y - pl->miny; - ny = (ny > 0) ? ny : (height - (-ny) % height); - *y = ny % height + pl->miny; - } - } - return false; /* TBD */ + return false; /* TBD */ } static region *rfindhash(int x, int y) { - unsigned int rid = coor_hashkey(x, y); - int key = HASH1(rid, RMAXHASH), gk = HASH2(rid, RMAXHASH); + unsigned int rid = coor_hashkey(x, y); + int key = HASH1(rid, RMAXHASH), gk = HASH2(rid, RMAXHASH); #if HASH_STATISTICS - ++hash_requests; + ++hash_requests; #endif - while (regionhash[key] != NULL && (regionhash[key] == DELMARKER - || regionhash[key]->x != x || regionhash[key]->y != y)) { - key = (key + gk) % RMAXHASH; + while (regionhash[key] != NULL && (regionhash[key] == DELMARKER + || regionhash[key]->x != x || regionhash[key]->y != y)) { + key = (key + gk) % RMAXHASH; #if HASH_STATISTICS - ++hash_misses; + ++hash_misses; #endif - } - return regionhash[key]; + } + return regionhash[key]; } void rhash(region * r) { - unsigned int rid = coor_hashkey(r->x, r->y); - int key = HASH1(rid, RMAXHASH), gk = HASH2(rid, RMAXHASH); - while (regionhash[key] != NULL && regionhash[key] != DELMARKER - && regionhash[key] != r) { - key = (key + gk) % RMAXHASH; - } - assert(regionhash[key] != r || !"trying to add the same region twice"); - regionhash[key] = r; + unsigned int rid = coor_hashkey(r->x, r->y); + int key = HASH1(rid, RMAXHASH), gk = HASH2(rid, RMAXHASH); + while (regionhash[key] != NULL && regionhash[key] != DELMARKER + && regionhash[key] != r) { + key = (key + gk) % RMAXHASH; + } + assert(regionhash[key] != r || !"trying to add the same region twice"); + regionhash[key] = r; } void runhash(region * r) { - unsigned int rid = coor_hashkey(r->x, r->y); - int key = HASH1(rid, RMAXHASH), gk = HASH2(rid, RMAXHASH); + unsigned int rid = coor_hashkey(r->x, r->y); + int key = HASH1(rid, RMAXHASH), gk = HASH2(rid, RMAXHASH); #ifdef FAST_CONNECT - int d, di; - for (d = 0, di = MAXDIRECTIONS / 2; d != MAXDIRECTIONS; ++d, ++di) { - region *rc = r->connect[d]; - if (rc != NULL) { - if (di >= MAXDIRECTIONS) - di -= MAXDIRECTIONS; - rc->connect[di] = NULL; - r->connect[d] = NULL; + int d, di; + for (d = 0, di = MAXDIRECTIONS / 2; d != MAXDIRECTIONS; ++d, ++di) { + region *rc = r->connect[d]; + if (rc != NULL) { + if (di >= MAXDIRECTIONS) + di -= MAXDIRECTIONS; + rc->connect[di] = NULL; + r->connect[d] = NULL; + } } - } #endif - while (regionhash[key] != NULL && regionhash[key] != r) { - key = (key + gk) % RMAXHASH; - } - assert(regionhash[key] == r || !"trying to remove a unit that is not hashed"); - regionhash[key] = DELMARKER; + while (regionhash[key] != NULL && regionhash[key] != r) { + key = (key + gk) % RMAXHASH; + } + assert(regionhash[key] == r || !"trying to remove a unit that is not hashed"); + regionhash[key] = DELMARKER; } region *r_connect(const region * r, direction_t dir) { - region *result; - int x, y; + region *result; + int x, y; #ifdef FAST_CONNECT - region *rmodify = (region *) r; - assert(dir >= 0 && dir < MAXDIRECTIONS); - if (r->connect[dir]) - return r->connect[dir]; + region *rmodify = (region *)r; + assert(dir >= 0 && dir < MAXDIRECTIONS); + if (r->connect[dir]) + return r->connect[dir]; #endif - assert(dir < MAXDIRECTIONS); - x = r->x + delta_x[dir]; - y = r->y + delta_y[dir]; - pnormalize(&x, &y, rplane(r)); - result = rfindhash(x, y); + assert(dir < MAXDIRECTIONS); + x = r->x + delta_x[dir]; + y = r->y + delta_y[dir]; + pnormalize(&x, &y, rplane(r)); + result = rfindhash(x, y); #ifdef FAST_CONNECT - if (result) { - rmodify->connect[dir] = result; - result->connect[back[dir]] = rmodify; - } + if (result) { + rmodify->connect[dir] = result; + result->connect[back[dir]] = rmodify; + } #endif - return result; + return result; } region *findregion(int x, int y) { - return rfindhash(x, y); + return rfindhash(x, y); } /* Contributed by Hubert Mackenberg. Thanks. @@ -364,342 +365,346 @@ region *findregion(int x, int y) */ static int koor_distance_orig(int x1, int y1, int x2, int y2) { - int dx = x1 - x2; - int dy = y1 - y2; + int dx = x1 - x2; + int dy = y1 - y2; - /* Bei negativem dy am Ursprung spiegeln, das veraendert - * den Abstand nicht - */ - if (dy < 0) { - dy = -dy; - dx = -dx; - } + /* Bei negativem dy am Ursprung spiegeln, das veraendert + * den Abstand nicht + */ + if (dy < 0) { + dy = -dy; + dx = -dx; + } - /* - * dy ist jetzt >=0, fuer dx sind 3 Faelle zu untescheiden - */ - if (dx >= 0) { - int result = dx + dy; - return result; - } else if (-dx >= dy) { - int result = -dx; - return result; - } else { - return dy; - } + /* + * dy ist jetzt >=0, fuer dx sind 3 Faelle zu untescheiden + */ + if (dx >= 0) { + int result = dx + dy; + return result; + } + else if (-dx >= dy) { + int result = -dx; + return result; + } + else { + return dy; + } } static int koor_distance_wrap_xy(int x1, int y1, int x2, int y2, int width, int height) { - int dx = x1 - x2; - int dy = y1 - y2; - int result, dist; - int mindist = _min(width, height) >> 1; + int dx = x1 - x2; + int dy = y1 - y2; + int result, dist; + int mindist = _min(width, height) >> 1; - /* Bei negativem dy am Ursprung spiegeln, das veraendert - * den Abstand nicht - */ - if (dy < 0) { - dy = -dy; - dx = -dx; - } - if (dx < 0) { - dx = width + dx; - } - /* dx,dy is now pointing northeast */ - result = dx + dy; - if (result <= mindist) + /* Bei negativem dy am Ursprung spiegeln, das veraendert + * den Abstand nicht + */ + if (dy < 0) { + dy = -dy; + dx = -dx; + } + if (dx < 0) { + dx = width + dx; + } + /* dx,dy is now pointing northeast */ + result = dx + dy; + if (result <= mindist) + return result; + + dist = (width - dx) + (height - dy); /* southwest */ + if (dist >= 0 && dist < result) { + result = dist; + if (result <= mindist) + return result; + } + dist = _max(dx, height - dy); + if (dist >= 0 && dist < result) { + result = dist; + if (result <= mindist) + return result; + } + dist = _max(width - dx, dy); + if (dist >= 0 && dist < result) + result = dist; return result; - - dist = (width - dx) + (height - dy); /* southwest */ - if (dist >= 0 && dist < result) { - result = dist; - if (result <= mindist) - return result; - } - dist = _max(dx, height - dy); - if (dist >= 0 && dist < result) { - result = dist; - if (result <= mindist) - return result; - } - dist = _max(width - dx, dy); - if (dist >= 0 && dist < result) - result = dist; - return result; } int koor_distance(int x1, int y1, int x2, int y2) { - const plane *p1 = findplane(x1, y1); - const plane *p2 = findplane(x2, y2); - if (p1 != p2) - return INT_MAX; - else { - int width = plane_width(p1); - int height = plane_height(p1); - if (width && height) { - return koor_distance_wrap_xy(x1, y1, x2, y2, width, height); - } else { - return koor_distance_orig(x1, y1, x2, y2); + const plane *p1 = findplane(x1, y1); + const plane *p2 = findplane(x2, y2); + if (p1 != p2) + return INT_MAX; + else { + int width = plane_width(p1); + int height = plane_height(p1); + if (width && height) { + return koor_distance_wrap_xy(x1, y1, x2, y2, width, height); + } + else { + return koor_distance_orig(x1, y1, x2, y2); + } } - } } int distance(const region * r1, const region * r2) { - return koor_distance(r1->x, r1->y, r2->x, r2->y); + return koor_distance(r1->x, r1->y, r2->x, r2->y); } void free_regionlist(region_list * rl) { - while (rl) { - region_list *rl2 = rl->next; - free(rl); - rl = rl2; - } + while (rl) { + region_list *rl2 = rl->next; + free(rl); + rl = rl2; + } } void add_regionlist(region_list ** rl, region * r) { - region_list *rl2 = (region_list *) malloc(sizeof(region_list)); + region_list *rl2 = (region_list *)malloc(sizeof(region_list)); - rl2->data = r; - rl2->next = *rl; + rl2->data = r; + rl2->next = *rl; - *rl = rl2; + *rl = rl2; } /********************/ /* at_horseluck */ /********************/ attrib_type at_horseluck = { - "horseluck", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - NO_READ, - ATF_UNIQUE + "horseluck", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + NO_READ, + ATF_UNIQUE }; /**********************/ /* at_peasantluck */ /**********************/ attrib_type at_peasantluck = { - "peasantluck", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - NO_READ, - ATF_UNIQUE + "peasantluck", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + NO_READ, + ATF_UNIQUE }; /*********************/ /* at_deathcount */ /*********************/ attrib_type at_deathcount = { - "deathcount", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - a_writeint, - a_readint, - ATF_UNIQUE + "deathcount", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + a_writeint, + a_readint, + ATF_UNIQUE }; /*********************/ /* at_woodcount */ /*********************/ attrib_type at_woodcount = { - "woodcount", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - a_readint, - ATF_UNIQUE + "woodcount", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + a_readint, + ATF_UNIQUE }; /*********************/ /* at_travelunit */ /*********************/ attrib_type at_travelunit = { - "travelunit", - DEFAULT_INIT, - DEFAULT_FINALIZE, - DEFAULT_AGE, - NO_WRITE, - NO_READ + "travelunit", + DEFAULT_INIT, + DEFAULT_FINALIZE, + DEFAULT_AGE, + NO_WRITE, + NO_READ }; void rsetroad(region * r, direction_t d, short val) { - connection *b; - region *r2 = rconnect(r, d); + connection *b; + region *r2 = rconnect(r, d); - if (!r2) { - return; - } - b = get_borders(r, r2); - while (b && b->type != &bt_road) { - b = b->next; - } - if (!b) { - if (!val) return; - b = new_border(&bt_road, r, r2); - } - if (r == b->from) { - b->data.sa[0] = val; - } else { - b->data.sa[1] = val; - } + if (!r2) { + return; + } + b = get_borders(r, r2); + while (b && b->type != &bt_road) { + b = b->next; + } + if (!b) { + if (!val) return; + b = new_border(&bt_road, r, r2); + } + if (r == b->from) { + b->data.sa[0] = val; + } + else { + b->data.sa[1] = val; + } } short rroad(const region * r, direction_t d) { - connection *b; - region *r2 = rconnect(r, d); + connection *b; + region *r2 = rconnect(r, d); - if (!r2) { - return 0; - } - b = get_borders(r, r2); - while (b && b->type != &bt_road) { - b = b->next; - } - if (!b) { - return 0; - } - - return (r == b->from) ? b->data.sa[0] : b->data.sa[1]; + if (!r2) { + return 0; + } + b = get_borders(r, r2); + while (b && b->type != &bt_road) { + b = b->next; + } + if (!b) { + return 0; + } + + return (r == b->from) ? b->data.sa[0] : b->data.sa[1]; } bool r_isforest(const region * r) { - if (fval(r->terrain, FOREST_REGION)) { - /* needs to be covered with at leas 48% trees */ - int mincover = (int)(r->terrain->size * 0.48); - int trees = rtrees(r, 2) + rtrees(r, 1); - return (trees * TREESIZE >= mincover); - } - return false; + if (fval(r->terrain, FOREST_REGION)) { + /* needs to be covered with at leas 48% trees */ + int mincover = (int)(r->terrain->size * 0.48); + int trees = rtrees(r, 2) + rtrees(r, 1); + return (trees * TREESIZE >= mincover); + } + return false; } bool is_coastregion(region * r) { - direction_t i; - int res = 0; + direction_t i; + int res = 0; - for (i = 0; !res && i < MAXDIRECTIONS; i++) { - region *rn = rconnect(r, i); - if (rn && fval(rn->terrain, SEA_REGION)) - res++; - } - return res!=0; + for (i = 0; !res && i < MAXDIRECTIONS; i++) { + region *rn = rconnect(r, i); + if (rn && fval(rn->terrain, SEA_REGION)) + res++; + } + return res != 0; } int rpeasants(const region * r) { - return ((r)->land ? (r)->land->peasants : 0); + return ((r)->land ? (r)->land->peasants : 0); } void rsetpeasants(region * r, int value) { - ((r)->land ? ((r)->land->peasants = - (value)) : (assert((value) >= 0), (value)), 0); + ((r)->land ? ((r)->land->peasants = + (value)) : (assert((value) >= 0), (value)), 0); } int rmoney(const region * r) { - return ((r)->land ? (r)->land->money : 0); + return ((r)->land ? (r)->land->money : 0); } void rsethorses(const region * r, int value) { - assert(value >= 0); - if (r->land) - r->land->horses = value; + assert(value >= 0); + if (r->land) + r->land->horses = value; } int rhorses(const region * r) { - return r->land ? r->land->horses : 0; + return r->land ? r->land->horses : 0; } void rsetmoney(region * r, int value) { - ((r)->land ? ((r)->land->money = - (value)) : (assert((value) >= 0), (value)), 0); + ((r)->land ? ((r)->land->money = + (value)) : (assert((value) >= 0), (value)), 0); } void r_setdemand(region * r, const luxury_type * ltype, int value) { - struct demand *d, **dp = &r->land->demands; + struct demand *d, **dp = &r->land->demands; - if (ltype == NULL) - return; + if (ltype == NULL) + return; - while (*dp && (*dp)->type != ltype) - dp = &(*dp)->next; - d = *dp; - if (!d) { - d = *dp = malloc(sizeof(struct demand)); - d->next = NULL; - d->type = ltype; - } - d->value = value; + while (*dp && (*dp)->type != ltype) + dp = &(*dp)->next; + d = *dp; + if (!d) { + d = *dp = malloc(sizeof(struct demand)); + d->next = NULL; + d->type = ltype; + } + d->value = value; } const item_type *r_luxury(region * r) { - struct demand *dmd; - if (r->land) { - if (!r->land->demands) { - fix_demand(r); + struct demand *dmd; + if (r->land) { + if (!r->land->demands) { + fix_demand(r); + } + for (dmd = r->land->demands; dmd; dmd = dmd->next) { + if (dmd->value == 0) + return dmd->type->itype; + } } - for (dmd = r->land->demands; dmd; dmd = dmd->next) { - if (dmd->value == 0) - return dmd->type->itype; - } - } - return NULL; + return NULL; } int r_demand(const region * r, const luxury_type * ltype) { - struct demand *d = r->land->demands; - while (d && d->type != ltype) - d = d->next; - if (!d) - return -1; - return d->value; + struct demand *d = r->land->demands; + while (d && d->type != ltype) + d = d->next; + if (!d) + return -1; + return d->value; } const char *rname(const region * r, const struct locale *lang) { - if (r->land && r->land->name) { - return r->land->name; - } - return LOC(lang, terrain_name(r)); + if (r->land && r->land->name) { + return r->land->name; + } + return LOC(lang, terrain_name(r)); } int rtrees(const region * r, int ageclass) { - return ((r)->land ? (r)->land->trees[ageclass] : 0); + return ((r)->land ? (r)->land->trees[ageclass] : 0); } int rsettrees(const region * r, int ageclass, int value) { - if (!r->land) - assert(value == 0); - else { - assert(value >= 0); - return r->land->trees[ageclass] = value; - } - return 0; + if (!r->land) + assert(value == 0); + else { + assert(value >= 0); + return r->land->trees[ageclass] = value; + } + return 0; } static region *last; @@ -708,33 +713,33 @@ static unsigned int max_index = 0; region *new_region(int x, int y, struct plane *pl, int uid) { - region *r; + region *r; - pnormalize(&x, &y, pl); - r = rfindhash(x, y); + pnormalize(&x, &y, pl); + r = rfindhash(x, y); - if (r) { - log_error("duplicate region discovered: %s(%d,%d)\n", regionname(r, NULL), x, y); - if (r->units) - log_error("duplicate region contains units\n"); + if (r) { + log_error("duplicate region discovered: %s(%d,%d)\n", regionname(r, NULL), x, y); + if (r->units) + log_error("duplicate region contains units\n"); + return r; + } + r = calloc(1, sizeof(region)); + r->x = x; + r->y = y; + r->uid = uid; + r->age = 1; + r->_plane = pl; + rhash(r); + hash_uid(r); + if (last) + addlist(&last, r); + else + addlist(®ions, r); + last = r; + assert(r->next == NULL); + r->index = ++max_index; return r; - } - r = calloc(1, sizeof(region)); - r->x = x; - r->y = y; - r->uid = uid; - r->age = 1; - r->_plane = pl; - rhash(r); - hash_uid(r); - if (last) - addlist(&last, r); - else - addlist(®ions, r); - last = r; - assert(r->next == NULL); - r->index = ++max_index; - return r; } static region *deleted_regions; @@ -742,159 +747,159 @@ static region *deleted_regions; void remove_region(region ** rlist, region * r) { - while (r->units) { - unit *u = r->units; - i_freeall(&u->items); - remove_unit(&r->units, u); - } + while (r->units) { + unit *u = r->units; + i_freeall(&u->items); + remove_unit(&r->units, u); + } - runhash(r); - unhash_uid(r); - while (*rlist && *rlist != r) - rlist = &(*rlist)->next; - assert(*rlist == r); - *rlist = r->next; - r->next = deleted_regions; - deleted_regions = r; + runhash(r); + unhash_uid(r); + while (*rlist && *rlist != r) + rlist = &(*rlist)->next; + assert(*rlist == r); + *rlist = r->next; + r->next = deleted_regions; + deleted_regions = r; } static void freeland(land_region * lr) { - while (lr->demands) { - struct demand *d = lr->demands; - lr->demands = d->next; - free(d); - } - if (lr->name) - free(lr->name); - free(lr); + while (lr->demands) { + struct demand *d = lr->demands; + lr->demands = d->next; + free(d); + } + if (lr->name) + free(lr->name); + free(lr); } void region_setresource(region * r, const resource_type * rtype, int value) { - rawmaterial *rm = r->resources; - while (rm) { - if (rm->type->rtype == rtype) { - rm->amount = value; - break; - } - rm = rm->next; - } - if (!rm) { - if (rtype == get_resourcetype(R_SILVER)) - rsetmoney(r, value); - else if (rtype == get_resourcetype(R_PEASANT)) - rsetpeasants(r, value); - else if (rtype == get_resourcetype(R_HORSE)) - rsethorses(r, value); - else { - int i; - for (i = 0; r->terrain->production[i].type; ++i) { - const terrain_production *production = r->terrain->production + i; - if (production->type==rtype) { - add_resource(r, 1, value, dice_rand(production->divisor), rtype); - break; + rawmaterial *rm = r->resources; + while (rm) { + if (rm->type->rtype == rtype) { + rm->amount = value; + break; + } + rm = rm->next; + } + if (!rm) { + if (rtype == get_resourcetype(R_SILVER)) + rsetmoney(r, value); + else if (rtype == get_resourcetype(R_PEASANT)) + rsetpeasants(r, value); + else if (rtype == get_resourcetype(R_HORSE)) + rsethorses(r, value); + else { + int i; + for (i = 0; r->terrain->production[i].type; ++i) { + const terrain_production *production = r->terrain->production + i; + if (production->type == rtype) { + add_resource(r, 1, value, dice_rand(production->divisor), rtype); + break; + } + } } - } } - } } int region_getresource(const region * r, const resource_type * rtype) { - const rawmaterial *rm; - for (rm = r->resources; rm; rm = rm->next) { - if (rm->type->rtype == rtype) { - return rm->amount; + const rawmaterial *rm; + for (rm = r->resources; rm; rm = rm->next) { + if (rm->type->rtype == rtype) { + return rm->amount; + } } - } - if (rtype == get_resourcetype(R_SILVER)) - return rmoney(r); - if (rtype == get_resourcetype(R_HORSE)) - return rhorses(r); - if (rtype == get_resourcetype(R_PEASANT)) - return rpeasants(r); - return 0; + if (rtype == get_resourcetype(R_SILVER)) + return rmoney(r); + if (rtype == get_resourcetype(R_HORSE)) + return rhorses(r); + if (rtype == get_resourcetype(R_PEASANT)) + return rpeasants(r); + return 0; } void free_region(region * r) { - if (last == r) - last = NULL; - free(r->display); - if (r->land) - freeland(r->land); + if (last == r) + last = NULL; + free(r->display); + if (r->land) + freeland(r->land); - if (r->msgs) { - free_messagelist(r->msgs); - r->msgs = 0; - } + if (r->msgs) { + free_messagelist(r->msgs); + r->msgs = 0; + } - while (r->individual_messages) { - struct individual_message *msg = r->individual_messages; - r->individual_messages = msg->next; - if (msg->msgs) - free_messagelist(msg->msgs); - free(msg); - } + while (r->individual_messages) { + struct individual_message *msg = r->individual_messages; + r->individual_messages = msg->next; + if (msg->msgs) + free_messagelist(msg->msgs); + free(msg); + } - while (r->attribs) - a_remove(&r->attribs, r->attribs); - while (r->resources) { - rawmaterial *res = r->resources; - r->resources = res->next; - free(res); - } + while (r->attribs) + a_remove(&r->attribs, r->attribs); + while (r->resources) { + rawmaterial *res = r->resources; + r->resources = res->next; + free(res); + } - while (r->donations) { - donation *don = r->donations; - r->donations = don->next; - free(don); - } + while (r->donations) { + donation *don = r->donations; + r->donations = don->next; + free(don); + } - while (r->units) { - unit *u = r->units; - r->units = u->next; - uunhash(u); - free_unit(u); - free(u); - } + while (r->units) { + unit *u = r->units; + r->units = u->next; + uunhash(u); + free_unit(u); + free(u); + } - while (r->buildings) { - building *b = r->buildings; - assert(b->region == r); - r->buildings = b->next; - bunhash(b); /* must be done here, because remove_building does it, and wasn't called */ - free_building(b); - } + while (r->buildings) { + building *b = r->buildings; + assert(b->region == r); + r->buildings = b->next; + bunhash(b); /* must be done here, because remove_building does it, and wasn't called */ + free_building(b); + } - while (r->ships) { - ship *s = r->ships; - assert(s->region == r); - r->ships = s->next; - sunhash(s); - free_ship(s); - } + while (r->ships) { + ship *s = r->ships; + assert(s->region == r); + r->ships = s->next; + sunhash(s); + free_ship(s); + } - free(r); + free(r); } void free_regions(void) { - memset(uidhash, 0, sizeof(uidhash)); - while (deleted_regions) { - region *r = deleted_regions; - deleted_regions = r->next; - free_region(r); - } - while (regions) { - region *r = regions; - regions = r->next; - runhash(r); - free_region(r); - } - max_index = 0; - last = NULL; + memset(uidhash, 0, sizeof(uidhash)); + while (deleted_regions) { + region *r = deleted_regions; + deleted_regions = r->next; + free_region(r); + } + while (regions) { + region *r = regions; + regions = r->next; + runhash(r); + free_region(r); + } + max_index = 0; + last = NULL; } /** creates a name for a region @@ -903,245 +908,256 @@ void free_regions(void) */ static char *makename(void) { - int s, v, k, e, p = 0, x = 0; - size_t nk, ne, nv, ns; - static char name[16]; - const char *kons = "bcdfghklmnprstvwz", - *start = "bcdgtskpvfr", - *end = "nlrdst", - *vowels = "aaaaaaaaaaaeeeeeeeeeeeeiiiiiiiiiiioooooooooooouuuuuuuuuuyy"; + int s, v, k, e, p = 0, x = 0; + size_t nk, ne, nv, ns; + static char name[16]; + const char *kons = "bcdfghklmnprstvwz", + *start = "bcdgtskpvfr", + *end = "nlrdst", + *vowels = "aaaaaaaaaaaeeeeeeeeeeeeiiiiiiiiiiioooooooooooouuuuuuuuuuyy"; - /* const char * vowels_latin1 = "aaaaaaaaaàâeeeeeeeeeéèêiiiiiiiiiíîoooooooooóòôuuuuuuuuuúyy"; */ + /* const char * vowels_latin1 = "aaaaaaaaaàâeeeeeeeeeéèêiiiiiiiiiíîoooooooooóòôuuuuuuuuuúyy"; */ - nk = strlen(kons); - ne = strlen(end); - nv = strlen(vowels); - ns = strlen(start); + nk = strlen(kons); + ne = strlen(end); + nv = strlen(vowels); + ns = strlen(start); - for (s = rng_int() % 3 + 2; s > 0; s--) { - if (x > 0) { - k = rng_int() % (int)nk; - name[p] = kons[k]; - p++; - } else { - k = rng_int() % (int)ns; - name[p] = start[k]; - p++; + for (s = rng_int() % 3 + 2; s > 0; s--) { + if (x > 0) { + k = rng_int() % (int)nk; + name[p] = kons[k]; + p++; + } + else { + k = rng_int() % (int)ns; + name[p] = start[k]; + p++; + } + v = rng_int() % (int)nv; + name[p] = vowels[v]; + p++; + if (rng_int() % 3 == 2 || s == 1) { + e = rng_int() % (int)ne; + name[p] = end[e]; + p++; + x = 1; + } + else + x = 0; } - v = rng_int() % (int)nv; - name[p] = vowels[v]; - p++; - if (rng_int() % 3 == 2 || s == 1) { - e = rng_int() % (int)ne; - name[p] = end[e]; - p++; - x = 1; - } else - x = 0; - } - name[p] = '\0'; - name[0] = (char)toupper(name[0]); - return name; + name[p] = '\0'; + name[0] = (char)toupper(name[0]); + return name; } void setluxuries(region * r, const luxury_type * sale) { - const luxury_type *ltype; + const luxury_type *ltype; - assert(r->land); + assert(r->land); - if (r->land->demands) - freelist(r->land->demands); + if (r->land->demands) + freelist(r->land->demands); - for (ltype = luxurytypes; ltype; ltype = ltype->next) { - struct demand *dmd = malloc(sizeof(struct demand)); - dmd->type = ltype; - if (ltype != sale) - dmd->value = 1 + rng_int() % 5; - else - dmd->value = 0; - dmd->next = r->land->demands; - r->land->demands = dmd; - } + for (ltype = luxurytypes; ltype; ltype = ltype->next) { + struct demand *dmd = malloc(sizeof(struct demand)); + dmd->type = ltype; + if (ltype != sale) + dmd->value = 1 + rng_int() % 5; + else + dmd->value = 0; + dmd->next = r->land->demands; + r->land->demands = dmd; + } } void terraform_region(region * r, const terrain_type * terrain) { - /* Resourcen, die nicht mehr vorkommen können, löschen */ - const terrain_type *oldterrain = r->terrain; - rawmaterial **lrm = &r->resources; + /* Resourcen, die nicht mehr vorkommen können, löschen */ + const terrain_type *oldterrain = r->terrain; + rawmaterial **lrm = &r->resources; - assert(terrain); + assert(terrain); - while (*lrm) { - rawmaterial *rm = *lrm; - const resource_type *rtype = NULL; + while (*lrm) { + rawmaterial *rm = *lrm; + const resource_type *rtype = NULL; - if (terrain->production != NULL) { - int i; - for (i = 0; terrain->production[i].type; ++i) { - if (rm->type->rtype == terrain->production[i].type) { - rtype = rm->type->rtype; - break; - } - } - } - if (rtype == NULL) { - *lrm = rm->next; - free(rm); - } else { - lrm = &rm->next; - } - } - - r->terrain = terrain; - terraform_resources(r); - - if (!fval(terrain, LAND_REGION)) { - region_setinfo(r, NULL); - if (r->land != NULL) { - i_freeall(&r->land->items); - freeland(r->land); - r->land = NULL; - } - rsettrees(r, 0, 0); - rsettrees(r, 1, 0); - rsettrees(r, 2, 0); - rsethorses(r, 0); - rsetpeasants(r, 0); - rsetmoney(r, 0); - freset(r, RF_ENCOUNTER); - freset(r, RF_MALLORN); - /* Beschreibung und Namen löschen */ - return; - } - - if (r->land) { - int d; - for (d=0;d!=MAXDIRECTIONS;++d) { - rsetroad(r, d, 0); - } - i_freeall(&r->land->items); - } else { - static struct surround { - struct surround *next; - const luxury_type *type; - int value; - } *trash = NULL, *nb = NULL; - const luxury_type *ltype = NULL; - direction_t d; - int mnr = 0; - - r->land = calloc(1, sizeof(land_region)); - r->land->ownership = NULL; - region_set_morale(r, MORALE_DEFAULT, -1); - region_setname(r, makename()); - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *nr = rconnect(r, d); - if (nr && nr->land) { - struct demand *sale = r->land->demands; - while (sale && sale->value != 0) - sale = sale->next; - if (sale) { - struct surround *sr = nb; - while (sr && sr->type != sale->type) - sr = sr->next; - if (!sr) { - if (trash) { - sr = trash; - trash = trash->next; - } else { - sr = calloc(1, sizeof(struct surround)); + if (terrain->production != NULL) { + int i; + for (i = 0; terrain->production[i].type; ++i) { + if (rm->type->rtype == terrain->production[i].type) { + rtype = rm->type->rtype; + break; + } } - sr->next = nb; - sr->type = sale->type; - sr->value = 1; - nb = sr; - } else - sr->value++; - ++mnr; } - } + if (rtype == NULL) { + *lrm = rm->next; + free(rm); + } + else { + lrm = &rm->next; + } } - if (!nb) { - int i = get_maxluxuries(); - if (i > 0) { - i = rng_int() % i; - ltype = luxurytypes; - while (i--) - ltype = ltype->next; - } - } else { - int i = rng_int() % mnr; - struct surround *srd = nb; - while (i > srd->value) { - i -= srd->value; - srd = srd->next; - } - if (srd->type) - setluxuries(r, srd->type); - while (srd->next != NULL) - srd = srd->next; - srd->next = trash; - trash = nb; - nb = NULL; - } - } - if (fval(terrain, LAND_REGION)) { - const item_type *itype = NULL; - char equip_hash[64]; + r->terrain = terrain; + terraform_resources(r); - /* TODO: put the equipment in struct terrain, faster */ - sprintf(equip_hash, "terrain_%s", terrain->_name); - equip_items(&r->land->items, get_equipment(equip_hash)); - - if (r->terrain->herbs) { - int len = 0; - while (r->terrain->herbs[len]) - ++len; - if (len) - itype = r->terrain->herbs[rng_int() % len]; - } - if (itype != NULL) { - rsetherbtype(r, itype); - rsetherbs(r, (short)(50 + rng_int() % 31)); - } else { - rsetherbtype(r, NULL); - } - if (oldterrain == NULL || !fval(oldterrain, LAND_REGION)) { - if (rng_int() % 100 < 3) - fset(r, RF_MALLORN); - else + if (!fval(terrain, LAND_REGION)) { + region_setinfo(r, NULL); + if (r->land != NULL) { + i_freeall(&r->land->items); + freeland(r->land); + r->land = NULL; + } + rsettrees(r, 0, 0); + rsettrees(r, 1, 0); + rsettrees(r, 2, 0); + rsethorses(r, 0); + rsetpeasants(r, 0); + rsetmoney(r, 0); + freset(r, RF_ENCOUNTER); freset(r, RF_MALLORN); - if (rng_int() % 100 < ENCCHANCE) { - fset(r, RF_ENCOUNTER); - } + /* Beschreibung und Namen löschen */ + return; } - } - if (oldterrain == NULL || terrain->size != oldterrain->size) { - if (terrain == newterrain(T_PLAIN)) { - rsethorses(r, rng_int() % (terrain->size / 50)); - if (rng_int() % 100 < 40) { - rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); - } - } else if (chance(0.2)) { - rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); - } else { - rsettrees(r, 2, 0); + if (r->land) { + int d; + for (d = 0; d != MAXDIRECTIONS; ++d) { + rsetroad(r, d, 0); + } + i_freeall(&r->land->items); } - rsettrees(r, 1, rtrees(r, 2) / 4); - rsettrees(r, 0, rtrees(r, 2) / 8); + else { + static struct surround { + struct surround *next; + const luxury_type *type; + int value; + } *trash = NULL, *nb = NULL; + const luxury_type *ltype = NULL; + direction_t d; + int mnr = 0; - if (!fval(r, RF_CHAOTIC)) { - int peasants; - peasants = (maxworkingpeasants(r) * (20 + dice_rand("6d10"))) / 100; - rsetpeasants(r, _max(100, peasants)); - rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL, - INT_MAX) + 1) + rng_int() % 5)); + r->land = calloc(1, sizeof(land_region)); + r->land->ownership = NULL; + region_set_morale(r, MORALE_DEFAULT, -1); + region_setname(r, makename()); + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *nr = rconnect(r, d); + if (nr && nr->land) { + struct demand *sale = r->land->demands; + while (sale && sale->value != 0) + sale = sale->next; + if (sale) { + struct surround *sr = nb; + while (sr && sr->type != sale->type) + sr = sr->next; + if (!sr) { + if (trash) { + sr = trash; + trash = trash->next; + } + else { + sr = calloc(1, sizeof(struct surround)); + } + sr->next = nb; + sr->type = sale->type; + sr->value = 1; + nb = sr; + } + else + sr->value++; + ++mnr; + } + } + } + if (!nb) { + // TODO: this is really lame + int i = get_maxluxuries(); + if (i > 0) { + i = rng_int() % i; + ltype = luxurytypes; + while (i--) + ltype = ltype->next; + } + } + else { + int i = rng_int() % mnr; + struct surround *srd = nb; + while (i > srd->value) { + i -= srd->value; + srd = srd->next; + } + if (srd->type) + setluxuries(r, srd->type); + while (srd->next != NULL) + srd = srd->next; + srd->next = trash; + trash = nb; + nb = NULL; + } + } + + if (fval(terrain, LAND_REGION)) { + const item_type *itype = NULL; + char equip_hash[64]; + + /* TODO: put the equipment in struct terrain, faster */ + sprintf(equip_hash, "terrain_%s", terrain->_name); + equip_items(&r->land->items, get_equipment(equip_hash)); + + if (r->terrain->herbs) { + int len = 0; + while (r->terrain->herbs[len]) + ++len; + if (len) + itype = r->terrain->herbs[rng_int() % len]; + } + if (itype != NULL) { + rsetherbtype(r, itype); + rsetherbs(r, (short)(50 + rng_int() % 31)); + } + else { + rsetherbtype(r, NULL); + } + if (oldterrain == NULL || !fval(oldterrain, LAND_REGION)) { + if (rng_int() % 100 < 3) + fset(r, RF_MALLORN); + else + freset(r, RF_MALLORN); + if (rng_int() % 100 < ENCCHANCE) { + fset(r, RF_ENCOUNTER); + } + } + } + + if (oldterrain == NULL || terrain->size != oldterrain->size) { + if (terrain == newterrain(T_PLAIN)) { + rsethorses(r, rng_int() % (terrain->size / 50)); + if (rng_int() % 100 < 40) { + rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); + } + } + else if (chance(0.2)) { + rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000); + } + else { + rsettrees(r, 2, 0); + } + rsettrees(r, 1, rtrees(r, 2) / 4); + rsettrees(r, 0, rtrees(r, 2) / 8); + + if (!fval(r, RF_CHAOTIC)) { + int peasants; + peasants = (maxworkingpeasants(r) * (20 + dice_rand("6d10"))) / 100; + rsetpeasants(r, _max(100, peasants)); + rsetmoney(r, rpeasants(r) * ((wage(r, NULL, NULL, + INT_MAX) + 1) + rng_int() % 5)); + } } - } } /** ENNO: @@ -1152,248 +1168,254 @@ void terraform_region(region * r, const terrain_type * terrain) #include "curse.h" int production(const region * r) { - /* muß rterrain(r) sein, nicht rterrain() wegen rekursion */ - int p = r->terrain->size; - if (curse_active(get_curse(r->attribs, ct_find("drought")))) - p /= 2; + /* muß rterrain(r) sein, nicht rterrain() wegen rekursion */ + int p = r->terrain->size; + if (curse_active(get_curse(r->attribs, ct_find("drought")))) + p /= 2; - return p; + return p; } int resolve_region_coor(variant id, void *address) { - region *r = findregion(id.sa[0], id.sa[1]); - if (r) { - *(region **) address = r; - return 0; - } - *(region **) address = NULL; - return -1; + region *r = findregion(id.sa[0], id.sa[1]); + if (r) { + *(region **)address = r; + return 0; + } + *(region **)address = NULL; + return -1; } int resolve_region_id(variant id, void *address) { - region *r = NULL; - if (id.i != 0) { - r = findregionbyid(id.i); - if (r == NULL) { - *(region **) address = NULL; - return -1; + region *r = NULL; + if (id.i != 0) { + r = findregionbyid(id.i); + if (r == NULL) { + *(region **)address = NULL; + return -1; + } } - } - *(region **) address = r; - return 0; + *(region **)address = r; + return 0; } variant read_region_reference(struct storage * store) { - variant result; - if (global.data_version < UIDHASH_VERSION) { - int n; - READ_INT(store, &n); - result.sa[0] = (short)n; - READ_INT(store, &n); - result.sa[1] = (short)n; - } else { - READ_INT(store, &result.i); - } - return result; + variant result; + if (global.data_version < UIDHASH_VERSION) { + int n; + READ_INT(store, &n); + result.sa[0] = (short)n; + READ_INT(store, &n); + result.sa[1] = (short)n; + } + else { + READ_INT(store, &result.i); + } + return result; } void write_region_reference(const region * r, struct storage *store) { - if (r) { - WRITE_INT(store, r->uid); - } else { - WRITE_INT(store, 0); - } + if (r) { + WRITE_INT(store, r->uid); + } + else { + WRITE_INT(store, 0); + } } struct message_list *r_getmessages(const struct region *r, - const struct faction *viewer) + const struct faction *viewer) { - struct individual_message *imsg = r->individual_messages; - while (imsg && (imsg)->viewer != viewer) - imsg = imsg->next; - if (imsg) - return imsg->msgs; - return NULL; + struct individual_message *imsg = r->individual_messages; + while (imsg && (imsg)->viewer != viewer) + imsg = imsg->next; + if (imsg) + return imsg->msgs; + return NULL; } struct message *r_addmessage(struct region *r, const struct faction *viewer, - struct message *msg) +struct message *msg) { - assert(r); - if (viewer) { - struct individual_message *imsg; - imsg = r->individual_messages; - while (imsg && imsg->viewer != viewer) - imsg = imsg->next; - if (imsg == NULL) { - imsg = malloc(sizeof(struct individual_message)); - imsg->next = r->individual_messages; - imsg->msgs = NULL; - r->individual_messages = imsg; - imsg->viewer = viewer; + assert(r); + if (viewer) { + struct individual_message *imsg; + imsg = r->individual_messages; + while (imsg && imsg->viewer != viewer) + imsg = imsg->next; + if (imsg == NULL) { + imsg = malloc(sizeof(struct individual_message)); + imsg->next = r->individual_messages; + imsg->msgs = NULL; + r->individual_messages = imsg; + imsg->viewer = viewer; + } + return add_message(&imsg->msgs, msg); } - return add_message(&imsg->msgs, msg); - } - return add_message(&r->msgs, msg); + return add_message(&r->msgs, msg); } struct faction *region_get_owner(const struct region *r) { - assert(rule_region_owners()); - if (r->land && r->land->ownership) { - return r->land->ownership->owner; - } - return NULL; + assert(rule_region_owners()); + if (r->land && r->land->ownership) { + return r->land->ownership->owner; + } + return NULL; } struct alliance *region_get_alliance(const struct region *r) { - assert(rule_region_owners()); - if (r->land && r->land->ownership) { - region_owner *own = r->land->ownership; - return own->owner ? own->owner->alliance : own->alliance; - } - return NULL; + assert(rule_region_owners()); + if (r->land && r->land->ownership) { + region_owner *own = r->land->ownership; + return own->owner ? own->owner->alliance : own->alliance; + } + return NULL; } void region_set_owner(struct region *r, struct faction *owner, int turn) { - assert(rule_region_owners()); - if (r->land) { - if (!r->land->ownership) { - r->land->ownership = malloc(sizeof(region_owner)); - assert(region_get_morale(r) == MORALE_DEFAULT); - r->land->ownership->owner = NULL; - r->land->ownership->alliance = NULL; - r->land->ownership->flags = 0; + assert(rule_region_owners()); + if (r->land) { + if (!r->land->ownership) { + r->land->ownership = malloc(sizeof(region_owner)); + assert(region_get_morale(r) == MORALE_DEFAULT); + r->land->ownership->owner = NULL; + r->land->ownership->alliance = NULL; + r->land->ownership->flags = 0; + } + r->land->ownership->since_turn = turn; + r->land->ownership->morale_turn = turn; + assert(r->land->ownership->owner != owner); + r->land->ownership->owner = owner; + if (owner) { + r->land->ownership->alliance = owner->alliance; + } } - r->land->ownership->since_turn = turn; - r->land->ownership->morale_turn = turn; - assert(r->land->ownership->owner != owner); - r->land->ownership->owner = owner; - if (owner) { - r->land->ownership->alliance = owner->alliance; - } - } } faction *update_owners(region * r) { - faction *f = NULL; - assert(rule_region_owners()); - if (r->land) { - building *bowner = largestbuilding(r, &cmp_current_owner, false); - building *blargest = largestbuilding(r, &cmp_taxes, false); - if (blargest) { - if (!bowner || bowner->size < blargest->size) { - /* region owners update? */ - unit *u = building_owner(blargest); - f = region_get_owner(r); - if (u == NULL) { - if (f) { - region_set_owner(r, NULL, turn); - r->land->ownership->flags |= OWNER_MOURNING; - f = NULL; - } - } else if (u->faction != f) { - if (!r->land->ownership) { - /* there has never been a prior owner */ - region_set_morale(r, MORALE_DEFAULT, turn); - } else { - alliance *al = region_get_alliance(r); - if (al && u->faction->alliance == al) { - int morale = _max(0, r->land->morale - MORALE_TRANSFER); - region_set_morale(r, morale, turn); - } else { - region_set_morale(r, MORALE_TAKEOVER, turn); - if (f) { - r->land->ownership->flags |= OWNER_MOURNING; - } + faction *f = NULL; + assert(rule_region_owners()); + if (r->land) { + building *bowner = largestbuilding(r, &cmp_current_owner, false); + building *blargest = largestbuilding(r, &cmp_taxes, false); + if (blargest) { + if (!bowner || bowner->size < blargest->size) { + /* region owners update? */ + unit *u = building_owner(blargest); + f = region_get_owner(r); + if (u == NULL) { + if (f) { + region_set_owner(r, NULL, turn); + r->land->ownership->flags |= OWNER_MOURNING; + f = NULL; + } + } + else if (u->faction != f) { + if (!r->land->ownership) { + /* there has never been a prior owner */ + region_set_morale(r, MORALE_DEFAULT, turn); + } + else { + alliance *al = region_get_alliance(r); + if (al && u->faction->alliance == al) { + int morale = _max(0, r->land->morale - MORALE_TRANSFER); + region_set_morale(r, morale, turn); + } + else { + region_set_morale(r, MORALE_TAKEOVER, turn); + if (f) { + r->land->ownership->flags |= OWNER_MOURNING; + } + } + } + region_set_owner(r, u->faction, turn); + f = u->faction; + } } - } - region_set_owner(r, u->faction, turn); - f = u->faction; } - } - } else if (r->land->ownership && r->land->ownership->owner) { - r->land->ownership->flags |= OWNER_MOURNING; - region_set_owner(r, NULL, turn); - f = NULL; + else if (r->land->ownership && r->land->ownership->owner) { + r->land->ownership->flags |= OWNER_MOURNING; + region_set_owner(r, NULL, turn); + f = NULL; + } } - } - return f; + return f; } void region_setinfo(struct region *r, const char *info) { - free(r->display); - r->display = info ? _strdup(info) : 0; + free(r->display); + r->display = info ? _strdup(info) : 0; } const char *region_getinfo(const region * r) { - return r->display ? r->display : ""; + return r->display ? r->display : ""; } void region_setname(struct region *r, const char *name) { - if (r->land) { - free(r->land->name); - r->land->name = name ? _strdup(name) : 0; - } + if (r->land) { + free(r->land->name); + r->land->name = name ? _strdup(name) : 0; + } } const char *region_getname(const region * r) { - if (r->land && r->land->name) { - return r->land->name; - } - return ""; + if (r->land && r->land->name) { + return r->land->name; + } + return ""; } int region_get_morale(const region * r) { - if (r->land) { - assert(r->land->morale >= 0 && r->land->morale <= MORALE_MAX); - return r->land->morale; - } - return -1; + if (r->land) { + assert(r->land->morale >= 0 && r->land->morale <= MORALE_MAX); + return r->land->morale; + } + return -1; } void region_set_morale(region * r, int morale, int turn) { - if (r->land) { - r->land->morale = (short)morale; - if (turn >= 0 && r->land->ownership) { - r->land->ownership->morale_turn = turn; + if (r->land) { + r->land->morale = (short)morale; + if (turn >= 0 && r->land->ownership) { + r->land->ownership->morale_turn = turn; + } + assert(r->land->morale >= 0 && r->land->morale <= MORALE_MAX); } - assert(r->land->morale >= 0 && r->land->morale <= MORALE_MAX); - } } void get_neighbours(const region * r, region ** list) { - int dir; - for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - list[dir] = rconnect(r, (direction_t)dir); - } + int dir; + for (dir = 0; dir != MAXDIRECTIONS; ++dir) { + list[dir] = rconnect(r, (direction_t)dir); + } } int owner_change(const region * r) { - if (r->land && r->land->ownership) { - return r->land->ownership->since_turn; - } - return INT_MIN; + if (r->land && r->land->ownership) { + return r->land->ownership->since_turn; + } + return INT_MIN; } bool is_mourning(const region * r, int in_turn) { - int change = owner_change(r); - return (change == in_turn - 1 - && (r->land->ownership->flags & OWNER_MOURNING)); + int change = owner_change(r); + return (change == in_turn - 1 + && (r->land->ownership->flags & OWNER_MOURNING)); } diff --git a/src/kernel/save.c b/src/kernel/save.c index 00cb89d3e..59040cba0 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1030,11 +1030,12 @@ void writeregion(struct gamedata *data, const region * r) WRITE_INT(data->store, rherbs(r)); WRITE_INT(data->store, rpeasants(r)); WRITE_INT(data->store, rmoney(r)); - if (r->land) + if (r->land) { for (demand = r->land->demands; demand; demand = demand->next) { WRITE_TOK(data->store, resourcename(demand->type->itype->rtype, 0)); WRITE_INT(data->store, demand->value); } + } WRITE_TOK(data->store, "end"); write_items(data->store, r->land->items); WRITE_SECTION(data->store); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index eb06803d2..16c1dbdfb 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -644,7 +644,7 @@ static weapon_type *xml_readweapon(xmlXPathContextPtr xpath, item_type * itype) xmlFree(propValue); propValue = xmlGetProp(node, BAD_CAST "value"); - wtype->damage[pos] = gc_add(_strdup((const char *)propValue)); + wtype->damage[pos] = _strdup((const char *)propValue); // TODO: this is a memory leak if (k == 0) wtype->damage[1 - pos] = wtype->damage[pos]; xmlFree(propValue); diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index 7083a85c9..2ac48bf46 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -8,7 +8,7 @@ This program may not be used, modified or distributed without prior permission by the authors of Eressea. -*/ + */ #include #include @@ -47,284 +47,284 @@ #include const terrain_type *random_terrain(const terrain_type * terrains[], - int distribution[], int size) + int distribution[], int size) { - int ndistribution = size; - const terrain_type *terrain; - int n; + int ndistribution = size; + const terrain_type *terrain; + int n; - if (distribution) { - ndistribution = 0; - for (n = 0; n != size; ++n) { - ndistribution += distribution[n]; + if (distribution) { + ndistribution = 0; + for (n = 0; n != size; ++n) { + ndistribution += distribution[n]; + } } - } - n = rng_int() % ndistribution; - if (distribution) { - int i; - for (i = 0; i != size; ++i) { - n -= distribution[i]; - if (n < 0) - break; + n = rng_int() % ndistribution; + if (distribution) { + int i; + for (i = 0; i != size; ++i) { + n -= distribution[i]; + if (n < 0) + break; + } + assert(i < size); + terrain = terrains[i]; } - assert(i < size); - terrain = terrains[i]; - } else { - terrain = terrains[n]; - } - return terrain; + else { + terrain = terrains[n]; + } + return terrain; } int seed_adamantium(region * r, int base) { - const resource_type *rtype = rt_find("adamantium"); - rawmaterial *rm; - for (rm = r->resources; rm; rm = rm->next) { - if (rm->type->rtype == rtype) - break; - } - if (!rm) { - add_resource(r, 1, base, 150, rtype); - } - return 0; + const resource_type *rtype = rt_find("adamantium"); + rawmaterial *rm; + for (rm = r->resources; rm; rm = rm->next) { + if (rm->type->rtype == rtype) + break; + } + if (!rm) { + add_resource(r, 1, base, 150, rtype); + } + return 0; } static int count_demand(const region * r) { - struct demand *dmd; - int c = 0; - if (r->land) { - for (dmd = r->land->demands; dmd; dmd = dmd->next) - c++; - } - return c; + struct demand *dmd; + int c = 0; + if (r->land) { + for (dmd = r->land->demands; dmd; dmd = dmd->next) + c++; + } + return c; } static int recurse_regions(region * r, region_list ** rlist, - bool(*fun) (const region * r)) +bool(*fun) (const region * r)) { - if (!fun(r)) - return 0; - else { - int len = 0; - direction_t d; - region_list *rl = calloc(sizeof(region_list), 1); - rl->next = *rlist; - rl->data = r; - (*rlist) = rl; - fset(r, RF_MARK); - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *nr = rconnect(r, d); - if (nr && !fval(nr, RF_MARK)) - len += recurse_regions(nr, rlist, fun); + if (!fun(r)) + return 0; + else { + int len = 0; + direction_t d; + region_list *rl = calloc(sizeof(region_list), 1); + rl->next = *rlist; + rl->data = r; + (*rlist) = rl; + fset(r, RF_MARK); + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *nr = rconnect(r, d); + if (nr && !fval(nr, RF_MARK)) + len += recurse_regions(nr, rlist, fun); + } + return len + 1; } - return len + 1; - } } static bool f_nolux(const region * r) { - if (r->land && count_demand(r) != get_maxluxuries()) - return true; - return false; + if (r->land && count_demand(r) != get_maxluxuries()) + return true; + return false; } int fix_demand(region * rd) { - region_list *rl, *rlist = NULL; - static const struct luxury_type **mlux = 0, **ltypes; - const luxury_type *sale = NULL; - int maxlux = 0; - int maxluxuries = get_maxluxuries(); + region_list *rl, *rlist = NULL; + static const luxury_type *mlux[MAXLUXURIES]; + const luxury_type *ltypes[MAXLUXURIES]; + const luxury_type *sale = NULL; + int maxlux = 0; + static int maxluxuries = 0; - if (maxluxuries == 0) - return 0; - recurse_regions(rd, &rlist, f_nolux); - if (mlux == 0) { - int i = 0; - mlux = - (const luxury_type **)gc_add(calloc(maxluxuries, - sizeof(const luxury_type *))); - ltypes = - (const luxury_type **)gc_add(calloc(maxluxuries, - sizeof(const luxury_type *))); - for (sale = luxurytypes; sale; sale = sale->next) { - ltypes[i++] = sale; + recurse_regions(rd, &rlist, f_nolux); + if (maxluxuries == 0) { + int i = 0; + for (sale = luxurytypes; sale; sale = sale->next) { + mlux[i] = 0; + ltypes[i++] = sale; + } + maxluxuries = i; } - } else { - int i; - for (i = 0; i != maxluxuries; ++i) - mlux[i] = 0; - } - for (rl = rlist; rl; rl = rl->next) { - region *r = rl->data; - direction_t d; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *nr = rconnect(r, d); - if (nr && nr->land && nr->land->demands) { - struct demand *dmd; - for (dmd = nr->land->demands; dmd; dmd = dmd->next) { - if (dmd->value == 0) { - int i; - for (i = 0; i != maxluxuries; ++i) { - if (mlux[i] == NULL) { - maxlux = i; - mlux[i] = dmd->type; - break; - } else if (mlux[i] == dmd->type) { - break; - } + else { + int i; + for (i = 0; i != maxluxuries; ++i) { + mlux[i] = 0; + } + } + for (rl = rlist; rl; rl = rl->next) { + region *r = rl->data; + direction_t d; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *nr = rconnect(r, d); + if (nr && nr->land && nr->land->demands) { + struct demand *dmd; + for (dmd = nr->land->demands; dmd; dmd = dmd->next) { + if (dmd->value == 0) { + int i; + for (i = 0; i != maxluxuries; ++i) { + if (mlux[i] == NULL) { + maxlux = i; + mlux[i] = dmd->type; + break; + } + else if (mlux[i] == dmd->type) { + break; + } + } + break; + } + } } - break; - } } - } + freset(r, RF_MARK); /* undo recursive marker */ } - freset(r, RF_MARK); /* undo recursive marker */ - } - if (maxlux < 2) { - int i; - for (i = maxlux; i != 2; ++i) { - int j; - do { - int k = rng_int() % maxluxuries; - mlux[i] = ltypes[k]; - for (j = 0; j != i; ++j) { - if (mlux[j] == mlux[i]) - break; + if (maxlux < 2) { + int i; + for (i = maxlux; i != 2; ++i) { + int j; + do { + int k = rng_int() % maxluxuries; + mlux[i] = ltypes[k]; + for (j = 0; j != i; ++j) { + if (mlux[j] == mlux[i]) + break; + } + } while (j != i); } - } while (j != i); + maxlux = 2; } - maxlux = 2; - } - for (rl = rlist; rl; rl = rl->next) { - region *r = rl->data; - sale = mlux[rng_int() % maxlux]; - if (sale) - setluxuries(r, sale); - } - while (rlist) { - rl = rlist->next; - free(rlist); - rlist = rl; - } - return 0; + for (rl = rlist; rl; rl = rl->next) { + region *r = rl->data; + sale = mlux[rng_int() % maxlux]; + if (sale) + setluxuries(r, sale); + } + while (rlist) { + rl = rlist->next; + free(rlist); + rlist = rl; + } + return 0; } /* nach 150 Runden ist Neustart erlaubt */ #define MINAGE_MULTI 150 newfaction *read_newfactions(const char *filename) { - newfaction *newfactions = NULL; - FILE *F = fopen(filename, "r"); - char buf[1024]; + newfaction *newfactions = NULL; + FILE *F = fopen(filename, "r"); + char buf[1024]; - if (F == NULL) - return NULL; - for (;;) { - faction *f; - char race[20], email[64], lang[8], password[16]; - newfaction *nf, **nfi; - int bonus = 0, subscription = 0; - int alliance = 0; + if (F == NULL) + return NULL; + for (;;) { + faction *f; + char race[20], email[64], lang[8], password[16]; + newfaction *nf, **nfi; + int bonus = 0, subscription = 0; + int alliance = 0; - if (fgets(buf, sizeof(buf), F) == NULL) - break; + if (fgets(buf, sizeof(buf), F) == NULL) + break; - email[0] = '\0'; - password[0] = '\0'; + email[0] = '\0'; + password[0] = '\0'; - if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus, - &subscription, password, &alliance) < 6) - break; - if (email[0] == '\0') - break; - if (password[0] == '\0') { - strcpy(password, itoa36(rng_int())); - strcat(password, itoa36(rng_int())); - } - for (f = factions; f; f = f->next) { - if (strcmp(f->email, email) == 0 && f->subscription - && f->age < MINAGE_MULTI) - break; - } - if (f && f->units) - continue; /* skip the ones we've already got */ - for (nf = newfactions; nf; nf = nf->next) { - if (strcmp(nf->email, email) == 0) - break; - } - if (nf) - continue; - nf = calloc(sizeof(newfaction), 1); - if (set_email(&nf->email, email) != 0) { - log_error("Invalid email address for subscription %s: %s\n", itoa36(subscription), email); - continue; - } - nf->password = _strdup(password); - nf->race = rc_find(race); - nf->subscription = subscription; - if (alliances != NULL) { - struct alliance *al = findalliance(alliance); - if (al == NULL) { - char zText[64]; - sprintf(zText, "Allianz %d", alliance); - al = makealliance(alliance, zText); - } - nf->allies = al; - } else { - nf->allies = NULL; - } - if (nf->race == NULL) { - /* if the script didn't supply the race as a token, then it gives us a - * race in the default locale (which means that itis a UTF8 string) */ - nf->race = findrace(race, default_locale); - if (nf->race == NULL) { - char buffer[32]; - size_t outbytes = sizeof(buffer) - 1; - size_t inbytes = strlen(race); - unicode_latin1_to_utf8(buffer, &outbytes, race, &inbytes); - buffer[outbytes] = 0; - nf->race = findrace(buffer, default_locale); - if (nf->race == NULL) { - log_error("new faction has unknown race '%s'.\n", race); - free(nf); - continue; + if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus, + &subscription, password, &alliance) < 6) + break; + if (email[0] == '\0') + break; + if (password[0] == '\0') { + strcpy(password, itoa36(rng_int())); + strcat(password, itoa36(rng_int())); } - } + for (f = factions; f; f = f->next) { + if (strcmp(f->email, email) == 0 && f->subscription + && f->age < MINAGE_MULTI) + break; + } + if (f && f->units) + continue; /* skip the ones we've already got */ + for (nf = newfactions; nf; nf = nf->next) { + if (strcmp(nf->email, email) == 0) + break; + } + if (nf) + continue; + nf = calloc(sizeof(newfaction), 1); + if (set_email(&nf->email, email) != 0) { + log_error("Invalid email address for subscription %s: %s\n", itoa36(subscription), email); + continue; + } + nf->password = _strdup(password); + nf->race = rc_find(race); + nf->subscription = subscription; + if (alliances != NULL) { + struct alliance *al = findalliance(alliance); + if (al == NULL) { + char zText[64]; + sprintf(zText, "Allianz %d", alliance); + al = makealliance(alliance, zText); + } + nf->allies = al; + } + else { + nf->allies = NULL; + } + if (nf->race == NULL) { + /* if the script didn't supply the race as a token, then it gives us a + * race in the default locale (which means that itis a UTF8 string) */ + nf->race = findrace(race, default_locale); + if (nf->race == NULL) { + char buffer[32]; + size_t outbytes = sizeof(buffer) - 1; + size_t inbytes = strlen(race); + unicode_latin1_to_utf8(buffer, &outbytes, race, &inbytes); + buffer[outbytes] = 0; + nf->race = findrace(buffer, default_locale); + if (nf->race == NULL) { + log_error("new faction has unknown race '%s'.\n", race); + free(nf); + continue; + } + } + } + nf->lang = get_locale(lang); + nf->bonus = bonus; + assert(nf->race && nf->email && nf->lang); + nfi = &newfactions; + while (*nfi) { + if ((*nfi)->race == nf->race) + break; + nfi = &(*nfi)->next; + } + nf->next = *nfi; + *nfi = nf; } - nf->lang = get_locale(lang); - nf->bonus = bonus; - assert(nf->race && nf->email && nf->lang); - nfi = &newfactions; - while (*nfi) { - if ((*nfi)->race == nf->race) - break; - nfi = &(*nfi)->next; - } - nf->next = *nfi; - *nfi = nf; - } - fclose(F); - return newfactions; + fclose(F); + return newfactions; } extern int numnewbies; static const terrain_type *preferred_terrain(const struct race *rc) { - terrain_t t = T_PLAIN; - if (rc == rc_find("dwarf")) - t = T_MOUNTAIN; - if (rc == rc_find("insect")) - t = T_DESERT; - if (rc == rc_find("halfling")) - t = T_SWAMP; - if (rc == rc_find("troll")) - t = T_MOUNTAIN; - return newterrain(t); + terrain_t t = T_PLAIN; + if (rc == rc_find("dwarf")) + t = T_MOUNTAIN; + if (rc == rc_find("insect")) + t = T_DESERT; + if (rc == rc_find("halfling")) + t = T_SWAMP; + if (rc == rc_find("troll")) + t = T_MOUNTAIN; + return newterrain(t); } #define REGIONS_PER_FACTION 2 @@ -335,169 +335,169 @@ static const terrain_type *preferred_terrain(const struct race *rc) static bool virgin_region(const region * r) { - direction_t d; - if (r == NULL) - return true; - if (fval(r->terrain, FORBIDDEN_REGION)) - return false; - if (r->units) - return false; - for (d = 0; d != MAXDIRECTIONS; ++d) { - const region *rn = rconnect(r, d); - if (rn) { - if (rn->age > r->age + 1) + direction_t d; + if (r == NULL) + return true; + if (fval(r->terrain, FORBIDDEN_REGION)) return false; - if (rn->units) + if (r->units) return false; - if (fval(rn->terrain, FORBIDDEN_REGION)) { - /* because it kinda sucks to have islands that are adjacent to a firewall */ - return false; - } + for (d = 0; d != MAXDIRECTIONS; ++d) { + const region *rn = rconnect(r, d); + if (rn) { + if (rn->age > r->age + 1) + return false; + if (rn->units) + return false; + if (fval(rn->terrain, FORBIDDEN_REGION)) { + /* because it kinda sucks to have islands that are adjacent to a firewall */ + return false; + } + } } - } - return true; + return true; } static quicklist * get_island(region * root) { - quicklist * ql, * result = 0; - int qi = 0; + quicklist * ql, *result = 0; + int qi = 0; - fset(root, RF_MARK); - ql_push(&result, root); + fset(root, RF_MARK); + ql_push(&result, root); - for (ql=result,qi=0; ql; ql_advance(&ql, &qi, 1)) { - int dir; - region *r = (region *)ql_get(ql, qi); - region * next[MAXDIRECTIONS]; + for (ql = result, qi = 0; ql; ql_advance(&ql, &qi, 1)) { + int dir; + region *r = (region *)ql_get(ql, qi); + region * next[MAXDIRECTIONS]; - get_neighbours(r, next); + get_neighbours(r, next); - for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - region *rn = next[dir]; - if (rn != NULL && rn->land && !fval(rn, RF_MARK)) { - fset(rn, RF_MARK); - ql_push(&result, rn); - } + for (dir = 0; dir != MAXDIRECTIONS; ++dir) { + region *rn = next[dir]; + if (rn != NULL && rn->land && !fval(rn, RF_MARK)) { + fset(rn, RF_MARK); + ql_push(&result, rn); + } + } } - } - for (ql=result,qi=0; ql; ql_advance(&ql, &qi, 1)) { - region *r = (region *)ql_get(ql, qi); - freset(r, RF_MARK); - } - return result; + for (ql = result, qi = 0; ql; ql_advance(&ql, &qi, 1)) { + region *r = (region *)ql_get(ql, qi); + freset(r, RF_MARK); + } + return result; } static void get_island_info(region * root, int *size_p, int *inhabited_p, int *maxage_p) { - int qi, size = 0, maxage = 0, inhabited = 0; - quicklist *ql, *island = NULL; - - ql_push(&island, root); - fset(root, RF_MARK); + int qi, size = 0, maxage = 0, inhabited = 0; + quicklist *ql, *island = NULL; - for (ql=island,qi=0; ql; ql_advance(&ql, &qi, 1)) { - int d; - region *r = (region *)ql_get(ql, qi); - if (r->units) { - unit *u; - for (u = r->units; u; u = u->next) { - if (!fval(u->faction, FFL_NOIDLEOUT) && u->faction->age > maxage) { - maxage = u->faction->age; + ql_push(&island, root); + fset(root, RF_MARK); + + for (ql = island, qi = 0; ql; ql_advance(&ql, &qi, 1)) { + int d; + region *r = (region *)ql_get(ql, qi); + if (r->units) { + unit *u; + for (u = r->units; u; u = u->next) { + if (!fval(u->faction, FFL_NOIDLEOUT) && u->faction->age > maxage) { + maxage = u->faction->age; + } + } + ++inhabited; + } + ++size; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn = rconnect(r, d); + if (rn && !fval(rn, RF_MARK) && rn->land) { + ql_push(&island, rn); + fset(rn, RF_MARK); + } } - } - ++inhabited; } - ++size; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn = rconnect(r, d); - if (rn && !fval(rn, RF_MARK) && rn->land) { - ql_push(&island, rn); - fset(rn, RF_MARK); - } + for (ql = island, qi = 0; ql; ql_advance(&ql, &qi, 1)) { + region *r = (region *)ql_get(ql, qi); + freset(r, RF_MARK); } - } - for (ql=island,qi=0; ql; ql_advance(&ql, &qi, 1)) { - region *r = (region *)ql_get(ql, qi); - freset(r, RF_MARK); - } - ql_free(island); - if (size_p) - *size_p = size; - if (inhabited_p) - *inhabited_p = inhabited; - if (maxage_p) - *maxage_p = maxage; + ql_free(island); + if (size_p) + *size_p = size; + if (inhabited_p) + *inhabited_p = inhabited; + if (maxage_p) + *maxage_p = maxage; } void free_newfaction(newfaction * nf) { - free(nf->email); - free(nf->password); - free(nf); + free(nf->email); + free(nf->password); + free(nf); } static void frame_regions(int age, const terrain_type * terrain) { - plane *hplane = get_homeplane(); - region *r = regions; - for (r = regions; r; r = r->next) { - plane *pl = rplane(r); - direction_t d; - if (r->age < age) - continue; - if (pl != hplane) - continue; /* only do this on the main world */ - if (r->terrain == terrain) - continue; + plane *hplane = get_homeplane(); + region *r = regions; + for (r = regions; r; r = r->next) { + plane *pl = rplane(r); + direction_t d; + if (r->age < age) + continue; + if (pl != hplane) + continue; /* only do this on the main world */ + if (r->terrain == terrain) + continue; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn = rconnect(r, d); - if (rn == NULL) { - int x = r->x + delta_x[d]; - int y = r->y + delta_y[d]; - pnormalize(&x, &y, pl); - rn = new_region(x, y, pl, 0); - terraform_region(rn, terrain); - rn->age = r->age; - } + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn = rconnect(r, d); + if (rn == NULL) { + int x = r->x + delta_x[d]; + int y = r->y + delta_y[d]; + pnormalize(&x, &y, pl); + rn = new_region(x, y, pl, 0); + terraform_region(rn, terrain); + rn->age = r->age; + } + } } - } } static void prepare_starting_region(region * r) { - int n, t; - double p; + int n, t; + double p; - assert(r->land); + assert(r->land); - /* population between 30% and 60% of max */ - p = rng_double(); - n = (int)(r->terrain->size * (0.3 + p * 0.3)); - rsetpeasants(r, n); + /* population between 30% and 60% of max */ + p = rng_double(); + n = (int)(r->terrain->size * (0.3 + p * 0.3)); + rsetpeasants(r, n); - /* trees: don't squash the peasants, and at least 5% should be forrest */ - t = (rtrees(r, 2) + rtrees(r, 1) / 2) * TREESIZE; - if (t < r->terrain->size / 20 || t + n > r->terrain->size) { - double p2 = 0.05 + rng_double() * (1.0 - p - 0.05); - int maxtrees = (int)(r->terrain->size / 1.25 / TREESIZE); /* 1.25 = each young tree will take 1/2 the space of old trees */ - int trees = (int)(p2 * maxtrees); + /* trees: don't squash the peasants, and at least 5% should be forrest */ + t = (rtrees(r, 2) + rtrees(r, 1) / 2) * TREESIZE; + if (t < r->terrain->size / 20 || t + n > r->terrain->size) { + double p2 = 0.05 + rng_double() * (1.0 - p - 0.05); + int maxtrees = (int)(r->terrain->size / 1.25 / TREESIZE); /* 1.25 = each young tree will take 1/2 the space of old trees */ + int trees = (int)(p2 * maxtrees); - rsettrees(r, 2, trees); - rsettrees(r, 1, trees / 2); - rsettrees(r, 0, trees / 4); - } + rsettrees(r, 2, trees); + rsettrees(r, 1, trees / 2); + rsettrees(r, 0, trees / 4); + } - /* horses: between 1% and 2% */ - p = rng_double(); - rsethorses(r, (int)(r->terrain->size * (0.01 + p * 0.01))); + /* horses: between 1% and 2% */ + p = rng_double(); + rsethorses(r, (int)(r->terrain->size * (0.01 + p * 0.01))); - if (!markets_module()) { - fix_demand(r); - } + if (!markets_module()) { + fix_demand(r); + } } /** create new island with up to nsize players @@ -505,551 +505,557 @@ static void prepare_starting_region(region * r) */ int autoseed(newfaction ** players, int nsize, int max_agediff) { - region *r = NULL; - region_list *rlist = NULL; - int rsize = 0, tsize = 0; - int isize = REGIONS_PER_FACTION; /* target size for the island */ - int psize = 0; /* players on this island */ - const terrain_type *volcano_terrain = get_terrain("volcano"); - static int nterrains = -1; - static const terrain_type **terrainarr = 0; - static int *distribution; + region *r = NULL; + region_list *rlist = NULL; + int rsize = 0, tsize = 0; + int isize = REGIONS_PER_FACTION; /* target size for the island */ + int psize = 0; /* players on this island */ + const terrain_type *volcano_terrain = get_terrain("volcano"); + static int nterrains = -1; + static const terrain_type **terrainarr = 0; + static int *distribution; - assert(players); - if (nterrains < 0) { - int n = 0; - const terrain_type *terrain = terrains(); - for (nterrains = 0; terrain; terrain = terrain->next) { - if (terrain->distribution) { - ++nterrains; - } - } - terrainarr = malloc(sizeof(terrain_type *) * nterrains); - distribution = malloc(sizeof(int) * nterrains); - for (terrain = terrains(); terrain; terrain = terrain->next) { - if (terrain->distribution) { - terrainarr[n] = terrain; - distribution[n++] = terrain->distribution; - } - } - } - frame_regions(16, newterrain(T_FIREWALL)); - - if (listlen(*players) < MINFACTIONS) - return 0; - - if (max_agediff > 0) { - region *rmin = NULL; - plane *hplane = get_homeplane(); - /* find a spot that's adjacent to the previous island, but virgin. - * like the last land virgin ocean region adjacent to land. - */ - for (r = regions; r; r = r->next) { - struct plane *pl = rplane(r); - if (r->age <= max_agediff && r->terrain == newterrain(T_OCEAN) - && pl == hplane && virgin_region(r)) { - direction_t d; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn = rconnect(r, d); - if (rn && rn->land && rn->age <= max_agediff && virgin_region(rn)) { - /* only expand islands that aren't single-islands and not too big already */ - int size, inhabitants, maxage; - get_island_info(rn, &size, &inhabitants, &maxage); - if (maxage <= max_agediff && size >= 2 && size < MAXISLANDSIZE) { - rmin = rn; - break; + assert(players); + if (nterrains < 0) { + int n = 0; + const terrain_type *terrain = terrains(); + for (nterrains = 0; terrain; terrain = terrain->next) { + if (terrain->distribution) { + ++nterrains; + } + } + terrainarr = malloc(sizeof(terrain_type *) * nterrains); + distribution = malloc(sizeof(int) * nterrains); + for (terrain = terrains(); terrain; terrain = terrain->next) { + if (terrain->distribution) { + terrainarr[n] = terrain; + distribution[n++] = terrain->distribution; } - } } - } } - if (rmin != NULL) { - faction *f; - quicklist *ql, *rlist = get_island(rmin); - int qi; + frame_regions(16, newterrain(T_FIREWALL)); - for (ql=rlist,qi=0;ql;ql_advance(&ql, &qi, 1)) { - region *r = (region *)ql_get(ql, qi); - unit *u; - for (u = r->units; u; u = u->next) { - f = u->faction; - if (!fval(f, FFL_MARK)) { - ++psize; - fset(f, FFL_MARK); - } + if (listlen(*players) < MINFACTIONS) + return 0; + + if (max_agediff > 0) { + region *rmin = NULL; + plane *hplane = get_homeplane(); + /* find a spot that's adjacent to the previous island, but virgin. + * like the last land virgin ocean region adjacent to land. + */ + for (r = regions; r; r = r->next) { + struct plane *pl = rplane(r); + if (r->age <= max_agediff && r->terrain == newterrain(T_OCEAN) + && pl == hplane && virgin_region(r)) { + direction_t d; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn = rconnect(r, d); + if (rn && rn->land && rn->age <= max_agediff && virgin_region(rn)) { + /* only expand islands that aren't single-islands and not too big already */ + int size, inhabitants, maxage; + get_island_info(rn, &size, &inhabitants, &maxage); + if (maxage <= max_agediff && size >= 2 && size < MAXISLANDSIZE) { + rmin = rn; + break; + } + } + } + } } - } - ql_free(rlist); - if (psize > 0) { - for (f = factions; f; f = f->next) { - freset(f, FFL_MARK); + if (rmin != NULL) { + faction *f; + quicklist *ql, *rlist = get_island(rmin); + int qi; + + for (ql = rlist, qi = 0; ql; ql_advance(&ql, &qi, 1)) { + region *r = (region *)ql_get(ql, qi); + unit *u; + for (u = r->units; u; u = u->next) { + f = u->faction; + if (!fval(f, FFL_MARK)) { + ++psize; + fset(f, FFL_MARK); + } + } + } + ql_free(rlist); + if (psize > 0) { + for (f = factions; f; f = f->next) { + freset(f, FFL_MARK); + } + } + if (psize < PLAYERS_PER_ISLAND) { + r = rmin; + } } - } - if (psize < PLAYERS_PER_ISLAND) { - r = rmin; - } } - } - if (r == NULL) { - region *rmin = NULL; - direction_t dmin = MAXDIRECTIONS; - plane *hplane = get_homeplane(); - /* find an empty spot. - * rmin = the youngest ocean region that has a missing neighbour - * dmin = direction in which it's empty - */ - for (r = regions; r; r = r->next) { - struct plane *pl = rplane(r); - if (r->terrain == newterrain(T_OCEAN) && pl == hplane && (rmin == NULL - || r->age <= max_agediff)) { + if (r == NULL) { + region *rmin = NULL; + direction_t dmin = MAXDIRECTIONS; + plane *hplane = get_homeplane(); + /* find an empty spot. + * rmin = the youngest ocean region that has a missing neighbour + * dmin = direction in which it's empty + */ + for (r = regions; r; r = r->next) { + struct plane *pl = rplane(r); + if (r->terrain == newterrain(T_OCEAN) && pl == hplane && (rmin == NULL + || r->age <= max_agediff)) { + direction_t d; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn = rconnect(r, d); + if (rn == NULL) + break; + } + if (d != MAXDIRECTIONS) { + rmin = r; + dmin = d; + } + } + } + + /* create a new region where we found the empty spot, and make it the first + * in our island. island regions are kept in rlist, so only new regions can + * get populated, and old regions are not overwritten */ + if (rmin != NULL) { + plane *pl = rplane(rmin); + int x = rmin->x + delta_x[dmin]; + int y = rmin->y + delta_y[dmin]; + pnormalize(&x, &y, pl); + assert(virgin_region(rconnect(rmin, dmin))); + r = new_region(x, y, pl, 0); + terraform_region(r, newterrain(T_OCEAN)); + } + } + if (r != NULL) { + add_regionlist(&rlist, r); + fset(r, RF_MARK); + rsize = 1; + } + + while (rsize && (nsize || isize >= REGIONS_PER_FACTION)) { + int i = rng_int() % rsize; + region_list **rnext = &rlist; + region_list *rfind; direction_t d; + while (i--) + rnext = &(*rnext)->next; + rfind = *rnext; + r = rfind->data; + freset(r, RF_MARK); + *rnext = rfind->next; + free(rfind); + --rsize; for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn = rconnect(r, d); - if (rn == NULL) - break; + region *rn = rconnect(r, d); + if (rn && fval(rn, RF_MARK)) + continue; + if (rn == NULL) { + plane *pl = rplane(r); + int x = r->x + delta_x[d]; + int y = r->y + delta_y[d]; + pnormalize(&x, &y, pl); + rn = new_region(x, y, pl, 0); + terraform_region(rn, newterrain(T_OCEAN)); + } + if (virgin_region(rn)) { + add_regionlist(&rlist, rn); + fset(rn, RF_MARK); + ++rsize; + } } - if (d != MAXDIRECTIONS) { - rmin = r; - dmin = d; + if (volcano_terrain != NULL && (rng_int() % VOLCANO_CHANCE == 0)) { + terraform_region(r, volcano_terrain); + } + else if (nsize && (rng_int() % isize == 0 || rsize == 0)) { + newfaction **nfp, *nextf = *players; + faction *f; + unit *u; + + isize += REGIONS_PER_FACTION; + terraform_region(r, preferred_terrain(nextf->race)); + prepare_starting_region(r); + ++tsize; + assert(r->land && r->units == 0); + u = addplayer(r, addfaction(nextf->email, nextf->password, nextf->race, + nextf->lang, nextf->subscription)); + f = u->faction; + fset(f, FFL_ISNEW); + f->alliance = nextf->allies; + + /* remove duplicate email addresses */ + nfp = &nextf->next; + while (*nfp) { + newfaction *nf = *nfp; + if (strcmp(nextf->email, nf->email) == 0) { + *nfp = nf->next; + free_newfaction(nf); + } + else + nfp = &nf->next; + } + *players = nextf->next; + free_newfaction(nextf); + + ++psize; + --nsize; + --isize; + if (psize >= PLAYERS_PER_ISLAND) + break; + } + else { + terraform_region(r, random_terrain(terrainarr, distribution, nterrains)); + --isize; } - } } - /* create a new region where we found the empty spot, and make it the first - * in our island. island regions are kept in rlist, so only new regions can - * get populated, and old regions are not overwritten */ - if (rmin != NULL) { - plane *pl = rplane(rmin); - int x = rmin->x + delta_x[dmin]; - int y = rmin->y + delta_y[dmin]; - pnormalize(&x, &y, pl); - assert(virgin_region(rconnect(rmin, dmin))); - r = new_region(x, y, pl, 0); - terraform_region(r, newterrain(T_OCEAN)); + if (nsize != 0) { + log_error( + ("Could not place all factions on the same island as requested\n")); } - } - if (r != NULL) { - add_regionlist(&rlist, r); - fset(r, RF_MARK); - rsize = 1; - } - while (rsize && (nsize || isize >= REGIONS_PER_FACTION)) { - int i = rng_int() % rsize; - region_list **rnext = &rlist; - region_list *rfind; - direction_t d; - while (i--) - rnext = &(*rnext)->next; - rfind = *rnext; - r = rfind->data; - freset(r, RF_MARK); - *rnext = rfind->next; - free(rfind); - --rsize; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn = rconnect(r, d); - if (rn && fval(rn, RF_MARK)) - continue; - if (rn == NULL) { - plane *pl = rplane(r); - int x = r->x + delta_x[d]; - int y = r->y + delta_y[d]; - pnormalize(&x, &y, pl); - rn = new_region(x, y, pl, 0); - terraform_region(rn, newterrain(T_OCEAN)); - } - if (virgin_region(rn)) { - add_regionlist(&rlist, rn); - fset(rn, RF_MARK); - ++rsize; - } - } - if (volcano_terrain != NULL && (rng_int() % VOLCANO_CHANCE == 0)) { - terraform_region(r, volcano_terrain); - } else if (nsize && (rng_int() % isize == 0 || rsize == 0)) { - newfaction **nfp, *nextf = *players; - faction *f; - unit *u; - - isize += REGIONS_PER_FACTION; - terraform_region(r, preferred_terrain(nextf->race)); - prepare_starting_region(r); - ++tsize; - assert(r->land && r->units == 0); - u = addplayer(r, addfaction(nextf->email, nextf->password, nextf->race, - nextf->lang, nextf->subscription)); - f = u->faction; - fset(f, FFL_ISNEW); - f->alliance = nextf->allies; - - /* remove duplicate email addresses */ - nfp = &nextf->next; - while (*nfp) { - newfaction *nf = *nfp; - if (strcmp(nextf->email, nf->email) == 0) { - *nfp = nf->next; - free_newfaction(nf); - } else - nfp = &nf->next; - } - *players = nextf->next; - free_newfaction(nextf); - - ++psize; - --nsize; - --isize; - if (psize >= PLAYERS_PER_ISLAND) - break; - } else { - terraform_region(r, random_terrain(terrainarr, distribution, nterrains)); - --isize; - } - } - - if (nsize != 0) { - log_error( - ("Could not place all factions on the same island as requested\n")); - } - - if (rlist) { + if (rlist) { #define MINOCEANDIST 3 #define MAXOCEANDIST 6 #define MAXFILLDIST 10 #define SPECIALCHANCE 80 - region_list **rbegin = &rlist; - int special = 1; - int oceandist = MINOCEANDIST + (rng_int() % (MAXOCEANDIST - MINOCEANDIST)); - while (oceandist--) { - region_list **rend = rbegin; - while (*rend) - rend = &(*rend)->next; - while (rbegin != rend) { - direction_t d; - region *r = (*rbegin)->data; - rbegin = &(*rbegin)->next; - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn = rconnect(r, d); - if (rn == NULL) { - const struct terrain_type *terrain = newterrain(T_OCEAN); - plane *pl = rplane(r); - int x = r->x + delta_x[d]; - int y = r->y + delta_y[d]; - pnormalize(&x, &y, pl); - rn = new_region(x, y, pl, 0); - if (rng_int() % SPECIALCHANCE < special) { - terrain = random_terrain(terrainarr, distribution, nterrains); - special = SPECIALCHANCE / 3; /* 33% chance auf noch eines */ - } else { - special = 1; + region_list **rbegin = &rlist; + int special = 1; + int oceandist = MINOCEANDIST + (rng_int() % (MAXOCEANDIST - MINOCEANDIST)); + while (oceandist--) { + region_list **rend = rbegin; + while (*rend) + rend = &(*rend)->next; + while (rbegin != rend) { + direction_t d; + region *r = (*rbegin)->data; + rbegin = &(*rbegin)->next; + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn = rconnect(r, d); + if (rn == NULL) { + const struct terrain_type *terrain = newterrain(T_OCEAN); + plane *pl = rplane(r); + int x = r->x + delta_x[d]; + int y = r->y + delta_y[d]; + pnormalize(&x, &y, pl); + rn = new_region(x, y, pl, 0); + if (rng_int() % SPECIALCHANCE < special) { + terrain = random_terrain(terrainarr, distribution, nterrains); + special = SPECIALCHANCE / 3; /* 33% chance auf noch eines */ + } + else { + special = 1; + } + terraform_region(rn, terrain); + /* the new region has an extra 20% chance to have mallorn */ + if (rng_int() % 100 < 20) + fset(r, RF_MALLORN); + add_regionlist(rend, rn); + } + } } - terraform_region(rn, terrain); - /* the new region has an extra 20% chance to have mallorn */ - if (rng_int() % 100 < 20) - fset(r, RF_MALLORN); - add_regionlist(rend, rn); - } - } - } - } - while (*rbegin) { - region *r = (*rbegin)->data; - plane *pl = rplane(r); - direction_t d; - rbegin = &(*rbegin)->next; - for (d = 0; d != MAXDIRECTIONS; ++d) - if (rconnect(r, d) == NULL) { - int i; - for (i = 1; i != MAXFILLDIST; ++i) { - int x = r->x + delta_x[d] * i; - int y = r->y + delta_y[d] * i; - pnormalize(&x, &y, pl); - if (findregion(x, y)) { - break; - } - } - if (i != MAXFILLDIST) { - while (--i) { - region *rn; - int x = r->x + delta_x[d] * i; - int y = r->y + delta_y[d] * i; - pnormalize(&x, &y, pl); - rn = new_region(x, y, pl, 0); - terraform_region(rn, newterrain(T_OCEAN)); - } - } + } + while (*rbegin) { + region *r = (*rbegin)->data; + plane *pl = rplane(r); + direction_t d; + rbegin = &(*rbegin)->next; + for (d = 0; d != MAXDIRECTIONS; ++d) + if (rconnect(r, d) == NULL) { + int i; + for (i = 1; i != MAXFILLDIST; ++i) { + int x = r->x + delta_x[d] * i; + int y = r->y + delta_y[d] * i; + pnormalize(&x, &y, pl); + if (findregion(x, y)) { + break; + } + } + if (i != MAXFILLDIST) { + while (--i) { + region *rn; + int x = r->x + delta_x[d] * i; + int y = r->y + delta_y[d] * i; + pnormalize(&x, &y, pl); + rn = new_region(x, y, pl, 0); + terraform_region(rn, newterrain(T_OCEAN)); + } + } + } + } + while (rlist) { + region_list *self = rlist; + rlist = rlist->next; + freset(self->data, RF_MARK); + free(self); } } - while (rlist) { - region_list *self = rlist; - rlist = rlist->next; - freset(self->data, RF_MARK); - free(self); - } - } - return tsize; + return tsize; } region_list *regionqueue_push(region_list ** rlist, region * r) { - region_list *rnew = malloc(sizeof(region_list)); - rnew->data = r; - rnew->next = 0; - while (*rlist) { - rlist = &(*rlist)->next; - } - *rlist = rnew; - return rnew; + region_list *rnew = malloc(sizeof(region_list)); + rnew->data = r; + rnew->next = 0; + while (*rlist) { + rlist = &(*rlist)->next; + } + *rlist = rnew; + return rnew; } region *regionqueue_pop(region_list ** rlist) { - if (*rlist) { - region *r = (*rlist)->data; - region_list *rpop = *rlist; - *rlist = rpop->next; - free(rpop); - return r; - } - return 0; + if (*rlist) { + region *r = (*rlist)->data; + region_list *rpop = *rlist; + *rlist = rpop->next; + free(rpop); + return r; + } + return 0; } #define GEOMAX 8 static struct geo { - int distribution; - terrain_t type; + int distribution; + terrain_t type; } geography_e3[GEOMAX] = { - { - 8, T_OCEAN}, { - 3, T_SWAMP}, { - 1, T_VOLCANO}, { - 3, T_DESERT}, { - 4, T_HIGHLAND}, { - 3, T_MOUNTAIN}, { - 2, T_GLACIER}, { - 1, T_PLAIN} + { + 8, T_OCEAN }, { + 3, T_SWAMP }, { + 1, T_VOLCANO }, { + 3, T_DESERT }, { + 4, T_HIGHLAND }, { + 3, T_MOUNTAIN }, { + 2, T_GLACIER }, { + 1, T_PLAIN } }; const terrain_type *random_terrain_e3(direction_t dir) { - static const terrain_type **terrainarr = 0; - static int *distribution = 0; + static const terrain_type **terrainarr = 0; + static int *distribution = 0; - if (!distribution) { - int n = 0; + if (!distribution) { + int n = 0; - terrainarr = malloc(GEOMAX * sizeof(const terrain_type *)); - distribution = malloc(GEOMAX * sizeof(int)); - for (n = 0; n != GEOMAX; ++n) { - terrainarr[n] = newterrain(geography_e3[n].type); - distribution[n] = geography_e3[n].distribution; + terrainarr = malloc(GEOMAX * sizeof(const terrain_type *)); + distribution = malloc(GEOMAX * sizeof(int)); + for (n = 0; n != GEOMAX; ++n) { + terrainarr[n] = newterrain(geography_e3[n].type); + distribution[n] = geography_e3[n].distribution; + } } - } - return random_terrain(terrainarr, distribution, GEOMAX); + return random_terrain(terrainarr, distribution, GEOMAX); } int random_neighbours(region * r, region_list ** rlist, - const terrain_type * (*terraformer) (direction_t)) +const terrain_type * (*terraformer) (direction_t)) { - int nsize = 0; - direction_t dir; - for (dir = 0; dir != MAXDIRECTIONS; ++dir) { - region *rn = rconnect(r, dir); - if (rn == NULL) { - const terrain_type *terrain = terraformer(dir); - plane *pl = rplane(r); - int x = r->x + delta_x[dir]; - int y = r->y + delta_y[dir]; - pnormalize(&x, &y, pl); - rn = new_region(x, y, pl, 0); - terraform_region(rn, terrain); - regionqueue_push(rlist, rn); - if (rn->land) { - ++nsize; - } + int nsize = 0; + direction_t dir; + for (dir = 0; dir != MAXDIRECTIONS; ++dir) { + region *rn = rconnect(r, dir); + if (rn == NULL) { + const terrain_type *terrain = terraformer(dir); + plane *pl = rplane(r); + int x = r->x + delta_x[dir]; + int y = r->y + delta_y[dir]; + pnormalize(&x, &y, pl); + rn = new_region(x, y, pl, 0); + terraform_region(rn, terrain); + regionqueue_push(rlist, rn); + if (rn->land) { + ++nsize; + } + } } - } - return nsize; + return nsize; } const terrain_type *get_ocean(direction_t dir) { - return newterrain(T_OCEAN); + return newterrain(T_OCEAN); } int region_quality(const region * r, region * rn[]) { - int n, result = 0; + int n, result = 0; - for (n = 0; n != MAXDIRECTIONS; ++n) { - if (rn[n] && rn[n]->land) { - if (rn[n]->terrain == newterrain(T_VOLCANO)) { - /* nobody likes volcanoes */ - result -= 2000; - } - result += rn[n]->land->peasants; + for (n = 0; n != MAXDIRECTIONS; ++n) { + if (rn[n] && rn[n]->land) { + if (rn[n]->terrain == newterrain(T_VOLCANO)) { + /* nobody likes volcanoes */ + result -= 2000; + } + result += rn[n]->land->peasants; + } } - } - return result; + return result; } static void oceans_around(region * r, region * rn[]) { - int n; - for (n = 0; n != MAXDIRECTIONS; ++n) { - region *rx = rn[n]; - if (rx == NULL) { - plane *pl = rplane(r); - int x = r->x + delta_x[n]; - int y = r->y + delta_y[n]; - pnormalize(&x, &y, pl); - rx = new_region(x, y, pl, 0); - terraform_region(rx, newterrain(T_OCEAN)); - rn[n] = rx; + int n; + for (n = 0; n != MAXDIRECTIONS; ++n) { + region *rx = rn[n]; + if (rx == NULL) { + plane *pl = rplane(r); + int x = r->x + delta_x[n]; + int y = r->y + delta_y[n]; + pnormalize(&x, &y, pl); + rx = new_region(x, y, pl, 0); + terraform_region(rx, newterrain(T_OCEAN)); + rn[n] = rx; + } } - } } #define SWAP_INTS(a, b) { a^=b; b^=a; a^=b; } static void smooth_island(region_list * island) { - region *rn[MAXDIRECTIONS]; - region_list *rlist = NULL; - for (rlist = island; rlist; rlist = rlist->next) { - region *r = rlist->data; - int n, nland = 0; + region *rn[MAXDIRECTIONS]; + region_list *rlist = NULL; + for (rlist = island; rlist; rlist = rlist->next) { + region *r = rlist->data; + int n, nland = 0; - if (r->land) { - get_neighbours(r, rn); - for (n = 0; n != MAXDIRECTIONS && nland <= 1; ++n) { - if (rn[n]->land) { - ++nland; - r = rn[n]; - } - } + if (r->land) { + get_neighbours(r, rn); + for (n = 0; n != MAXDIRECTIONS && nland <= 1; ++n) { + if (rn[n]->land) { + ++nland; + r = rn[n]; + } + } - if (nland == 1) { - get_neighbours(r, rn); - oceans_around(r, rn); - for (n = 0; n != MAXDIRECTIONS; ++n) { - int n1 = (n + 1) % MAXDIRECTIONS; - int n2 = (n + 1 + MAXDIRECTIONS) % MAXDIRECTIONS; - if (!rn[n]->land && rn[n1] != r && rn[n2] != r) { - r = rlist->data; - runhash(r); - runhash(rn[n]); - SWAP_INTS(r->x, rn[n]->x); - SWAP_INTS(r->y, rn[n]->y); - rhash(r); - rhash(rn[n]); - rlist->data = r; - oceans_around(r, rn); - break; - } + if (nland == 1) { + get_neighbours(r, rn); + oceans_around(r, rn); + for (n = 0; n != MAXDIRECTIONS; ++n) { + int n1 = (n + 1) % MAXDIRECTIONS; + int n2 = (n + 1 + MAXDIRECTIONS) % MAXDIRECTIONS; + if (!rn[n]->land && rn[n1] != r && rn[n2] != r) { + r = rlist->data; + runhash(r); + runhash(rn[n]); + SWAP_INTS(r->x, rn[n]->x); + SWAP_INTS(r->y, rn[n]->y); + rhash(r); + rhash(rn[n]); + rlist->data = r; + oceans_around(r, rn); + break; + } + } + } } - } } - } } static void starting_region(region * r, region * rn[]) { - int n; + int n; - oceans_around(r, rn); - freset(r, RF_MARK); - for (n = 0; n != MAXDIRECTIONS; ++n) { - freset(rn[n], RF_MARK); - } - terraform_region(r, newterrain(T_PLAIN)); - prepare_starting_region(r); - addplayer(r, addfaction("enno@eressea.de", itoa36(rng_int()), races, default_locale, 0)); + oceans_around(r, rn); + freset(r, RF_MARK); + for (n = 0; n != MAXDIRECTIONS; ++n) { + freset(rn[n], RF_MARK); + } + terraform_region(r, newterrain(T_PLAIN)); + prepare_starting_region(r); + addplayer(r, addfaction("enno@eressea.de", itoa36(rng_int()), races, default_locale, 0)); } /* E3A island generation */ int build_island_e3(int x, int y, int numfactions, int minsize) { #define MIN_QUALITY 1000 - int nfactions = 0; - region_list *rlist = NULL; - region_list *island = NULL; - plane *pl = findplane(x, y); - region *r = findregion(x, y); - int nsize = 1; - int q, maxq = INT_MIN, minq = INT_MAX; + int nfactions = 0; + region_list *rlist = NULL; + region_list *island = NULL; + plane *pl = findplane(x, y); + region *r = findregion(x, y); + int nsize = 1; + int q, maxq = INT_MIN, minq = INT_MAX; - if (!r) - r = new_region(x, y, pl, 0); - assert(!r->units); - do { - terraform_region(r, random_terrain_e3(NODIRECTION)); - } while (!r->land); + if (!r) + r = new_region(x, y, pl, 0); + assert(!r->units); + do { + terraform_region(r, random_terrain_e3(NODIRECTION)); + } while (!r->land); - while (r) { - fset(r, RF_MARK); - if (r->land) { - if (nsize < minsize) { - nsize += random_neighbours(r, &rlist, &random_terrain_e3); - } else { - nsize += random_neighbours(r, &rlist, &get_ocean); - } + while (r) { + fset(r, RF_MARK); + if (r->land) { + if (nsize < minsize) { + nsize += random_neighbours(r, &rlist, &random_terrain_e3); + } + else { + nsize += random_neighbours(r, &rlist, &get_ocean); + } + } + regionqueue_push(&island, r); + r = regionqueue_pop(&rlist); } - regionqueue_push(&island, r); - r = regionqueue_pop(&rlist); - } - smooth_island(island); + smooth_island(island); + + if (nsize > minsize / 2) { + for (rlist = island; rlist; rlist = rlist->next) { + r = rlist->data; + if (r->land && fval(r, RF_MARK)) { + region *rn[MAXDIRECTIONS]; + + get_neighbours(r, rn); + q = region_quality(r, rn); + if (q >= MIN_QUALITY && nfactions < numfactions) { + starting_region(r, rn); + minq = _min(minq, q); + maxq = _max(maxq, q); + ++nfactions; + } + } + } + + for (rlist = island; rlist && nfactions < numfactions; rlist = rlist->next) { + r = rlist->data; + if (!r->land && fval(r, RF_MARK)) { + region *rn[MAXDIRECTIONS]; + get_neighbours(r, rn); + q = region_quality(r, rn); + if (q >= MIN_QUALITY * 4 / 3 && nfactions < numfactions) { + starting_region(r, rn); + minq = _min(minq, q); + maxq = _max(maxq, q); + ++nfactions; + } + } + } + } - if (nsize > minsize / 2) { for (rlist = island; rlist; rlist = rlist->next) { - r = rlist->data; - if (r->land && fval(r, RF_MARK)) { - region *rn[MAXDIRECTIONS]; - - get_neighbours(r, rn); - q = region_quality(r, rn); - if (q >= MIN_QUALITY && nfactions < numfactions) { - starting_region(r, rn); - minq = _min(minq, q); - maxq = _max(maxq, q); - ++nfactions; + r = rlist->data; + if (r->units) { + region *rn[MAXDIRECTIONS]; + get_neighbours(r, rn); + q = region_quality(r, rn); + if (q - minq > (maxq - minq) * 2 / 3) { + terraform_region(r, newterrain(T_HIGHLAND)); + prepare_starting_region(r); + } + r->land->money = 50000; /* 2% = 1000 silver */ } - } - } - - for (rlist = island; rlist && nfactions < numfactions; rlist = rlist->next) { - r = rlist->data; - if (!r->land && fval(r, RF_MARK)) { - region *rn[MAXDIRECTIONS]; - get_neighbours(r, rn); - q = region_quality(r, rn); - if (q >= MIN_QUALITY * 4 / 3 && nfactions < numfactions) { - starting_region(r, rn); - minq = _min(minq, q); - maxq = _max(maxq, q); - ++nfactions; + else if (r->land) { + r->land->money *= 4; } - } } - } - - for (rlist = island; rlist; rlist = rlist->next) { - r = rlist->data; - if (r->units) { - region *rn[MAXDIRECTIONS]; - get_neighbours(r, rn); - q = region_quality(r, rn); - if (q - minq > (maxq - minq) * 2 / 3) { - terraform_region(r, newterrain(T_HIGHLAND)); - prepare_starting_region(r); - } - r->land->money = 50000; /* 2% = 1000 silver */ - } else if (r->land) { - r->land->money *= 4; - } - } - return nfactions; + return nfactions; }