Merge branch 'master' into develop

Conflicts:
	src/gmtool.c
	src/modules/autoseed.c
This commit is contained in:
Enno Rehling 2017-08-18 20:31:14 +02:00
commit 54b5b09e15
26 changed files with 198 additions and 124 deletions

View File

@ -1,10 +1,7 @@
Freust Du Dich, dass es diese Woche wieder einen Eressea-Report gibt?
Möchtest Du dazu beitragen, dass das auch nächste Woche wieder passiert?
Eressea ist ein freiwilliges gratis-Angebot, und die Spielleitung bezahlt
seit Jahren die Entwicklung und das Hosting aus eigener Tasche. Wenn Dir
das etwas wert ist, kannst Du das auf
https://flattr.com/thing/681354/Eressea zum Ausdruck bringen.
Diese Mail enthält ein Attachment mit Deinem Eressea-Report in Diese Mail enthält ein Attachment mit Deinem Eressea-Report in
komprimierter Form. Um ihn zu entpacken benötigst Du ein Programm, komprimierter Form. Um ihn zu entpacken benötigst Du ein Programm,
das ZIP-Archive öffnen kann, wie z.B. 7-Zip (http://www.7-zip.org/) das ZIP-Archive öffnen kann, wie z.B. 7-Zip (http://www.7-zip.org/)
Eressea ist ein kostenloses Angebot von Freiwilligen, und die Spielleitung bezahlt
seit Jahren die Entwicklung und den Betrieb aus eigener Tasche. Wenn Dir
das etwas wert ist, kannst Du das Spiel auf https://www.patreon.com/enno unterstützen.

View File

@ -30,6 +30,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
static void a_writekeys(const attrib *a, const void *o, storage *store) { static void a_writekeys(const attrib *a, const void *o, storage *store) {
int i, *keys = (int *)a->data.v; int i, *keys = (int *)a->data.v;
assert(keys[0] < 4096 && keys[0]>0);
WRITE_INT(store, keys[0]); WRITE_INT(store, keys[0]);
for (i = 0; i < keys[0]; ++i) { for (i = 0; i < keys[0]; ++i) {
WRITE_INT(store, keys[i * 2 + 1]); WRITE_INT(store, keys[i * 2 + 1]);
@ -60,6 +61,9 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) {
static int a_readkey(attrib *a, void *owner, struct gamedata *data) { static int a_readkey(attrib *a, void *owner, struct gamedata *data) {
int res = a_readint(a, owner, data); int res = a_readint(a, owner, data);
if (data->version>=KEYVAL_VERSION) {
return AT_READ_FAIL;
}
return (res != AT_READ_FAIL) ? AT_READ_DEPR : res; return (res != AT_READ_FAIL) ? AT_READ_DEPR : res;
} }
@ -78,35 +82,12 @@ attrib_type at_keys = {
}; };
static void a_upgradekeys(attrib **alist, attrib *abegin) { static void a_upgradekeys(attrib **alist, attrib *abegin) {
int n = 0, *keys = 0; attrib *a, *ak;
int i = 0, val[8];
attrib *a, *ak = a_find(*alist, &at_keys); ak = a_find(*alist, &at_keys);
if (ak) { if (ak) alist = &ak;
keys = (int *)ak->data.v;
if (keys) n = keys[0];
}
for (a = abegin; a && a->type == abegin->type; a = a->next) { for (a = abegin; a && a->type == abegin->type; a = a->next) {
val[i * 2] = a->data.i; key_set(alist, a->data.i, 1);
val[i * 2 + 1] = 1;
if (++i == 4) {
keys = realloc(keys, sizeof(int) * (2 * (n + i) + 1));
memcpy(keys + 2 * n + 1, val, sizeof(val));
n += i;
i = 0;
}
}
if (i > 0) {
keys = realloc(keys, sizeof(int) * (2 * (n + i) + 1));
memcpy(keys + 2 * n + 1, val, sizeof(int)*i*2);
if (!ak) {
ak = a_add(alist, a_new(&at_keys));
}
}
if (ak) {
ak->data.v = keys;
if (keys) {
keys[0] = n + i;
}
} }
} }
@ -115,7 +96,7 @@ attrib_type at_key = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
a_writeint, NULL,
a_readkey, a_readkey,
a_upgradekeys a_upgradekeys
}; };
@ -133,9 +114,10 @@ void key_set(attrib ** alist, int key, int val)
if (keys) { if (keys) {
n = keys[0]; n = keys[0];
} }
/* TODO: too many allocations, unsorted array */
keys = realloc(keys, sizeof(int) *(2 * n + 3)); keys = realloc(keys, sizeof(int) *(2 * n + 3));
/* TODO: does insertion sort pay off here? prob. not. */
keys[0] = n + 1; keys[0] = n + 1;
assert(keys[0] < 4096 && keys[0]>=0);
keys[2 * n + 1] = key; keys[2 * n + 1] = key;
keys[2 * n + 2] = val; keys[2 * n + 2] = val;
a->data.v = keys; a->data.v = keys;
@ -150,6 +132,7 @@ void key_unset(attrib ** alist, int key)
int i, *keys = (int *)a->data.v; int i, *keys = (int *)a->data.v;
if (keys) { if (keys) {
int n = keys[0]; int n = keys[0];
assert(keys[0] < 4096 && keys[0]>0);
for (i = 0; i != n; ++i) { for (i = 0; i != n; ++i) {
if (keys[2 * i + 1] == key) { if (keys[2 * i + 1] == key) {
memmove(keys + 2 * i + 1, keys + 2 * n - 1, 2 * sizeof(int)); memmove(keys + 2 * i + 1, keys + 2 * n - 1, 2 * sizeof(int));
@ -168,6 +151,7 @@ int key_get(attrib *alist, int key) {
if (a) { if (a) {
int i, *keys = (int *)a->data.v; int i, *keys = (int *)a->data.v;
if (keys) { if (keys) {
/* TODO: binary search this! */
for (i = 0; i != keys[0]; ++i) { for (i = 0; i != keys[0]; ++i) {
if (keys[i*2+1] == key) { if (keys[i*2+1] == key) {
return keys[i * 2 + 2]; return keys[i * 2 + 2];

View File

@ -55,6 +55,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <attributes/racename.h> #include <attributes/racename.h>
#include <attributes/otherfaction.h> #include <attributes/otherfaction.h>
#include <attributes/moved.h> #include <attributes/moved.h>
#include <spells/buildingcurse.h>
/* util includes */ /* util includes */
#include <util/assert.h> #include <util/assert.h>
@ -1920,9 +1921,7 @@ int skilldiff(troop at, troop dt, int dist)
skdiff -= beff; skdiff -= beff;
is_protected = 2; is_protected = 2;
if (b->attribs) { if (b->attribs) {
const curse_type *magicwalls_ct = ct_find("magicwalls"); if (curse_active(get_curse(b->attribs, &ct_magicwalls))) {
if (magicwalls_ct
&& curse_active(get_curse(b->attribs, magicwalls_ct))) {
/* Verdoppelt Burgenbonus */ /* Verdoppelt Burgenbonus */
skdiff -= beff; skdiff -= beff;
} }

View File

@ -11,6 +11,9 @@
#include <kernel/race.h> #include <kernel/race.h>
#include <kernel/region.h> #include <kernel/region.h>
#include <kernel/unit.h> #include <kernel/unit.h>
#include <spells/buildingcurse.h>
#include <util/functions.h> #include <util/functions.h>
#include <util/rand.h> #include <util/rand.h>
#include <util/rng.h> #include <util/rng.h>
@ -468,12 +471,11 @@ static void test_battle_skilldiff_building(CuTest *tc)
unit *ua, *ud; unit *ua, *ud;
battle *b = NULL; battle *b = NULL;
building_type *btype; building_type *btype;
const curse_type *strongwall_ct, *magicwalls_ct; const curse_type *strongwall_ct;
test_setup(); test_setup();
btype = setup_castle(); btype = setup_castle();
strongwall_ct = ct_find("strongwall"); strongwall_ct = ct_find("strongwall");
magicwalls_ct = ct_find("magicwalls");
r = test_create_region(0, 0, 0); r = test_create_region(0, 0, 0);
ud = test_create_unit(test_create_faction(0), r); ud = test_create_unit(test_create_faction(0), r);
@ -489,7 +491,7 @@ static void test_battle_skilldiff_building(CuTest *tc)
ud->building->size = 10; ud->building->size = 10;
CuAssertIntEquals(tc, -1, skilldiff(ta, td, 0)); CuAssertIntEquals(tc, -1, skilldiff(ta, td, 0));
create_curse(NULL, &ud->building->attribs, magicwalls_ct, 1, 1, 1, 1); create_curse(NULL, &ud->building->attribs, &ct_magicwalls, 1, 1, 1, 1);
CuAssertIntEquals(tc, -2, skilldiff(ta, td, 0)); CuAssertIntEquals(tc, -2, skilldiff(ta, td, 0));
create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1); create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1);

View File

@ -150,10 +150,9 @@ static int tolua_make_island(lua_State * L)
int x = (int)tolua_tonumber(L, 1, 0); int x = (int)tolua_tonumber(L, 1, 0);
int y = (int)tolua_tonumber(L, 2, 0); int y = (int)tolua_tonumber(L, 2, 0);
int s = (int)tolua_tonumber(L, 3, 0); int s = (int)tolua_tonumber(L, 3, 0);
int n = (int)tolua_tonumber(L, 4, s / 3);
n = build_island_e3(NULL, x, y, n, s); s = build_island_e3(x, y, s, NULL, 0);
lua_pushinteger(L, n); lua_pushinteger(L, s);
return 1; return 1;
} }

View File

@ -53,6 +53,19 @@ attrib_type at_chaoscount = {
ATF_UNIQUE ATF_UNIQUE
}; };
void set_chaoscount(struct region *r, int deaths)
{
if (deaths==0) {
a_removeall(&r->attribs, &at_chaoscount);
} else {
attrib *a = a_find(r->attribs, &at_chaoscount);
if (!a) {
a = a_add(&r->attribs, a_new(&at_chaoscount));
}
a->data.i = deaths;
}
}
int get_chaoscount(const region * r) int get_chaoscount(const region * r)
{ {
attrib *a = a_find(r->attribs, &at_chaoscount); attrib *a = a_find(r->attribs, &at_chaoscount);

View File

@ -29,6 +29,7 @@ extern "C" {
void chaos_register(void); void chaos_register(void);
void chaos_update(void); void chaos_update(void);
void set_chaoscount(struct region *r, int deaths);
int get_chaoscount(const struct region * r); int get_chaoscount(const struct region * r);
void add_chaoscount(struct region * r, int deaths); void add_chaoscount(struct region * r, int deaths);

View File

@ -499,11 +499,12 @@ static void test_modify_production(CuTest *tc) {
CuAssertIntEquals(tc, 11, get_item(u, itype)); CuAssertIntEquals(tc, 11, get_item(u, itype));
CuAssertIntEquals(tc, 290, region_getresource(u->region, rtype)); /* used 10 stones to make 10 stones */ CuAssertIntEquals(tc, 290, region_getresource(u->region, rtype)); /* used 10 stones to make 10 stones */
rtype->modifiers = calloc(2, sizeof(resource_mod)); rtype->modifiers = calloc(3, sizeof(resource_mod));
rtype->modifiers[0].type = RMT_PROD_SAVE; rtype->modifiers[0].type = RMT_PROD_SAVE;
rtype->modifiers[0].race = u->_race; rtype->modifiers[0].race = u->_race;
rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d); rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d);
rtype->modifiers[0].value.sa[1] = 100; rtype->modifiers[0].value.sa[1] = 100;
rtype->modifiers[1].type = RMT_END;
make_item(u, itype, 10); make_item(u, itype, 10);
split_allocations(u->region); split_allocations(u->region);
CuAssertIntEquals(tc, 21, get_item(u, itype)); CuAssertIntEquals(tc, 21, get_item(u, itype));
@ -541,6 +542,7 @@ static void test_modify_production(CuTest *tc) {
rtype->modifiers[1].type = RMT_PROD_REQUIRE; rtype->modifiers[1].type = RMT_PROD_REQUIRE;
rtype->modifiers[1].race = u_race(u); rtype->modifiers[1].race = u_race(u);
rtype->modifiers[1].btype = NULL; rtype->modifiers[1].btype = NULL;
rtype->modifiers[2].type = RMT_END;
test_clear_messages(u->faction); test_clear_messages(u->faction);
make_item(u, itype, 10); make_item(u, itype, 10);

View File

@ -15,6 +15,7 @@
#include "gmtool.h" #include "gmtool.h"
#include "gmtool_structs.h" #include "gmtool_structs.h"
#include "chaos.h"
#include "console.h" #include "console.h"
#include "listbox.h" #include "listbox.h"
#include "wormhole.h" #include "wormhole.h"
@ -45,6 +46,7 @@
#include <attributes/attributes.h> #include <attributes/attributes.h>
#include <triggers/triggers.h> #include <triggers/triggers.h>
#include <util/attrib.h>
#include <util/log.h> #include <util/log.h>
#include <util/unicode.h> #include <util/unicode.h>
#include <util/lists.h> #include <util/lists.h>
@ -515,6 +517,46 @@ static void statusline(WINDOW * win, const char *str)
wnoutrefresh(win); wnoutrefresh(win);
} }
static void reset_region(region *r) {
set_chaoscount(r, 0);
r->flags = 0;
a_removeall(&r->attribs, NULL);
while (r->units) {
remove_unit(&r->units, r->units);
}
while (r->ships) {
remove_ship(&r->ships, r->ships);
}
while (r->buildings) {
remove_building(&r->buildings, r->buildings);
}
}
static void reset_cursor(state *st) {
int nx = st->cursor.x;
int ny = st->cursor.y;
region *r;
pnormalize(&nx, &ny, st->cursor.pl);
if ((r = findregion(nx, ny)) != NULL) {
reset_region(r);
}
}
static void reset_rect(state *st) {
int x, y, bs = 3;
for (x=0;x!=bs;++x) {
for (y = 0; y != bs; ++y) {
region *r;
int nx = st->cursor.x + x;
int ny = st->cursor.y + y;
pnormalize(&nx, &ny, st->cursor.pl);
if ((r = findregion(nx, ny)) != NULL) {
reset_region(r);
}
}
}
}
static void terraform_at(coordinate * c, const terrain_type * terrain) static void terraform_at(coordinate * c, const terrain_type * terrain)
{ {
if (terrain != NULL) { if (terrain != NULL) {
@ -844,8 +886,20 @@ static void seed_player(state *st, const newfaction *player) {
pnormalize(&nx, &ny, st->cursor.pl); pnormalize(&nx, &ny, st->cursor.pl);
r = findregion(nx, ny); r = findregion(nx, ny);
if (r) { if (r) {
addplayer(r, addfaction(player->email, player->password, player->race, const char *at = strchr(player->email, '@');
player->lang, player->subscription)); faction *f;
addplayer(r, f = addfaction(player->email, player->password,
player->race, player->lang,
player->subscription));
if (at) {
char fname[64];
size_t len = at - player->email;
if (len>4 && len<sizeof(fname)) {
memcpy(fname, player->email, len);
fname[len]=0;
faction_setname(f, fname);
}
}
} }
} }
} }
@ -912,15 +966,15 @@ static void handlekey(state * st, int c)
break; break;
case 'B': case 'B':
cnormalize(&st->cursor, &nx, &ny); cnormalize(&st->cursor, &nx, &ny);
minpop = config_get_int("editor.population.min", 8); minpop = config_get_int("editor.island.min", 8);
maxpop = config_get_int("editor.population.max", minpop); maxpop = config_get_int("editor.island.max", minpop);
if (maxpop > minpop) { if (maxpop > minpop) {
n = rng_int() % (maxpop - minpop) + minpop; n = rng_int() % (maxpop - minpop) + minpop;
} }
else { else {
n = minpop; n = minpop;
} }
build_island_e3(&new_players, nx, ny, n, n * 3); build_island_e3(nx, ny, n, NULL, 0);
st->modified = 1; st->modified = 1;
st->wnd_info->update |= 1; st->wnd_info->update |= 1;
st->wnd_status->update |= 1; st->wnd_status->update |= 1;
@ -934,6 +988,12 @@ static void handlekey(state * st, int c)
st->wnd_status->update |= 1; st->wnd_status->update |= 1;
st->wnd_map->update |= 1; st->wnd_map->update |= 1;
break; break;
case 'c': /* clear/reset */
reset_cursor(st);
break;
case 'C': /* clear/reset */
reset_rect(st);
break;
case 0x09: /* tab = next selected */ case 0x09: /* tab = next selected */
if (regions != NULL) { if (regions != NULL) {
map_region *mr = cursor_region(&st->display, cursor); map_region *mr = cursor_region(&st->display, cursor);

View File

@ -22,6 +22,7 @@
#include <kernel/unit.h> #include <kernel/unit.h>
#include <attributes/fleechance.h> #include <attributes/fleechance.h>
#include <spells/shipcurse.h>
/* triggers includes */ /* triggers includes */
#include <triggers/changerace.h> #include <triggers/changerace.h>
@ -88,7 +89,6 @@ static int
use_speedsail(struct unit *u, const struct item_type *itype, int amount, use_speedsail(struct unit *u, const struct item_type *itype, int amount,
struct order *ord) struct order *ord)
{ {
curse *c;
double effect; double effect;
ship *sh = u->ship; ship *sh = u->ship;
if (!sh) { if (!sh) {
@ -97,9 +97,7 @@ struct order *ord)
} }
effect = SPEEDSAIL_EFFECT; effect = SPEEDSAIL_EFFECT;
c = create_curse(u, &sh->attribs, ct_find("shipspeedup"), 20, INT_MAX, create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, effect, 0);
effect, 0);
c_setflag(c, CURSE_NOAGE);
ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u, ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u,
SPEEDSAIL_EFFECT)); SPEEDSAIL_EFFECT));

View File

@ -61,14 +61,14 @@ static curse *cursehash[MAXENTITYHASH];
void c_setflag(curse * c, unsigned int flags) void c_setflag(curse * c, unsigned int flags)
{ {
assert(c); assert(c);
c->flags = (c->flags & ~flags) | (flags & (c->type->flags ^ flags)); c->mask = (c->mask & ~flags) | (flags & (c->type->flags ^ flags));
} }
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
void c_clearflag(curse * c, unsigned int flags) void c_clearflag(curse * c, unsigned int flags)
{ {
assert(c); assert(c);
c->flags = (c->flags & ~flags) | (c->type->flags & flags); c->mask = (c->mask & ~flags) | (c->type->flags & flags);
} }
void chash(curse * c) void chash(curse * c)
@ -180,14 +180,13 @@ int curse_read(attrib * a, void *owner, gamedata *data)
int ur; int ur;
char cursename[64]; char cursename[64];
int n; int n;
int flags;
float flt; float flt;
assert(!c->no); assert(!c->no);
READ_INT(store, &c->no); READ_INT(store, &c->no);
chash(c); chash(c);
READ_TOK(store, cursename, sizeof(cursename)); READ_TOK(store, cursename, sizeof(cursename));
READ_INT(store, &flags); READ_INT(store, &c->mask);
READ_INT(store, &c->duration); READ_INT(store, &c->duration);
READ_FLT(store, &flt); READ_FLT(store, &flt);
c->vigour = flt; c->vigour = flt;
@ -214,7 +213,6 @@ int curse_read(attrib * a, void *owner, gamedata *data)
assert(result == 0); assert(result == 0);
return AT_READ_FAIL; return AT_READ_FAIL;
} }
c->flags = flags;
if (data->version < EXPLICIT_CURSE_ISNEW_VERSION) { if (data->version < EXPLICIT_CURSE_ISNEW_VERSION) {
c_clearflag(c, CURSE_ISNEW); c_clearflag(c, CURSE_ISNEW);
} }
@ -239,21 +237,13 @@ int curse_read(attrib * a, void *owner, gamedata *data)
void curse_write(const attrib * a, const void *owner, struct storage *store) void curse_write(const attrib * a, const void *owner, struct storage *store)
{ {
unsigned int flags;
curse *c = (curse *)a->data.v; curse *c = (curse *)a->data.v;
const curse_type *ct = c->type; const curse_type *ct = c->type;
unit *mage = (c->magician && c->magician->number) ? c->magician : NULL; unit *mage = (c->magician && c->magician->number) ? c->magician : NULL;
/* copied from c_clearflag */
#if RELEASE_VERSION < EXPLICIT_CURSE_ISNEW_VERSION
flags = (c->flags & ~CURSE_ISNEW) | (c->type->flags & CURSE_ISNEW);
#else
flags = c->flags | c->type->flags;
#endif
WRITE_INT(store, c->no); WRITE_INT(store, c->no);
WRITE_TOK(store, ct->cname); WRITE_TOK(store, ct->cname);
WRITE_INT(store, flags); WRITE_INT(store, c->mask);
WRITE_INT(store, c->duration); WRITE_INT(store, c->duration);
WRITE_FLT(store, (float)c->vigour); WRITE_FLT(store, (float)c->vigour);
write_unit_reference(mage, store); write_unit_reference(mage, store);
@ -306,6 +296,7 @@ void ct_register(const curse_type * ct)
selist **ctlp = cursetypes + hash; selist **ctlp = cursetypes + hash;
assert(ct->age==NULL || (ct->flags&CURSE_NOAGE) == 0); assert(ct->age==NULL || (ct->flags&CURSE_NOAGE) == 0);
assert((ct->flags&CURSE_ISNEW) == 0);
selist_set_insert(ctlp, (void *)ct, NULL); selist_set_insert(ctlp, (void *)ct, NULL);
++ct_changes; ++ct_changes;
} }
@ -553,7 +544,7 @@ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct,
c = (curse *)a->data.v; c = (curse *)a->data.v;
c->type = ct; c->type = ct;
c->flags = 0; c->mask = 0;
c->vigour = vigour; c->vigour = vigour;
c->duration = duration; c->duration = duration;
c->effect = effect; c->effect = effect;
@ -633,7 +624,7 @@ static void do_transfer_curse(curse * c, const unit * u, unit * u2, int n)
bool dogive = false; bool dogive = false;
const curse_type *ct = c->type; const curse_type *ct = c->type;
switch ((ct->flags | c->flags) & CURSE_SPREADMASK) { switch (c_flags(c) & CURSE_SPREADMASK) {
case CURSE_SPREADALWAYS: case CURSE_SPREADALWAYS:
dogive = true; dogive = true;
men = u2->number + n; men = u2->number + n;
@ -666,7 +657,7 @@ static void do_transfer_curse(curse * c, const unit * u, unit * u2, int n)
if (dogive) { if (dogive) {
curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour, curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour,
c->duration, c->effect, men); c->duration, c->effect, men);
cnew->flags = c->flags; cnew->mask = c->mask;
if (ct->typ == CURSETYP_UNIT) if (ct->typ == CURSETYP_UNIT)
set_cursedmen(cnew, men); set_cursedmen(cnew, men);

View File

@ -187,7 +187,7 @@ extern "C" {
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
/* Allgemeine Zauberwirkungen */ /* Allgemeine Zauberwirkungen */
#define c_flags(c) ((c)->type->flags ^ (c)->flags) #define c_flags(c) ((c)->type->flags ^ (c)->mask)
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
@ -215,7 +215,7 @@ extern "C" {
double vigour; /* Stärke der Verzauberung, Widerstand gegen Antimagie */ double vigour; /* Stärke der Verzauberung, Widerstand gegen Antimagie */
double effect; double effect;
int no; /* 'Einheitennummer' dieses Curse */ int no; /* 'Einheitennummer' dieses Curse */
int flags; /* WARNING: these are XORed with type->flags! */ int mask; /* This is XORed with type->flags, see c_flags()! */
int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */ int duration; /* Dauer der Verzauberung. Wird jede Runde vermindert */
} curse; } curse;

View File

@ -106,7 +106,7 @@ static void test_memstream(CuTest *tc) {
storage store; storage store;
stream out = { 0 }; stream out = { 0 };
char buf[1024]; char buf[1024];
int val=0; int val = 0;
mstream_init(&out); mstream_init(&out);
binstore_init(&store, &out); binstore_init(&store, &out);
@ -137,11 +137,13 @@ static void test_write_flag(CuTest *tc) {
mstream_init(&data.strm); mstream_init(&data.strm);
gamedata_init(&data, &store, RELEASE_VERSION); gamedata_init(&data, &store, RELEASE_VERSION);
setup_curse(&fix, "gbdream"); setup_curse(&fix, "magicwalls");
c = fix.c; c = fix.c;
r = fix.r; r = fix.r;
uid = r->uid; uid = r->uid;
c->flags = CURSE_ISNEW; c_setflag(c, CURSE_ISNEW);
c_setflag(c, CURSE_IMMUNE);
CuAssertIntEquals(tc, c->type->flags | CURSE_IMMUNE | CURSE_ISNEW, c_flags(c));
write_game(&data); write_game(&data);
free_gamedata(); free_gamedata();
data.strm.api->rewind(data.strm.handle); data.strm.api->rewind(data.strm.handle);
@ -150,7 +152,7 @@ static void test_write_flag(CuTest *tc) {
CuAssertPtrNotNull(tc, r); CuAssertPtrNotNull(tc, r);
CuAssertPtrNotNull(tc, r->attribs); CuAssertPtrNotNull(tc, r->attribs);
c = (curse *)r->attribs->data.v; c = (curse *)r->attribs->data.v;
CuAssertIntEquals(tc, CURSE_ISNEW, c->flags); CuAssertIntEquals(tc, c->type->flags | CURSE_IMMUNE | CURSE_ISNEW, c_flags(c));
mstream_done(&data.strm); mstream_done(&data.strm);
gamedata_done(&data); gamedata_done(&data);

View File

@ -283,15 +283,25 @@ faction *addfaction(const char *email, const char *password,
return f; return f;
} }
#define PEASANT_MIN (10 * RECRUITFRACTION)
#define PEASANT_MAX (20 * RECRUITFRACTION)
unit *addplayer(region * r, faction * f) unit *addplayer(region * r, faction * f)
{ {
unit *u; unit *u;
const char * name;
const struct equipment* eq; const struct equipment* eq;
assert(r->land);
if (rpeasants(r) < PEASANT_MIN) {
rsetpeasants(r, PEASANT_MIN + rng_int() % (PEASANT_MAX - PEASANT_MIN));
}
assert(f->units == NULL); assert(f->units == NULL);
faction_setorigin(f, 0, r->x, r->y); faction_setorigin(f, 0, r->x, r->y);
u = create_unit(r, f, 1, f->race, 0, NULL, NULL); u = create_unit(r, f, 1, f->race, 0, NULL, NULL);
eq = get_equipment("first_unit"); name = config_get("rules.equip_first");
eq = get_equipment(name ? name : "first_unit");
if (eq) { if (eq) {
equip_items(&u->items, eq); equip_items(&u->items, eq);
} }

View File

@ -42,6 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <util/xml.h> #include <util/xml.h>
#include <attributes/movement.h> #include <attributes/movement.h>
#include <spells/shipcurse.h>
#include <storage.h> #include <storage.h>
#include <selist.h> #include <selist.h>
@ -365,7 +366,7 @@ int shipspeed(const ship * sh, const unit * u)
a = a->next; a = a->next;
} }
c = get_curse(sh->attribs, ct_find("shipspeedup")); c = get_curse(sh->attribs, &ct_shipspeedup);
while (c) { while (c) {
k += curse_geteffect_int(c); k += curse_geteffect_int(c);
c = c->nexthash; c = c->nexthash;

View File

@ -462,7 +462,7 @@ static void test_shipspeed_shipspeedup(CuTest *tc) {
register_shipcurse(); register_shipcurse();
assert(sh && cap && crew); assert(sh && cap && crew);
create_curse(0, &sh->attribs, ct_find("shipspeedup"), 1, 1, 3, 0); create_curse(0, &sh->attribs, &ct_shipspeedup, 1, 1, 3, 0);
CuAssertIntEquals_Msg(tc, "shipspeedup adds effect to range", sh->type->range + 3, shipspeed(sh, cap)); CuAssertIntEquals_Msg(tc, "shipspeedup adds effect to range", sh->type->range + 3, shipspeed(sh, cap));
test_cleanup(); test_cleanup();
} }

View File

@ -70,6 +70,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include <attributes/racename.h> #include <attributes/racename.h>
#include <attributes/raceprefix.h> #include <attributes/raceprefix.h>
#include <attributes/stealth.h> #include <attributes/stealth.h>
#include <spells/buildingcurse.h>
/* util includes */ /* util includes */
#include <util/attrib.h> #include <util/attrib.h>
@ -3872,7 +3873,6 @@ int siege_cmd(unit * u, order * ord)
building *b; building *b;
int d, pooled; int d, pooled;
int bewaffnete, katapultiere = 0; int bewaffnete, katapultiere = 0;
const curse_type *magicwalls_ct;
resource_type *rt_catapultammo = NULL; resource_type *rt_catapultammo = NULL;
resource_type *rt_catapult = NULL; resource_type *rt_catapult = NULL;
@ -3891,7 +3891,6 @@ int siege_cmd(unit * u, order * ord)
} }
/* schaden durch katapulte */ /* schaden durch katapulte */
magicwalls_ct = ct_find("magicwalls");
rt_catapultammo = rt_find("catapultammo"); rt_catapultammo = rt_find("catapultammo");
rt_catapult = rt_find("catapult"); rt_catapult = rt_find("catapult");
@ -3932,7 +3931,7 @@ int siege_cmd(unit * u, order * ord)
d = MIN(d, b->size - 1); d = MIN(d, b->size - 1);
/* meldung, schaden anrichten */ /* meldung, schaden anrichten */
if (d && !curse_active(get_curse(b->attribs, magicwalls_ct))) { if (d && !curse_active(get_curse(b->attribs, &ct_magicwalls))) {
b->size -= d; b->size -= d;
use_pooled(u, rt_catapultammo, use_pooled(u, rt_catapultammo,
GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d); GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d);

View File

@ -16,7 +16,7 @@
#include "market.h" #include "market.h"
/* kernel includes */ /* kernel includes */
#include <kernel/alliance.h> #include <kernel/alliance.h>
#include <kernel/item.h> #include <kernel/item.h>
#include <kernel/region.h> #include <kernel/region.h>
@ -94,7 +94,7 @@ static int count_demand(const region * r)
static int static int
recurse_regions(region * r, region_list ** rlist, recurse_regions(region * r, region_list ** rlist,
bool(*fun) (const region * r)) bool(*fun) (const region * r))
{ {
if (!fun(r)) if (!fun(r))
return 0; return 0;
@ -157,30 +157,37 @@ newfaction *read_newfactions(const char *filename)
password[0] = '\0'; password[0] = '\0';
if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus, if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus,
&subscription, password, &alliance) < 3) &subscription, password, &alliance) < 3) {
break; break;
if (email[0] == '\0') }
break; if (email[0] == '#') {
if (email[0] == '#') continue;
}
if (email[0] == '\0') {
break; break;
}
if (password[0] == '\0') { if (password[0] == '\0') {
size_t sz; size_t sz;
sz = strlcpy(password, itoa36(rng_int()), sizeof(password)); sz = strlcpy(password, itoa36(rng_int()), sizeof(password));
sz += strlcat(password, itoa36(rng_int()), sizeof(password)); sz += strlcat(password, itoa36(rng_int()), sizeof(password));
} }
for (f = factions; f; f = f->next) { for (f = factions; f; f = f->next) {
if (strcmp(f->email, email) == 0 && f->subscription if (strcmp(f->email, email) == 0 && f->age < MINAGE_MULTI) {
&& f->age < MINAGE_MULTI) log_warning("email %s already in use by %s", email, factionname(f));
break; break;
} }
}
if (f && f->units) if (f && f->units)
continue; /* skip the ones we've already got */ continue; /* skip the ones we've already got */
for (nf = newfactions; nf; nf = nf->next) { for (nf = newfactions; nf; nf = nf->next) {
if (strcmp(nf->email, email) == 0) if (strcmp(nf->email, email) == 0) {
log_warning("duplicate new faction %s", email);
break; break;
} }
if (nf) }
if (nf) {
continue; continue;
}
nf = calloc(sizeof(newfaction), 1); nf = calloc(sizeof(newfaction), 1);
if (set_email(&nf->email, email) != 0) { if (set_email(&nf->email, email) != 0) {
log_error("Invalid email address for subscription %s: %s\n", itoa36(subscription), email); log_error("Invalid email address for subscription %s: %s\n", itoa36(subscription), email);
@ -778,25 +785,29 @@ const terrain_type *random_terrain_e3(direction_t dir)
return random_terrain(terrainarr, distribution, GEOMAX); return random_terrain(terrainarr, distribution, GEOMAX);
} }
int static int
random_neighbours(region * r, region_list ** rlist, random_neighbours(region * r, region_list ** rlist,
const terrain_type * (*terraformer) (direction_t)) const terrain_type * (*terraformer) (direction_t), int n)
{ {
int nsize = 0; int nsize = 0;
direction_t dir; direction_t dir;
for (dir = 0; dir != MAXDIRECTIONS; ++dir) { for (dir = 0; dir != MAXDIRECTIONS; ++dir) {
region *rn = rconnect(r, dir); region *rn = rconnect(r, dir);
if (rn == NULL) { if (rn == NULL || (!rn->units && !rn->land)) {
const terrain_type *terrain = terraformer(dir); const terrain_type *terrain = terraformer(dir);
if (!rn) {
plane *pl = rplane(r); plane *pl = rplane(r);
int x = r->x + delta_x[dir]; int x = r->x + delta_x[dir];
int y = r->y + delta_y[dir]; int y = r->y + delta_y[dir];
pnormalize(&x, &y, pl); pnormalize(&x, &y, pl);
rn = new_region(x, y, pl, 0); rn = new_region(x, y, pl, 0);
}
terraform_region(rn, terrain); terraform_region(rn, terrain);
regionqueue_push(rlist, rn); regionqueue_push(rlist, rn);
if (rn->land) { if (rn->land) {
++nsize; if (++nsize >= n) {
break;
}
} }
} }
} }
@ -906,7 +917,7 @@ static void starting_region(newfaction ** players, region * r, region * rn[])
} }
/* E3A island generation */ /* E3A island generation */
int build_island_e3(newfaction ** players, int x, int y, int numfactions, int minsize) int build_island_e3(int x, int y, int minsize, newfaction ** players, int numfactions)
{ {
#define MIN_QUALITY 1000 #define MIN_QUALITY 1000
int nfactions = 0; int nfactions = 0;
@ -917,9 +928,10 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi
int nsize = 1; int nsize = 1;
int q, maxq = INT_MIN, minq = INT_MAX; int q, maxq = INT_MIN, minq = INT_MAX;
if (!r) if (r && r->units) return 0;
if (!r) {
r = new_region(x, y, pl, 0); r = new_region(x, y, pl, 0);
assert(!r->units); }
do { do {
terraform_region(r, random_terrain_e3(NODIRECTION)); terraform_region(r, random_terrain_e3(NODIRECTION));
} while (!r->land); } while (!r->land);
@ -928,10 +940,10 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi
fset(r, RF_MARK); fset(r, RF_MARK);
if (r->land) { if (r->land) {
if (nsize < minsize) { if (nsize < minsize) {
nsize += random_neighbours(r, &rlist, &random_terrain_e3); nsize += random_neighbours(r, &rlist, &random_terrain_e3, minsize - nsize);
} }
else { else {
nsize += random_neighbours(r, &rlist, &get_ocean); nsize += random_neighbours(r, &rlist, &get_ocean, minsize - nsize);
} }
} }
regionqueue_push(&island, r); regionqueue_push(&island, r);
@ -948,7 +960,7 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi
get_neighbours(r, rn); get_neighbours(r, rn);
q = region_quality(r, rn); q = region_quality(r, rn);
if (q >= MIN_QUALITY && nfactions < numfactions && *players) { if (q >= MIN_QUALITY && nfactions < numfactions && players && *players) {
starting_region(players, r, rn); starting_region(players, r, rn);
minq = MIN(minq, q); minq = MIN(minq, q);
maxq = MAX(maxq, q); maxq = MAX(maxq, q);
@ -963,7 +975,7 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi
region *rn[MAXDIRECTIONS]; region *rn[MAXDIRECTIONS];
get_neighbours(r, rn); get_neighbours(r, rn);
q = region_quality(r, rn); q = region_quality(r, rn);
if (q >= MIN_QUALITY * 4 / 3 && nfactions < numfactions && *players) { if (q >= MIN_QUALITY * 4 / 3 && nfactions < numfactions && players && *players) {
starting_region(players, r, rn); starting_region(players, r, rn);
minq = MIN(minq, q); minq = MIN(minq, q);
maxq = MAX(maxq, q); maxq = MAX(maxq, q);
@ -986,7 +998,7 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi
rsetmoney(r, 50000); /* 2% = 1000 silver */ rsetmoney(r, 50000); /* 2% = 1000 silver */
} }
else if (r->land) { else if (r->land) {
rsetmoney(r, rmoney(r) *4); rsetmoney(r, rmoney(r) * 4);
} }
} }
return nfactions; return nfactions;

View File

@ -38,8 +38,7 @@ extern "C" {
extern const struct terrain_type *random_terrain(const struct terrain_type extern const struct terrain_type *random_terrain(const struct terrain_type
*terrains[], int distribution[], int size); *terrains[], int distribution[], int size);
extern int seed_adamantium(struct region *r, int base); extern int build_island_e3(int x, int y, int minsize, newfaction **players, int numfactions);
extern int build_island_e3(newfaction **players, int x, int y, int numfactions, int minsize);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -2074,7 +2074,7 @@ static int sp_homestone(castorder * co)
return 0; return 0;
} }
c = create_curse(mage, &mage->building->attribs, ct_find("magicwalls"), c = create_curse(mage, &mage->building->attribs, &ct_magicwalls,
force * force, 1, zero_effect, 0); force * force, 1, zero_effect, 0);
if (c == NULL) { if (c == NULL) {

View File

@ -75,7 +75,7 @@ CURSETYP_NORM, 0, M_SUMEFFECT, cinfo_magicrunes
}; };
/* Heimstein-Zauber */ /* Heimstein-Zauber */
static struct curse_type ct_magicwalls = { "magicwalls", const struct curse_type ct_magicwalls = { "magicwalls",
CURSETYP_NORM, CURSE_ONLYONE|CURSE_NOAGE, NO_MERGE, cinfo_building CURSETYP_NORM, CURSE_ONLYONE|CURSE_NOAGE, NO_MERGE, cinfo_building
}; };

View File

@ -21,6 +21,9 @@ extern "C" {
struct locale; struct locale;
struct curse; struct curse;
struct message; struct message;
struct curse_type;
extern const struct curse_type ct_magicwalls;
extern void register_buildingcurse(void); extern void register_buildingcurse(void);
struct message *cinfo_building(const void *obj, objtype_t typ, const struct curse * c, int self); struct message *cinfo_building(const void *obj, objtype_t typ, const struct curse * c, int self);

View File

@ -54,7 +54,7 @@ static message *cinfo_cursed_by_the_gods(const void *obj, objtype_t typ,
static struct curse_type ct_godcursezone = { static struct curse_type ct_godcursezone = {
"godcursezone", "godcursezone",
CURSETYP_NORM, CURSE_IMMUNE | CURSE_ISNEW, (NO_MERGE), CURSETYP_NORM, CURSE_IMMUNE, (NO_MERGE),
cinfo_cursed_by_the_gods, cinfo_cursed_by_the_gods,
}; };
@ -80,7 +80,7 @@ static message *cinfo_dreamcurse(const void *obj, objtype_t typ, const curse * c
static struct curse_type ct_gbdream = { static struct curse_type ct_gbdream = {
"gbdream", "gbdream",
CURSETYP_NORM, CURSE_ISNEW, (NO_MERGE), cinfo_dreamcurse CURSETYP_NORM, 0, (NO_MERGE), cinfo_dreamcurse
}; };
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -193,7 +193,7 @@ static struct curse_type ct_fogtrap = {
static struct curse_type ct_maelstrom = { static struct curse_type ct_maelstrom = {
"maelstrom", "maelstrom",
CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR),
cinfo_simple cinfo_simple
}; };
@ -227,7 +227,7 @@ static struct curse_type ct_drought = {
static struct curse_type ct_badlearn = { static struct curse_type ct_badlearn = {
"badlearn", "badlearn",
CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR),
cinfo_simple cinfo_simple
}; };

View File

@ -73,14 +73,14 @@ static message *cinfo_shipnodrift(const void *obj, objtype_t typ, const curse *
} }
static struct curse_type ct_stormwind = { "stormwind", static struct curse_type ct_stormwind = { "stormwind",
CURSETYP_NORM, 0, NO_MERGE, cinfo_ship CURSETYP_NORM, CURSE_NOAGE, NO_MERGE, cinfo_ship
}; };
static struct curse_type ct_nodrift = { "nodrift", static struct curse_type ct_nodrift = { "nodrift",
CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_shipnodrift CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_shipnodrift
}; };
static struct curse_type ct_shipspeedup = { "shipspeedup", const struct curse_type ct_shipspeedup = { "shipspeedup",
CURSETYP_NORM, 0, 0, cinfo_ship CURSETYP_NORM, 0, 0, cinfo_ship
}; };

View File

@ -22,6 +22,8 @@ extern "C" {
struct message; struct message;
struct curse; struct curse;
extern const struct curse_type ct_shipspeedup;
struct message *cinfo_ship(const void *obj, objtype_t typ, struct message *cinfo_ship(const void *obj, objtype_t typ,
const struct curse *c, int self); const struct curse *c, int self);
void register_shipcurse(void); void register_shipcurse(void);

View File

@ -170,7 +170,7 @@ message *cinfo_unit(const void *obj, objtype_t typ, const curse * c, int self)
static struct curse_type ct_orcish = { static struct curse_type ct_orcish = {
"orcish", "orcish",
CURSETYP_UNIT, CURSE_SPREADMODULO | CURSE_ISNEW, M_MEN, CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN,
cinfo_unit cinfo_unit
}; };