From 12222c6562a8d7b11504ac845086746a33d279ac Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 23 Jul 2017 09:08:03 +0200 Subject: [PATCH 01/20] first unit should get money and wood --- conf/e2/rules.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conf/e2/rules.xml b/conf/e2/rules.xml index 7bde2205f..45b9030d3 100644 --- a/conf/e2/rules.xml +++ b/conf/e2/rules.xml @@ -20,6 +20,11 @@ + + + + + From a5d350fe3a5ea68e246e3c1e1e059696b48b1256 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 23 Jul 2017 09:15:23 +0200 Subject: [PATCH 02/20] seed a single faction from newplayers file. --- src/gmtool.c | 64 ++++++++++++++++++++++++++++++++-------------------- src/gmtool.h | 1 - 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/gmtool.c b/src/gmtool.c index 674e139f7..6db857ad9 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -1,4 +1,4 @@ -/* +/* * +-------------------+ Christian Schlittchen * | | Enno Rehling * | Eressea PBEM host | Katja Zedel @@ -81,7 +81,7 @@ int gm_codepage = -1; static void unicode_remove_diacritics(const char *rp, char *wp) { while (*rp) { - if (gm_codepage >=0 && *rp & 0x80) { + if (gm_codepage >= 0 && *rp & 0x80) { size_t sz = 0; unsigned char ch; switch (gm_codepage) { @@ -115,7 +115,7 @@ int umvwprintw(WINDOW *win, int y, int x, const char *format, ...) { va_start(args, format); memset(buffer, 0, sizeof(buffer)); - vsnprintf(buffer, sizeof(buffer)-1, format, args); + vsnprintf(buffer, sizeof(buffer) - 1, format, args); va_end(args); simplify(buffer, buffer); @@ -344,7 +344,7 @@ map_region *cursor_region(const view * v, const coordinate * c) static void draw_cursor(WINDOW * win, selection * s, const view * v, const coordinate * c, -int show) + int show) { int lines = getmaxy(win) / THEIGHT; int xp, yp, nx, ny; @@ -814,7 +814,7 @@ static void select_regions(state * st, int selectmode) st->wnd_map->update |= 3; } -void loaddata(state *st) { +static void loaddata(state *st) { char datafile[MAX_PATH]; askstring(st->wnd_status->handle, "save as:", datafile, sizeof(datafile)); @@ -824,7 +824,7 @@ void loaddata(state *st) { } } -void savedata(state *st) { +static void savedata(state *st) { char datafile[MAX_PATH]; askstring(st->wnd_status->handle, "save as:", datafile, sizeof(datafile)); @@ -835,6 +835,20 @@ void savedata(state *st) { } } +static void seed_player(state *st, const newfaction *player) { + if (player) { + region *r; + int nx = st->cursor.x; + int ny = st->cursor.y; + + pnormalize(&nx, &ny, st->cursor.pl); + r = findregion(nx, ny); + if (r) { + addplayer(r, addfaction(player->email, player->password, player->race, + player->lang, player->subscription)); + } + } +} static void handlekey(state * st, int c) { window *wnd; @@ -897,10 +911,6 @@ static void handlekey(state * st, int c) loaddata(st); break; case 'B': - if (!new_players) { - join_path(basepath(), "newfactions", sbuffer, sizeof(sbuffer)); - new_players = read_newfactions(sbuffer); - } cnormalize(&st->cursor, &nx, &ny); minpop = config_get_int("editor.population.min", 8); maxpop = config_get_int("editor.population.max", minpop); @@ -1111,13 +1121,15 @@ static void handlekey(state * st, int c) else tag_region(st->selected, nx, ny); break; - case 'A': - if (!new_players) { - join_path(basepath(), "newfactions", sbuffer, sizeof(sbuffer)); - new_players = read_newfactions(sbuffer); + case 's': /* seed */ + if (new_players) { + newfaction * next = new_players->next; + seed_player(st, new_players); + free(new_players->email); + free(new_players->password); + free(new_players); + new_players = next; } - seed_players(&new_players, false); - st->wnd_map->update |= 1; break; case '/': statusline(st->wnd_status->handle, "find-"); @@ -1289,13 +1301,15 @@ void run_mapper(void) int split = 20; state *st; point tl; -/* FIXME: dsiable logging - int old_flags = log_flags; - log_flags &= ~(LOG_CPERROR | LOG_CPWARNING); -*/ + char sbuffer[512]; + + if (!new_players) { + join_path(basepath(), "newfactions", sbuffer, sizeof(sbuffer)); + new_players = read_newfactions(sbuffer); + } + init_curses(); curs_set(1); - set_readline(curses_readline); assert(stdscr); getbegyx(stdscr, x, y); @@ -1384,15 +1398,15 @@ void run_mapper(void) set_readline(NULL); curs_set(1); endwin(); -/* FIXME: reset logging - log_flags = old_flags; -*/ + /* FIXME: reset logging + log_flags = old_flags; + */ state_close(st); } int curses_readline(struct lua_State *L, char *buffer, size_t size, -const char *prompt) + const char *prompt) { UNUSED_ARG(L); askstring(hstatus, prompt, buffer, size); diff --git a/src/gmtool.h b/src/gmtool.h index 3a682f453..04f062f4b 100644 --- a/src/gmtool.h +++ b/src/gmtool.h @@ -22,7 +22,6 @@ extern "C" { struct terrain_type; struct newfaction; - int gmmain(int argc, char *argv[]); int curses_readline(struct lua_State *L, char *buffer, size_t size, const char *prompt); From 3151fe9f9bc8396d058c316b665375010f58c2f2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 23 Jul 2017 09:27:28 +0200 Subject: [PATCH 03/20] ignore comments in newfactions --- src/modules/autoseed.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index ffab4ca46..66013149c 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -157,9 +157,13 @@ newfaction *read_newfactions(const char *filename) password[0] = '\0'; if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus, - &subscription, password, &alliance) < 3) + &subscription, password, &alliance) < 3) { break; - if (email[0] == '\0') + } + if (email[0] == '#') { + continue; + } + if (email[0] == '\0') break; if (password[0] == '\0') { size_t sz; From 822292c99a68a235925dd6381be55e4c2c3358c8 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 27 Jul 2017 16:16:54 +0200 Subject: [PATCH 04/20] do not seed factions when creating islands with 'B'. --- src/gmtool.c | 2 +- src/modules/autoseed.c | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/gmtool.c b/src/gmtool.c index 6db857ad9..3e33203ce 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -920,7 +920,7 @@ static void handlekey(state * st, int c) else { n = minpop; } - build_island_e3(&new_players, nx, ny, n, n * 3); + build_island_e3(NULL, nx, ny, n, n * 3); st->modified = 1; st->wnd_info->update |= 1; st->wnd_status->update |= 1; diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index ffab4ca46..6ec945a09 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -784,13 +784,15 @@ const terrain_type * (*terraformer) (direction_t)) direction_t dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = rconnect(r, dir); - if (rn == NULL) { + if (rn == NULL || !rn->land) { 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); + if (!rn) { + 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) { @@ -946,7 +948,7 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi get_neighbours(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); minq = MIN(minq, q); maxq = MAX(maxq, q); @@ -961,7 +963,7 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi region *rn[MAXDIRECTIONS]; get_neighbours(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); minq = MIN(minq, q); maxq = MAX(maxq, q); From 847e6f3e43d7d7a905b583d704892b42204e6516 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 27 Jul 2017 16:36:45 +0200 Subject: [PATCH 05/20] limit island size from configuration, deal with existing units. --- src/bind_gmtool.c | 5 ++--- src/gmtool.c | 6 +++--- src/modules/autoseed.c | 21 ++++++++++++--------- src/modules/autoseed.h | 3 +-- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/bind_gmtool.c b/src/bind_gmtool.c index e4ae939f9..18efbd994 100644 --- a/src/bind_gmtool.c +++ b/src/bind_gmtool.c @@ -150,10 +150,9 @@ static int tolua_make_island(lua_State * L) int x = (int)tolua_tonumber(L, 1, 0); int y = (int)tolua_tonumber(L, 2, 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); - lua_pushinteger(L, n); + s = build_island_e3(x, y, s, NULL, 0); + lua_pushinteger(L, s); return 1; } diff --git a/src/gmtool.c b/src/gmtool.c index 3e33203ce..d9afd738e 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -912,15 +912,15 @@ static void handlekey(state * st, int c) break; case 'B': cnormalize(&st->cursor, &nx, &ny); - minpop = config_get_int("editor.population.min", 8); - maxpop = config_get_int("editor.population.max", minpop); + minpop = config_get_int("editor.island.min", 8); + maxpop = config_get_int("editor.island.max", minpop); if (maxpop > minpop) { n = rng_int() % (maxpop - minpop) + minpop; } else { n = minpop; } - build_island_e3(NULL, nx, ny, n, n * 3); + build_island_e3(nx, ny, n, NULL, 0); st->modified = 1; st->wnd_info->update |= 1; st->wnd_status->update |= 1; diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index 6ec945a09..a23c0554d 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -776,15 +776,15 @@ const terrain_type *random_terrain_e3(direction_t dir) return random_terrain(terrainarr, distribution, GEOMAX); } -int +static int random_neighbours(region * r, region_list ** rlist, -const terrain_type * (*terraformer) (direction_t)) +const terrain_type * (*terraformer) (direction_t), int n) { int nsize = 0; direction_t dir; for (dir = 0; dir != MAXDIRECTIONS; ++dir) { region *rn = rconnect(r, dir); - if (rn == NULL || !rn->land) { + if (rn == NULL || (!rn->units && !rn->land)) { const terrain_type *terrain = terraformer(dir); if (!rn) { plane *pl = rplane(r); @@ -796,7 +796,9 @@ const terrain_type * (*terraformer) (direction_t)) terraform_region(rn, terrain); regionqueue_push(rlist, rn); if (rn->land) { - ++nsize; + if (++nsize >= n) { + break; + } } } } @@ -906,7 +908,7 @@ static void starting_region(newfaction ** players, region * r, region * rn[]) } /* 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 int nfactions = 0; @@ -917,9 +919,10 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi int nsize = 1; 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); - assert(!r->units); + } do { terraform_region(r, random_terrain_e3(NODIRECTION)); } while (!r->land); @@ -928,10 +931,10 @@ int build_island_e3(newfaction ** players, int x, int y, int numfactions, int mi fset(r, RF_MARK); if (r->land) { if (nsize < minsize) { - nsize += random_neighbours(r, &rlist, &random_terrain_e3); + nsize += random_neighbours(r, &rlist, &random_terrain_e3, minsize-nsize); } else { - nsize += random_neighbours(r, &rlist, &get_ocean); + nsize += random_neighbours(r, &rlist, &get_ocean, minsize - nsize); } } regionqueue_push(&island, r); diff --git a/src/modules/autoseed.h b/src/modules/autoseed.h index 06ce646c2..65bdccb7f 100644 --- a/src/modules/autoseed.h +++ b/src/modules/autoseed.h @@ -38,8 +38,7 @@ extern "C" { extern const struct terrain_type *random_terrain(const struct terrain_type *terrains[], int distribution[], int size); - extern int seed_adamantium(struct region *r, int base); - extern int build_island_e3(newfaction **players, int x, int y, int numfactions, int minsize); + extern int build_island_e3(int x, int y, int minsize, newfaction **players, int numfactions); #ifdef __cplusplus } From 594cbc4a05c6c81ef06f332f547d655823ba894b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 30 Jul 2017 11:10:06 +0200 Subject: [PATCH 06/20] Neuer Email Body, mit Patreon Link. --- etc/report-mail.de.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/etc/report-mail.de.txt b/etc/report-mail.de.txt index e40d86b53..42f7503d2 100644 --- a/etc/report-mail.de.txt +++ b/etc/report-mail.de.txt @@ -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 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/) + +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. From 4675cf1d05834c4018e69385b899383b4be2e790 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 30 Jul 2017 14:05:33 +0200 Subject: [PATCH 07/20] allow config to override first unit equipment --- src/kernel/faction.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index ae60ce439..e804534c4 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -286,12 +286,14 @@ faction *addfaction(const char *email, const char *password, unit *addplayer(region * r, faction * f) { unit *u; + const char * name; const struct equipment* eq; assert(f->units == NULL); faction_setorigin(f, 0, r->x, r->y); 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) { equip_items(&u->items, eq); } From c387e985b8c02a87cf9ea60caef3ce85e0aaa325 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 7 Aug 2017 18:38:10 +0200 Subject: [PATCH 08/20] gmtool can clear regions --- src/chaos.c | 13 +++++++++++++ src/chaos.h | 1 + src/gmtool.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/src/chaos.c b/src/chaos.c index 58cd7af73..abd74b5d9 100644 --- a/src/chaos.c +++ b/src/chaos.c @@ -53,6 +53,19 @@ attrib_type at_chaoscount = { 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) { attrib *a = a_find(r->attribs, &at_chaoscount); diff --git a/src/chaos.h b/src/chaos.h index 6e62a0d17..0c2667083 100644 --- a/src/chaos.h +++ b/src/chaos.h @@ -29,6 +29,7 @@ extern "C" { void chaos_register(void); void chaos_update(void); + void set_chaoscount(struct region *r, int deaths); int get_chaoscount(const struct region * r); void add_chaoscount(struct region * r, int deaths); diff --git a/src/gmtool.c b/src/gmtool.c index d9afd738e..24c1735e8 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -15,6 +15,7 @@ #include "gmtool.h" #include "gmtool_structs.h" +#include "chaos.h" #include "console.h" #include "listbox.h" #include "wormhole.h" @@ -45,6 +46,7 @@ #include #include +#include #include #include #include @@ -515,6 +517,46 @@ static void statusline(WINDOW * win, const char *str) 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) { if (terrain != NULL) { @@ -934,6 +976,12 @@ static void handlekey(state * st, int c) st->wnd_status->update |= 1; st->wnd_map->update |= 1; break; + case 'c': /* clear/reset */ + reset_cursor(st); + break; + case 'C': /* clear/reset */ + reset_rect(st); + break; case 0x09: /* tab = next selected */ if (regions != NULL) { map_region *mr = cursor_region(&st->display, cursor); From 2aab736b5911e1f53f0412082a3347d297db4329 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 7 Aug 2017 18:58:39 +0200 Subject: [PATCH 09/20] try giving new factions a name --- src/gmtool.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/gmtool.c b/src/gmtool.c index 24c1735e8..a07feab43 100644 --- a/src/gmtool.c +++ b/src/gmtool.c @@ -886,8 +886,20 @@ static void seed_player(state *st, const newfaction *player) { pnormalize(&nx, &ny, st->cursor.pl); r = findregion(nx, ny); if (r) { - addplayer(r, addfaction(player->email, player->password, player->race, - player->lang, player->subscription)); + const char *at = strchr(player->email, '@'); + 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 && lenemail, len); + fname[len]=0; + faction_setname(f, fname); + } + } } } } From 1aa142d8214d865231ea37ac8878793052a68f0a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 9 Aug 2017 19:04:49 +0200 Subject: [PATCH 10/20] log warnings for duplicate new emails. --- src/modules/autoseed.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index ad8eb6731..efb61245e 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -16,7 +16,7 @@ #include "market.h" -/* kernel includes */ + /* kernel includes */ #include #include #include @@ -94,7 +94,7 @@ static int count_demand(const region * r) static int recurse_regions(region * r, region_list ** rlist, -bool(*fun) (const region * r)) + bool(*fun) (const region * r)) { if (!fun(r)) return 0; @@ -159,12 +159,13 @@ newfaction *read_newfactions(const char *filename) if (sscanf(buf, "%54s %20s %8s %d %d %16s %d", email, race, lang, &bonus, &subscription, password, &alliance) < 3) { break; - } - if (email[0] == '#') { + } + if (email[0] == '#') { continue; } - if (email[0] == '\0') + if (email[0] == '\0') { break; + } if (password[0] == '\0') { size_t sz; sz = strlcpy(password, itoa36(rng_int()), sizeof(password)); @@ -172,17 +173,22 @@ newfaction *read_newfactions(const char *filename) } for (f = factions; f; f = f->next) { if (strcmp(f->email, email) == 0 && f->subscription - && f->age < MINAGE_MULTI) + && f->age < MINAGE_MULTI) { + log_warning("email %s already in use by %s", email, factionname(f)); 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) + if (strcmp(nf->email, email) == 0) { + log_warning("duplicate new faction %s", email); break; + } } - if (nf) + 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); @@ -782,7 +788,7 @@ const terrain_type *random_terrain_e3(direction_t dir) static int random_neighbours(region * r, region_list ** rlist, -const terrain_type * (*terraformer) (direction_t), int n) + const terrain_type * (*terraformer) (direction_t), int n) { int nsize = 0; direction_t dir; @@ -935,7 +941,7 @@ int build_island_e3(int x, int y, int minsize, newfaction ** players, int numfac fset(r, RF_MARK); if (r->land) { if (nsize < minsize) { - nsize += random_neighbours(r, &rlist, &random_terrain_e3, minsize-nsize); + nsize += random_neighbours(r, &rlist, &random_terrain_e3, minsize - nsize); } else { nsize += random_neighbours(r, &rlist, &get_ocean, minsize - nsize); @@ -993,7 +999,7 @@ int build_island_e3(int x, int y, int minsize, newfaction ** players, int numfac rsetmoney(r, 50000); /* 2% = 1000 silver */ } else if (r->land) { - rsetmoney(r, rmoney(r) *4); + rsetmoney(r, rmoney(r) * 4); } } return nfactions; From bbeac6625075aa7457c3e97d2a3efce9b0a47150 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 9 Aug 2017 19:18:45 +0200 Subject: [PATCH 11/20] fix dupe detection --- src/modules/autoseed.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index efb61245e..343c742ee 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -172,8 +172,7 @@ newfaction *read_newfactions(const char *filename) sz += strlcat(password, itoa36(rng_int()), sizeof(password)); } for (f = factions; f; f = f->next) { - if (strcmp(f->email, email) == 0 && f->subscription - && f->age < MINAGE_MULTI) { + if (strcmp(f->email, email) == 0 && f->age < MINAGE_MULTI) { log_warning("email %s already in use by %s", email, factionname(f)); break; } From c4f7e36903cb8bc12e5dbfd01dbe04c6350ef46d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 9 Aug 2017 19:39:29 +0200 Subject: [PATCH 12/20] fix valgrind report in a test (bad rtype construction) --- src/economy.test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/economy.test.c b/src/economy.test.c index 802610880..83c103f7f 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -499,11 +499,12 @@ static void test_modify_production(CuTest *tc) { CuAssertIntEquals(tc, 11, get_item(u, itype)); 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].race = u->_race; rtype->modifiers[0].value.sa[0] = (short)(0.5+100*d); rtype->modifiers[0].value.sa[1] = 100; + rtype->modifiers[1].type = RMT_END; make_item(u, itype, 10); split_allocations(u->region); 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].race = u_race(u); rtype->modifiers[1].btype = NULL; + rtype->modifiers[2].type = RMT_END; test_clear_messages(u->faction); make_item(u, itype, 10); From 62d8024c49507afd20c07ff4a280901d17cd511e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 9 Aug 2017 19:18:45 +0200 Subject: [PATCH 13/20] fix dupe detection --- src/modules/autoseed.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index efb61245e..343c742ee 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -172,8 +172,7 @@ newfaction *read_newfactions(const char *filename) sz += strlcat(password, itoa36(rng_int()), sizeof(password)); } for (f = factions; f; f = f->next) { - if (strcmp(f->email, email) == 0 && f->subscription - && f->age < MINAGE_MULTI) { + if (strcmp(f->email, email) == 0 && f->age < MINAGE_MULTI) { log_warning("email %s already in use by %s", email, factionname(f)); break; } From 9d8e9cc00b4080737f9e83822110b7e0ac270c93 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 16 Aug 2017 20:48:03 +0200 Subject: [PATCH 14/20] at_keys is overflowing, add an assert to detect it --- src/attributes/key.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/attributes/key.c b/src/attributes/key.c index 31580bccf..e28788002 100644 --- a/src/attributes/key.c +++ b/src/attributes/key.c @@ -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) { int i, *keys = (int *)a->data.v; + assert(keys[0] < 4096 && keys[0]>0); WRITE_INT(store, keys[0]); for (i = 0; i < keys[0]; ++i) { WRITE_INT(store, keys[i * 2 + 1]); @@ -105,7 +106,8 @@ static void a_upgradekeys(attrib **alist, attrib *abegin) { if (ak) { ak->data.v = keys; if (keys) { - keys[0] = n + i; + keys[0] = i + n; + assert(keys[0] < 4096 && keys[0]>=0); } } } @@ -136,6 +138,7 @@ void key_set(attrib ** alist, int key, int val) keys = realloc(keys, sizeof(int) *(2 * n + 3)); /* TODO: does insertion sort pay off here? prob. not. */ keys[0] = n + 1; + assert(keys[0] < 4096 && keys[0]>=0); keys[2 * n + 1] = key; keys[2 * n + 2] = val; a->data.v = keys; @@ -150,6 +153,7 @@ void key_unset(attrib ** alist, int key) int i, *keys = (int *)a->data.v; if (keys) { int n = keys[0]; + assert(keys[0] < 4096 && keys[0]>0); for (i = 0; i != n; ++i) { if (keys[2 * i + 1] == key) { memmove(keys + 2 * i + 1, keys + 2 * n - 1, 2 * sizeof(int)); From 6d050bb6c2b4c288e30073aff6312deedca4b507 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 16 Aug 2017 21:33:02 +0200 Subject: [PATCH 15/20] fix a_key attribute still being written. simplify (and slow down) key upgrades. --- src/attributes/key.c | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/src/attributes/key.c b/src/attributes/key.c index e28788002..27347097f 100644 --- a/src/attributes/key.c +++ b/src/attributes/key.c @@ -79,36 +79,12 @@ attrib_type at_keys = { }; static void a_upgradekeys(attrib **alist, attrib *abegin) { - int n = 0, *keys = 0; - int i = 0, val[8]; - attrib *a, *ak = a_find(*alist, &at_keys); - if (ak) { - keys = (int *)ak->data.v; - if (keys) n = keys[0]; - } + attrib *a, *ak; + + ak = a_find(*alist, &at_keys); + if (ak) alist = &ak; for (a = abegin; a && a->type == abegin->type; a = a->next) { - val[i * 2] = a->data.i; - 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] = i + n; - assert(keys[0] < 4096 && keys[0]>=0); - } + key_set(alist, a->data.i, 1); } } @@ -117,7 +93,7 @@ attrib_type at_key = { NULL, NULL, NULL, - a_writeint, + NULL, a_readkey, a_upgradekeys }; @@ -135,8 +111,8 @@ void key_set(attrib ** alist, int key, int val) if (keys) { n = keys[0]; } + /* TODO: too many allocations, unsorted array */ keys = realloc(keys, sizeof(int) *(2 * n + 3)); - /* TODO: does insertion sort pay off here? prob. not. */ keys[0] = n + 1; assert(keys[0] < 4096 && keys[0]>=0); keys[2 * n + 1] = key; @@ -172,6 +148,7 @@ int key_get(attrib *alist, int key) { if (a) { int i, *keys = (int *)a->data.v; if (keys) { + /* TODO: binary search this! */ for (i = 0; i != keys[0]; ++i) { if (keys[i*2+1] == key) { return keys[i * 2 + 2]; From a8e9da1c1953a6abd95a6bcf1538e04e1a3ae9bf Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 16 Aug 2017 21:48:04 +0200 Subject: [PATCH 16/20] do not upgrade keys for later data versions --- src/attributes/key.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/attributes/key.c b/src/attributes/key.c index 27347097f..1bd5cd9b4 100644 --- a/src/attributes/key.c +++ b/src/attributes/key.c @@ -61,6 +61,9 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) { static int a_readkey(attrib *a, void *owner, struct gamedata *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; } From 293cb78de8a84cf087a425d4045f0d6b12e25a17 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 19:36:17 +0200 Subject: [PATCH 17/20] BUG 2356: add a failing test. --- src/kernel/curse.test.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/kernel/curse.test.c b/src/kernel/curse.test.c index 56c3288f8..a9271f897 100644 --- a/src/kernel/curse.test.c +++ b/src/kernel/curse.test.c @@ -106,7 +106,7 @@ static void test_memstream(CuTest *tc) { storage store; stream out = { 0 }; char buf[1024]; - int val=0; + int val = 0; mstream_init(&out); binstore_init(&store, &out); @@ -137,11 +137,13 @@ static void test_write_flag(CuTest *tc) { mstream_init(&data.strm); gamedata_init(&data, &store, RELEASE_VERSION); - setup_curse(&fix, "gbdream"); + setup_curse(&fix, "magicwalls"); c = fix.c; r = fix.r; 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); free_gamedata(); data.strm.api->rewind(data.strm.handle); @@ -150,7 +152,7 @@ static void test_write_flag(CuTest *tc) { CuAssertPtrNotNull(tc, r); CuAssertPtrNotNull(tc, r->attribs); 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); gamedata_done(&data); @@ -160,7 +162,7 @@ static void test_write_flag(CuTest *tc) { static void test_curse_cache(CuTest *tc) { int cache = 0; - const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL }; + const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL }; test_setup(); CuAssertIntEquals(tc, true, ct_changed(&cache)); CuAssertIntEquals(tc, false, ct_changed(&cache)); From c8b2ce79002fb7a662438eaaf460e2a6685f8ea2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 18:42:59 +0200 Subject: [PATCH 18/20] BUG 2356: fix curse read/write rename curse::flags to curse::mask, use c_flags. fix some curse_type having CURSE_ISNEW fixed. --- src/battle.c | 5 ++--- src/battle.test.c | 8 +++++--- src/items.c | 4 ++-- src/kernel/curse.c | 25 ++++++++----------------- src/kernel/curse.h | 4 ++-- src/kernel/ship.c | 3 ++- src/kernel/ship.test.c | 2 +- src/laws.c | 5 ++--- src/spells.c | 2 +- src/spells/buildingcurse.c | 2 +- src/spells/buildingcurse.h | 3 +++ src/spells/regioncurse.c | 8 ++++---- src/spells/shipcurse.c | 4 ++-- src/spells/shipcurse.h | 2 ++ src/spells/unitcurse.c | 2 +- 15 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/battle.c b/src/battle.c index 19f30e59c..a9130f2ef 100644 --- a/src/battle.c +++ b/src/battle.c @@ -54,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* util includes */ #include @@ -1905,9 +1906,7 @@ int skilldiff(troop at, troop dt, int dist) skdiff -= beff; is_protected = 2; if (b->attribs) { - const curse_type *magicwalls_ct = ct_find("magicwalls"); - if (magicwalls_ct - && curse_active(get_curse(b->attribs, magicwalls_ct))) { + if (curse_active(get_curse(b->attribs, &ct_magicwalls))) { /* Verdoppelt Burgenbonus */ skdiff -= beff; } diff --git a/src/battle.test.c b/src/battle.test.c index b00d06a98..290ef6d74 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -11,6 +11,9 @@ #include #include #include + +#include + #include #include @@ -463,12 +466,11 @@ static void test_battle_skilldiff_building(CuTest *tc) unit *ua, *ud; battle *b = NULL; building_type *btype; - const curse_type *strongwall_ct, *magicwalls_ct; + const curse_type *strongwall_ct; test_setup(); btype = setup_castle(); strongwall_ct = ct_find("strongwall"); - magicwalls_ct = ct_find("magicwalls"); r = test_create_region(0, 0, 0); ud = test_create_unit(test_create_faction(0), r); @@ -484,7 +486,7 @@ static void test_battle_skilldiff_building(CuTest *tc) ud->building->size = 10; 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)); create_curse(NULL, &ud->building->attribs, strongwall_ct, 1, 1, 2, 1); diff --git a/src/items.c b/src/items.c index 0f97ea675..37299563f 100644 --- a/src/items.c +++ b/src/items.c @@ -22,6 +22,7 @@ #include #include +#include /* triggers includes */ #include @@ -97,9 +98,8 @@ struct order *ord) } effect = SPEEDSAIL_EFFECT; - c = create_curse(u, &sh->attribs, ct_find("shipspeedup"), 20, INT_MAX, + c = create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, effect, 0); - c_setflag(c, CURSE_NOAGE); ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u, SPEEDSAIL_EFFECT)); diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 01e77eace..5b881eb82 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -61,14 +61,14 @@ static curse *cursehash[MAXENTITYHASH]; void c_setflag(curse * c, unsigned int flags) { 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) { assert(c); - c->flags = (c->flags & ~flags) | (c->type->flags & flags); + c->mask = (c->mask & ~flags) | (c->type->flags & flags); } void chash(curse * c) @@ -180,14 +180,13 @@ int curse_read(attrib * a, void *owner, gamedata *data) int ur; char cursename[64]; int n; - int flags; float flt; assert(!c->no); READ_INT(store, &c->no); chash(c); READ_TOK(store, cursename, sizeof(cursename)); - READ_INT(store, &flags); + READ_INT(store, &c->mask); READ_INT(store, &c->duration); READ_FLT(store, &flt); c->vigour = flt; @@ -214,7 +213,6 @@ int curse_read(attrib * a, void *owner, gamedata *data) assert(result == 0); return AT_READ_FAIL; } - c->flags = flags; if (data->version < EXPLICIT_CURSE_ISNEW_VERSION) { 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) { - unsigned int flags; curse *c = (curse *)a->data.v; const curse_type *ct = c->type; 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_TOK(store, ct->cname); - WRITE_INT(store, flags); + WRITE_INT(store, c->mask); WRITE_INT(store, c->duration); WRITE_FLT(store, (float)c->vigour); write_unit_reference(mage, store); @@ -306,6 +296,7 @@ void ct_register(const curse_type * ct) selist **ctlp = cursetypes + hash; assert(ct->age==NULL || (ct->flags&CURSE_NOAGE) == 0); + assert((ct->flags&CURSE_ISNEW) == 0); selist_set_insert(ctlp, (void *)ct, NULL); ++ct_changes; } @@ -553,7 +544,7 @@ static curse *make_curse(unit * mage, attrib ** ap, const curse_type * ct, c = (curse *)a->data.v; c->type = ct; - c->flags = 0; + c->mask = 0; c->vigour = vigour; c->duration = duration; c->effect = effect; @@ -638,7 +629,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) bool dogive = false; const curse_type *ct = c->type; - switch ((ct->flags | c->flags) & CURSE_SPREADMASK) { + switch (c_flags(c) & CURSE_SPREADMASK) { case CURSE_SPREADALWAYS: dogive = true; men = u2->number + n; @@ -671,7 +662,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) if (dogive) { curse *cnew = make_curse(c->magician, &u2->attribs, c->type, c->vigour, c->duration, c->effect, men); - cnew->flags = c->flags; + cnew->mask = c->mask; if (ct->typ == CURSETYP_UNIT) set_cursedmen(cnew, men); diff --git a/src/kernel/curse.h b/src/kernel/curse.h index 543755c2b..b28427fcd 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -187,7 +187,7 @@ extern "C" { /* ------------------------------------------------------------- */ /* 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 effect; 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 */ } curse; diff --git a/src/kernel/ship.c b/src/kernel/ship.c index 220c16619..234a91631 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -42,6 +42,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include #include #include @@ -365,7 +366,7 @@ int shipspeed(const ship * sh, const unit * u) a = a->next; } - c = get_curse(sh->attribs, ct_find("shipspeedup")); + c = get_curse(sh->attribs, &ct_shipspeedup); while (c) { k += curse_geteffect_int(c); c = c->nexthash; diff --git a/src/kernel/ship.test.c b/src/kernel/ship.test.c index b003f74b9..541ddee9a 100644 --- a/src/kernel/ship.test.c +++ b/src/kernel/ship.test.c @@ -462,7 +462,7 @@ static void test_shipspeed_shipspeedup(CuTest *tc) { register_shipcurse(); 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)); test_cleanup(); } diff --git a/src/laws.c b/src/laws.c index e16cbd583..5c7d36b51 100644 --- a/src/laws.c +++ b/src/laws.c @@ -70,6 +70,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* util includes */ #include @@ -3885,7 +3886,6 @@ int siege_cmd(unit * u, order * ord) building *b; int d, pooled; int bewaffnete, katapultiere = 0; - const curse_type *magicwalls_ct; resource_type *rt_catapultammo = NULL; resource_type *rt_catapult = NULL; @@ -3904,7 +3904,6 @@ int siege_cmd(unit * u, order * ord) } /* schaden durch katapulte */ - magicwalls_ct = ct_find("magicwalls"); rt_catapultammo = rt_find("catapultammo"); rt_catapult = rt_find("catapult"); @@ -3945,7 +3944,7 @@ int siege_cmd(unit * u, order * ord) d = MIN(d, b->size - 1); /* 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; use_pooled(u, rt_catapultammo, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, d); diff --git a/src/spells.c b/src/spells.c index 0c6bb2722..7931be8b8 100644 --- a/src/spells.c +++ b/src/spells.c @@ -2072,7 +2072,7 @@ static int sp_homestone(castorder * co) 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); if (c == NULL) { diff --git a/src/spells/buildingcurse.c b/src/spells/buildingcurse.c index 9c87aaba4..f1a3b3773 100644 --- a/src/spells/buildingcurse.c +++ b/src/spells/buildingcurse.c @@ -75,7 +75,7 @@ CURSETYP_NORM, 0, M_SUMEFFECT, cinfo_magicrunes }; /* 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 }; diff --git a/src/spells/buildingcurse.h b/src/spells/buildingcurse.h index 46989829a..2150dc3b6 100644 --- a/src/spells/buildingcurse.h +++ b/src/spells/buildingcurse.h @@ -21,6 +21,9 @@ extern "C" { struct locale; struct curse; struct message; + struct curse_type; + + extern const struct curse_type ct_magicwalls; extern void register_buildingcurse(void); struct message *cinfo_building(const void *obj, objtype_t typ, const struct curse * c, int self); diff --git a/src/spells/regioncurse.c b/src/spells/regioncurse.c index b10f3046f..1d69574df 100644 --- a/src/spells/regioncurse.c +++ b/src/spells/regioncurse.c @@ -57,7 +57,7 @@ static message *cinfo_cursed_by_the_gods(const void *obj, objtype_t typ, static struct curse_type ct_godcursezone = { "godcursezone", - CURSETYP_NORM, CURSE_IMMUNE | CURSE_ISNEW, (NO_MERGE), + CURSETYP_NORM, CURSE_IMMUNE, (NO_MERGE), cinfo_cursed_by_the_gods, }; @@ -83,7 +83,7 @@ static message *cinfo_dreamcurse(const void *obj, objtype_t typ, const curse * c static struct curse_type ct_gbdream = { "gbdream", - CURSETYP_NORM, CURSE_ISNEW, (NO_MERGE), cinfo_dreamcurse + CURSETYP_NORM, 0, (NO_MERGE), cinfo_dreamcurse }; /* --------------------------------------------------------------------- */ @@ -196,7 +196,7 @@ static struct curse_type ct_fogtrap = { static struct curse_type ct_maelstrom = { "maelstrom", - CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), + CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; @@ -214,7 +214,7 @@ static struct curse_type ct_drought = { static struct curse_type ct_badlearn = { "badlearn", - CURSETYP_NORM, CURSE_ISNEW, (M_DURATION | M_VIGOUR), + CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; diff --git a/src/spells/shipcurse.c b/src/spells/shipcurse.c index b6a722ad3..0295695a1 100644 --- a/src/spells/shipcurse.c +++ b/src/spells/shipcurse.c @@ -73,14 +73,14 @@ static message *cinfo_shipnodrift(const void *obj, objtype_t typ, const curse * } 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", 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 }; diff --git a/src/spells/shipcurse.h b/src/spells/shipcurse.h index 9ac57b142..a41f9edee 100644 --- a/src/spells/shipcurse.h +++ b/src/spells/shipcurse.h @@ -22,6 +22,8 @@ extern "C" { struct message; struct curse; + extern const struct curse_type ct_shipspeedup; + struct message *cinfo_ship(const void *obj, objtype_t typ, const struct curse *c, int self); void register_shipcurse(void); diff --git a/src/spells/unitcurse.c b/src/spells/unitcurse.c index ded4a1676..0a19629f1 100644 --- a/src/spells/unitcurse.c +++ b/src/spells/unitcurse.c @@ -170,7 +170,7 @@ message *cinfo_unit(const void *obj, objtype_t typ, const curse * c, int self) static struct curse_type ct_orcish = { "orcish", - CURSETYP_UNIT, CURSE_SPREADMODULO | CURSE_ISNEW, M_MEN, + CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, cinfo_unit }; From 7a4a49160c8337479c53da9a8a25129e45f2ba0e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 19:48:34 +0200 Subject: [PATCH 19/20] unused variable --- src/items.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/items.c b/src/items.c index 37299563f..e33aed1bc 100644 --- a/src/items.c +++ b/src/items.c @@ -89,7 +89,6 @@ static int use_speedsail(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { - curse *c; double effect; ship *sh = u->ship; if (!sh) { @@ -98,8 +97,7 @@ struct order *ord) } effect = SPEEDSAIL_EFFECT; - c = create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, - effect, 0); + create_curse(u, &sh->attribs, &ct_shipspeedup, 20, INT_MAX, effect, 0); ADDMSG(&u->faction->msgs, msg_message("use_speedsail", "unit speed", u, SPEEDSAIL_EFFECT)); From aa618609964a794449f4d6f96ae67fa86784e986 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 18 Aug 2017 20:20:12 +0200 Subject: [PATCH 20/20] BUG 2357: make sure starting regions have enough recruits --- src/kernel/faction.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index e804534c4..0b099df0f 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -283,12 +283,20 @@ faction *addfaction(const char *email, const char *password, return f; } +#define PEASANT_MIN (10 * RECRUITFRACTION) +#define PEASANT_MAX (20 * RECRUITFRACTION) + unit *addplayer(region * r, faction * f) { unit *u; const char * name; 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); faction_setorigin(f, 0, r->x, r->y); u = create_unit(r, f, 1, f->race, 0, NULL, NULL);