diff --git a/src/attributes/attributes.c b/src/attributes/attributes.c index 37c7418dc..e9990397d 100644 --- a/src/attributes/attributes.c +++ b/src/attributes/attributes.c @@ -54,6 +54,7 @@ attrib_type at_unitdissolve = { void register_attributes(void) { + at_deprecate("gm", a_readint); at_register(&at_stealth); at_register(&at_object); at_register(&at_unitdissolve); @@ -61,7 +62,6 @@ void register_attributes(void) at_register(&at_raceprefix); at_register(&at_iceberg); at_register(&at_key); - at_deprecate("gm", a_readint); at_register(&at_follow); at_register(&at_targetregion); at_register(&at_orcification); @@ -69,6 +69,7 @@ void register_attributes(void) at_register(&at_reduceproduction); at_register(&at_otherfaction); at_register(&at_racename); + at_register(&at_speedup); at_register(&at_movement); at_register(&at_moved); } diff --git a/src/attributes/movement.c b/src/attributes/movement.c index 4a393ed97..ff206ecfd 100644 --- a/src/attributes/movement.c +++ b/src/attributes/movement.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "movement.h" +#include #include #include @@ -60,3 +61,20 @@ void set_movement(attrib ** alist, int type) a = a_add(alist, a_new(&at_movement)); a->data.i |= type; } + +static int age_speedup(attrib * a) +{ + if (a->data.sa[0] > 0) { + a->data.sa[0] = a->data.sa[0] - a->data.sa[1]; + } + return (a->data.sa[0] > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; +} + +attrib_type at_speedup = { + "speedup", + NULL, NULL, + age_speedup, + a_writeint, + a_readint +}; + diff --git a/src/attributes/movement.h b/src/attributes/movement.h index 0fe4cfc83..86fe32b02 100644 --- a/src/attributes/movement.h +++ b/src/attributes/movement.h @@ -22,11 +22,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif - extern bool get_movement(struct attrib *const *alist, int type); - extern void set_movement(struct attrib **alist, int type); + bool get_movement(struct attrib *const *alist, int type); + void set_movement(struct attrib **alist, int type); extern struct attrib_type at_movement; - + extern struct attrib_type at_speedup; + #ifdef __cplusplus } #endif diff --git a/src/chaos.c b/src/chaos.c index 476c36f67..24ee6d0b1 100644 --- a/src/chaos.c +++ b/src/chaos.c @@ -156,20 +156,20 @@ static void chaos(region * r) case 0: mfac = 100; u = - createunit(r, get_monsters(), rng_int() % 8 + 1, - get_race(RC_FIREDRAGON)); + create_unit(r, get_monsters(), rng_int() % 8 + 1, + get_race(RC_FIREDRAGON), 0, NULL, NULL); break; case 1: mfac = 500; u = - createunit(r, get_monsters(), rng_int() % 4 + 1, - get_race(RC_DRAGON)); + create_unit(r, get_monsters(), rng_int() % 4 + 1, + get_race(RC_DRAGON), 0, NULL, NULL); break; default: mfac = 1000; u = - createunit(r, get_monsters(), rng_int() % 2 + 1, - get_race(RC_WYRM)); + create_unit(r, get_monsters(), rng_int() % 2 + 1, + get_race(RC_WYRM), 0, NULL, NULL); break; } if (mfac) 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/items/speedsail.c b/src/items/speedsail.c index 8f76cca00..5ae691b64 100644 --- a/src/items/speedsail.c +++ b/src/items/speedsail.c @@ -29,7 +29,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include +#include /* util includes */ #include diff --git a/src/kernel/config.c b/src/kernel/config.c index db55b8976..c7fa16fff 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -26,10 +26,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "alliance.h" #include "ally.h" #include "alchemy.h" +#include "curse.h" #include "connection.h" #include "building.h" #include "calendar.h" -#include "curse.h" #include "direction.h" #include "faction.h" #include "group.h" @@ -442,117 +442,8 @@ int verbosity = 1; FILE *debug; -static int ShipSpeedBonus(const unit * u) -{ - static int level = -1; - if (level == -1) { - level = - get_param_int(global.parameters, "movement.shipspeed.skillbonus", 0); - } - if (level > 0) { - ship *sh = u->ship; - int skl = effskill(u, SK_SAILING); - int minsk = (sh->type->cptskill + 1) / 2; - return (skl - minsk) / level; - } - return 0; -} - -int shipspeed(const ship * sh, const unit * u) -{ - double k = sh->type->range; - static const curse_type *stormwind_ct, *nodrift_ct; - static bool init; - attrib *a; - curse *c; - - if (!init) { - init = true; - stormwind_ct = ct_find("stormwind"); - nodrift_ct = ct_find("nodrift"); - } - - assert(u->ship == sh); - assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ - if (sh->size != sh->type->construction->maxsize) - return 0; - - if (curse_active(get_curse(sh->attribs, stormwind_ct))) - k *= 2; - if (curse_active(get_curse(sh->attribs, nodrift_ct))) - k += 1; - - if (u->faction->race == u_race(u)) { - /* race bonus for this faction? */ - if (fval(u_race(u), RCF_SHIPSPEED)) { - k += 1; - } - } - - k += ShipSpeedBonus(u); - - a = a_find(sh->attribs, &at_speedup); - while (a != NULL && a->type == &at_speedup) { - k += a->data.sa[0]; - a = a->next; - } - - c = get_curse(sh->attribs, ct_find("shipspeedup")); - while (c) { - k += curse_geteffect(c); - c = c->nexthash; - } - -#ifdef SHIPSPEED - k *= SHIPSPEED; -#endif - - if (sh->damage) - k = - (k * (sh->size * DAMAGE_SCALE - sh->damage) + sh->size * DAMAGE_SCALE - - 1) / (sh->size * DAMAGE_SCALE); - - return (int)k; -} - /* ----------------------------------------------------------------------- */ -void verify_data(void) -{ -#ifndef NDEBUG - int lf = -1; - faction *f; - unit *u; - int mage, alchemist; - - if (verbosity >= 1) - puts(" - checking data for correctness..."); - - for (f = factions; f; f = f->next) { - mage = 0; - alchemist = 0; - for (u = f->units; u; u = u->nextF) { - if (eff_skill(u, SK_MAGIC, u->region)) { - mage += u->number; - } - if (eff_skill(u, SK_ALCHEMY, u->region)) - alchemist += u->number; - if (u->number > UNIT_MAXSIZE) { - if (lf != f->no) { - lf = f->no; - log_printf(stdout, "Partei %s:\n", factionid(f)); - } - log_warning("Einheit %s hat %d Personen\n", unitid(u), u->number); - } - } - if (f->no != 0 && ((mage > 3 && f->race != get_race(RC_ELF)) || mage > 4)) - log_error("Partei %s hat %d Magier.\n", factionid(f), mage); - if (alchemist > 3) - log_error("Partei %s hat %d Alchemisten.\n", factionid(f), alchemist); - } -#endif -} - int distribute(int old, int new_value, int n) { int i; @@ -570,23 +461,6 @@ int distribute(int old, int new_value, int n) return t; } -int change_hitpoints(unit * u, int value) -{ - int hp = u->hp; - - hp += value; - - /* Jede Person benötigt mindestens 1 HP */ - if (hp < u->number) { - if (hp < 0) { /* Einheit tot */ - hp = 0; - } - scale_number(u, hp); - } - u->hp = hp; - return hp; -} - bool unit_has_cursed_item(const unit * u) { item *itm = u->items; @@ -1030,12 +904,6 @@ int newcontainerid(void) return random_no; } -unit *createunit(region * r, faction * f, int number, const struct race * rc) -{ - assert(rc); - return create_unit(r, f, number, rc, 0, NULL, NULL); -} - bool idle(faction * f) { return (bool)(f ? false : true); @@ -1048,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); @@ -1305,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 = { @@ -1318,9 +1155,6 @@ attrib_type at_germs = { ATF_UNIQUE }; -/*********************/ -/* at_guard */ -/*********************/ attrib_type at_guard = { "guard", DEFAULT_INIT, @@ -1392,38 +1226,6 @@ bool faction_id_is_unused(int id) return findfaction(id) == NULL; } -int weight(const unit * u) -{ - int w = 0, n = 0, in_bag = 0; - const resource_type *rtype = get_resourcetype(R_BAG_OF_HOLDING); - item *itm; - - for (itm = u->items; itm; itm = itm->next) { - w = itm->type->weight * itm->number; - n += w; - if (rtype && !fval(itm->type, ITF_BIG)) { - in_bag += w; - } - } - - n += u->number * u_race(u)->weight; - - if (rtype) { - w = i_get(u->items, rtype->itype) * BAGCAPACITY; - if (w > in_bag) w = in_bag; - n -= w; - } - - return n; -} - -void make_undead_unit(unit * u) -{ - free_orders(&u->orders); - name_unit(u); - fset(u, UFL_ISNEW); -} - unsigned int guard_flags(const unit * u) { unsigned int flags = @@ -1816,7 +1618,6 @@ static int read_ext(attrib * a, void *owner, struct storage *store) void attrib_init(void) { /* Alle speicherbaren Attribute müssen hier registriert werden */ - at_register(&at_speedup); at_register(&at_shiptrail); at_register(&at_familiar); at_register(&at_familiarmage); diff --git a/src/kernel/config.h b/src/kernel/config.h index ea521d5c8..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) */ @@ -91,7 +92,6 @@ extern "C" { #define want(option) (1<units == NULL); set_ursprung(f, 0, r->x, r->y); - u = createunit(r, f, 1, f->race); + u = create_unit(r, f, 1, f->race, 0, NULL, NULL); equip_items(&u->faction->items, get_equipment("new_faction")); equip_unit(u, get_equipment("first_unit")); sprintf(buffer, "first_%s", u_race(u)->_name); 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..ca776aff9 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -274,20 +274,8 @@ int readorders(const char *filename) const char *s; init_tokens_str(b); s = gettoken(token, sizeof(token)); - p = s ? findparam(s, lang) : NOPARAM; + p = (s && s[0] != '@') ? findparam(s, lang) : NOPARAM; switch (p) { -#undef LOCALE_CHANGE -#ifdef LOCALE_CHANGE - case P_LOCALE: - { - const char *s = getstrtoken(); - if (f && get_locale(s)) { - f->locale = get_locale(s); - } - } - b = getbuf(F, enc_gamedata); - break; -#endif case P_GAMENAME: case P_FACTION: f = factionorders(); @@ -311,8 +299,8 @@ int readorders(const char *filename) break; } init_tokens_str(b); - b = getstrtoken(); - p = (!b || b[0] == '@') ? NOPARAM : findparam(b, lang); + s = gettoken(token, sizeof(token)); + p = (s && s[0] != '@') ? findparam(s, lang) : NOPARAM; } while ((p != P_UNIT || !f) && p != P_FACTION && p != P_NEXT && p != P_GAMENAME); break; @@ -1030,11 +1018,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/ship.c b/src/kernel/ship.c index 8f29737dd..afd3dc9f3 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.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 @@ -22,6 +22,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* kernel includes */ #include "build.h" +#include "curse.h" +#include "faction.h" #include "unit.h" #include "item.h" #include "race.h" @@ -39,6 +41,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include + #include /* libc includes */ @@ -53,48 +57,48 @@ static local_names *snames; const ship_type *findshiptype(const char *name, const struct locale *lang) { - local_names *sn = snames; - variant var; + local_names *sn = snames; + variant var; - while (sn) { - if (sn->lang == lang) - break; - sn = sn->next; - } - if (!sn) { - quicklist *ql; - int qi; - - sn = (local_names *) calloc(sizeof(local_names), 1); - sn->next = snames; - sn->lang = lang; - - for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) { - ship_type *stype = (ship_type *) ql_get(ql, qi); - variant var2; - const char *n = locale_string(lang, stype->_name); - var2.v = (void *)stype; - addtoken(&sn->names, n, var2); + while (sn) { + if (sn->lang == lang) + break; + sn = sn->next; } - snames = sn; - } - if (findtoken(sn->names, name, &var) == E_TOK_NOMATCH) - return NULL; - return (const ship_type *)var.v; + if (!sn) { + quicklist *ql; + int qi; + + sn = (local_names *)calloc(sizeof(local_names), 1); + sn->next = snames; + sn->lang = lang; + + for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) { + ship_type *stype = (ship_type *)ql_get(ql, qi); + variant var2; + const char *n = locale_string(lang, stype->_name); + var2.v = (void *)stype; + addtoken(&sn->names, n, var2); + } + snames = sn; + } + if (findtoken(sn->names, name, &var) == E_TOK_NOMATCH) + return NULL; + return (const ship_type *)var.v; } static ship_type *st_find_i(const char *name) { - quicklist *ql; - int qi; + quicklist *ql; + int qi; - for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) { - ship_type *stype = (ship_type *) ql_get(ql, qi); - if (strcmp(stype->_name, name) == 0) { - return stype; + for (qi = 0, ql = shiptypes; ql; ql_advance(&ql, &qi, 1)) { + ship_type *stype = (ship_type *)ql_get(ql, qi); + if (strcmp(stype->_name, name) == 0) { + return stype; + } } - } - return NULL; + return NULL; } const ship_type *st_find(const char *name) { @@ -115,60 +119,60 @@ ship_type *st_get_or_create(const char * name) { ship *shiphash[MAXSHIPHASH]; void shash(ship * s) { - ship *old = shiphash[s->no % MAXSHIPHASH]; + ship *old = shiphash[s->no % MAXSHIPHASH]; - shiphash[s->no % MAXSHIPHASH] = s; - s->nexthash = old; + shiphash[s->no % MAXSHIPHASH] = s; + s->nexthash = old; } void sunhash(ship * s) { - ship **show; + ship **show; - for (show = &shiphash[s->no % MAXSHIPHASH]; *show; show = &(*show)->nexthash) { - if ((*show)->no == s->no) - break; - } - if (*show) { - assert(*show == s); - *show = (*show)->nexthash; - s->nexthash = 0; - } + for (show = &shiphash[s->no % MAXSHIPHASH]; *show; show = &(*show)->nexthash) { + if ((*show)->no == s->no) + break; + } + if (*show) { + assert(*show == s); + *show = (*show)->nexthash; + s->nexthash = 0; + } } static ship *sfindhash(int i) { - ship *old; + ship *old; - for (old = shiphash[i % MAXSHIPHASH]; old; old = old->nexthash) - if (old->no == i) - return old; - return 0; + for (old = shiphash[i % MAXSHIPHASH]; old; old = old->nexthash) + if (old->no == i) + return old; + return 0; } struct ship *findship(int i) { - return sfindhash(i); + return sfindhash(i); } struct ship *findshipr(const region * r, int n) { - ship *sh; + ship *sh; - for (sh = r->ships; sh; sh = sh->next) { - if (sh->no == n) { - assert(sh->region == r); - return sh; + for (sh = r->ships; sh; sh = sh->next) { + if (sh->no == n) { + assert(sh->region == r); + return sh; + } } - } - return 0; + return 0; } void damage_ship(ship * sh, double percent) { - double damage = - DAMAGE_SCALE * sh->type->damage * percent * sh->size + sh->damage; - sh->damage = (int)damage; + double damage = + DAMAGE_SCALE * sh->type->damage * percent * sh->size + sh->damage; + sh->damage = (int)damage; } /* Alte Schiffstypen: */ @@ -176,62 +180,62 @@ static ship *deleted_ships; ship *new_ship(const ship_type * stype, region * r, const struct locale *lang) { - static char buffer[32]; - ship *sh = (ship *) calloc(1, sizeof(ship)); - const char *sname = 0; + static char buffer[32]; + ship *sh = (ship *)calloc(1, sizeof(ship)); + const char *sname = 0; - assert(stype); - sh->no = newcontainerid(); - sh->coast = NODIRECTION; - sh->type = stype; - sh->region = r; + assert(stype); + sh->no = newcontainerid(); + sh->coast = NODIRECTION; + sh->type = stype; + sh->region = r; - sname = LOC(lang, stype->_name); - if (!sname) { - sname = LOC(lang, parameters[P_SHIP]); + sname = LOC(lang, stype->_name); if (!sname) { - sname = parameters[P_SHIP]; + sname = LOC(lang, parameters[P_SHIP]); + if (!sname) { + sname = parameters[P_SHIP]; + } } - } - assert(sname); - slprintf(buffer, sizeof(buffer), "%s %s", sname, shipid(sh)); - sh->name = _strdup(buffer); - shash(sh); - if (r) { - addlist(&r->ships, sh); - } - return sh; + assert(sname); + slprintf(buffer, sizeof(buffer), "%s %s", sname, shipid(sh)); + sh->name = _strdup(buffer); + shash(sh); + if (r) { + addlist(&r->ships, sh); + } + return sh; } void remove_ship(ship ** slist, ship * sh) { - region *r = sh->region; - unit *u = r->units; + region *r = sh->region; + unit *u = r->units; - handle_event(sh->attribs, "destroy", sh); - while (u) { - if (u->ship == sh) { - leave_ship(u); + handle_event(sh->attribs, "destroy", sh); + while (u) { + if (u->ship == sh) { + leave_ship(u); + } + u = u->next; } - u = u->next; - } - sunhash(sh); - while (*slist && *slist != sh) - slist = &(*slist)->next; - assert(*slist); - *slist = sh->next; - sh->next = deleted_ships; - deleted_ships = sh; - sh->region = NULL; + sunhash(sh); + while (*slist && *slist != sh) + slist = &(*slist)->next; + assert(*slist); + *slist = sh->next; + sh->next = deleted_ships; + deleted_ships = sh; + sh->region = NULL; } void free_ship(ship * s) { - while (s->attribs) - a_remove(&s->attribs, s->attribs); - free(s->name); - free(s->display); - free(s); + while (s->attribs) + a_remove(&s->attribs, s->attribs); + free(s->name); + free(s->display); + free(s); } void free_shiptypes(void) { @@ -242,121 +246,194 @@ void free_shiptypes(void) { void free_ships(void) { - while (deleted_ships) { - ship *s = deleted_ships; - deleted_ships = s->next; - } + while (deleted_ships) { + ship *s = deleted_ships; + deleted_ships = s->next; + } } const char *write_shipname(const ship * sh, char *ibuf, size_t size) { - slprintf(ibuf, size, "%s (%s)", sh->name, itoa36(sh->no)); - return ibuf; + slprintf(ibuf, size, "%s (%s)", sh->name, itoa36(sh->no)); + return ibuf; +} + +static int ShipSpeedBonus(const unit * u) +{ + static int level = -1; + if (level == -1) { + level = + get_param_int(global.parameters, "movement.shipspeed.skillbonus", 0); + } + if (level > 0) { + ship *sh = u->ship; + int skl = effskill(u, SK_SAILING); + int minsk = (sh->type->cptskill + 1) / 2; + return (skl - minsk) / level; + } + return 0; +} + +int shipspeed(const ship * sh, const unit * u) +{ + double k = sh->type->range; + static const struct curse_type *stormwind_ct, *nodrift_ct; + static bool init; + attrib *a; + struct curse *c; + + if (!init) { + init = true; + stormwind_ct = ct_find("stormwind"); + nodrift_ct = ct_find("nodrift"); + } + + assert(u->ship == sh); + assert(sh->type->construction->improvement == NULL); /* sonst ist construction::size nicht ship_type::maxsize */ + if (sh->size != sh->type->construction->maxsize) + return 0; + + if (curse_active(get_curse(sh->attribs, stormwind_ct))) + k *= 2; + if (curse_active(get_curse(sh->attribs, nodrift_ct))) + k += 1; + + if (u->faction->race == u_race(u)) { + /* race bonus for this faction? */ + if (fval(u_race(u), RCF_SHIPSPEED)) { + k += 1; + } + } + + k += ShipSpeedBonus(u); + + a = a_find(sh->attribs, &at_speedup); + while (a != NULL && a->type == &at_speedup) { + k += a->data.sa[0]; + a = a->next; + } + + c = get_curse(sh->attribs, ct_find("shipspeedup")); + while (c) { + k += curse_geteffect(c); + c = c->nexthash; + } + +#ifdef SHIPSPEED + k *= SHIPSPEED; +#endif + + if (sh->damage) + k = + (k * (sh->size * DAMAGE_SCALE - sh->damage) + sh->size * DAMAGE_SCALE - + 1) / (sh->size * DAMAGE_SCALE); + + return (int)k; } const char *shipname(const ship * sh) { - typedef char name[OBJECTIDSIZE + 1]; - static name idbuf[8]; - static int nextbuf = 0; - char *ibuf = idbuf[(++nextbuf) % 8]; - return write_shipname(sh, ibuf, sizeof(name)); + typedef char name[OBJECTIDSIZE + 1]; + static name idbuf[8]; + static int nextbuf = 0; + char *ibuf = idbuf[(++nextbuf) % 8]; + return write_shipname(sh, ibuf, sizeof(name)); } int shipcapacity(const ship * sh) { - int i = sh->type->cargo; + int i = sh->type->cargo; - /* sonst ist construction:: size nicht ship_type::maxsize */ - assert(!sh->type->construction - || sh->type->construction->improvement == NULL); + /* sonst ist construction:: size nicht ship_type::maxsize */ + assert(!sh->type->construction + || sh->type->construction->improvement == NULL); - if (sh->type->construction && sh->size != sh->type->construction->maxsize) - return 0; + if (sh->type->construction && sh->size != sh->type->construction->maxsize) + return 0; - if (sh->damage) { - i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE)); - } - return i; + if (sh->damage) { + i = (int)ceil(i * (1.0 - sh->damage / sh->size / (double)DAMAGE_SCALE)); + } + return i; } void getshipweight(const ship * sh, int *sweight, int *scabins) { - unit *u; + unit *u; - *sweight = 0; - *scabins = 0; + *sweight = 0; + *scabins = 0; - for (u = sh->region->units; u; u = u->next) { - if (u->ship == sh) { - *sweight += weight(u); - if (sh->type->cabins) { - int pweight = u->number * u_race(u)->weight; - /* weight goes into number of cabins, not cargo */ - *scabins += pweight; - *sweight -= pweight; - } + for (u = sh->region->units; u; u = u->next) { + if (u->ship == sh) { + *sweight += weight(u); + if (sh->type->cabins) { + int pweight = u->number * u_race(u)->weight; + /* weight goes into number of cabins, not cargo */ + *scabins += pweight; + *sweight -= pweight; + } + } } - } } void ship_set_owner(unit * u) { - assert(u && u->ship); - u->ship->_owner = u; + assert(u && u->ship); + u->ship->_owner = u; } static unit * ship_owner_ex(const ship * sh, const struct faction * last_owner) { - unit *u, *heir = 0; + unit *u, *heir = 0; - /* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit - * nehmen. */ - for (u = sh->region->units; u; u = u->next) { - if (u->ship == sh) { - if (u->number > 0) { - if (heir && last_owner && heir->faction!=last_owner && u->faction==last_owner) { - heir = u; - break; /* we found someone from the same faction who is not dead. let's take this guy */ + /* Eigentümer tot oder kein Eigentümer vorhanden. Erste lebende Einheit + * nehmen. */ + for (u = sh->region->units; u; u = u->next) { + if (u->ship == sh) { + if (u->number > 0) { + if (heir && last_owner && heir->faction != last_owner && u->faction == last_owner) { + heir = u; + break; /* we found someone from the same faction who is not dead. let's take this guy */ + } + else if (!heir) { + heir = u; /* you'll do in an emergency */ + } + } } - else if (!heir) { - heir = u; /* you'll do in an emergency */ - } - } } - } - return heir; + return heir; } void ship_update_owner(ship * sh) { - unit * owner = sh->_owner; - sh->_owner = ship_owner_ex(sh, owner?owner->faction:0); + unit * owner = sh->_owner; + sh->_owner = ship_owner_ex(sh, owner ? owner->faction : 0); } unit *ship_owner(const ship * sh) { - unit *owner = sh->_owner; - if (!owner || (owner->ship!=sh || owner->number<=0)) { - unit * heir = ship_owner_ex(sh, owner?owner->faction:0); - return (heir && heir->number>0) ? heir : 0; - } - return owner; + unit *owner = sh->_owner; + if (!owner || (owner->ship != sh || owner->number <= 0)) { + unit * heir = ship_owner_ex(sh, owner ? owner->faction : 0); + return (heir && heir->number > 0) ? heir : 0; + } + return owner; } void write_ship_reference(const struct ship *sh, struct storage *store) { - WRITE_INT(store, (sh && sh->region) ? sh->no : 0); + WRITE_INT(store, (sh && sh->region) ? sh->no : 0); } void ship_setname(ship * self, const char *name) { - free(self->name); - if (name) - self->name = _strdup(name); - else - self->name = NULL; + free(self->name); + if (name) + self->name = _strdup(name); + else + self->name = NULL; } const char *ship_getname(const ship * self) { - return self->name; + return self->name; } diff --git a/src/kernel/ship.h b/src/kernel/ship.h index 7c9b2d1bf..d879837d8 100644 --- a/src/kernel/ship.h +++ b/src/kernel/ship.h @@ -124,6 +124,7 @@ extern "C" { extern const char *ship_getname(const struct ship *self); extern void ship_setname(struct ship *self, const char *name); + int shipspeed(const struct ship *sh, const struct unit *u); #ifdef __cplusplus } diff --git a/src/kernel/teleport.c b/src/kernel/teleport.c index 2fc7794f1..d0f5db424 100644 --- a/src/kernel/teleport.c +++ b/src/kernel/teleport.c @@ -159,8 +159,8 @@ void spawn_braineaters(float chance) /* Neues Monster ? */ if (next-- == 0) { unit *u = - createunit(r, f0, 1 + rng_int() % 10 + rng_int() % 10, - get_race(RC_HIRNTOETER)); + create_unit(r, f0, 1 + rng_int() % 10 + rng_int() % 10, + get_race(RC_HIRNTOETER), 0, NULL, NULL); equip_unit(u, get_equipment("monster_braineater")); next = rng_int() % (int)(chance * 100); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 22dc8bc55..e837e6b15 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -67,6 +67,31 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define FIND_FOREIGN_TEMP +int weight(const unit * u) +{ + int w = 0, n = 0, in_bag = 0; + const resource_type *rtype = get_resourcetype(R_BAG_OF_HOLDING); + item *itm; + + for (itm = u->items; itm; itm = itm->next) { + w = itm->type->weight * itm->number; + n += w; + if (rtype && !fval(itm->type, ITF_BIG)) { + in_bag += w; + } + } + + n += u->number * u_race(u)->weight; + + if (rtype) { + w = i_get(u->items, rtype->itype) * BAGCAPACITY; + if (w > in_bag) w = in_bag; + n -= w; + } + + return n; +} + attrib_type at_creator = { "creator" /* Rest ist NULL; temporaeres, nicht alterndes Attribut */ diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 45948bdb2..17ae915f3 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -125,6 +125,7 @@ extern "C" { extern struct attrib_type at_showskchange; int ualias(const struct unit *u); + int weight(const struct unit *u); const struct race *u_irace(const struct unit *u); const struct race *u_race(const struct unit *u); 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/arena.c b/src/modules/arena.c index ff752a5a4..1ce4763a5 100644 --- a/src/modules/arena.c +++ b/src/modules/arena.c @@ -367,7 +367,7 @@ static void guardian_faction(plane * pl, int id) } if (u) continue; - u = createunit(r, f, 1, get_race(RC_GOBLIN)); + u = create_unit(r, f, 1, get_race(RC_GOBLIN), 0, NULL, NULL); set_string(&u->name, "Igjarjuks Auge"); i_change(&u->items, it_find("roi"), 1); set_order(&u->thisorder, NULL); diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index 7083a85c9..8840da8d2 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,287 @@ #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 = -1; - 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; + // TODO: this entire function is impossible to understand + recurse_regions(rd, &rlist, f_nolux); + if (maxluxuries < 0) { + int i = 0; + for (sale = luxurytypes; sale; sale = sale->next) { + 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; - } + if (maxluxuries == 0) { + return -1; + } + 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 +338,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 +508,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; } diff --git a/src/monsters.c b/src/monsters.c index 93242dfa7..8c3f5bcf6 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -630,7 +630,7 @@ static void recruit_dracoids(unit * dragon, int size) region *r = dragon->region; const struct item *weapon = NULL; order *new_order = NULL; - unit *un = createunit(r, f, size, get_race(RC_DRACOID)); + unit *un = create_unit(r, f, size, get_race(RC_DRACOID), 0, NULL, NULL); fset(un, UFL_ISNEW | UFL_MOVED); @@ -908,7 +908,7 @@ void spawn_dragons(void) unit *u; if (fval(r->terrain, SEA_REGION) && rng_int() % 10000 < 1) { - u = createunit(r, monsters, 1, get_race(RC_SEASERPENT)); + u = create_unit(r, monsters, 1, get_race(RC_SEASERPENT), 0, NULL, NULL); fset(u, UFL_ISNEW | UFL_MOVED); equip_unit(u, get_equipment("monster_seaserpent")); } @@ -918,9 +918,9 @@ void spawn_dragons(void) || r->terrain == newterrain(T_DESERT)) && rng_int() % 10000 < (5 + 100 * chaosfactor(r))) { if (chance(0.80)) { - u = createunit(r, monsters, nrand(60, 20) + 1, get_race(RC_FIREDRAGON)); + u = create_unit(r, monsters, nrand(60, 20) + 1, get_race(RC_FIREDRAGON), 0, NULL, NULL); } else { - u = createunit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON)); + u = create_unit(r, monsters, nrand(30, 20) + 1, get_race(RC_DRAGON), 0, NULL, NULL); } fset(u, UFL_ISNEW | UFL_MOVED); equip_unit(u, get_equipment("monster_dragon")); @@ -983,7 +983,7 @@ void spawn_undead(void) break; } - u = createunit(r, monsters, undead, rc); + u = create_unit(r, monsters, undead, rc, 0, NULL, NULL); fset(u, UFL_ISNEW | UFL_MOVED); if ((rc == get_race(RC_SKELETON) || rc == get_race(RC_ZOMBIE)) && rng_int() % 10 < 4) { diff --git a/src/move.c b/src/move.c index 4b295896e..fe500b293 100644 --- a/src/move.c +++ b/src/move.c @@ -170,22 +170,6 @@ attrib_type at_shiptrail = { shiptrail_read }; -static int age_speedup(attrib * a) -{ - if (a->data.sa[0] > 0) { - a->data.sa[0] = a->data.sa[0] - a->data.sa[1]; - } - return (a->data.sa[0] > 0) ? AT_AGE_KEEP : AT_AGE_REMOVE; -} - -attrib_type at_speedup = { - "speedup", - NULL, NULL, - age_speedup, - a_writeint, - a_readint -}; - /* ------------------------------------------------------------- */ static attrib_type at_driveweight = { diff --git a/src/move.h b/src/move.h index 8e3d63e7f..3e808c769 100644 --- a/src/move.h +++ b/src/move.h @@ -31,7 +31,6 @@ extern "C" { struct ship; struct building_type; - extern struct attrib_type at_speedup; extern struct attrib_type at_shiptrail; /* die Zahlen sind genau äquivalent zu den race Flags */ diff --git a/src/races/races.h b/src/races/races.h index 94e5633bc..ac75cb75b 100644 --- a/src/races/races.h +++ b/src/races/races.h @@ -15,7 +15,8 @@ extern "C" { #endif - extern void register_races(void); + void register_races(void); + void make_undead_unit(struct unit *); #ifdef __cplusplus } diff --git a/src/races/zombies.c b/src/races/zombies.c index 97a826c3f..ed7ee4e86 100644 --- a/src/races/zombies.c +++ b/src/races/zombies.c @@ -17,6 +17,7 @@ /* kernel includes */ #include +#include #include #include #include @@ -35,6 +36,13 @@ #define age_chance(a,b,p) (_max(0,a-b)*p) +void make_undead_unit(unit * u) +{ + free_orders(&u->orders); + name_unit(u); + fset(u, UFL_ISNEW); +} + void age_undead(unit * u) { region *r = u->region; diff --git a/src/spells.c b/src/spells.c index 913403341..9474a69cc 100644 --- a/src/spells.c +++ b/src/spells.c @@ -56,6 +56,8 @@ #include #include +#include + /* util includes */ #include #include @@ -2782,6 +2784,23 @@ static int sp_unholypower(castorder * co) return cast_level; } +static int change_hitpoints(unit * u, int value) +{ + int hp = u->hp; + + hp += value; + + /* Jede Person benötigt mindestens 1 HP */ + if (hp < u->number) { + if (hp < 0) { /* Einheit tot */ + hp = 0; + } + scale_number(u, hp); + } + u->hp = hp; + return hp; +} + static int dc_age(struct curse *c) /* age returns 0 if the attribute needs to be removed, !=0 otherwise */ {