From 87873702ca18de73a3711917ad2b0780469bed09 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 24 Sep 2016 20:31:31 +0200 Subject: [PATCH 01/57] eliminate RS_FARVISION enum, there is no other kind of RC_SPELL. --- src/battle.c | 75 +++++++++++++++++++++++++-------------------- src/kernel/config.h | 1 + src/magic.h | 6 ---- src/main.c | 3 ++ src/reports.c | 19 ++---------- src/reports.test.c | 24 +++++++++++++++ src/spells.c | 7 ++--- 7 files changed, 75 insertions(+), 60 deletions(-) diff --git a/src/battle.c b/src/battle.c index 1bbaaadfe..aa0c486eb 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1649,11 +1649,51 @@ static castorder * create_castorder_combat(castorder *co, fighter *fig, const sp return co; } +#ifdef FFL_CURSED +static void summon_igjarjuk(battle *b, spellrank spellranks[]) { + side *s; + castorder *co; + + for (s = b->sides; s != b->sides + b->nsides; ++s) { + fighter *fig = 0; + if (s->bf->attacker && fval(s->faction, FFL_CURSED)) { + spell *sp = find_spell("igjarjuk"); + if (sp) { + int si; + for (si = 0; s->enemies[si]; ++si) { + side *se = s->enemies[si]; + if (se && !fval(se->faction, FFL_NPC)) { + fighter *fi; + for (fi = se->fighters; fi; fi = fi->next) { + if (fi && (!fig || fig->unit->number > fi->unit->number)) { + fig = fi; + if (fig->unit->number == 1) { + break; + } + } + } + if (fig && fig->unit->number == 1) { + break; + } + } + } + if (fig) { + co = create_castorder_combat(0, fig, sp, 10, 10); + co->magician.fig = fig; + add_castorder(&spellranks[sp->rank], co); + break; + } + } + } + } +} +#endif + void do_combatmagic(battle * b, combatmagic_t was) { side *s; - region *r = b->region; castorder *co; + region *r = b->region; int level, rank, sl; spellrank spellranks[MAX_SPELLRANK]; @@ -1661,38 +1701,7 @@ void do_combatmagic(battle * b, combatmagic_t was) #ifdef FFL_CURSED if (was == DO_PRECOMBATSPELL) { - for (s = b->sides; s != b->sides + b->nsides; ++s) { - fighter *fig = 0; - if (s->bf->attacker && fval(s->faction, FFL_CURSED)) { - spell *sp = find_spell("igjarjuk"); - if (sp) { - int si; - for (si = 0; s->enemies[si]; ++si) { - side *se = s->enemies[si]; - if (se && !fval(se->faction, FFL_NPC)) { - fighter *fi; - for (fi = se->fighters; fi; fi = fi->next) { - if (fi && (!fig || fig->unit->number > fi->unit->number)) { - fig = fi; - if (fig->unit->number == 1) { - break; - } - } - } - if (fig && fig->unit->number == 1) { - break; - } - } - } - if (fig) { - co = create_castorder_combat(0, fig, sp, 10, 10); - co->magician.fig = fig; - add_castorder(&spellranks[sp->rank], co); - break; - } - } - } - } + summon_igjarjuk(b, spellranks); } #endif for (s = b->sides; s != b->sides + b->nsides; ++s) { diff --git a/src/kernel/config.h b/src/kernel/config.h index 74565e25e..c3b758f48 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -159,6 +159,7 @@ struct param; unsigned int data_turn; void *vm_state; int data_version; /* TODO: eliminate in favor of gamedata.version */ + int debug; struct _dictionary_ *inifile; struct global_functions { int(*wage) (const struct region * r, const struct faction * f, diff --git a/src/magic.h b/src/magic.h index 257ba11c4..59ef92475 100644 --- a/src/magic.h +++ b/src/magic.h @@ -184,12 +184,6 @@ extern "C" { SPC_LINEAR /* Komponenten pro Level und müssen vorhanden sein */ }; - enum { - RS_DUMMY, - RS_FARVISION, - MAX_REGIONSPELLS - }; - /* ------------------------------------------------------------- */ /* Prototypen */ diff --git a/src/main.c b/src/main.c index 58a15edc0..086197d29 100644 --- a/src/main.c +++ b/src/main.c @@ -184,6 +184,9 @@ static int parse_args(int argc, char **argv, int *exitcode) else { const char *arg; switch (argi[1]) { + case 'd': // check configuration for consistency + i = get_arg(argc, argv, 2, i, &arg, 0); + global.debug = arg ? atoi(arg) : 0xff; case 'r': i = get_arg(argc, argv, 2, i, &arg, 0); config_set("config.rules", arg); diff --git a/src/reports.c b/src/reports.c index ff076a866..dc0edf1b3 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1308,17 +1308,6 @@ static void cb_add_seen(region *r, unit *u, void *cbdata) { } } -static bool unit_cansee(const unit *u) -{ - const race *rc = u_race(u); - static const race *rc_spell; - static int rc_cache; - if (rc_changed(&rc_cache)) { - rc_spell = get_race(RC_SPELL); - } - return (rc!=rc_spell || u->number == RS_FARVISION); -} - /** set region.seen based on visibility by one faction. * * this function may also update ctx->last and ctx->first for potential @@ -1355,9 +1344,7 @@ void prepare_report(report_context *ctx, faction *f) u = building_owner(b); if (u && u->faction==f) { prepare_lighthouse(b, ctx); - if (unit_cansee(u)) { - add_seen_nb(f, r, seen_unit); - } + add_seen_nb(f, r, seen_unit); } } } @@ -1366,9 +1353,7 @@ void prepare_report(report_context *ctx, faction *f) } for (u = r->units; u; u = u->next) { if (u->faction==f) { - if (unit_cansee(u)) { - add_seen_nb(f, r, seen_unit); - } + add_seen_nb(f, r, seen_unit); if (fval(r, RF_LIGHTHOUSE)) { if (u->building && u->building->type == bt_lighthouse && inside_building(u)) { /* we are in a lighthouse. add the regions we can see from here! */ diff --git a/src/reports.test.c b/src/reports.test.c index d9b427ff2..d5801ebab 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -425,6 +425,29 @@ static void test_seen_travelthru(CuTest *tc) { test_cleanup(); } +static void test_report_far_vision(CuTest *tc) { + unit *u1, *u2; + faction *f; + region *r1, *r2; + const race *rc; + test_setup(); + f = test_create_faction(0); + r1 = test_create_region(0, 0, 0); + u1 = test_create_unit(f, r1); + r2 = test_create_region(10, 0, 0); + rc = test_create_race("spell"); + u2 = create_unit(r2, u1->faction, 1, rc, 0, "spell/dreamreading", NULL); + set_number(u2, 1); + report_context ctx; + prepare_report(&ctx, f); + CuAssertPtrEquals(tc, r1, ctx.first); + CuAssertPtrEquals(tc, 0, ctx.last); + CuAssertIntEquals(tc, seen_unit, r1->seen.mode); + CuAssertIntEquals(tc, seen_unit, r2->seen.mode); + finish_reports(&ctx); + test_cleanup(); +} + CuSuite *get_reports_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -434,6 +457,7 @@ CuSuite *get_reports_suite(void) SUITE_ADD_TEST(suite, test_prepare_lighthouse); SUITE_ADD_TEST(suite, test_prepare_lighthouse_capacity); SUITE_ADD_TEST(suite, test_prepare_travelthru); + SUITE_ADD_TEST(suite, test_report_far_vision); SUITE_ADD_TEST(suite, test_reorder_units); SUITE_ADD_TEST(suite, test_seen_faction); SUITE_ADD_TEST(suite, test_regionid); diff --git a/src/spells.c b/src/spells.c index 4f2d49d9d..84700926c 100644 --- a/src/spells.c +++ b/src/spells.c @@ -4168,7 +4168,7 @@ static int sp_pump(castorder * co) } u = - create_unit(rt, mage->faction, RS_FARVISION, get_race(RC_SPELL), 0, + create_unit(rt, mage->faction, 1, get_race(RC_SPELL), 0, "spell/pump", NULL); u->age = 2; set_level(u, SK_PERCEPTION, effskill(target, SK_PERCEPTION, 0)); @@ -4812,9 +4812,8 @@ int sp_dreamreading(castorder * co) } u2 = - create_unit(u->region, mage->faction, RS_FARVISION, get_race(RC_SPELL), 0, + create_unit(u->region, mage->faction, 1, get_race(RC_SPELL), 0, "spell/dreamreading", NULL); - set_number(u2, 1); u2->age = 2; /* Nur fuer diese Runde. */ set_level(u2, SK_PERCEPTION, effskill(u, SK_PERCEPTION, u2->region)); @@ -5691,7 +5690,7 @@ int sp_viewreality(castorder * co) region *rt = rl2->data; if (!is_cursed(rt->attribs, C_ASTRALBLOCK, 0)) { u = - create_unit(rt, mage->faction, RS_FARVISION, get_race(RC_SPELL), 0, + create_unit(rt, mage->faction, 1, get_race(RC_SPELL), 0, "spell/viewreality", NULL); set_level(u, SK_PERCEPTION, co->level / 2); u->age = 2; From de58fa6aa08bf69b76e5b07d287b54061d55f550 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 24 Sep 2016 20:50:35 +0200 Subject: [PATCH 02/57] harmless refactoring: create RC_SPELL units from a common function. --- src/spells.c | 34 ++++++++++++++-------------------- src/spells.h | 1 - 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/spells.c b/src/spells.c index 84700926c..ce0a8d980 100644 --- a/src/spells.c +++ b/src/spells.c @@ -4111,6 +4111,14 @@ static int sp_bigrecruit(castorder * co) return cast_level; } +static void watch_region(region *r, faction *f, int perception) { + unit *u; + + u = create_unit(r, f, 1, get_race(RC_SPELL), 0, NULL, NULL); + u->age = 2; + set_level(u, SK_PERCEPTION, perception); +} + /* ------------------------------------------------------------- */ /* Name: Aushorchen * Stufe: 7 @@ -4167,12 +4175,7 @@ static int sp_pump(castorder * co) return cast_level / 2; } - u = - create_unit(rt, mage->faction, 1, get_race(RC_SPELL), 0, - "spell/pump", NULL); - u->age = 2; - set_level(u, SK_PERCEPTION, effskill(target, SK_PERCEPTION, 0)); - + watch_region(rt, mage->faction, effskill(target, SK_PERCEPTION, 0)); return cast_level; } @@ -4778,7 +4781,7 @@ int sp_clonecopy(castorder * co) /* ------------------------------------------------------------- */ int sp_dreamreading(castorder * co) { - unit *u, *u2; + unit *u; region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; @@ -4811,11 +4814,7 @@ int sp_dreamreading(castorder * co) return 0; } - u2 = - create_unit(u->region, mage->faction, 1, get_race(RC_SPELL), 0, - "spell/dreamreading", NULL); - u2->age = 2; /* Nur fuer diese Runde. */ - set_level(u2, SK_PERCEPTION, effskill(u, SK_PERCEPTION, u2->region)); + watch_region(u->region, mage->faction, effskill(u, SK_PERCEPTION, u->region)); msg = msg_message("sp_dreamreading_effect", "mage unit region", mage, u, @@ -5612,7 +5611,7 @@ int sp_showastral(castorder * co) region *r2 = rl2->data; if (!is_cursed(r2->attribs, C_ASTRALBLOCK, 0)) { for (u = r2->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPECIAL) && u_race(u) != get_race(RC_SPELL)) + if (u_race(u) != get_race(RC_SPELL)) n++; } } @@ -5632,7 +5631,7 @@ int sp_showastral(castorder * co) for (rl2 = rl; rl2; rl2 = rl2->next) { if (!is_cursed(rl2->data->attribs, C_ASTRALBLOCK, 0)) { for (u = rl2->data->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPECIAL) && u_race(u) != get_race(RC_SPELL)) { + if (u_race(u) != get_race(RC_SPELL)) { c++; scat(unitname(u)); scat(" ("); @@ -5670,7 +5669,6 @@ int sp_showastral(castorder * co) int sp_viewreality(castorder * co) { region_list *rl, *rl2; - unit *u; region *r = co_get_region(co); unit *mage = co->magician.u; int cast_level = co->level; @@ -5689,11 +5687,7 @@ int sp_viewreality(castorder * co) for (rl2 = rl; rl2; rl2 = rl2->next) { region *rt = rl2->data; if (!is_cursed(rt->attribs, C_ASTRALBLOCK, 0)) { - u = - create_unit(rt, mage->faction, 1, get_race(RC_SPELL), 0, - "spell/viewreality", NULL); - set_level(u, SK_PERCEPTION, co->level / 2); - u->age = 2; + watch_region(rt, mage->faction, co->level / 2); } } diff --git a/src/spells.h b/src/spells.h index 65270a164..1ad68e131 100644 --- a/src/spells.h +++ b/src/spells.h @@ -28,7 +28,6 @@ extern "C" { struct message; void register_spells(void); - void set_spelldata(struct spell *sp); int sp_baddreams(castorder * co); int sp_gooddreams(castorder * co); From 4353773c3ba5b6f1c8b17254815a06ad6e635bc9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 24 Sep 2016 21:09:15 +0200 Subject: [PATCH 03/57] far_vision test uses watch_region, checkes faction.interval --- src/reports.test.c | 8 +++++--- src/spells.c | 3 ++- src/spells.h | 4 ++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/reports.test.c b/src/reports.test.c index d5801ebab..91e052683 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -6,6 +6,7 @@ #include "lighthouse.h" #include "travelthru.h" #include "keyword.h" +#include "spells.h" #include #include @@ -426,7 +427,7 @@ static void test_seen_travelthru(CuTest *tc) { } static void test_report_far_vision(CuTest *tc) { - unit *u1, *u2; + unit *u1; faction *f; region *r1, *r2; const race *rc; @@ -436,8 +437,9 @@ static void test_report_far_vision(CuTest *tc) { u1 = test_create_unit(f, r1); r2 = test_create_region(10, 0, 0); rc = test_create_race("spell"); - u2 = create_unit(r2, u1->faction, 1, rc, 0, "spell/dreamreading", NULL); - set_number(u2, 1); + watch_region(r2, f, 10); + CuAssertPtrEquals(tc, r1, f->first); + CuAssertPtrEquals(tc, r2, f->last); report_context ctx; prepare_report(&ctx, f); CuAssertPtrEquals(tc, r1, ctx.first); diff --git a/src/spells.c b/src/spells.c index ce0a8d980..b14b588ee 100644 --- a/src/spells.c +++ b/src/spells.c @@ -4111,7 +4111,8 @@ static int sp_bigrecruit(castorder * co) return cast_level; } -static void watch_region(region *r, faction *f, int perception) { +void watch_region(region *r, faction *f, int perception) +{ unit *u; u = create_unit(r, f, 1, get_race(RC_SPELL), 0, NULL, NULL); diff --git a/src/spells.h b/src/spells.h index 1ad68e131..c10ee1c6c 100644 --- a/src/spells.h +++ b/src/spells.h @@ -25,10 +25,14 @@ extern "C" { struct ship; struct curse; struct unit; + struct faction; + struct region; struct message; void register_spells(void); + void watch_region(struct region *r, struct faction *f, int perception); + int sp_baddreams(castorder * co); int sp_gooddreams(castorder * co); From 15702daf995009b97b8dfad6b22347a08ab3f54e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 25 Sep 2016 13:01:51 +0200 Subject: [PATCH 04/57] Add a new attribute and RF_OBSERVER flag. --- src/creport.c | 4 +- src/kernel/region.h | 2 +- src/kernel/types.h | 2 +- src/report.c | 25 ++-- src/reports.c | 10 +- src/reports.test.c | 4 +- src/spells.c | 278 ++++++++++++++++++++++++++++---------------- src/spells.h | 3 +- src/spells.test.c | 20 ++++ 9 files changed, 225 insertions(+), 123 deletions(-) diff --git a/src/creport.c b/src/creport.c index 5e7442030..373cff2dc 100644 --- a/src/creport.c +++ b/src/creport.c @@ -1404,7 +1404,7 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r) } cr_output_curses_compat(F, f, r, TYP_REGION); cr_borders(r, f, r->seen.mode, F); - if (r->seen.mode == seen_unit && is_astral(r) + if (r->seen.mode >= seen_unit && is_astral(r) && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { /* Sonderbehandlung Teleport-Ebene */ region_list *rl = astralregions(r, inhabitable); @@ -1427,7 +1427,7 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r) } cr_output_travelthru(F, r, f); - if (r->seen.mode == seen_unit || r->seen.mode == seen_travel) { + if (r->seen.mode >= seen_travel) { message_list *mlist = r_getmessages(r, f); cr_output_messages(F, r->msgs, f); if (mlist) { diff --git a/src/kernel/region.h b/src/kernel/region.h index 6e231529d..f68a58fc5 100644 --- a/src/kernel/region.h +++ b/src/kernel/region.h @@ -34,7 +34,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #define RF_MALLORN (1<<1) /* persistent */ #define RF_BLOCKED (1<<2) /* persistent */ -#define RF_UNUSED_3 (1<<3) +#define RF_OBSERVER (1<<3) /* persistent */ #define RF_UNUSED_4 (1<<4) #define RF_UNUSED_5 (1<<5) #define RF_UNUSED_6 (1<<6) diff --git a/src/kernel/types.h b/src/kernel/types.h index e0521635e..99daaf521 100644 --- a/src/kernel/types.h +++ b/src/kernel/types.h @@ -79,8 +79,8 @@ typedef enum { seen_neighbour, seen_lighthouse, seen_travel, - seen_far, seen_unit, + seen_spell, seen_battle } seen_mode; diff --git a/src/report.c b/src/report.c index c7093da73..ed448190c 100644 --- a/src/report.c +++ b/src/report.c @@ -992,7 +992,7 @@ static void describe(stream *out, const region * r, faction * f) } /* iron & stone */ - if (r->seen.mode == seen_unit) { + if (r->seen.mode >= seen_unit) { resource_report result[MAX_RAWMATERIALS]; int n, numresults = report_resources(r, result, MAX_RAWMATERIALS, f, true); @@ -1190,7 +1190,7 @@ static void describe(stream *out, const region * r, faction * f) *bufp = 0; paragraph(out, buf, 0, 0, 0); - if (r->seen.mode == seen_unit && is_astral(r) && + if (r->seen.mode >= seen_unit && is_astral(r) && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { /* Sonderbehandlung Teleport-Ebene */ region_list *rl = astralregions(r, inhabitable); @@ -2285,7 +2285,7 @@ report_plaintext(const char *filename, report_context * ctx, continue; /* Beschreibung */ - if (r->seen.mode == seen_unit) { + if (r->seen.mode >= seen_unit) { anyunits = 1; describe(out, r, f); if (markets_module() && r->land) { @@ -2317,27 +2317,18 @@ report_plaintext(const char *filename, report_context * ctx, write_travelthru(out, r, f); } else { - if (r->seen.mode == seen_far) { - describe(out, r, f); - newline(out); - guards(out, r, f); - newline(out); - write_travelthru(out, r, f); - } - else { - describe(out, r, f); - newline(out); - write_travelthru(out, r, f); - } + describe(out, r, f); + newline(out); + write_travelthru(out, r, f); } /* Statistik */ - if (wants_stats && r->seen.mode == seen_unit) + if (wants_stats && r->seen.mode >= seen_unit) statistics(out, r, f); /* Nachrichten an REGION in der Region */ - if (r->seen.mode == seen_unit || r->seen.mode == seen_travel) { + if (r->seen.mode >= seen_travel) { // TODO: Bug 2073 message_list *mlist = r_getmessages(r, f); if (mlist) { diff --git a/src/reports.c b/src/reports.c index dc0edf1b3..92955e448 100644 --- a/src/reports.c +++ b/src/reports.c @@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "reports.h" #include "laws.h" +#include "spells.h" #include "travelthru.h" #include "lighthouse.h" #include "donations.h" @@ -92,6 +93,7 @@ const char *visibility[] = { "travel", "far", "unit", + "spell", "battle" }; @@ -943,9 +945,9 @@ const struct unit *ucansee(const struct faction *f, const struct unit *u, int stealth_modifier(seen_mode mode) { switch (mode) { + case seen_spell: case seen_unit: return 0; - case seen_far: case seen_lighthouse: return -2; case seen_travel: @@ -1336,6 +1338,12 @@ void prepare_report(report_context *ctx, faction *f) for (r = ctx->first; r!=ctx->last; r = r->next) { unit *u; + if (fval(r, RF_OBSERVER)) { + int skill = get_observer(r, f); + if (skill >= 0) { + add_seen_nb(f, r, seen_spell); + } + } if (fval(r, RF_LIGHTHOUSE)) { /* region owners get the report from lighthouses */ if (rule_region_owners && bt_lighthouse) { diff --git a/src/reports.test.c b/src/reports.test.c index 91e052683..72c8e46eb 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -437,7 +437,7 @@ static void test_report_far_vision(CuTest *tc) { u1 = test_create_unit(f, r1); r2 = test_create_region(10, 0, 0); rc = test_create_race("spell"); - watch_region(r2, f, 10); + set_observer(r2, f, 10); CuAssertPtrEquals(tc, r1, f->first); CuAssertPtrEquals(tc, r2, f->last); report_context ctx; @@ -445,7 +445,7 @@ static void test_report_far_vision(CuTest *tc) { CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, 0, ctx.last); CuAssertIntEquals(tc, seen_unit, r1->seen.mode); - CuAssertIntEquals(tc, seen_unit, r2->seen.mode); + CuAssertIntEquals(tc, seen_spell, r2->seen.mode); finish_reports(&ctx); test_cleanup(); } diff --git a/src/spells.c b/src/spells.c index b14b588ee..8e3887fd9 100644 --- a/src/spells.c +++ b/src/spells.c @@ -1,4 +1,4 @@ -/* +/* * * * Eressea PB(E)M host Copyright (C) 1998-2015 @@ -32,7 +32,7 @@ #include #include -/* kernel includes */ + /* kernel includes */ #include #include #include @@ -440,40 +440,40 @@ report_effect(region * r, unit * mage, message * seen, message * unseen) * */ -/* ------------------------------------------------------------- */ -/* Name: Vertrauter - * Stufe: 10 - * - * Wirkung: - * Der Magier beschwoert einen Vertrauten, ein kleines Tier, welches - * dem Magier zu Diensten ist. Der Magier kann durch die Augen des - * Vertrauten sehen, und durch den Vertrauten zaubern, allerdings nur - * mit seiner halben Stufe. Je nach Vertrautem erhaelt der Magier - * evtl diverse Skillmodifikationen. Der Typ des Vertrauten ist - * zufaellig bestimmt, wird aber durch Magiegebiet und Rasse beeinflußt. - * "Tierische" Vertraute brauchen keinen Unterhalt. - * - * Ein paar Moeglichkeiten: - * Magieg. Rasse Besonderheiten - * Eule Tybied -/- fliegt, Auraregeneration - * Rabe Ilaun -/- fliegt - * Imp Draig -/- Magieresistenz? - * Fuchs Gwyrrd -/- Wahrnehmung - * ???? Cerddor -/- ???? (Singvogel?, Papagei?) - * Adler -/- -/- fliegt, +Wahrnehmung, =^=Adlerauge-Spruch? - * Kraehe -/- -/- fliegt, +Tarnung (weil unauffaellig) - * Delphin -/- Meerm. schwimmt - * Wolf -/- Ork - * Hund -/- Mensch kann evtl BEWACHE ausfuehren - * Ratte -/- Goblin - * Albatros -/- -/- fliegt, kann auf Ozean "landen" - * Affe -/- -/- kann evtl BEKLAUE ausfuehren - * Goblin -/- !Goblin normale Einheit - * Katze -/- !Katze normale Einheit - * Daemon -/- !Daemon normale Einheit - * - * Spezielle V. fuer Katzen, Trolle, Elfen, Daemonen, Insekten, Zwerge? - */ + /* ------------------------------------------------------------- */ + /* Name: Vertrauter + * Stufe: 10 + * + * Wirkung: + * Der Magier beschwoert einen Vertrauten, ein kleines Tier, welches + * dem Magier zu Diensten ist. Der Magier kann durch die Augen des + * Vertrauten sehen, und durch den Vertrauten zaubern, allerdings nur + * mit seiner halben Stufe. Je nach Vertrautem erhaelt der Magier + * evtl diverse Skillmodifikationen. Der Typ des Vertrauten ist + * zufaellig bestimmt, wird aber durch Magiegebiet und Rasse beeinflußt. + * "Tierische" Vertraute brauchen keinen Unterhalt. + * + * Ein paar Moeglichkeiten: + * Magieg. Rasse Besonderheiten + * Eule Tybied -/- fliegt, Auraregeneration + * Rabe Ilaun -/- fliegt + * Imp Draig -/- Magieresistenz? + * Fuchs Gwyrrd -/- Wahrnehmung + * ???? Cerddor -/- ???? (Singvogel?, Papagei?) + * Adler -/- -/- fliegt, +Wahrnehmung, =^=Adlerauge-Spruch? + * Kraehe -/- -/- fliegt, +Tarnung (weil unauffaellig) + * Delphin -/- Meerm. schwimmt + * Wolf -/- Ork + * Hund -/- Mensch kann evtl BEWACHE ausfuehren + * Ratte -/- Goblin + * Albatros -/- -/- fliegt, kann auf Ozean "landen" + * Affe -/- -/- kann evtl BEKLAUE ausfuehren + * Goblin -/- !Goblin normale Einheit + * Katze -/- !Katze normale Einheit + * Daemon -/- !Daemon normale Einheit + * + * Spezielle V. fuer Katzen, Trolle, Elfen, Daemonen, Insekten, Zwerge? + */ static const race *select_familiar(const race * magerace, magic_t magiegebiet) { @@ -604,7 +604,7 @@ static int sp_summon_familiar(castorder * co) if (dh == 0) { bytes = strlcpy(bufp, (const char *)LOC(mage->faction->locale, - "list_and"), size); + "list_and"), size); } else { bytes = strlcpy(bufp, (const char *)", ", size); @@ -615,7 +615,7 @@ static int sp_summon_familiar(castorder * co) } bytes = strlcpy(bufp, (const char *)skillname((skill_t)sk, mage->faction->locale), - size); + size); assert(bytes <= INT_MAX); if (wrptr(&bufp, &size, (int)bytes) != 0) WARN_STATIC_BUFFER(); @@ -1246,7 +1246,7 @@ static void fumble_ents(const castorder * co) * Flag: * (FARCASTING | SPELLLEVEL | UNITSPELL | TESTCANSEE | TESTRESISTANCE) */ -/* Syntax: ZAUBER [REGION x y] [STUFE 2] "Rosthauch" 1111 2222 3333 */ + /* Syntax: ZAUBER [REGION x y] [STUFE 2] "Rosthauch" 1111 2222 3333 */ typedef struct iron_weapon { const struct item_type *type; @@ -1259,7 +1259,7 @@ static iron_weapon *ironweapons = NULL; void add_ironweapon(const struct item_type *type, const struct item_type *rusty, -float chance) + float chance) { iron_weapon *iweapon = malloc(sizeof(iron_weapon)); assert_alloc(iweapon); @@ -1366,7 +1366,7 @@ static int sp_rosthauch(castorder * co) * Flag: * (UNITSPELL | SPELLLEVEL | ONSHIPCAST | TESTCANSEE) */ -/* Syntax: ZAUBER [STUFE n] "Kaelteschutz" eh1 [eh2 [eh3 [...]]] */ + /* Syntax: ZAUBER [STUFE n] "Kaelteschutz" eh1 [eh2 [eh3 [...]]] */ static int sp_kaelteschutz(castorder * co) { @@ -1410,7 +1410,7 @@ static int sp_kaelteschutz(castorder * co) u)); if (u->faction != mage->faction) ADDMSG(&u->faction->msgs, msg_message("heat_effect", "mage target", - cansee(u->faction, r, mage, 0) ? mage : NULL, u)); + cansee(u->faction, r, mage, 0) ? mage : NULL, u)); i = cast_level; } /* Erstattung? */ @@ -1430,7 +1430,7 @@ static int sp_kaelteschutz(castorder * co) * Flag: * (UNITSPELL | TESTCANSEE | SPELLLEVEL) */ -/* Syntax: ZAUBER "Funkenregen" eh1 */ + /* Syntax: ZAUBER "Funkenregen" eh1 */ static int sp_sparkle(castorder * co) { @@ -1503,11 +1503,11 @@ static int sp_create_irongolem(castorder * co) int number = lovar(force * 8 * RESOURCE_QUANTITY); static int cache; static const race * golem_rc; - + if (rc_changed(&cache)) { golem_rc = rc_find("irongolem"); } - + if (number < 1) { number = 1; } @@ -1529,8 +1529,8 @@ static int sp_create_irongolem(castorder * co) ADDMSG(&mage->faction->msgs, msg_message("magiccreate_effect", "region command unit amount object", - mage->region, co->order, mage, number, - LOC(mage->faction->locale, rc_name_s(golem_rc, (u2->number == 1) ? NAME_SINGULAR : NAME_PLURAL)))); + mage->region, co->order, mage, number, + LOC(mage->faction->locale, rc_name_s(golem_rc, (u2->number == 1) ? NAME_SINGULAR : NAME_PLURAL)))); return cast_level; } @@ -1572,7 +1572,7 @@ static int sp_create_stonegolem(castorder * co) int number = lovar(co->force * 5 * RESOURCE_QUANTITY); static int cache; static const race * golem_rc; - + if (rc_changed(&cache)) { golem_rc = rc_find("stonegolem"); } @@ -1596,8 +1596,8 @@ static int sp_create_stonegolem(castorder * co) ADDMSG(&mage->faction->msgs, msg_message("magiccreate_effect", "region command unit amount object", - mage->region, co->order, mage, number, - LOC(mage->faction->locale, rc_name_s(golem_rc, (u2->number == 1) ? NAME_SINGULAR : NAME_PLURAL)))); + mage->region, co->order, mage, number, + LOC(mage->faction->locale, rc_name_s(golem_rc, (u2->number == 1) ? NAME_SINGULAR : NAME_PLURAL)))); return cast_level; } @@ -2203,17 +2203,17 @@ static int sp_ironkeeper(castorder * co) fset(keeper, UFL_ANON_FACTION); } - { - trigger *tkill = trigger_killunit(keeper); - add_trigger(&keeper->attribs, "timer", trigger_timeout(cast_level + 2, - tkill)); - } + { + trigger *tkill = trigger_killunit(keeper); + add_trigger(&keeper->attribs, "timer", trigger_timeout(cast_level + 2, + tkill)); + } - msg = msg_message("summon_effect", "mage amount race", mage, 1, u_race(keeper)); - r_addmessage(r, NULL, msg); - msg_release(msg); + msg = msg_message("summon_effect", "mage amount race", mage, 1, u_race(keeper)); + r_addmessage(r, NULL, msg); + msg_release(msg); - return cast_level; + return cast_level; } /* ------------------------------------------------------------- */ @@ -2384,7 +2384,7 @@ void patzer_peasantmob(const castorder * co) u = create_unit(r, f, n, get_race(RC_PEASANT), 0, LOC(f->locale, "angry_mob"), - NULL); + NULL); fset(u, UFL_ISNEW); /* guard(u, GUARD_ALL); hier zu frueh! Befehl BEWACHE setzten */ addlist(&u->orders, create_order(K_GUARD, lang, NULL)); @@ -2457,7 +2457,7 @@ static int sp_forest_fire(castorder * co) freset(u->faction, FFL_SELECT); msg = msg_message("forestfire_effect", "mage region amount", mage, r, - destroyed + vernichtet_schoesslinge); + destroyed + vernichtet_schoesslinge); r_addmessage(r, NULL, msg); add_message(&mage->faction->msgs, msg); msg_release(msg); @@ -2627,10 +2627,10 @@ static int sp_summondragon(castorder * co) number = 6; break; } - { - trigger *tsummon = trigger_createunit(r, f, race, number); - add_trigger(&r->attribs, "timer", trigger_timeout(time, tsummon)); - } + { + trigger *tsummon = trigger_createunit(r, f, race, number); + add_trigger(&r->attribs, "timer", trigger_timeout(time, tsummon)); + } } } @@ -2705,15 +2705,15 @@ static int sp_firewall(castorder * co) } /* melden, 1x pro Partei */ - { - message *seen = msg_message("firewall_effect", "mage region", mage, r); - message *unseen = msg_message("firewall_effect", "mage region", NULL, r); - report_effect(r, mage, seen, unseen); - msg_release(seen); - msg_release(unseen); - } + { + message *seen = msg_message("firewall_effect", "mage region", mage, r); + message *unseen = msg_message("firewall_effect", "mage region", NULL, r); + report_effect(r, mage, seen, unseen); + msg_release(seen); + msg_release(unseen); + } - return cast_level; + return cast_level; } /* ------------------------------------------------------------- */ @@ -2861,7 +2861,7 @@ static int dc_age(struct curse *c) damage *= (1.0 - magic_resistance(u)); hp = change_hitpoints(u, -(int)damage); - ADDMSG(&u->faction->msgs, msg_message((hp>0)?"poison_damage":"poison_death", "region unit", r, u)); + ADDMSG(&u->faction->msgs, msg_message((hp > 0) ? "poison_damage" : "poison_death", "region unit", r, u)); if (*up == u) up = &u->next; } @@ -2916,7 +2916,7 @@ static int dc_read_compat(struct attrib *a, void *target, gamedata *data) effect = strength; c = create_curse(u, &r->attribs, &ct_deathcloud, strength * 2, duration, - effect, 0); + effect, 0); c->data.v = r; if (u == NULL) { ur_add(var, &c->magician, resolve_unit); @@ -3123,7 +3123,7 @@ static bool chaosgate_valid(const connection * b) } static struct region *chaosgate_move(const connection * b, struct unit *u, -struct region *from, struct region *to, bool routing) + struct region *from, struct region *to, bool routing) { if (!routing) { int maxhp = u->hp / 4; @@ -3317,7 +3317,7 @@ static int sp_bloodsacrifice(castorder * co) change_spellpoints(mage, aura); ADDMSG(&mage->faction->msgs, msg_message("sp_bloodsacrifice_effect", - "unit region command amount", mage, mage->region, co->order, aura)); + "unit region command amount", mage, mage->region, co->order, aura)); return cast_level; } @@ -3811,7 +3811,7 @@ static int sp_raisepeasantmob(castorder * co) u = create_unit(r, monsters, n, get_race(RC_PEASANT), 0, LOC(monsters->locale, - "furious_mob"), NULL); + "furious_mob"), NULL); fset(u, UFL_ISNEW); guard(u, GUARD_ALL); a = a_new(&at_unitdissolve); @@ -4111,13 +4111,92 @@ static int sp_bigrecruit(castorder * co) return cast_level; } -void watch_region(region *r, faction *f, int perception) +typedef struct obs_data { + faction *f; + int skill; + int timer; +} obs_data; + +static void obs_init(struct attrib *a) { - unit *u; + a->data.v = malloc(sizeof(obs_data)); +} - u = create_unit(r, f, 1, get_race(RC_SPELL), 0, NULL, NULL); - u->age = 2; - set_level(u, SK_PERCEPTION, perception); +static void obs_done(struct attrib *a) +{ + free(a->data.v); +} + +static int obs_age(struct attrib *a, void *owner) +{ + obs_data *od = (obs_data *)a->data.v; + update_interval(od->f, (region *)owner); + return --od->timer; +} + +static void obs_write(const struct attrib *a, const void *owner, struct storage *store) +{ + obs_data *od = (obs_data *)a->data.v; + write_faction_reference(od->f, store); + WRITE_INT(store, od->skill); + WRITE_INT(store, od->timer); +} + +static int obs_read(struct attrib *a, void *owner, struct gamedata *data) +{ + obs_data *od = (obs_data *)a->data.v; + + read_reference(&od->f, data, read_faction_reference, resolve_faction); + READ_INT(data->store, &od->skill); + READ_INT(data->store, &od->timer); + return AT_READ_OK; +} + +attrib_type at_observer = { "observer", obs_init, obs_done, obs_age, obs_write, obs_read }; + +static attrib *make_observer(faction *f, int perception) +{ + attrib * a = a_new(&at_observer); + obs_data *od = (obs_data *)a->data.v; + od->f = f; + od->skill = perception; + od->timer = 2; + return a; +} + +int get_observer(region *r, faction *f) { + if (fval(r, RF_OBSERVER)) { + attrib *a = a_find(r->attribs, &at_observer); + while (a && a->type == &at_observer) { + obs_data *od = (obs_data *)a->data.v; + if (od->f == f) { + return od->skill; + } + a = a->next; + } + } + return -1; +} + +void set_observer(region *r, faction *f, int skill) +{ + update_interval(f, r); + if (fval(r, RF_OBSERVER)) { + attrib *a = a_find(r->attribs, &at_observer); + while (a && a->type == &at_observer) { + obs_data *od = (obs_data *)a->data.v; + if (od->f == f && od->skill < skill) { + od->skill = skill; + od->timer = 2; + return; + } + a = a->nexttype; + } + } + else { + fset(r, RF_OBSERVER); + } + a_add(&r->attribs, make_observer(f, skill)); } /* ------------------------------------------------------------- */ @@ -4133,7 +4212,7 @@ void watch_region(region *r, faction *f, int perception) * (UNITSPELL | TESTCANSEE) */ -/* restistenz der einheit pruefen */ + /* restistenz der einheit pruefen */ static int sp_pump(castorder * co) { unit *u, *target; @@ -4176,7 +4255,7 @@ static int sp_pump(castorder * co) return cast_level / 2; } - watch_region(rt, mage->faction, effskill(target, SK_PERCEPTION, 0)); + set_observer(rt, mage->faction, effskill(target, SK_PERCEPTION, 0)); return cast_level; } @@ -4400,7 +4479,7 @@ static int sp_raisepeasants(castorder * co) u2 = create_unit(r, mage->faction, bauern, get_race(RC_PEASANT), 0, - LOC(mage->faction->locale, "furious_mob"), mage); + LOC(mage->faction->locale, "furious_mob"), mage); fset(u2, UFL_LOCKED); if (rule_stealth_anon()) { @@ -4414,7 +4493,7 @@ static int sp_raisepeasants(castorder * co) msg = msg_message("sp_raisepeasants_effect", "mage region amount", mage, r, - u2->number); + u2->number); r_addmessage(r, NULL, msg); if (mage->region != r) { add_message(&mage->faction->msgs, msg); @@ -4527,7 +4606,7 @@ int sp_icastle(castorder * co) if (type == bt_illusion) { b->size = (rng_int() % (int)((power * power) + 1) * 10); } - else if (type->maxsize >0) { + else if (type->maxsize > 0) { b->size = type->maxsize; } else { @@ -4766,7 +4845,7 @@ int sp_clonecopy(castorder * co) "clone_of"), unitname(mage)); clone = create_unit(target_region, mage->faction, 1, get_race(RC_CLONE), 0, name, - mage); + mage); setstatus(clone, ST_FLEE); fset(clone, UFL_LOCKED); @@ -4815,11 +4894,11 @@ int sp_dreamreading(castorder * co) return 0; } - watch_region(u->region, mage->faction, effskill(u, SK_PERCEPTION, u->region)); + set_observer(u->region, mage->faction, effskill(u, SK_PERCEPTION, u->region)); msg = msg_message("sp_dreamreading_effect", "mage unit region", mage, u, - u->region); + u->region); r_addmessage(r, mage->faction, msg); msg_release(msg); return cast_level; @@ -5622,7 +5701,8 @@ int sp_showastral(castorder * co) /* sprintf(buf, "%s kann niemanden im astralen Nebel entdecken.", unitname(mage)); */ cmistake(mage, co->order, 220, MSG_MAGIC); - } else { + } + else { /* Ausgeben */ @@ -5642,13 +5722,14 @@ int sp_showastral(castorder * co) } icat(u->number); scat(" "); - scat(LOC(mage->faction->locale, rc_name_s(u_race(u), (u->number==1) ? NAME_SINGULAR:NAME_PLURAL))); + scat(LOC(mage->faction->locale, rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL))); scat(", Entfernung "); icat(distance(rl2->data, rt)); scat(")"); if (c == n - 1) { scat(" und "); - } else if (c < n - 1) { + } + else if (c < n - 1) { scat(", "); } } @@ -5688,7 +5769,7 @@ int sp_viewreality(castorder * co) for (rl2 = rl; rl2; rl2 = rl2->next) { region *rt = rl2->data; if (!is_cursed(rt->attribs, C_ASTRALBLOCK, 0)) { - watch_region(rt, mage->faction, co->level / 2); + set_observer(rt, mage->faction, co->level / 2); } } @@ -6262,8 +6343,8 @@ int sp_speed2(castorder * co) * Flags: * (FARCASTING | SPELLLEVEL | ONSHIPCAST | TESTCANSEE) */ -/* Jeder gebrochene Zauber verbraucht c->vigour an Zauberkraft - * (force) */ + /* Jeder gebrochene Zauber verbraucht c->vigour an Zauberkraft + * (force) */ int sp_q_antimagie(castorder * co) { attrib **ap; @@ -6411,7 +6492,7 @@ int sp_break_curse(castorder * co) /* Es wurde kein Ziel gefunden */ ADDMSG(&mage->faction->msgs, msg_message("spelltargetnotfound", "unit region command", - mage, mage->region, co->order)); + mage, mage->region, co->order)); } /* curse aufloesen, wenn zauber staerker (force > vigour) */ @@ -6718,6 +6799,7 @@ void register_spells(void) register_borders(); at_register(&at_wdwpyramid); + at_register(&at_observer); at_register(&at_deathcloud_compat); /* init_firewall(); */ diff --git a/src/spells.h b/src/spells.h index c10ee1c6c..6e1b194e6 100644 --- a/src/spells.h +++ b/src/spells.h @@ -31,7 +31,8 @@ extern "C" { void register_spells(void); - void watch_region(struct region *r, struct faction *f, int perception); + void set_observer(struct region *r, struct faction *f, int perception); + int get_observer(struct region *r, struct faction *f); int sp_baddreams(castorder * co); int sp_gooddreams(castorder * co); diff --git a/src/spells.test.c b/src/spells.test.c index 3c773d489..a3f624d40 100644 --- a/src/spells.test.c +++ b/src/spells.test.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -106,9 +107,28 @@ static void test_bad_dreams(CuTest *tc) { test_cleanup(); } +static void test_watch_region(CuTest *tc) { + region *r; + faction *f; + test_setup(); + test_create_race("spell"); + CuAssertPtrNotNull(tc, get_race(RC_SPELL)); + r = test_create_region(0, 0, 0); + f = test_create_faction(0); + CuAssertIntEquals(tc, -1, get_observer(r, f)); + set_observer(r, f, 0); + CuAssertIntEquals(tc, 0, get_observer(r, f)); + set_observer(r, f, 10); + CuAssertIntEquals(tc, 10, get_observer(r, f)); + CuAssertIntEquals(tc, RF_OBSERVER, fval(r, RF_OBSERVER)); + CuAssertPtrNotNull(tc, r->attribs); + test_cleanup(); +} + CuSuite *get_spells_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_watch_region); SUITE_ADD_TEST(suite, test_good_dreams); SUITE_ADD_TEST(suite, test_bad_dreams); SUITE_ADD_TEST(suite, test_dreams); From 58d9aa58a042516a7494e15e180a39724668a216 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 May 2017 11:09:45 +0200 Subject: [PATCH 05/57] =?UTF-8?q?BUG=202326:=20Untote=20Helden=20fehlen=20?= =?UTF-8?q?in=20der=20Kampf=C3=BCbersicht=20https://bugs.eressea.de/view.p?= =?UTF-8?q?hp=3Fid=3D2326?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/kernel/unit.c | 9 +++++++-- src/kernel/unit.h | 3 ++- src/spells/combatspells.c | 5 +---- tests/runtests.bat | 1 + 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/kernel/unit.c b/src/kernel/unit.c index ab5f72f35..75daf2417 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -981,7 +981,7 @@ void move_unit(unit * u, region * r, unit ** ulist) /* ist mist, aber wegen nicht skalierender attribute notwendig: */ #include "alchemy.h" -void transfermen(unit * u, unit * dst, int n) +void clone_men(unit * u, unit * dst, int n) { const attrib *a; int hp = u->hp; @@ -1074,7 +1074,6 @@ void transfermen(unit * u, unit * dst, int n) transfer_curse(u, dst, n); } } - scale_number(u, u->number - n); if (dst) { set_number(dst, dst->number + n); hp -= u->hp; @@ -1100,6 +1099,12 @@ void transfermen(unit * u, unit * dst, int n) } } +void transfermen(unit * u, unit * dst, int n) +{ + clone_men(u, dst, n); + scale_number(u, u->number - n); +} + struct building *inside_building(const struct unit *u) { if (!u->building) { diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 8ae13c5e2..beea74ee7 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -165,7 +165,8 @@ extern "C" { void set_level(struct unit *u, skill_t id, int level); int get_level(const struct unit *u, skill_t id); - extern void transfermen(struct unit *src, struct unit *dst, int n); + void transfermen(struct unit *src, struct unit *dst, int n); + void clone_men(struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */ int eff_skill(const struct unit *u, const struct skill *sv, const struct region *r); int effskill_study(const struct unit *u, skill_t sk, const struct region *r); diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 08f38c8ea..16f6ee5e9 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -1668,11 +1668,8 @@ int sp_undeadhero(struct castorder * co) } /* transfer dead people to new unit, set hitpoints to those of old unit */ - transfermen(du, u, j); + clone_men(du, u, j); /* for reporting reasons, do not remove the dead */ u->hp = u->number * unit_max_hp(du); - assert(j <= df->side->casualties); - df->side->casualties -= j; - df->side->dead -= j; /* counting total number of undead */ undead += j; diff --git a/tests/runtests.bat b/tests/runtests.bat index b6f70768f..95ac17be4 100644 --- a/tests/runtests.bat +++ b/tests/runtests.bat @@ -3,6 +3,7 @@ IF EXIST ..\build-vs10 SET BUILD=..\build-vs10\eressea\Debug IF EXIST ..\build-vs11 SET BUILD=..\build-vs11\eressea\Debug IF EXIST ..\build-vs12 SET BUILD=..\build-vs12\eressea\Debug IF EXIST ..\build-vs14 SET BUILD=..\build-vs14\eressea\Debug +REM IF EXIST ..\build-vs15 SET BUILD=..\build-vs15\eressea\Debug SET SERVER=%BUILD%\eressea.exe %BUILD%\test_eressea.exe %SERVER% ..\scripts\run-tests.lua From 88626fb16382afd95c5da3ebf08c2636624659a0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 May 2017 12:26:04 +0200 Subject: [PATCH 06/57] optimization: select_fighters. use select_fighters with callback to reduce the number of selected units for (most) combat spells. --- src/battle.c | 28 ++++- src/battle.h | 32 ++--- src/spells/combatspells.c | 237 ++++++++++++++++++++------------------ 3 files changed, 170 insertions(+), 127 deletions(-) diff --git a/src/battle.c b/src/battle.c index 19f30e59c..5075b247b 100644 --- a/src/battle.c +++ b/src/battle.c @@ -439,7 +439,7 @@ static int get_row(const side * s, int row, const side * vs) return result; } -static int get_unitrow(const fighter * af, const side * vs) +int get_unitrow(const fighter * af, const side * vs) { int row = statusrow(af->status); if (vs == NULL) { @@ -1589,8 +1589,7 @@ static troop select_opponent(battle * b, troop at, int mindist, int maxdist) return dt; } -selist *fighters(battle * b, const side * vs, int minrow, int maxrow, - int mask) +selist *select_fighters(battle * b, const side * vs, int mask, select_fun cb, void *cbdata) { side *s; selist *fightervp = 0; @@ -1613,8 +1612,7 @@ selist *fighters(battle * b, const side * vs, int minrow, int maxrow, assert(mask == (FS_HELP | FS_ENEMY) || !"invalid alliance state"); } for (fig = s->fighters; fig; fig = fig->next) { - int row = get_unitrow(fig, vs); - if (row >= minrow && row <= maxrow) { + if (cb(vs, fig, cbdata)) { selist_push(&fightervp, fig); } } @@ -1623,6 +1621,26 @@ selist *fighters(battle * b, const side * vs, int minrow, int maxrow, return fightervp; } +struct selector { + int minrow; + int maxrow; +}; + +static bool select_row(const side *vs, const fighter *fig, void *cbdata) +{ + struct selector *sel = (struct selector *)cbdata; + int row = get_unitrow(fig, vs); + return (row >= sel->minrow && row <= sel->maxrow); +} + +selist *fighters(battle * b, const side * vs, int minrow, int maxrow, int mask) +{ + struct selector sel; + sel.maxrow = maxrow; + sel.minrow = minrow; + return select_fighters(b, vs, mask, select_row, &sel); +} + static void report_failed_spell(struct battle * b, struct unit * mage, const struct spell *sp) { message *m = msg_message("battle::spell_failed", "unit spell", mage, sp); diff --git a/src/battle.h b/src/battle.h index 4e20d00d8..3c86c2c8d 100644 --- a/src/battle.h +++ b/src/battle.h @@ -229,15 +229,17 @@ extern "C" { fighter * get_fighter(battle * b, const struct unit * u); /* END battle interface */ - extern void do_battles(void); + void do_battles(void); /* for combat spells and special attacks */ enum { SELECT_ADVANCE = 0x1, SELECT_DISTANCE = 0x2, SELECT_FIND = 0x4 }; enum { ALLY_SELF, ALLY_ANY }; - extern troop select_enemy(struct fighter *af, int minrow, int maxrow, + int get_unitrow(const fighter * af, const side * vs); + + troop select_enemy(struct fighter *af, int minrow, int maxrow, int select); - extern troop select_ally(struct fighter *af, int minrow, int maxrow, + troop select_ally(struct fighter *af, int minrow, int maxrow, int allytype); int count_enemies(struct battle *b, const struct fighter *af, @@ -246,21 +248,25 @@ extern "C" { int calculate_armor(troop dt, const struct weapon_type *dwtype, const struct weapon_type *awtype, union variant *magres); bool terminate(troop dt, troop at, int type, const char *damage, bool missile); - extern void message_all(battle * b, struct message *m); - extern int hits(troop at, troop dt, weapon * awp); - extern void damage_building(struct battle *b, struct building *bldg, + void message_all(battle * b, struct message *m); + int hits(troop at, troop dt, weapon * awp); + void damage_building(struct battle *b, struct building *bldg, int damage_abs); + + typedef bool(*select_fun)(const struct side *vs, const struct fighter *fig, void *cbdata); + struct selist *select_fighters(struct battle *b, const struct side *vs, int mask, select_fun cb, void *cbdata); struct selist *fighters(struct battle *b, const struct side *vs, int minrow, int maxrow, int mask); + int count_allies(const struct side *as, int minrow, int maxrow, int select, int allytype); - extern bool helping(const struct side *as, const struct side *ds); - extern void rmfighter(fighter * df, int i); - extern struct fighter *select_corpse(struct battle *b, struct fighter *af); - extern int statusrow(int status); - extern void drain_exp(struct unit *u, int d); - extern void kill_troop(troop dt); - extern void remove_troop(troop dt); /* not the same as the badly named rmtroop */ + bool helping(const struct side *as, const struct side *ds); + void rmfighter(fighter * df, int i); + struct fighter *select_corpse(struct battle *b, struct fighter *af); + int statusrow(int status); + void drain_exp(struct unit *u, int d); + void kill_troop(troop dt); + void remove_troop(troop dt); /* not the same as the badly named rmtroop */ bool is_attacker(const fighter * fig); struct battle *make_battle(struct region * r); diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 16f6ee5e9..1f3ad47e4 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -256,6 +256,17 @@ static void scramble_fighters(selist * ql) } } +static bool select_armed(const side *vs, const fighter *fig, void *cbdata) +{ + int row = get_unitrow(fig, vs); + + UNUSED_ARG(cbdata); + if (row >= FIGHT_ROW && row < BEHIND_ROW) { + return fig->alive > 0 && fig->weapons; + } + return false; +} + /* Rosthauch */ int sp_combatrosthauch(struct castorder * co) { @@ -275,52 +286,42 @@ int sp_combatrosthauch(struct castorder * co) return 0; } - fgs = fighters(b, fi->side, FIGHT_ROW, BEHIND_ROW - 1, FS_ENEMY); + fgs = select_fighters(b, fi->side, FS_ENEMY, select_armed, NULL); scramble_fighters(fgs); - for (qi = 0, ql = fgs; ql; selist_advance(&ql, &qi, 1)) { + for (qi = 0, ql = fgs; force>0 && ql; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); - - if (df->alive == 0) - continue; - if (force <= 0) - break; - - /* da n MIN(force, x), sollte force maximal auf 0 sinken */ - assert(force >= 0); - - if (df->weapons) { - int w; - for (w = 0; df->weapons[w].type != NULL; ++w) { - weapon *wp = df->weapons; - int n = MIN(force, wp->used); - if (n) { - requirement *mat = wp->type->itype->construction->materials; - bool iron = false; - while (mat && mat->number > 0) { - if (mat->rtype == get_resourcetype(R_IRON)) { - iron = true; - break; - } - mat++; + int w; + + for (w = 0; df->weapons[w].type != NULL; ++w) { + weapon *wp = df->weapons; + int n = MIN(force, wp->used); + if (n) { + requirement *mat = wp->type->itype->construction->materials; + bool iron = false; + while (mat && mat->number > 0) { + if (mat->rtype == get_resourcetype(R_IRON)) { + iron = true; + break; } - if (iron) { - int p; - force -= n; - wp->used -= n; - k += n; - i_change(&df->unit->items, wp->type->itype, -n); - for (p = 0; n && p != df->unit->number; ++p) { - if (df->person[p].missile == wp) { - df->person[p].missile = NULL; - --n; - } + mat++; + } + if (iron) { + int p; + force -= n; + wp->used -= n; + k += n; + i_change(&df->unit->items, wp->type->itype, -n); + for (p = 0; n && p != df->unit->number; ++p) { + if (df->person[p].missile == wp) { + df->person[p].missile = NULL; + --n; } - for (p = 0; n && p != df->unit->number; ++p) { - if (df->person[p].melee == wp) { - df->person[p].melee = NULL; - --n; - } + } + for (p = 0; n && p != df->unit->number; ++p) { + if (df->person[p].melee == wp) { + df->person[p].melee = NULL; + --n; } } } @@ -889,6 +890,13 @@ int sp_strong_wall(struct castorder * co) return level; } +static bool select_alive(const side *vs, const fighter *fig, void *cbdata) +{ + UNUSED_ARG(vs); + UNUSED_ARG(cbdata); + return fig->alive > 0; +} + /** Spells: chaosrow / song of confusion. * German Title: 'Gesang der Verwirrung' */ @@ -915,7 +923,7 @@ int sp_chaosrow(struct castorder * co) power = chaosrow ? (power * 40) : get_force(power, 5); - fgs = fighters(b, fi->side, FIGHT_ROW, NUMROWS, FS_ENEMY); + fgs = select_fighters(b, fi->side, FS_ENEMY, select_alive, NULL); scramble_fighters(fgs); for (qi = 0, ql = fgs; ql; selist_advance(&ql, &qi, 1)) { @@ -977,9 +985,18 @@ int sp_chaosrow(struct castorder * co) return level; } +static bool select_afraid(const side *vs, const fighter *fig, void *cbdata) +{ + int row = get_unitrow(fig, vs); + UNUSED_ARG(cbdata); + if (row >= FIGHT_ROW && row <= AVOID_ROW) { + return fig->alive + fig->run.number < fig->unit->number; + } + return false; +} + /* Gesang der Furcht (Kampfzauber) */ /* Panik (Pr�kampfzauber) */ - int flee_spell(struct castorder * co, int strength) { fighter * fi = co->magician.fig; @@ -994,23 +1011,20 @@ int flee_spell(struct castorder * co, int strength) int force; force = (int)get_force(power, strength); - if (!count_enemies(b, fi, FIGHT_ROW, AVOID_ROW, SELECT_ADVANCE | SELECT_FIND)) { + if (force<=0 || !count_enemies(b, fi, FIGHT_ROW, AVOID_ROW, SELECT_ADVANCE | SELECT_FIND)) { msg = msg_message("sp_flee_effect_0", "mage spell", mage, sp); message_all(b, msg); msg_release(msg); return 0; } - fgs = fighters(b, fi->side, FIGHT_ROW, AVOID_ROW, FS_ENEMY); + fgs = select_fighters(b, fi->side, FS_ENEMY, select_afraid, NULL); scramble_fighters(fgs); - for (qi = 0, ql = fgs; ql; selist_advance(&ql, &qi, 1)) { + for (qi = 0, ql = fgs; force > 0 && ql; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); - for (n = 0; n != df->alive; ++n) { - if (force < 0) - break; - + for (n = 0; force > 0 && n != df->alive; ++n) { if (df->person[n].flags & FL_PANICED) { /* bei SPL_SONG_OF_FEAR m�glich */ df->person[n].attack -= 1; --force; @@ -1556,8 +1570,8 @@ int sp_healing(struct castorder * co) message *msg; bool use_item = has_ao_healing(mage); - /* bis zu 11 Personen pro Stufe (einen HP m�ssen sie ja noch - * haben, sonst w�ren sie tot) k�nnen geheilt werden */ + /* bis zu 11 Personen pro Stufe (einen HP muessen sie ja noch + * haben, sonst waeren sie tot) koennen geheilt werden */ if (use_item) { healhp *= 2; @@ -1589,6 +1603,19 @@ int sp_healing(struct castorder * co) return level; } +static bool select_hero(const side *vs, const fighter *fig, void *cbdata) +{ + UNUSED_ARG(cbdata); + + if (playerrace(u_race(fig->unit))) { + int row = get_unitrow(fig, vs); + if (row >= FIGHT_ROW && row <= AVOID_ROW) { + return fig->alive + fig->run.number < fig->unit->number; + } + } + return false; +} + int sp_undeadhero(struct castorder * co) { fighter * fi = co->magician.fig; @@ -1603,77 +1630,69 @@ int sp_undeadhero(struct castorder * co) int force = (int)get_force(power, 0); double c = 0.50 + 0.02 * power; - /* Liste aus allen K�mpfern */ - fgs = fighters(b, fi->side, FIGHT_ROW, AVOID_ROW, FS_ENEMY | FS_HELP); + /* Liste aus allen Kaempfern */ + fgs = select_fighters(b, fi->side, FS_ENEMY | FS_HELP, select_hero, NULL); scramble_fighters(fgs); - for (qi = 0, ql = fgs; ql; selist_advance(&ql, &qi, 1)) { + for (qi = 0, ql = fgs; ql && force>0; selist_advance(&ql, &qi, 1)) { fighter *df = (fighter *)selist_get(ql, qi); unit *du = df->unit; + int j = 0; - if (force <= 0) - break; - - /* keine Monster */ - if (!playerrace(u_race(du))) - continue; - - if (df->alive + df->run.number < du->number) { - int j = 0; - - /* Wieviele Untote k�nnen wir aus dieser Einheit wecken? */ - for (n = df->alive + df->run.number; n != du->number; n++) { - if (chance(c)) { - ++j; - if (--force <= 0) - break; - } + /* Wieviele Untote koennen wir aus dieser Einheit wecken? */ + for (n = df->alive + df->run.number; force>0 && n != du->number; n++) { + if (chance(c)) { + ++j; + --force; } + } - if (j > 0) { - item **ilist; - unit *u = - create_unit(r, mage->faction, 0, get_race(RC_UNDEAD), 0, unit_getname(du), - du); + if (j > 0) { + item **ilist; + unit *u = + create_unit(r, mage->faction, 0, get_race(RC_UNDEAD), 0, unit_getname(du), + du); - /* new units gets some stats from old unit */ + /* new units gets some stats from old unit */ - if (du->display) { - unit_setinfo(u, du->display); - } - else { - unit_setinfo(u, NULL); - } - setstatus(u, du->status); - setguard(u, false); - for (ilist = &du->items; *ilist;) { - item *itm = *ilist; - int loot = itm->number * j / du->number; - if (loot != itm->number) { - int split = itm->number * j % du->number; - if (split > 0 && (rng_int() % du->number) < split) { - ++loot; - } - } - i_change(&u->items, itm->type, loot); - i_change(ilist, itm->type, -loot); - if (*ilist == itm) { - ilist = &itm->next; + if (du->display) { + unit_setinfo(u, du->display); + } + else { + unit_setinfo(u, NULL); + } + setstatus(u, du->status); + setguard(u, false); + for (ilist = &du->items; *ilist;) { + item *itm = *ilist; + int loot = itm->number * j / du->number; + if (loot != itm->number) { + int split = itm->number * j % du->number; + if (split > 0 && (rng_int() % du->number) < split) { + ++loot; } } - - /* inherit stealth from magician */ - if (mage->flags & UFL_ANON_FACTION) { - u->flags |= UFL_ANON_FACTION; + i_change(&u->items, itm->type, loot); + i_change(ilist, itm->type, -loot); + if (*ilist == itm) { + ilist = &itm->next; } + } - /* transfer dead people to new unit, set hitpoints to those of old unit */ - clone_men(du, u, j); /* for reporting reasons, do not remove the dead */ - u->hp = u->number * unit_max_hp(du); - - /* counting total number of undead */ - undead += j; + /* inherit stealth from magician */ + if (mage->flags & UFL_ANON_FACTION) { + u->flags |= UFL_ANON_FACTION; } + + /* transfer dead people to new unit, set hitpoints to those of old unit */ + transfermen(du, u, j); + u->hp = u->number * unit_max_hp(du); + assert(j <= df->side->casualties); + df->side->casualties -= j; + df->side->dead -= j; + + /* counting total number of undead */ + undead += j; } } selist_free(fgs); From 0755830754f7249957e0c6ce017f08e24d95410c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 May 2017 23:47:54 +0200 Subject: [PATCH 07/57] fix compilation, test still fails --- src/laws.test.c | 4 ---- src/reports.test.c | 6 ++---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/laws.test.c b/src/laws.test.c index 7e5df0b56..4d6adbfe9 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -1446,10 +1446,6 @@ static void test_show_both(CuTest *tc) { test_cleanup(); } -static int low_wage(const region * r, const faction * f, const race * rc, int in_turn) { - return 1; -} - static void test_immigration(CuTest * tc) { region *r; diff --git a/src/reports.test.c b/src/reports.test.c index dd27ee360..f602ade46 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -714,16 +714,14 @@ static void test_region_distance_ql(CuTest *tc) { } static void test_report_far_vision(CuTest *tc) { - unit *u1; faction *f; region *r1, *r2; - const race *rc; test_setup(); f = test_create_faction(0); r1 = test_create_region(0, 0, 0); - u1 = test_create_unit(f, r1); + test_create_unit(f, r1); r2 = test_create_region(10, 0, 0); - rc = test_create_race("spell"); + test_create_race("spell"); set_observer(r2, f, 10); CuAssertPtrEquals(tc, r1, f->first); CuAssertPtrEquals(tc, r2, f->last); From 17ed46e6a8b15205793f666d383178d09fbb3738 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 22 May 2017 19:50:18 +0200 Subject: [PATCH 08/57] fix test --- src/reports.test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/reports.test.c b/src/reports.test.c index dd27ee360..88219a5d5 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -547,6 +547,7 @@ static void test_prepare_lighthouse_owners(CuTest *tc) const struct terrain_type *t_ocean, *t_plain; test_setup(); + enable_skill(SK_PERCEPTION, false); config_set("rules.region_owner_pay_building", "lighthouse"); config_set("rules.region_owners", "1"); t_ocean = test_create_terrain("ocean", SEA_REGION); @@ -555,6 +556,7 @@ static void test_prepare_lighthouse_owners(CuTest *tc) r1 = test_create_region(0, 0, t_plain); r2 = test_create_region(1, 0, t_ocean); r3 = test_create_region(2, 0, t_ocean); + r3 = test_create_region(3, 0, t_ocean); btype = test_create_buildingtype("lighthouse"); b = test_create_building(r1, btype); b->flags |= BLD_MAINTAINED; @@ -564,8 +566,7 @@ static void test_prepare_lighthouse_owners(CuTest *tc) u = test_create_unit(test_create_faction(0), r1); u->building = b; region_set_owner(b->region, f, 0); - set_level(u, SK_PERCEPTION, 3); - CuAssertIntEquals(tc, 2, lighthouse_range(b, f, NULL)); + CuAssertIntEquals(tc, 2, lighthouse_range(b, NULL, NULL)); prepare_report(&ctx, f); CuAssertPtrEquals(tc, r1, ctx.first); CuAssertPtrEquals(tc, NULL, ctx.last); From 51f8f87072f9197fa589b9cf7bbdc94dd172263a Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 22 May 2017 21:15:42 +0200 Subject: [PATCH 09/57] eliminate the O(n) lighthouse/inside complexity from prepare_report --- src/reports.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/reports.c b/src/reports.c index 146a8529f..934a5ae36 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1425,7 +1425,8 @@ void prepare_report(report_context *ctx, faction *f) for (r = ctx->first; r!=ctx->last; r = r->next) { unit *u; - int range = 0; + building *b; + int br = 0, c = 0, range = 0; if (fval(r, RF_OBSERVER)) { int skill = get_observer(r, f); if (skill >= 0) { @@ -1435,7 +1436,6 @@ void prepare_report(report_context *ctx, faction *f) if (fval(r, RF_LIGHTHOUSE)) { /* region owners get the report from lighthouses */ if (rule_region_owners && f == region_get_owner(r)) { - building *b; for (b = rbuildings(r); b; b = b->next) { if (b && b->type == bt_lighthouse) { /* region owners get maximm range */ @@ -1445,6 +1445,8 @@ void prepare_report(report_context *ctx, faction *f) } } } + + b = NULL; for (u = r->units; u; u = u->next) { /* if we have any unit in this region, then we get seen_unit access */ if (u->faction == f) { @@ -1453,13 +1455,27 @@ void prepare_report(report_context *ctx, faction *f) * or the size, if perception is not a skill */ if (!fval(r, RF_LIGHTHOUSE)) { - /* it's enough to mark the region once, and if there are + /* it's enough to add the region once, and if there are * no lighthouses, there is no need to look at more units */ break; } - if (range == 0 && u->building && u->building->type == bt_lighthouse && inside_building(u)) { - int br = lighthouse_range(u->building, f, u); - if (br > range) range = br; + } + if (range == 0 && u->building && u->building->type == bt_lighthouse) { + if (u->building && b != u->building) { + b = u->building; + c = buildingcapacity(b); + br = 0; + } + c -= u->number; + if (u->faction == f && c >= 0) { + /* unit is one of ours, and inside the current lighthouse */ + if (br == 0) { + /* lazy-calculate the range */ + br = lighthouse_range(u->building, f, u); + } + if (br > range) { + range = br; + } } } } From 95a9bb4ab904b579058c2607d65ceeaddc477f69 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 22 May 2017 21:53:10 +0200 Subject: [PATCH 10/57] register missing attribute. --- src/spells.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spells.c b/src/spells.c index fa3d9a368..da60bfc57 100644 --- a/src/spells.c +++ b/src/spells.c @@ -6848,7 +6848,8 @@ void register_spells(void) #ifdef COMPAT_DEATHCLOUD at_deprecate("zauber_todeswolke", dc_read_compat); #endif - + at_register(&at_observer); + /* init_firewall(); */ ct_register(&ct_firewall); ct_register(&ct_deathcloud); From 611d69908fb82079d83071566978f6717301faef Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 22 May 2017 22:08:18 +0200 Subject: [PATCH 11/57] remove unnecessary code. --- src/spells.test.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/spells.test.c b/src/spells.test.c index b6d3a2ab7..3a048e021 100644 --- a/src/spells.test.c +++ b/src/spells.test.c @@ -113,8 +113,6 @@ static void test_watch_region(CuTest *tc) { region *r; faction *f; test_setup(); - test_create_race("spell"); - CuAssertPtrNotNull(tc, get_race(RC_SPELL)); r = test_create_region(0, 0, 0); f = test_create_faction(0); CuAssertIntEquals(tc, -1, get_observer(r, f)); From 30cfe2c0c0c4306f7a1f4f2f61dbc7575eca8a3d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 24 May 2017 08:18:55 +0200 Subject: [PATCH 12/57] convert RC_SPELL to at_observer during readgame. --- src/attributes/attributes.c | 90 ++++++++++++++++++++++++++++++++++ src/attributes/attributes.h | 6 +++ src/kernel/save.c | 27 +++++++---- src/reports.c | 1 + src/reports.test.c | 4 +- src/spells.c | 97 ++----------------------------------- src/spells.h | 3 -- src/spells.test.c | 10 ++-- 8 files changed, 128 insertions(+), 110 deletions(-) diff --git a/src/attributes/attributes.c b/src/attributes/attributes.c index f699fdb57..610bea684 100644 --- a/src/attributes/attributes.c +++ b/src/attributes/attributes.c @@ -56,9 +56,98 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include #include +#include +typedef struct obs_data { + faction *f; + int skill; + int timer; +} obs_data; + +static void obs_init(struct attrib *a) +{ + a->data.v = malloc(sizeof(obs_data)); +} + +static void obs_done(struct attrib *a) +{ + free(a->data.v); +} + +static int obs_age(struct attrib *a, void *owner) +{ + obs_data *od = (obs_data *)a->data.v; + update_interval(od->f, (region *)owner); + return --od->timer; +} + +static void obs_write(const struct attrib *a, const void *owner, struct storage *store) +{ + obs_data *od = (obs_data *)a->data.v; + write_faction_reference(od->f, store); + WRITE_INT(store, od->skill); + WRITE_INT(store, od->timer); +} + +static int obs_read(struct attrib *a, void *owner, struct gamedata *data) +{ + obs_data *od = (obs_data *)a->data.v; + + read_reference(&od->f, data, read_faction_reference, resolve_faction); + READ_INT(data->store, &od->skill); + READ_INT(data->store, &od->timer); + return AT_READ_OK; +} + +attrib_type at_observer = { "observer", obs_init, obs_done, obs_age, obs_write, obs_read }; + +static attrib *make_observer(faction *f, int perception) +{ + attrib * a = a_new(&at_observer); + obs_data *od = (obs_data *)a->data.v; + od->f = f; + od->skill = perception; + od->timer = 2; + return a; +} + +int get_observer(region *r, faction *f) { + if (fval(r, RF_OBSERVER)) { + attrib *a = a_find(r->attribs, &at_observer); + while (a && a->type == &at_observer) { + obs_data *od = (obs_data *)a->data.v; + if (od->f == f) { + return od->skill; + } + a = a->next; + } + } + return -1; +} + +void set_observer(region *r, faction *f, int skill, int turns) +{ + update_interval(f, r); + if (fval(r, RF_OBSERVER)) { + attrib *a = a_find(r->attribs, &at_observer); + while (a && a->type == &at_observer) { + obs_data *od = (obs_data *)a->data.v; + if (od->f == f && od->skill < skill) { + od->skill = skill; + od->timer = turns; + return; + } + a = a->nexttype; + } + } + else { + fset(r, RF_OBSERVER); + } + a_add(&r->attribs, make_observer(f, skill)); +} attrib_type at_unitdissolve = { "unitdissolve", NULL, NULL, NULL, a_writechars, a_readchars @@ -123,6 +212,7 @@ void register_attributes(void) at_register(&at_stealth); at_register(&at_dict); at_register(&at_unitdissolve); + at_register(&at_observer); at_register(&at_overrideroads); at_register(&at_raceprefix); at_register(&at_iceberg); diff --git a/src/attributes/attributes.h b/src/attributes/attributes.h index 4ec3150ec..19b371dbb 100644 --- a/src/attributes/attributes.h +++ b/src/attributes/attributes.h @@ -23,8 +23,14 @@ extern "C" { #endif struct attrib_type; + struct region; + struct faction; + extern void register_attributes(void); + void set_observer(struct region *r, struct faction *f, int perception, int turns); + int get_observer(struct region *r, struct faction *f); + #ifdef __cplusplus } #endif diff --git a/src/kernel/save.c b/src/kernel/save.c index 39f2a129f..983190e7d 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -48,6 +48,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "lighthouse.h" /* attributes includes */ +#include #include #include @@ -1621,6 +1622,7 @@ int read_game(gamedata *data) { int rmax = maxregions; storage * store = data->store; const struct building_type *bt_lighthouse = bt_find("lighthouse"); + const struct race *rc_spell = rc_find("spell"); if (data->version >= SAVEGAMEID_VERSION) { int gameid; @@ -1705,19 +1707,24 @@ int read_game(gamedata *data) { while (--p >= 0) { unit *u = read_unit(data); - if (data->version < JSON_REPORT_VERSION) { - if (u->_name && fval(u->faction, FFL_NPC)) { - if (!u->_name[0] || unit_name_equals_race(u)) { - unit_setname(u, NULL); + if (u_race(u) == rc_spell) { + set_observer(r, u->faction, get_level(u, SK_PERCEPTION), u->age); + free_unit(u); + } + else { + if (data->version < JSON_REPORT_VERSION) { + if (u->_name && fval(u->faction, FFL_NPC)) { + if (!u->_name[0] || unit_name_equals_race(u)) { + unit_setname(u, NULL); + } } } + assert(u->region == NULL); + u->region = r; + *up = u; + up = &u->next; + update_interval(u->faction, r); } - assert(u->region == NULL); - u->region = r; - *up = u; - up = &u->next; - - update_interval(u->faction, r); } if ((nread & 0x3FF) == 0) { /* das spart extrem Zeit */ diff --git a/src/reports.c b/src/reports.c index 934a5ae36..10a21af8d 100644 --- a/src/reports.c +++ b/src/reports.c @@ -70,6 +70,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include /* attributes includes */ +#include #include #include #include diff --git a/src/reports.test.c b/src/reports.test.c index aed0b4cb8..74750e9b5 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -722,8 +723,7 @@ static void test_report_far_vision(CuTest *tc) { r1 = test_create_region(0, 0, 0); test_create_unit(f, r1); r2 = test_create_region(10, 0, 0); - test_create_race("spell"); - set_observer(r2, f, 10); + set_observer(r2, f, 10, 2); CuAssertPtrEquals(tc, r1, f->first); CuAssertPtrEquals(tc, r2, f->last); report_context ctx; diff --git a/src/spells.c b/src/spells.c index da60bfc57..36a7656c6 100644 --- a/src/spells.c +++ b/src/spells.c @@ -25,6 +25,8 @@ #include "monsters.h" #include "teleport.h" +#include + #include #include #include @@ -4115,94 +4117,6 @@ static int sp_bigrecruit(castorder * co) return cast_level; } -typedef struct obs_data { - faction *f; - int skill; - int timer; -} obs_data; - -static void obs_init(struct attrib *a) -{ - a->data.v = malloc(sizeof(obs_data)); -} - -static void obs_done(struct attrib *a) -{ - free(a->data.v); -} - -static int obs_age(struct attrib *a, void *owner) -{ - obs_data *od = (obs_data *)a->data.v; - update_interval(od->f, (region *)owner); - return --od->timer; -} - -static void obs_write(const struct attrib *a, const void *owner, struct storage *store) -{ - obs_data *od = (obs_data *)a->data.v; - write_faction_reference(od->f, store); - WRITE_INT(store, od->skill); - WRITE_INT(store, od->timer); -} - -static int obs_read(struct attrib *a, void *owner, struct gamedata *data) -{ - obs_data *od = (obs_data *)a->data.v; - - read_reference(&od->f, data, read_faction_reference, resolve_faction); - READ_INT(data->store, &od->skill); - READ_INT(data->store, &od->timer); - return AT_READ_OK; -} - -attrib_type at_observer = { "observer", obs_init, obs_done, obs_age, obs_write, obs_read }; - -static attrib *make_observer(faction *f, int perception) -{ - attrib * a = a_new(&at_observer); - obs_data *od = (obs_data *)a->data.v; - od->f = f; - od->skill = perception; - od->timer = 2; - return a; -} - -int get_observer(region *r, faction *f) { - if (fval(r, RF_OBSERVER)) { - attrib *a = a_find(r->attribs, &at_observer); - while (a && a->type == &at_observer) { - obs_data *od = (obs_data *)a->data.v; - if (od->f == f) { - return od->skill; - } - a = a->next; - } - } - return -1; -} - -void set_observer(region *r, faction *f, int skill) -{ - update_interval(f, r); - if (fval(r, RF_OBSERVER)) { - attrib *a = a_find(r->attribs, &at_observer); - while (a && a->type == &at_observer) { - obs_data *od = (obs_data *)a->data.v; - if (od->f == f && od->skill < skill) { - od->skill = skill; - od->timer = 2; - return; - } - a = a->nexttype; - } - } - else { - fset(r, RF_OBSERVER); - } - a_add(&r->attribs, make_observer(f, skill)); -} - /* ------------------------------------------------------------- */ /* Name: Aushorchen * Stufe: 7 @@ -4259,7 +4173,7 @@ static int sp_pump(castorder * co) return cast_level / 2; } - set_observer(rt, mage->faction, effskill(target, SK_PERCEPTION, 0)); + set_observer(rt, mage->faction, effskill(target, SK_PERCEPTION, 0), 2); return cast_level; } @@ -4892,7 +4806,7 @@ int sp_dreamreading(castorder * co) return 0; } - set_observer(u->region, mage->faction, effskill(u, SK_PERCEPTION, u->region)); + set_observer(u->region, mage->faction, effskill(u, SK_PERCEPTION, u->region), 2); msg = msg_message("sp_dreamreading_effect", "mage unit region", mage, u, @@ -5765,7 +5679,7 @@ int sp_viewreality(castorder * co) for (rl2 = rl; rl2; rl2 = rl2->next) { region *rt = rl2->data; if (!is_cursed(rt->attribs, C_ASTRALBLOCK, 0)) { - set_observer(rt, mage->faction, co->level / 2); + set_observer(rt, mage->faction, co->level / 2, 2); } } @@ -6848,7 +6762,6 @@ void register_spells(void) #ifdef COMPAT_DEATHCLOUD at_deprecate("zauber_todeswolke", dc_read_compat); #endif - at_register(&at_observer); /* init_firewall(); */ ct_register(&ct_firewall); diff --git a/src/spells.h b/src/spells.h index d45f04d68..33a263733 100644 --- a/src/spells.h +++ b/src/spells.h @@ -32,9 +32,6 @@ extern "C" { void register_magicresistance(void); void register_spells(void); - void set_observer(struct region *r, struct faction *f, int perception); - int get_observer(struct region *r, struct faction *f); - int sp_baddreams(castorder * co); int sp_gooddreams(castorder * co); diff --git a/src/spells.test.c b/src/spells.test.c index 3a048e021..00a88cbf8 100644 --- a/src/spells.test.c +++ b/src/spells.test.c @@ -1,4 +1,7 @@ #include + +#include "spells.h" + #include #include #include @@ -10,7 +13,8 @@ #include #include #include -#include "spells.h" + +#include #include #include @@ -116,9 +120,9 @@ static void test_watch_region(CuTest *tc) { r = test_create_region(0, 0, 0); f = test_create_faction(0); CuAssertIntEquals(tc, -1, get_observer(r, f)); - set_observer(r, f, 0); + set_observer(r, f, 0, 2); CuAssertIntEquals(tc, 0, get_observer(r, f)); - set_observer(r, f, 10); + set_observer(r, f, 10, 2); CuAssertIntEquals(tc, 10, get_observer(r, f)); CuAssertIntEquals(tc, RF_OBSERVER, fval(r, RF_OBSERVER)); CuAssertPtrNotNull(tc, r->attribs); From 18daa9db2f14a8d25d718195480581fbdee4cdd6 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 24 May 2017 08:52:19 +0200 Subject: [PATCH 13/57] entirely remove RC_SPELL --- src/chaos.c | 10 ++---- src/economy.c | 5 ++- src/give.c | 7 +--- src/kernel/race.c | 2 +- src/kernel/race.h | 3 +- src/kernel/save.c | 6 ++-- src/kernel/unit.c | 3 +- src/kernel/unit.test.c | 21 ------------ src/laws.c | 22 +++--------- src/magic.c | 6 +--- src/randenc.c | 2 +- src/spells.c | 77 ++++++++++++++++++++---------------------- src/util/gamedata.h | 3 +- src/volcano.c | 2 +- 14 files changed, 57 insertions(+), 112 deletions(-) diff --git a/src/chaos.c b/src/chaos.c index 58cd7af73..5628b68f4 100644 --- a/src/chaos.c +++ b/src/chaos.c @@ -112,9 +112,7 @@ static unit *random_unit(const region * r) unit *u; for (u = r->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPELL)) { - c += u->number; - } + c += u->number; } if (c == 0) { @@ -125,9 +123,7 @@ static unit *random_unit(const region * r) u = r->units; while (u && c < n) { - if (u_race(u) != get_race(RC_SPELL)) { - c += u->number; - } + c += u->number; u = u->next; } @@ -203,7 +199,7 @@ static void chaos(region * r) for (up = &r->units; *up;) { unit *u = *up; - if (u_race(u) != get_race(RC_SPELL) && u->ship == 0 && !canfly(u)) { + if (u->ship == 0 && !canfly(u)) { ADDMSG(&u->faction->msgs, msg_message("tidalwave_kill", "region unit", r, u)); remove_unit(up, u); diff --git a/src/economy.c b/src/economy.c index 0bc056b56..3e13f0643 100644 --- a/src/economy.c +++ b/src/economy.c @@ -2978,13 +2978,12 @@ void produce(struct region *r) static int bt_cache; static const struct building_type *caravan_bt; static int rc_cache; - static const race *rc_spell, *rc_insect, *rc_aquarian; + static const race *rc_insect, *rc_aquarian; if (bt_changed(&bt_cache)) { caravan_bt = bt_find("caravan"); } if (rc_changed(&rc_cache)) { - rc_spell = get_race(RC_SPELL); rc_insect = get_race(RC_INSECT); rc_aquarian = get_race(RC_AQUARIAN); } @@ -3022,7 +3021,7 @@ void produce(struct region *r) bool trader = false; keyword_t todo; - if (u_race(u) == rc_spell || fval(u, UFL_LONGACTION)) + if (fval(u, UFL_LONGACTION)) continue; if (u_race(u) == rc_insect && r_insectstalled(r) && diff --git a/src/give.c b/src/give.c index 060ecbbb9..26b193d0d 100644 --- a/src/give.c +++ b/src/give.c @@ -667,12 +667,7 @@ void give_cmd(unit * u, order * ord) return; } - if (u2 && u_race(u2) == get_race(RC_SPELL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - return; - } - else if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { + if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) && !ucontact(u2, u)) { cmistake(u, ord, 40, MSG_COMMERCE); return; } diff --git a/src/kernel/race.c b/src/kernel/race.c index a2c37d87d..14fb66331 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -69,7 +69,7 @@ const char *racenames[MAXRACES] = { "dwarf", "elf", NULL, "goblin", "human", "troll", "demon", "insect", "halfling", "cat", "aquarian", "orc", "snotling", "undead", NULL, "youngdragon", "dragon", "wyrm", "ent", "catdragon", "dracoid", - NULL, "spell", "irongolem", "stonegolem", "shadowdemon", + NULL, NULL, "irongolem", "stonegolem", "shadowdemon", "shadowmaster", "mountainguard", "alp", "toad", "braineater", "peasant", "wolf", NULL, NULL, NULL, NULL, "songdragon", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff --git a/src/kernel/race.h b/src/kernel/race.h index 5c320ea05..a8933dae8 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -72,8 +72,7 @@ extern "C" { RC_BIRTHDAYDRAGON, RC_DRACOID, - RC_SPELL = 22, - RC_IRONGOLEM, + RC_IRONGOLEM = 23, RC_STONEGOLEM, RC_SHADOW, RC_SHADOWLORD, diff --git a/src/kernel/save.c b/src/kernel/save.c index 983190e7d..7a9e12286 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -132,8 +132,6 @@ static unit *unitorders(FILE * F, int enc, struct faction *f) i = getid(); u = findunitg(i, NULL); - if (u && u_race(u) == get_race(RC_SPELL)) - return NULL; if (u && u->faction == f) { order **ordp; @@ -852,7 +850,7 @@ void write_unit(struct gamedata *data, const unit * u) WRITE_SECTION(data->store); write_items(data->store, u->items); WRITE_SECTION(data->store); - if (u->hp == 0 && u_race(u)!= get_race(RC_SPELL)) { + if (u->hp == 0 && data->version < NORCSPELL_VERSION) { log_error("unit %s has 0 hitpoints, adjusting.", itoa36(u->no)); ((unit *)u)->hp = u->number; } @@ -1707,7 +1705,7 @@ int read_game(gamedata *data) { while (--p >= 0) { unit *u = read_unit(data); - if (u_race(u) == rc_spell) { + if (data->version < NORCSPELL_VERSION && u_race(u) == rc_spell) { set_observer(r, u->faction, get_level(u, SK_PERCEPTION), u->age); free_unit(u); } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index ab5f72f35..4a9540ba9 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1891,8 +1891,7 @@ void remove_empty_units_in_region(region * r) set_number(u, 0); } } - if ((u->number == 0 && u_race(u) != get_race(RC_SPELL)) || (u->age <= 0 - && u_race(u) == get_race(RC_SPELL))) { + if (u->number == 0) { remove_unit(up, u); } if (*up == u) diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 096da9d62..54b07b63f 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -97,26 +97,6 @@ static void test_remove_units_with_dead_faction(CuTest *tc) { test_cleanup(); } -static void test_remove_units_ignores_spells(CuTest *tc) { - unit *u; - int uid; - - test_cleanup(); - test_create_world(); - - u = create_unit(findregion(0, 0), test_create_faction(test_create_race("human")), 1, test_create_race("spell"), 0, 0, 0); - uid = u->no; - u->number = 0; - u->age = 1; - remove_empty_units_in_region(u->region); - CuAssertPtrNotNull(tc, findunit(uid)); - CuAssertPtrNotNull(tc, u->region); - u->age = 0; - remove_empty_units_in_region(u->region); - CuAssertPtrEquals(tc, 0, findunit(uid)); - test_cleanup(); -} - static void test_scale_number(CuTest *tc) { unit *u; const struct potion_type *ptype; @@ -555,7 +535,6 @@ CuSuite *get_unit_suite(void) SUITE_ADD_TEST(suite, test_update_monster_name); SUITE_ADD_TEST(suite, test_remove_unit); SUITE_ADD_TEST(suite, test_remove_empty_units); - SUITE_ADD_TEST(suite, test_remove_units_ignores_spells); SUITE_ADD_TEST(suite, test_remove_units_without_faction); SUITE_ADD_TEST(suite, test_remove_units_with_dead_faction); SUITE_ADD_TEST(suite, test_remove_empty_units_in_region); diff --git a/src/laws.c b/src/laws.c index e16cbd583..01da6f4ee 100644 --- a/src/laws.c +++ b/src/laws.c @@ -154,22 +154,11 @@ static bool RemoveNMRNewbie(void) static void age_unit(region * r, unit * u) { static int rc_cache; - static const race *rc_spell; + const race *rc = u_race(u); - if (rc_changed(&rc_cache)) { - rc_spell = get_race(RC_SPELL); - } - if (u_race(u) == rc_spell) { - if (--u->age <= 0) { - remove_unit(&r->units, u); - } - } - else { - const race *rc = u_race(u); - ++u->age; - if (u->number > 0 && rc->age_unit) { - rc->age_unit(u); - } + ++u->age; + if (u->number > 0 && rc->age_unit) { + rc->age_unit(u); } if (u->region && is_astral(u->region)) { item **itemp = &u->items; @@ -2676,8 +2665,7 @@ int guard_on_cmd(unit * u, struct order *ord) if (fval(u, UFL_MOVED)) { cmistake(u, ord, 187, MSG_EVENT); } - else if (fval(u_race(u), RCF_ILLUSIONARY) - || u_race(u) == get_race(RC_SPELL)) { + else if (fval(u_race(u), RCF_ILLUSIONARY)) { cmistake(u, ord, 95, MSG_EVENT); } else { diff --git a/src/magic.c b/src/magic.c index a20fbc477..1af357a7c 100644 --- a/src/magic.c +++ b/src/magic.c @@ -1209,9 +1209,6 @@ target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus) skill *sv; unit *u = (unit *)obj; - if (u_race(u)==get_race(RC_SPELL)) { - return true; - } at = effskill(magician, SK_MAGIC, 0); for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { @@ -2780,7 +2777,6 @@ void magic(void) int rank; castorder *co; spellrank spellranks[MAX_SPELLRANK]; - const race *rc_spell = get_race(RC_SPELL); const race *rc_insect = get_race(RC_INSECT); memset(spellranks, 0, sizeof(spellranks)); @@ -2790,7 +2786,7 @@ void magic(void) for (u = r->units; u; u = u->next) { order *ord; - if (u->number <= 0 || u_race(u) == rc_spell) + if (u->number <= 0) continue; if (u_race(u) == rc_insect && r_insectstalled(r) && diff --git a/src/randenc.c b/src/randenc.c index ab51d64b1..e46d5fa24 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -418,7 +418,7 @@ void drown(region * r) while (*up) { unit *u = *up; - if (!(u->ship || u_race(u) == get_race(RC_SPELL) || u->number == 0 || canswim(u) || canfly(u))) { + if (!(u->ship || u->number == 0 || canswim(u) || canfly(u))) { scale_number(u, 0); ADDMSG(&u->faction->msgs, msg_message("drown", "unit region", u, r)); } diff --git a/src/spells.c b/src/spells.c index 36a7656c6..fc8c445b7 100644 --- a/src/spells.c +++ b/src/spells.c @@ -1694,7 +1694,7 @@ static int sp_great_drought(castorder * co) rsetterrain(r, T_OCEAN); /* Einheiten duerfen hier auf keinen Fall geloescht werden! */ for (u = r->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPELL) && u->ship == 0) { + if (!u->ship) { set_number(u, 0); } } @@ -5601,8 +5601,7 @@ int sp_showastral(castorder * co) region *r2 = rl2->data; if (!is_cursed(r2->attribs, C_ASTRALBLOCK, 0)) { for (u = r2->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPELL)) - n++; + n++; } } } @@ -5622,26 +5621,24 @@ int sp_showastral(castorder * co) for (rl2 = rl; rl2; rl2 = rl2->next) { if (!is_cursed(rl2->data->attribs, C_ASTRALBLOCK, 0)) { for (u = rl2->data->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPELL)) { - c++; - scat(unitname(u)); - scat(" ("); - if (!fval(u, UFL_ANON_FACTION)) { - scat(factionname(u->faction)); - scat(", "); - } - icat(u->number); - scat(" "); - scat(LOC(mage->faction->locale, rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL))); - scat(", Entfernung "); - icat(distance(rl2->data, rt)); - scat(")"); - if (c == n - 1) { - scat(" und "); - } - else if (c < n - 1) { - scat(", "); - } + c++; + scat(unitname(u)); + scat(" ("); + if (!fval(u, UFL_ANON_FACTION)) { + scat(factionname(u->faction)); + scat(", "); + } + icat(u->number); + scat(" "); + scat(LOC(mage->faction->locale, rc_name_s(u_race(u), (u->number == 1) ? NAME_SINGULAR : NAME_PLURAL))); + scat(", Entfernung "); + icat(distance(rl2->data, rt)); + scat(")"); + if (c == n - 1) { + scat(" und "); + } + else if (c < n - 1) { + scat(", "); } } } @@ -5758,24 +5755,22 @@ int sp_disruptastral(castorder * co) if (trl != NULL) { for (u = r2->units; u; u = u->next) { - if (u_race(u) != get_race(RC_SPELL)) { - region_list *trl2 = trl; - region *tr; - int c = rng_int() % inhab_regions; - - /* Zufaellige Zielregion suchen */ - while (c-- != 0) - trl2 = trl2->next; - tr = trl2->data; - - if (!is_magic_resistant(mage, u, 0) && can_survive(u, tr)) { - message *msg = msg_message("disrupt_astral", "unit region", u, tr); - add_message(&u->faction->msgs, msg); - add_message(&tr->msgs, msg); - msg_release(msg); - - move_unit(u, tr, NULL); - } + region_list *trl2 = trl; + region *tr; + int c = rng_int() % inhab_regions; + + /* Zufaellige Zielregion suchen */ + while (c-- != 0) + trl2 = trl2->next; + tr = trl2->data; + + if (!is_magic_resistant(mage, u, 0) && can_survive(u, tr)) { + message *msg = msg_message("disrupt_astral", "unit region", u, tr); + add_message(&u->faction->msgs, msg); + add_message(&tr->msgs, msg); + msg_release(msg); + + move_unit(u, tr, NULL); } } free_regionlist(trl); diff --git a/src/util/gamedata.h b/src/util/gamedata.h index 452a6e527..f4983a981 100644 --- a/src/util/gamedata.h +++ b/src/util/gamedata.h @@ -34,10 +34,11 @@ #define NOWATCH_VERSION 354 /* plane->watchers is gone */ #define KEYVAL_VERSION 355 /* at_keys has values */ #define NOLANDITEM_VERSION 356 /* land_region has no items */ +#define NORCSPELL_VERSION 357 /* data contains no RC_SPELL units */ /* unfinished: */ #define CRYPT_VERSION 400 /* passwords are encrypted */ -#define RELEASE_VERSION NOLANDITEM_VERSION /* current datafile */ +#define RELEASE_VERSION NORCSPELL_VERSION /* current datafile */ #define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */ #define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */ diff --git a/src/volcano.c b/src/volcano.c index 9734bb2cd..db7166de0 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -82,7 +82,7 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic) int i, dead = 0, hp_rem = 0, heiltrank; assert(u->number); - if (fval(u_race(u), RCF_ILLUSIONARY) || u_race(u) == get_race(RC_SPELL)) { + if (fval(u_race(u), RCF_ILLUSIONARY)) { return 0; } From 153039fdefb48863ae40fd3d3d0be5c07e4923a7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 24 May 2017 08:58:46 +0200 Subject: [PATCH 14/57] fix gcc compilation, unused variable --- src/laws.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/laws.c b/src/laws.c index 01da6f4ee..ba088a8bb 100644 --- a/src/laws.c +++ b/src/laws.c @@ -153,7 +153,6 @@ static bool RemoveNMRNewbie(void) static void age_unit(region * r, unit * u) { - static int rc_cache; const race *rc = u_race(u); ++u->age; From 1687e31d5febff1759abbe9b8a2e3650d50d92f5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 28 May 2017 12:51:41 +0200 Subject: [PATCH 15/57] starting a new release --- src/kernel/version.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kernel/version.c b/src/kernel/version.c index 39f4f30e6..0842b3d8e 100644 --- a/src/kernel/version.c +++ b/src/kernel/version.c @@ -5,7 +5,7 @@ #ifndef ERESSEA_VERSION /* the version number, if it was not passed to make with -D */ -#define ERESSEA_VERSION "3.12.0" +#define ERESSEA_VERSION "3.13.0" #endif const char *eressea_version(void) { From 5b807e2057ea0b59935005985e1781dbc085ff4e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Jun 2017 14:12:23 +0200 Subject: [PATCH 16/57] crash casued by spell conversion. remove unit from faction, not only region! also remove spammy warning that has no value. --- src/kernel/save.c | 1 + src/kernel/unit.c | 4 +++- src/magic.c | 1 - 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/kernel/save.c b/src/kernel/save.c index 7a9e12286..83a218622 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1707,6 +1707,7 @@ int read_game(gamedata *data) { if (data->version < NORCSPELL_VERSION && u_race(u) == rc_spell) { set_observer(r, u->faction, get_level(u, SK_PERCEPTION), u->age); + u_setfaction(u, NULL); free_unit(u); } else { diff --git a/src/kernel/unit.c b/src/kernel/unit.c index e6b8757ef..d5317ec72 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1400,10 +1400,12 @@ int invisible(const unit * target, const unit * viewer) /** remove the unit from memory. * this frees all memory that's only accessible through the unit, * and you should already have called uunhash and removed the unit from the - * region. + * region and faction. */ void free_unit(unit * u) { + assert(!u->region); + assert(!u->faction); free(u->_name); free(u->display); free_order(u->thisorder); diff --git a/src/magic.c b/src/magic.c index 3cac1cb52..93c5009f5 100644 --- a/src/magic.c +++ b/src/magic.c @@ -3010,7 +3010,6 @@ int cast_spell(struct castorder *co) fun = get_spellcast(sp->sname); if (!fun) { - log_warning("no spell function for %s, try callback", sp->sname); return callbacks.cast_spell(co, fname); } return fun(co); From 8c11cb676f08c9f096afd8b08be768a76c6d9f8b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Jun 2017 14:18:28 +0200 Subject: [PATCH 17/57] fix some failing tests. --- src/kernel/region.c | 2 ++ src/kernel/unit.c | 1 + 2 files changed, 3 insertions(+) diff --git a/src/kernel/region.c b/src/kernel/region.c index 5cb86ff47..dc2fee21d 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -918,6 +918,8 @@ void free_region(region * r) unit *u = r->units; r->units = u->next; uunhash(u); + u->region = NULL; + u_setfaction(u, NULL); free_unit(u); free(u); } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index d5317ec72..61cdac6c0 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -749,6 +749,7 @@ void free_units(void) while (deleted_units) { unit *u = deleted_units; deleted_units = deleted_units->next; + u_setfaction(u, NULL); free_unit(u); free(u); } From 728f7ed3897219daf0f5c4c7ac715a5633215987 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Jun 2017 14:33:13 +0200 Subject: [PATCH 18/57] Revert "fix some failing tests." This reverts commit 8c11cb676f08c9f096afd8b08be768a76c6d9f8b. --- src/kernel/region.c | 2 -- src/kernel/unit.c | 1 - 2 files changed, 3 deletions(-) diff --git a/src/kernel/region.c b/src/kernel/region.c index dc2fee21d..5cb86ff47 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -918,8 +918,6 @@ void free_region(region * r) unit *u = r->units; r->units = u->next; uunhash(u); - u->region = NULL; - u_setfaction(u, NULL); free_unit(u); free(u); } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 61cdac6c0..d5317ec72 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -749,7 +749,6 @@ void free_units(void) while (deleted_units) { unit *u = deleted_units; deleted_units = deleted_units->next; - u_setfaction(u, NULL); free_unit(u); free(u); } From 3e0bc4f26d4ef233d3eb05f28605b6495f7ff416 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 4 Jun 2017 14:35:15 +0200 Subject: [PATCH 19/57] cannot assert that free_unit has no faction (complicated reasons) --- src/kernel/region.c | 1 + src/kernel/unit.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kernel/region.c b/src/kernel/region.c index 5cb86ff47..b582c406e 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -917,6 +917,7 @@ void free_region(region * r) while (r->units) { unit *u = r->units; r->units = u->next; + u->region = NULL; uunhash(u); free_unit(u); free(u); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index d5317ec72..7b6f135fc 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -1400,12 +1400,11 @@ int invisible(const unit * target, const unit * viewer) /** remove the unit from memory. * this frees all memory that's only accessible through the unit, * and you should already have called uunhash and removed the unit from the - * region and faction. + * region. */ void free_unit(unit * u) { assert(!u->region); - assert(!u->faction); free(u->_name); free(u->display); free_order(u->thisorder); From 1273abb967c10a0b71daef0588918e6070b888bf Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 24 Jun 2017 13:36:18 +0200 Subject: [PATCH 20/57] Getrennte Befehle fuer PFLANZE und ZUECHTE --- conf/keywords.json | 6 ++++-- src/economy.c | 3 ++- src/kernel/order.c | 9 ++++++--- src/keyword.c | 1 + src/keyword.h | 3 ++- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/conf/keywords.json b/conf/keywords.json index 4c9fa905d..4f8f27f5b 100644 --- a/conf/keywords.json +++ b/conf/keywords.json @@ -1,7 +1,8 @@ { "keywords": { "en" : { - "grow": [ "GROW", "BREED", "PLANT" ], + "plant": "PLANT", + "grow": [ "GROW", "BREED" ], "promote": ["PROMOTE", "PROMOTION" ], "combat": [ "COMBAT", "FIGHT" ] }, @@ -53,7 +54,8 @@ "cast": ["ZAUBERE", "ZAUBERN"], "show": ["ZEIGE", "ZEIGEN"], "destroy": ["ZERSTÖRE", "ZERSTÖREN"], - "grow": ["ZÃœCHTE", "PFLANZE", "ZÃœCHTEN", "PFLANZEN"], + "grow": ["ZÃœCHTE", "ZÃœCHTEN"], + "plant": ["PFLANZE", "PFLANZEN"], "default": "DEFAULT", "origin": "URSPRUNG", "email": "EMAIL", diff --git a/src/economy.c b/src/economy.c index 3e13f0643..df2f2ea25 100644 --- a/src/economy.c +++ b/src/economy.c @@ -3098,7 +3098,8 @@ void produce(struct region *r) sabotage_cmd(u, u->thisorder); break; - case K_BREED: + case K_PLANT: + case K_GROW: breed_cmd(u, u->thisorder); break; diff --git a/src/kernel/order.c b/src/kernel/order.c index 6fbb53040..d64da0131 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -446,7 +446,8 @@ bool is_repeated(keyword_t kwd) case K_SABOTAGE: case K_STUDY: case K_TEACH: - case K_BREED: + case K_GROW: + case K_PLANT: case K_PIRACY: case K_MAKE: case K_LOOT: @@ -485,7 +486,8 @@ bool is_exclusive(const order * ord) case K_SABOTAGE: case K_STUDY: case K_TEACH: - case K_BREED: + case K_GROW: + case K_PLANT: case K_PIRACY: case K_MAKE: case K_LOOT: @@ -525,7 +527,8 @@ bool is_long(keyword_t kwd) case K_SABOTAGE: case K_STUDY: case K_TEACH: - case K_BREED: + case K_GROW: + case K_PLANT: case K_PIRACY: case K_MAKE: case K_LOOT: diff --git a/src/keyword.c b/src/keyword.c index ba05cbe4b..cb56fe940 100644 --- a/src/keyword.c +++ b/src/keyword.c @@ -134,6 +134,7 @@ const char *keywords[MAXKEYWORDS] = { "cast", "show", "destroy", + "plant", "grow", "default", "origin", diff --git a/src/keyword.h b/src/keyword.h index 19e55e88f..9be7f9f4e 100644 --- a/src/keyword.h +++ b/src/keyword.h @@ -58,7 +58,8 @@ extern "C" K_CAST, K_RESHOW, K_DESTROY, - K_BREED, + K_PLANT, + K_GROW, K_DEFAULT, K_URSPRUNG, K_EMAIL, From 2dab88b1189b1eeceb25bdafc7e15772aa81e024 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 25 Jun 2017 08:21:14 +0200 Subject: [PATCH 21/57] cmistake no return value, no mistakes --- src/kernel/messages.c | 11 +++++------ src/kernel/messages.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/kernel/messages.c b/src/kernel/messages.c index d3cd4f99b..b8d33f08c 100644 --- a/src/kernel/messages.c +++ b/src/kernel/messages.c @@ -258,15 +258,14 @@ message * msg_error(const unit * u, struct order *ord, int mno) { return msg_feedback(u, ord, msgname, ""); } -message * cmistake(const unit * u, struct order *ord, int mno, int mtype) +void cmistake(const unit * u, struct order *ord, int mno, int mtype) { - message * result; + message * msg; UNUSED_ARG(mtype); - result = msg_error(u, ord, mno); - if (result) { - ADDMSG(&u->faction->msgs, result); + msg = msg_error(u, ord, mno); + if (msg) { + ADDMSG(&u->faction->msgs, msg); } - return result; } void syntax_error(const struct unit *u, struct order *ord) diff --git a/src/kernel/messages.h b/src/kernel/messages.h index a42342153..4eca65fc1 100644 --- a/src/kernel/messages.h +++ b/src/kernel/messages.h @@ -60,7 +60,7 @@ extern "C" { #define ADDMSG(msgs, mcreate) { message * mx = mcreate; if (mx) { assert(mx->refcount>=1); add_message(msgs, mx); msg_release(mx); } } void syntax_error(const struct unit *u, struct order *ord); - struct message * cmistake(const struct unit *u, struct order *ord, int mno, int mtype); + void cmistake(const struct unit *u, struct order *ord, int mno, int mtype); struct message * msg_error(const struct unit * u, struct order *ord, int mno); #ifdef __cplusplus } From beecc0e323afa5ac57c31f8318d2d0ba30f379fe Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 25 Jun 2017 14:07:50 +0200 Subject: [PATCH 22/57] BUG 2343: fix clone_men (hitpoints), add test. --- src/kernel/curse.c | 6 +++--- src/kernel/curse.h | 4 ++-- src/kernel/unit.c | 13 ++++++------- src/kernel/unit.h | 2 +- src/kernel/unit.test.c | 24 ++++++++++++++++++++++++ src/upkeep.c | 1 + 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 01e77eace..4a3e1c045 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -493,7 +493,7 @@ const curse_type * ct) /* ------------------------------------------------------------- */ /* gibt bei Personenbeschränkten Verzauberungen die Anzahl der * betroffenen Personen zurück. Ansonsten wird 0 zurückgegeben. */ -int get_cursedmen(unit * u, const curse * c) +int get_cursedmen(const unit * u, const curse * c) { int cursedmen = u->number; @@ -631,7 +631,7 @@ curse *create_curse(unit * magician, attrib ** ap, const curse_type * ct, /* hier müssen alle c-typen, die auf Einheiten gezaubert werden können, * berücksichtigt werden */ -static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) +static void do_transfer_curse(curse * c, const unit * u, unit * u2, int n) { int cursedmen = 0; int men = get_cursedmen(u, c); @@ -678,7 +678,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) } } -void transfer_curse(unit * u, unit * u2, int n) +void transfer_curse(const unit * u, unit * u2, int n) { attrib *a; diff --git a/src/kernel/curse.h b/src/kernel/curse.h index 543755c2b..a4fd1c430 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -267,7 +267,7 @@ extern "C" { /* gibt bei Personenbeschränkten Verzauberungen die Anzahl der * betroffenen Personen zurück. Ansonsten wird 0 zurückgegeben. */ - int get_cursedmen(struct unit *u, const struct curse *c); + int get_cursedmen(const struct unit *u, const struct curse *c); /* setzt/loescht Spezialflag einer Verzauberung (zB 'dauert ewig') */ void c_setflag(curse * c, unsigned int flag); @@ -277,7 +277,7 @@ extern "C" { * korrekt gehandhabt werden. Je nach internen Flag kann dies * unterschiedlich gewünscht sein * */ - void transfer_curse(struct unit *u, struct unit *u2, int n); + void transfer_curse(const struct unit *u, struct unit *u2, int n); /* gibt pointer auf die erste curse-struct zurück, deren Typ ctype ist, * oder einen NULL-pointer diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 7b6f135fc..bdd5ac232 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -981,10 +981,9 @@ void move_unit(unit * u, region * r, unit ** ulist) /* ist mist, aber wegen nicht skalierender attribute notwendig: */ #include "alchemy.h" -void clone_men(unit * u, unit * dst, int n) +void clone_men(const unit * u, unit * dst, int n) { const attrib *a; - int hp = u->hp; region *r = u->region; if (n == 0) @@ -1073,11 +1072,9 @@ void clone_men(unit * u, unit * dst, int n) if (u->attribs) { transfer_curse(u, dst, n); } - } - if (dst) { set_number(dst, dst->number + n); - hp -= u->hp; - dst->hp += hp; + dst->hp += u->hp * dst->number / u->number; + assert(dst->hp >= dst->number); /* TODO: Das ist schnarchlahm! und gehoert nicht hierhin */ a = a_find(dst->attribs, &at_effect); while (a && a->type == &at_effect) { @@ -1530,7 +1527,9 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace, /* u->race muss bereits gesetzt sein, wird fuer default-hp gebraucht */ /* u->region auch */ - u->hp = unit_max_hp(u) * number; + if (number > 0) { + u->hp = unit_max_hp(u) * number; + } if (dname) { u->_name = strdup(dname); diff --git a/src/kernel/unit.h b/src/kernel/unit.h index beea74ee7..dede956b5 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -166,7 +166,7 @@ extern "C" { void set_level(struct unit *u, skill_t id, int level); int get_level(const struct unit *u, skill_t id); void transfermen(struct unit *src, struct unit *dst, int n); - void clone_men(struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */ + void clone_men(const struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */ int eff_skill(const struct unit *u, const struct skill *sv, const struct region *r); int effskill_study(const struct unit *u, skill_t sk, const struct region *r); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 54b07b63f..6ab8ee21a 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -525,6 +525,29 @@ static void test_unlimited_units(CuTest *tc) { test_cleanup(); } +static void test_clone_men(CuTest *tc) { + unit *u1, *u2; + region *r; + faction *f; + test_setup(); + r = test_create_region(0, 0, NULL); + f = test_create_faction(NULL); + u1 = test_create_unit(f, r); + scale_number(u1, 10); + u2 = test_create_unit(f, r); + scale_number(u2, 0); + CuAssertIntEquals(tc, 10, u1->number); + CuAssertIntEquals(tc, 200, u1->hp); + CuAssertIntEquals(tc, 0, u2->number); + CuAssertIntEquals(tc, 0, u2->hp); + clone_men(u1, u2, 1); + CuAssertIntEquals(tc, 10, u1->number); + CuAssertIntEquals(tc, 200, u1->hp); + CuAssertIntEquals(tc, 1, u2->number); + CuAssertIntEquals(tc, 20, u2->hp); + test_cleanup(); +} + CuSuite *get_unit_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -533,6 +556,7 @@ CuSuite *get_unit_suite(void) SUITE_ADD_TEST(suite, test_unit_name); SUITE_ADD_TEST(suite, test_unit_name_from_race); SUITE_ADD_TEST(suite, test_update_monster_name); + SUITE_ADD_TEST(suite, test_clone_men); SUITE_ADD_TEST(suite, test_remove_unit); SUITE_ADD_TEST(suite, test_remove_empty_units); SUITE_ADD_TEST(suite, test_remove_units_without_faction); diff --git a/src/upkeep.c b/src/upkeep.c index 8494d7f25..c4a937a45 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -191,6 +191,7 @@ void get_food(region * r) int need = lifestyle(u); faction *f = u->faction; + assert(u->hp > 0); need -= MAX(0, get_money(u)); if (need > 0) { From de1e0ae9163cbb4ec8125affe19e1653aea040a2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 9 Jul 2017 10:43:53 +0200 Subject: [PATCH 23/57] fix indentation --- src/reports.c | 154 +++++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/src/reports.c b/src/reports.c index 8937d1d97..1a269caa5 100644 --- a/src/reports.c +++ b/src/reports.c @@ -161,15 +161,15 @@ size_t report_status(const unit * u, const struct locale *lang, char *fsbuf, siz const char *lname = locale_name(lang); struct locale *wloc = get_locale(lname); log_warning("no translation for combat status %s in %s", combatstatus[u->status], lname); - locale_setstring(wloc, combatstatus[u->status], combatstatus[u->status]+7); - len = strlcpy(fsbuf, combatstatus[u->status]+7, buflen); + locale_setstring(wloc, combatstatus[u->status], combatstatus[u->status] + 7); + len = strlcpy(fsbuf, combatstatus[u->status] + 7, buflen); } else { len = strlcpy(fsbuf, status, buflen); } if (fval(u, UFL_NOAID)) { - len += strlcat(fsbuf+len, ", ", buflen-len); - len += strlcat(fsbuf+len, LOC(lang, "status_noaid"), buflen-len); + len += strlcat(fsbuf + len, ", ", buflen - len); + len += strlcat(fsbuf + len, LOC(lang, "status_noaid"), buflen - len); } return len; @@ -201,7 +201,7 @@ const char *hp_status(const unit * u) void report_item(const unit * owner, const item * i, const faction * viewer, -const char **name, const char **basename, int *number, bool singular) + const char **name, const char **basename, int *number, bool singular) { const resource_type *rsilver = get_resourcetype(R_SILVER); @@ -251,7 +251,7 @@ const char **name, const char **basename, int *number, bool singular) if (name) *name = LOC(viewer->locale, resourcename(i->type->rtype, - NMF_APPEARANCE | ((i->number != 1 && !singular) ? GR_PLURAL : 0))); + NMF_APPEARANCE | ((i->number != 1 && !singular) ? GR_PLURAL : 0))); if (basename) *basename = resourcename(i->type->rtype, NMF_APPEARANCE); if (number) { @@ -286,7 +286,7 @@ static size_t buforder(char *buffer, size_t size, const order * ord, int mode) WARN_STATIC_BUFFER(); } - return bufp-buffer; + return bufp - buffer; } /** create a report of a list of items to a non-owner. @@ -349,7 +349,7 @@ report_items(const unit *u, item * result, int size, const unit * owner, return n; } -static void report_resource(resource_report * result, const resource_type *rtype, +static void report_resource(resource_report * result, const resource_type *rtype, int number, int level) { assert(rtype); @@ -381,7 +381,7 @@ void report_race(const struct unit *u, const char **name, const char **illusion) void report_building(const struct building *b, const char **name, -const char **illusion) + const char **illusion) { if (name) { *name = buildingtype(b->type, b, b->size); @@ -400,7 +400,7 @@ const char **illusion) int report_resources(const region * r, resource_report * result, int size, -const faction * viewer, bool see_unit) + const faction * viewer, bool see_unit) { int n = 0; @@ -487,7 +487,7 @@ const faction * viewer, bool see_unit) int bufunit(const faction * f, const unit * u, unsigned int indent, seen_mode mode, char *buf, -size_t size) + size_t size) { int i, dh; int getarnt = fval(u, UFL_ANON_FACTION); @@ -626,7 +626,7 @@ size_t size) skill *sv; for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { size_t bytes = spskill(bufp, size, f->locale, u, sv, &dh, 1); - assert(bytes <=INT_MAX); + assert(bytes <= INT_MAX); if (wrptr(&bufp, &size, (int)bytes) != 0) WARN_STATIC_BUFFER(); } @@ -796,7 +796,7 @@ size_t size) size_t spskill(char *buffer, size_t size, const struct locale * lang, -const struct unit * u, struct skill * sv, int *dh, int days) + const struct unit * u, struct skill * sv, int *dh, int days) { char *bufp = buffer; int i, effsk; @@ -856,7 +856,7 @@ const struct unit * u, struct skill * sv, int *dh, int days) WARN_STATIC_BUFFER(); } } - return bufp-buffer; + return bufp - buffer; } void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark) @@ -927,7 +927,7 @@ void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark) void spunit(struct strlist **SP, const struct faction *f, const unit * u, unsigned int indent, -seen_mode mode) + seen_mode mode) { char buf[DISPLAYSIZE]; int dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); @@ -1013,7 +1013,7 @@ static void cb_add_address(region *r, unit *ut, void *cbdata) { address_data *data = (address_data *)cbdata; faction *f = data->f; - if (ut->faction==f) { + if (ut->faction == f) { unit *u; for (u = r->units; u; u = u->next) { faction *sf = visible_faction(f, u); @@ -1140,8 +1140,8 @@ void reports_done(void) { int get_regions_distance_arr(region *rc, int radius, region *result[], int size) { int n = 0, i; - - if (size>n) { + + if (size > n) { result[n++] = rc; fset(rc, RF_MARK); } @@ -1151,7 +1151,7 @@ int get_regions_distance_arr(region *rc, int radius, region *result[], int size) r = result[i]; dist = distance(rc, r); - if (distseen.modeseen.mode < seen_neighbour) { rn->seen.mode = seen_neighbour; - if (first->index>rn->index) first = rn; - if (last->indexindex) last = rn; + if (first->index > rn->index) first = rn; + if (last->index < rn->index) last = rn; } } } @@ -1390,14 +1390,14 @@ static region *firstregion(faction * f) static void cb_add_seen(region *r, unit *u, void *cbdata) { faction *f = (faction *)cbdata; - if (u->faction==f) { + if (u->faction == f) { add_seen_nb(f, r, seen_travel); } } /** set region.seen based on visibility by one faction. * - * this function may also update ctx->last and ctx->first for potential + * this function may also update ctx->last and ctx->first for potential * lighthouses and travelthru reports */ void prepare_report(report_context *ctx, faction *f) @@ -1411,8 +1411,8 @@ void prepare_report(report_context *ctx, faction *f) rule_region_owners = config_token("rules.region_owner_pay_building", bt_lighthouse->_name); } - if (f->age<=2) { - if ((f->flags&FFL_PWMSG)==0) { + if (f->age <= 2) { + if ((f->flags&FFL_PWMSG) == 0) { /* TODO: this assumes unencrypted passwords */ f->flags |= FFL_PWMSG; ADDMSG(&f->msgs, msg_message("changepasswd", "value", f->_password)); @@ -1428,66 +1428,66 @@ void prepare_report(report_context *ctx, faction *f) ctx->first = firstregion(f); ctx->last = lastregion(f); - for (r = ctx->first; r!=ctx->last; r = r->next) { - unit *u; - building *b; - int br = 0, c = 0, range = 0; - if (fval(r, RF_OBSERVER)) { - int skill = get_observer(r, f); - if (skill >= 0) { - add_seen_nb(f, r, seen_spell); + for (r = ctx->first; r != ctx->last; r = r->next) { + unit *u; + building *b; + int br = 0, c = 0, range = 0; + if (fval(r, RF_OBSERVER)) { + int skill = get_observer(r, f); + if (skill >= 0) { + add_seen_nb(f, r, seen_spell); + } } - } - if (fval(r, RF_LIGHTHOUSE)) { - /* region owners get the report from lighthouses */ - if (rule_region_owners && f == region_get_owner(r)) { - for (b = rbuildings(r); b; b = b->next) { - if (b && b->type == bt_lighthouse) { - /* region owners get maximm range */ - int br = lighthouse_range(b, NULL, NULL); - if (br > range) range = br; + if (fval(r, RF_LIGHTHOUSE)) { + /* region owners get the report from lighthouses */ + if (rule_region_owners && f == region_get_owner(r)) { + for (b = rbuildings(r); b; b = b->next) { + if (b && b->type == bt_lighthouse) { + /* region owners get maximm range */ + int br = lighthouse_range(b, NULL, NULL); + if (br > range) range = br; + } } } } - } - b = NULL; - for (u = r->units; u; u = u->next) { - /* if we have any unit in this region, then we get seen_unit access */ - if (u->faction == f) { - add_seen_nb(f, r, seen_unit); - /* units inside the lighthouse get range based on their perception - * or the size, if perception is not a skill - */ - if (!fval(r, RF_LIGHTHOUSE)) { - /* it's enough to add the region once, and if there are - * no lighthouses, there is no need to look at more units */ - break; - } - } - if (range == 0 && u->building && u->building->type == bt_lighthouse) { - if (u->building && b != u->building) { - b = u->building; - c = buildingcapacity(b); - br = 0; + b = NULL; + for (u = r->units; u; u = u->next) { + /* if we have any unit in this region, then we get seen_unit access */ + if (u->faction == f) { + add_seen_nb(f, r, seen_unit); + /* units inside the lighthouse get range based on their perception + * or the size, if perception is not a skill + */ + if (!fval(r, RF_LIGHTHOUSE)) { + /* it's enough to add the region once, and if there are + * no lighthouses, there is no need to look at more units */ + break; + } } - c -= u->number; - if (u->faction == f && c >= 0) { - /* unit is one of ours, and inside the current lighthouse */ - if (br == 0) { - /* lazy-calculate the range */ - br = lighthouse_range(u->building, f, u); + if (range == 0 && u->building && u->building->type == bt_lighthouse) { + if (u->building && b != u->building) { + b = u->building; + c = buildingcapacity(b); + br = 0; } - if (br > range) { - range = br; + c -= u->number; + if (u->faction == f && c >= 0) { + /* unit is one of ours, and inside the current lighthouse */ + if (br == 0) { + /* lazy-calculate the range */ + br = lighthouse_range(u->building, f, u); + } + if (br > range) { + range = br; + } } } } - } - if (range > 0) { - /* we are in at least one lighthouse. add the regions we can see from here! */ - prepare_lighthouse(f, r, range); - } + if (range > 0) { + /* we are in at least one lighthouse. add the regions we can see from here! */ + prepare_lighthouse(f, r, range); + } if (fval(r, RF_TRAVELUNIT) && r->seen.mode < seen_travel) { travelthru_map(r, cb_add_seen, f); @@ -1702,7 +1702,7 @@ const char *trailinto(const region * r, const struct locale *lang) size_t sz; sz = strlcpy(ref, tname, sizeof(ref)); - sz += strlcat(ref+sz, "_trail", sizeof(ref)-sz); + sz += strlcat(ref + sz, "_trail", sizeof(ref) - sz); s = LOC(lang, ref); if (s && *s) { if (strstr(s, "%s")) From 60efb12d7023c73280d737ebe8f7c2344e751452 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 11 Jun 2017 14:43:46 +0200 Subject: [PATCH 24/57] Zombies koennen Personen gebn --- res/e3a/races.xml | 2 +- res/eressea/races.xml | 2 +- scripts/tests/e2/e2features.lua | 16 ++++++++ scripts/tests/e2/init.lua | 1 + scripts/tests/e3/init.lua | 1 + scripts/tests/e3/rules.lua | 17 +++++++++ scripts/tests/undead.lua | 66 +++++++++++++++++++++++++++++++++ 7 files changed, 103 insertions(+), 2 deletions(-) create mode 100644 scripts/tests/undead.lua diff --git a/res/e3a/races.xml b/res/e3a/races.xml index 8b0cfae6d..349b60a09 100644 --- a/res/e3a/races.xml +++ b/res/e3a/races.xml @@ -783,7 +783,7 @@ - + diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 986e2b85f..56c0c541b 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -1031,7 +1031,7 @@ - + diff --git a/scripts/tests/e2/e2features.lua b/scripts/tests/e2/e2features.lua index 1a4047d63..ffe3266e3 100644 --- a/scripts/tests/e2/e2features.lua +++ b/scripts/tests/e2/e2features.lua @@ -408,3 +408,19 @@ end function test_calendar_season_2328() assert_equal("fall", get_season(1026)) end + +function test_give_to_other_okay() + -- can give a person to another faction + eressea.settings.set("GiveRestriction", "0") + local r = region.create(0, 0, "plain") + local f1 = faction.create("human") + local f2 = faction.create("human") + + local u1 = unit.create(f1, r, 2, "human") + local u2 = unit.create(f2, r, 1, "human") + u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + process_orders() + assert_equal(1, u1.number) + assert_equal(2, u2.number) +end diff --git a/scripts/tests/e2/init.lua b/scripts/tests/e2/init.lua index 7fbc0eb95..fd2f0b423 100644 --- a/scripts/tests/e2/init.lua +++ b/scripts/tests/e2/init.lua @@ -21,3 +21,4 @@ require 'tests.process' require 'tests.xmas' require 'tests.production' require 'tests.spells' +require 'tests.undead' diff --git a/scripts/tests/e3/init.lua b/scripts/tests/e3/init.lua index fc0586f89..04b7da4a2 100644 --- a/scripts/tests/e3/init.lua +++ b/scripts/tests/e3/init.lua @@ -14,3 +14,4 @@ require 'tests.items' require 'tests.magicbag' require 'tests.process' require 'tests.production' +require 'tests.undead' diff --git a/scripts/tests/e3/rules.lua b/scripts/tests/e3/rules.lua index 7eb2f13a3..92e02f29b 100644 --- a/scripts/tests/e3/rules.lua +++ b/scripts/tests/e3/rules.lua @@ -991,3 +991,20 @@ function test_bug2187() set_rule("rules.food.flags", "4") end + + +function test_give_to_other_fails() + -- E3: cannot give a person to another faction + local r = region.create(0, 0, "plain") + local f1 = faction.create("human") + local f2 = faction.create("human") + + local u1 = unit.create(f1, r, 2, "human") + local u2 = unit.create(f2, r, 1, "human") + -- u2:add_order("HELFE " .. itoa36(f1.id) .. " GIB") + u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + process_orders() + assert_equal(2, u1.number) + assert_equal(1, u2.number) +end diff --git a/scripts/tests/undead.lua b/scripts/tests/undead.lua new file mode 100644 index 000000000..1ed94620b --- /dev/null +++ b/scripts/tests/undead.lua @@ -0,0 +1,66 @@ +require "lunit" + +module("tests.undead", package.seeall, lunit.testcase) + +function setup() + eressea.free_game() + eressea.settings.set("nmr.timeout", "0") + eressea.settings.set("NewbieImmunity", "0") + eressea.settings.set("rules.food.flags", "4") + eressea.settings.set("rules.encounters", "0") + eressea.settings.set("rules.peasants.growth", "1") + eressea.settings.set("study.random_progress", "0") + eressea.settings.set("GiveRestriction", "0") +end + +function test_give_undead_to_self() + -- generic undead cannot be given + local r = region.create(0, 0, "plain") + local f = faction.create("human") + local u1 = unit.create(f, r, 2, "undead") + local u2 = unit.create(f, r, 1, "undead") + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + process_orders() + assert_equal(2, u1.number) + assert_equal(1, u2.number) +end + +function test_give_self_undead_fail() + -- disallow giving basic undead units + local r = region.create(0, 0, "plain") + local f = faction.create("human") + local u1 = unit.create(f, r, 2, "undead") + local u2 = unit.create(f, r, 1, "undead") + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + process_orders() + assert_equal(2, u1.number) + assert_equal(1, u2.number) +end + +function test_give_other_zombie_fail() + -- cannot give undead units to another faction + local r = region.create(0, 0, "plain") + local f1 = faction.create("human") + local f2 = faction.create("human") + + local u1 = unit.create(f1, r, 2, "zombie") + local u2 = unit.create(f2, r, 1, "zombie") + u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + -- TODO: Migranten blockieren das derzeit, nicht Untoten-Eigenschaften + process_orders() + assert_equal(2, u1.number) + assert_equal(1, u2.number) +end + +function test_give_self_zombie_okay() + -- allow giving undead units to own units of same race + local r = region.create(0, 0, "plain") + local f = faction.create("human") + local u1 = unit.create(f, r, 2, "zombie") + local u2 = unit.create(f, r, 1, "zombie") + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + process_orders() + assert_equal(1, u1.number) + assert_equal(2, u2.number) +end From 2107a84b0d47693a84f28399c7fa5f5ee360309c Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 9 Jul 2017 15:25:33 +0200 Subject: [PATCH 25/57] also allow GIVE for ghouls and skeletons. --- res/e3a/races.xml | 4 ++-- res/eressea/races.xml | 4 ++-- scripts/tests/undead.lua | 26 +++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/res/e3a/races.xml b/res/e3a/races.xml index 349b60a09..48162aa26 100644 --- a/res/e3a/races.xml +++ b/res/e3a/races.xml @@ -750,7 +750,7 @@ - + @@ -812,7 +812,7 @@ - + diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 56c0c541b..2af45fc60 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -1000,7 +1000,7 @@ - + @@ -1058,7 +1058,7 @@ - + diff --git a/scripts/tests/undead.lua b/scripts/tests/undead.lua index 1ed94620b..121701b1e 100644 --- a/scripts/tests/undead.lua +++ b/scripts/tests/undead.lua @@ -54,7 +54,7 @@ function test_give_other_zombie_fail() end function test_give_self_zombie_okay() - -- allow giving undead units to own units of same race + -- allow giving zombie units to own units of same race local r = region.create(0, 0, "plain") local f = faction.create("human") local u1 = unit.create(f, r, 2, "zombie") @@ -64,3 +64,27 @@ function test_give_self_zombie_okay() assert_equal(1, u1.number) assert_equal(2, u2.number) end + +function test_give_self_skeleton_okay() + -- allow giving skeleton units to own units of same race + local r = region.create(0, 0, "plain") + local f = faction.create("human") + local u1 = unit.create(f, r, 2, "skeleton") + local u2 = unit.create(f, r, 1, "skeleton") + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + process_orders() + assert_equal(1, u1.number) + assert_equal(2, u2.number) +end + +function test_give_self_ghoul_okay() + -- allow giving ghoul units to own units of same race + local r = region.create(0, 0, "plain") + local f = faction.create("human") + local u1 = unit.create(f, r, 2, "ghoul") + local u2 = unit.create(f, r, 1, "ghoul") + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + process_orders() + assert_equal(1, u1.number) + assert_equal(2, u2.number) +end From 6d1f4f06debe42f4a862acdfe03302e395f6f66e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 9 Jul 2017 15:37:42 +0200 Subject: [PATCH 26/57] BUG 2256: kill the FFL_NEWID flag --- src/kernel/faction.c | 1 - src/kernel/faction.h | 19 +++++++++---------- src/renumber.c | 4 ---- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/kernel/faction.c b/src/kernel/faction.c index ae60ce439..d8d7f6f1c 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -497,7 +497,6 @@ void renumber_faction(faction * f, int no) funhash(f); f->no = no; fhash(f); - fset(f, FFL_NEWID); } void update_interval(struct faction *f, struct region *r) diff --git a/src/kernel/faction.h b/src/kernel/faction.h index e0cd893a1..64832053b 100644 --- a/src/kernel/faction.h +++ b/src/kernel/faction.h @@ -36,21 +36,20 @@ extern "C" { struct selist; /* faction flags */ -#define FFL_NEWID (1<<0) /* Die Partei hat bereits einmal ihre no gewechselt */ +#define FFL_NOAID (1<<0) /* Hilfsflag Kampf */ #define FFL_ISNEW (1<<1) #define FFL_PWMSG (1<<2) /* received a "new password" message */ #define FFL_QUIT (1<<3) #define FFL_CURSED (1<<4) /* you're going to have a bad time */ #define FFL_DEFENDER (1<<10) -#define FFL_NOAID (1<<21) /* Hilfsflag Kampf */ -#define FFL_SELECT (1<<22) /* ehemals f->dh, u->dh, r->dh, etc... */ -#define FFL_MARK (1<<23) /* f�r markierende algorithmen, die das - * hinterher auch wieder l�schen m�ssen! - * (FFL_SELECT muss man vorher initialisieren, - * FL_MARK hinterher l�schen) */ -#define FFL_NOIDLEOUT (1<<24) /* Partei stirbt nicht an NMRs */ -#define FFL_NPC (1<<25) /* eine Partei mit Monstern */ -#define FFL_SAVEMASK (FFL_DEFENDER|FFL_NEWID|FFL_NPC|FFL_NOIDLEOUT|FFL_CURSED) +#define FFL_SELECT (1<<22) /* ehemals f->dh, u->dh, r->dh, etc... */ +#define FFL_MARK (1<<23) /* fuer markierende algorithmen, die das + * hinterher auch wieder loeschen muessen! + * (FFL_SELECT muss man vorher initialisieren, + * FL_MARK hinterher loeschen) */ +#define FFL_NOIDLEOUT (1<<24) /* Partei stirbt nicht an NMRs */ +#define FFL_NPC (1<<25) /* eine Partei mit Monstern */ +#define FFL_SAVEMASK (FFL_DEFENDER|FFL_NPC|FFL_NOIDLEOUT|FFL_CURSED) typedef struct faction { struct faction *next; diff --git a/src/renumber.c b/src/renumber.c index de2b5a490..30769403f 100644 --- a/src/renumber.c +++ b/src/renumber.c @@ -40,10 +40,6 @@ void renumber_factions(void) if (!a) continue; want = a->data.i; - if (fval(f, FFL_NEWID)) { - ADDMSG(&f->msgs, msg_message("renumber_twice", "id", want)); - continue; - } if (!faction_id_is_unused(want)) { a_remove(&f->attribs, a); ADDMSG(&f->msgs, msg_message("renumber_inuse", "id", want)); From 518db87015c8c19356ca9d2c56acf814e493710f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 9 Jul 2017 15:41:11 +0200 Subject: [PATCH 27/57] eliminate unused message --- res/core/messages.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index 5bb36e345..006abd685 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -8001,14 +8001,6 @@ "$unit($unit) tried but failed to send $unit($target) to another world." - - - - - "NUMMER PARTEI $int36($id): Die Partei kann nicht mehr als einmal ihre Nummer wecheln." - "NUMBER FACTION $int36($id): Your faction can only change its number once." - - From de9d73bd5a035b511275a7b5af323acf520ae4db Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 9 Jul 2017 15:43:37 +0200 Subject: [PATCH 28/57] fix test to match new flag values --- scripts/tests/common.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/tests/common.lua b/scripts/tests/common.lua index 936d2a79b..2f10b3e8a 100644 --- a/scripts/tests/common.lua +++ b/scripts/tests/common.lua @@ -51,7 +51,7 @@ function test_flags() local f = create_faction('halfling') local u = unit.create(f, r, 1) local no = itoa36(f.id) - local flags = 50332673 + local flags = 50332672 f.flags = flags eressea.write_game("test.dat") From 8344f41a709a0b3c67795a631d19c0af3c9363a3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 15 Jul 2017 12:28:26 +0200 Subject: [PATCH 29/57] allow GIVE for juju, ghast, skelord, too. make the tests nicer. --- res/e3a/races.xml | 6 ++-- res/eressea/races.xml | 6 ++-- scripts/tests/undead.lua | 65 +++++++++++++++++++++++++++------------- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/res/e3a/races.xml b/res/e3a/races.xml index 48162aa26..cbcac8576 100644 --- a/res/e3a/races.xml +++ b/res/e3a/races.xml @@ -732,7 +732,7 @@ - + @@ -767,7 +767,7 @@ - + @@ -797,7 +797,7 @@ - + diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 2af45fc60..69eda9557 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -983,7 +983,7 @@ - + @@ -1016,7 +1016,7 @@ - + @@ -1044,7 +1044,7 @@ - + diff --git a/scripts/tests/undead.lua b/scripts/tests/undead.lua index 121701b1e..420709973 100644 --- a/scripts/tests/undead.lua +++ b/scripts/tests/undead.lua @@ -37,17 +37,28 @@ function test_give_self_undead_fail() assert_equal(1, u2.number) end -function test_give_other_zombie_fail() - -- cannot give undead units to another faction +local function setup_give_self(race) + local r = region.create(0, 0, "plain") + local f = faction.create("human") + local u1 = unit.create(f, r, 2, race) + local u2 = unit.create(f, r, 1, race) + u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + return u1, u2 +end + +local function setup_give_other(race) local r = region.create(0, 0, "plain") local f1 = faction.create("human") local f2 = faction.create("human") - - local u1 = unit.create(f1, r, 2, "zombie") - local u2 = unit.create(f2, r, 1, "zombie") + local u1 = unit.create(f1, r, 2, race) + local u2 = unit.create(f2, r, 1, race) u2:add_order("KONTAKTIERE " .. itoa36(u1.id)) u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") - -- TODO: Migranten blockieren das derzeit, nicht Untoten-Eigenschaften + return u1, u2 +end + +function test_give_other_zombie_fail() + u1, u2 = setup_give_other("zombie") process_orders() assert_equal(2, u1.number) assert_equal(1, u2.number) @@ -55,11 +66,7 @@ end function test_give_self_zombie_okay() -- allow giving zombie units to own units of same race - local r = region.create(0, 0, "plain") - local f = faction.create("human") - local u1 = unit.create(f, r, 2, "zombie") - local u2 = unit.create(f, r, 1, "zombie") - u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + u1, u2 = setup_give_self("zombie") process_orders() assert_equal(1, u1.number) assert_equal(2, u2.number) @@ -67,11 +74,7 @@ end function test_give_self_skeleton_okay() -- allow giving skeleton units to own units of same race - local r = region.create(0, 0, "plain") - local f = faction.create("human") - local u1 = unit.create(f, r, 2, "skeleton") - local u2 = unit.create(f, r, 1, "skeleton") - u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + u1, u2 = setup_give_self("skeleton") process_orders() assert_equal(1, u1.number) assert_equal(2, u2.number) @@ -79,11 +82,31 @@ end function test_give_self_ghoul_okay() -- allow giving ghoul units to own units of same race - local r = region.create(0, 0, "plain") - local f = faction.create("human") - local u1 = unit.create(f, r, 2, "ghoul") - local u2 = unit.create(f, r, 1, "ghoul") - u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") + u1, u2 = setup_give_self("ghoul") + process_orders() + assert_equal(1, u1.number) + assert_equal(2, u2.number) +end + +function test_give_self_ghast_okay() + -- allow giving ghast units to own units of same race + u1, u2 = setup_give_self("ghast") + process_orders() + assert_equal(1, u1.number) + assert_equal(2, u2.number) +end + +function test_give_self_juju_okay() + -- allow giving juju units to own units of same race + u1, u2 = setup_give_self("juju") + process_orders() + assert_equal(1, u1.number) + assert_equal(2, u2.number) +end + +function test_give_self_skeletonlord_okay() + -- allow giving skeletonlord units to own units of same race + u1, u2 = setup_give_self("skeletonlord") process_orders() assert_equal(1, u1.number) assert_equal(2, u2.number) From f934e4d5e3b8d0abbaa66e4e2ba317852848fd25 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 12:31:47 +0200 Subject: [PATCH 30/57] remove unused ECF_KEEP_ITEM flag. --- res/core/messages.xml | 10 ---------- src/give.c | 19 ------------------- src/kernel/jsonconf.test.c | 1 - src/kernel/pool.c | 6 ------ src/kernel/race.h | 1 - src/kernel/unit.c | 21 +++------------------ src/kernel/xmlreader.c | 2 -- src/laws.c | 2 +- src/upkeep.c | 13 +++---------- 9 files changed, 7 insertions(+), 68 deletions(-) diff --git a/res/core/messages.xml b/res/core/messages.xml index 006abd685..a500a41ac 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -1062,16 +1062,6 @@ "$unit($unit) in $region($region): '$order($command)' - $race($race,0) können nichts stehelen." "$unit($unit) in $region($region): '$order($command)' - $race($race,0) cannot steal anything." - - - - - - - - "$unit($unit) in $region($region): '$order($command)' - $race($race,0) geben nichts weg." - "$unit($unit) in $region($region): '$order($command)' - $race($race,0) do not give things away." - diff --git a/src/give.c b/src/give.c index 26b193d0d..543d29fc9 100644 --- a/src/give.c +++ b/src/give.c @@ -678,11 +678,6 @@ void give_cmd(unit * u, order * ord) } else if (p == P_HERBS) { bool given = false; - if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } if (!can_give(u, u2, NULL, GIVE_HERBS)) { feedback_give_not_allowed(u, ord); return; @@ -741,11 +736,6 @@ void give_cmd(unit * u, order * ord) if (!s || *s == 0) { /* GIVE ALL items that you have */ /* do these checks once, not for each item we have: */ - if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_notake", "race", u_race(u2))); @@ -785,10 +775,6 @@ void give_cmd(unit * u, order * ord) } } } - else if ((u_race(u)->ec_flags & ECF_KEEP_ITEM) && u2 != NULL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - } else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_notake", "race", u_race(u2))); @@ -844,11 +830,6 @@ void give_cmd(unit * u, order * ord) } if (u2 != NULL) { - if ((u_race(u)->ec_flags & ECF_KEEP_ITEM)) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "race_nogive", "race", u_race(u))); - return; - } if (!(u_race(u2)->ec_flags & GETITEM)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_notake", "race", u_race(u2))); diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index 2f54eeb8d..d526bc7b8 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -59,7 +59,6 @@ static void test_flags(CuTest *tc) { check_flag(tc, "dragon", RCF_DRAGON); check_flag(tc, "fly", RCF_FLY); check_ec_flag(tc, "getitem", GETITEM); - check_ec_flag(tc, "keepitem", ECF_KEEP_ITEM); check_ec_flag(tc, "giveperson", GIVEPERSON); check_ec_flag(tc, "giveunit", GIVEUNIT); test_cleanup(); diff --git a/src/kernel/pool.c b/src/kernel/pool.c index 8dfd589c3..dae726566 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -179,9 +179,6 @@ int count) if (u != v) { int mask; - if ((u_race(v)->ec_flags & ECF_KEEP_ITEM)) - continue; - if (v->faction == f) { mask = (mode >> 3) & (GET_SLACK | GET_RESERVE); } @@ -232,9 +229,6 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) for (v = r->units; use > 0 && v != NULL; v = v->next) { if (u != v) { int mask; - if ((u_race(v)->ec_flags & ECF_KEEP_ITEM)) - continue; - if (v->faction == f) { mask = (mode >> 3) & (GET_SLACK | GET_RESERVE); } diff --git a/src/kernel/race.h b/src/kernel/race.h index a8933dae8..3980bea72 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -233,7 +233,6 @@ extern "C" { #define RCF_FAMILIAR (1<<31) /* may be a familiar */ /* Economic flags */ -#define ECF_KEEP_ITEM (1<<1) /* gibt Gegenst�nde weg */ #define GIVEPERSON (1<<2) /* �bergibt Personen */ #define GIVEUNIT (1<<3) /* Einheiten an andere Partei �bergeben */ #define GETITEM (1<<4) /* nimmt Gegenst�nde an */ diff --git a/src/kernel/unit.c b/src/kernel/unit.c index bdd5ac232..b4f942a3d 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -225,13 +225,6 @@ static buddy *get_friends(const unit * u, int *numfriends) nf->number = 0; *fr = nf; } - else if (nf->faction == u2->faction - && !(u_race(u2)->ec_flags & ECF_KEEP_ITEM)) { - /* we don't like to gift it to units that won't give it back */ - if ((u_race(nf->unit)->ec_flags & ECF_KEEP_ITEM)) { - nf->unit = u2; - } - } nf->number += u2->number; number += u2->number; } @@ -269,8 +262,6 @@ int gift_items(unit * u, int flags) if (u->items == NULL || fval(u_race(u), RCF_ILLUSIONARY)) return 0; - if ((u_race(u)->ec_flags & ECF_KEEP_ITEM)) - return 0; /* at first, I should try giving my crap to my own units in this region */ if (u->faction && (u->faction->flags & FFL_QUIT) == 0 && (flags & GIFT_SELF)) { @@ -279,15 +270,9 @@ int gift_items(unit * u, int flags) if (u2 != u && u2->faction == u->faction && u2->number > 0) { /* some units won't take stuff: */ if (u_race(u2)->ec_flags & GETITEM) { - /* we don't like to gift it to units that won't give it back */ - if (!(u_race(u2)->ec_flags & ECF_KEEP_ITEM)) { - i_merge(&u2->items, &u->items); - u->items = NULL; - break; - } - else { - u3 = u2; - } + i_merge(&u2->items, &u->items); + u->items = NULL; + break; } } } diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 9953f7335..e4f3b960e 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1423,8 +1423,6 @@ static int parse_races(xmlDocPtr doc) if (xml_bvalue(node, "irongolem", false)) rc->flags |= RCF_IRONGOLEM; - if (xml_bvalue(node, "keepitem", false)) - rc->ec_flags |= ECF_KEEP_ITEM; if (xml_bvalue(node, "giveperson", false)) rc->ec_flags |= GIVEPERSON; if (xml_bvalue(node, "giveunit", false)) diff --git a/src/laws.c b/src/laws.c index ba088a8bb..1d24346e6 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2823,7 +2823,7 @@ static void age_stonecircle(building *b) { if (!mage && is_mage(u)) { mage = u; } - if (rtype && (u_race(u)->ec_flags & ECF_KEEP_ITEM) == 0) { + if (rtype) { int n, unicorns = 0; for (n = 0; n != u->number; ++n) { if (chance(0.02)) { diff --git a/src/upkeep.c b/src/upkeep.c index c4a937a45..d7626084d 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -38,11 +38,6 @@ int lifestyle(const unit * u) return need; } -static bool help_money(const unit * u) -{ - return !(u_race(u)->ec_flags & ECF_KEEP_ITEM); -} - static void help_feed(unit * donor, unit * u, int *need_p) { int need = *need_p; @@ -172,7 +167,7 @@ void get_food(region * r) unit *v; for (v = r->units; need && v; v = v->next) { - if (v->faction == u->faction && help_money(v)) { + if (v->faction == u->faction) { int give = get_money(v) - lifestyle(v); give = MIN(need, give); if (give > 0) { @@ -202,8 +197,7 @@ void get_food(region * r) faction *owner = region_get_owner(r); if (owner && owner != u->faction) { for (v = r->units; v; v = v->next) { - if (v->faction == owner && alliedunit(v, f, HELP_MONEY) - && help_money(v)) { + if (v->faction == owner && alliedunit(v, f, HELP_MONEY)) { help_feed(v, u, &need); break; } @@ -211,8 +205,7 @@ void get_food(region * r) } } for (v = r->units; need && v; v = v->next) { - if (v->faction != f && alliedunit(v, f, HELP_MONEY) - && help_money(v)) { + if (v->faction != f && alliedunit(v, f, HELP_MONEY)) { help_feed(v, u, &need); } } From eb1dc731cb0a9c2c346a907055a46eb996780e2f Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 12:33:55 +0200 Subject: [PATCH 31/57] consistently rename ec_flags constants (ECF_*) --- src/give.c | 14 +++++++------- src/give.test.c | 2 +- src/kernel/jsonconf.test.c | 6 +++--- src/kernel/pool.c | 4 ++-- src/kernel/race.h | 6 +++--- src/kernel/unit.c | 4 ++-- src/kernel/xmlreader.c | 6 +++--- src/laws.c | 2 +- src/tests.c | 2 +- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/give.c b/src/give.c index 543d29fc9..d147c41f8 100644 --- a/src/give.c +++ b/src/give.c @@ -682,7 +682,7 @@ void give_cmd(unit * u, order * ord) feedback_give_not_allowed(u, ord); return; } - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + if (u2 && !(u_race(u2)->ec_flags & ECF_GETITEM)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_notake", "race", u_race(u2))); return; @@ -716,7 +716,7 @@ void give_cmd(unit * u, order * ord) } else if (p == P_UNIT) { /* Einheiten uebergeben */ - if (!(u_race(u)->ec_flags & GIVEUNIT)) { + if (!(u_race(u)->ec_flags & ECF_GIVEUNIT)) { cmistake(u, ord, 167, MSG_COMMERCE); return; } @@ -736,7 +736,7 @@ void give_cmd(unit * u, order * ord) if (!s || *s == 0) { /* GIVE ALL items that you have */ /* do these checks once, not for each item we have: */ - if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + if (u2 && !(u_race(u2)->ec_flags & ECF_GETITEM)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_notake", "race", u_race(u2))); return; @@ -763,7 +763,7 @@ void give_cmd(unit * u, order * ord) } else { if (isparam(s, u->faction->locale, P_PERSON)) { - if (!(u_race(u)->ec_flags & GIVEPERSON)) { + if (!(u_race(u)->ec_flags & ECF_GIVEPERSON)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); } @@ -775,7 +775,7 @@ void give_cmd(unit * u, order * ord) } } } - else if (u2 && !(u_race(u2)->ec_flags & GETITEM)) { + else if (u2 && !(u_race(u2)->ec_flags & ECF_GETITEM)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_notake", "race", u_race(u2))); } @@ -816,7 +816,7 @@ void give_cmd(unit * u, order * ord) if (isparam(s, u->faction->locale, P_PERSON)) { message * msg; - if (!(u_race(u)->ec_flags & GIVEPERSON)) { + if (!(u_race(u)->ec_flags & ECF_GIVEPERSON)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_noregroup", "race", u_race(u))); return; @@ -830,7 +830,7 @@ void give_cmd(unit * u, order * ord) } if (u2 != NULL) { - if (!(u_race(u2)->ec_flags & GETITEM)) { + if (!(u_race(u2)->ec_flags & ECF_GETITEM)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "race_notake", "race", u_race(u2))); return; diff --git a/src/give.test.c b/src/give.test.c index 33a9ebfd9..f38028e10 100644 --- a/src/give.test.c +++ b/src/give.test.c @@ -36,7 +36,7 @@ static void setup_give(struct give *env) { assert(env->f1); rc = test_create_race(env->f1->race ? env->f1->race->_name : "humon"); - rc->ec_flags |= GIVEPERSON; + rc->ec_flags |= ECF_GIVEPERSON; env->r = test_create_region(0, 0, ter); env->src = test_create_unit(env->f1, env->r); diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index d526bc7b8..cb79cafc4 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -58,9 +58,9 @@ static void test_flags(CuTest *tc) { check_flag(tc, "undead", RCF_UNDEAD); check_flag(tc, "dragon", RCF_DRAGON); check_flag(tc, "fly", RCF_FLY); - check_ec_flag(tc, "getitem", GETITEM); - check_ec_flag(tc, "giveperson", GIVEPERSON); - check_ec_flag(tc, "giveunit", GIVEUNIT); + check_ec_flag(tc, "getitem", ECF_GETITEM); + check_ec_flag(tc, "giveperson", ECF_GIVEPERSON); + check_ec_flag(tc, "giveunit", ECF_GIVEUNIT); test_cleanup(); } diff --git a/src/kernel/pool.c b/src/kernel/pool.c index dae726566..c252be566 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -160,7 +160,7 @@ int count) region *r = u->region; int have = get_resource(u, rtype); - if ((u_race(u)->ec_flags & GETITEM) == 0) { + if ((u_race(u)->ec_flags & ECF_GETITEM) == 0) { mode &= (GET_SLACK | GET_RESERVE); } @@ -201,7 +201,7 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) region *r = u->region; int n = 0, have = get_resource(u, rtype); - if ((u_race(u)->ec_flags & GETITEM) == 0) { + if ((u_race(u)->ec_flags & ECF_GETITEM) == 0) { mode &= (GET_SLACK | GET_RESERVE); } diff --git a/src/kernel/race.h b/src/kernel/race.h index 3980bea72..2dec5f06b 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -233,9 +233,9 @@ extern "C" { #define RCF_FAMILIAR (1<<31) /* may be a familiar */ /* Economic flags */ -#define GIVEPERSON (1<<2) /* �bergibt Personen */ -#define GIVEUNIT (1<<3) /* Einheiten an andere Partei �bergeben */ -#define GETITEM (1<<4) /* nimmt Gegenst�nde an */ +#define ECF_GIVEPERSON (1<<2) /* �bergibt Personen */ +#define ECF_GIVEUNIT (1<<3) /* Einheiten an andere Partei �bergeben */ +#define ECF_GETITEM (1<<4) /* nimmt Gegenst�nde an */ #define ECF_REC_ETHEREAL (1<<7) /* Rekrutiert aus dem Nichts */ #define ECF_REC_UNLIMITED (1<<8) /* Rekrutiert ohne Limit */ diff --git a/src/kernel/unit.c b/src/kernel/unit.c index b4f942a3d..821514cd0 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -213,7 +213,7 @@ static buddy *get_friends(const unit * u, int *numfriends) buddy *nf, **fr = &friends; /* some units won't take stuff: */ - if (u_race(u2)->ec_flags & GETITEM) { + if (u_race(u2)->ec_flags & ECF_GETITEM) { while (*fr && (*fr)->faction->no < u2->faction->no) fr = &(*fr)->next; nf = *fr; @@ -269,7 +269,7 @@ int gift_items(unit * u, int flags) for (u2 = r->units; u2; u2 = u2->next) { if (u2 != u && u2->faction == u->faction && u2->number > 0) { /* some units won't take stuff: */ - if (u_race(u2)->ec_flags & GETITEM) { + if (u_race(u2)->ec_flags & ECF_GETITEM) { i_merge(&u2->items, &u->items); u->items = NULL; break; diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index e4f3b960e..a9d38798a 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1424,11 +1424,11 @@ static int parse_races(xmlDocPtr doc) rc->flags |= RCF_IRONGOLEM; if (xml_bvalue(node, "giveperson", false)) - rc->ec_flags |= GIVEPERSON; + rc->ec_flags |= ECF_GIVEPERSON; if (xml_bvalue(node, "giveunit", false)) - rc->ec_flags |= GIVEUNIT; + rc->ec_flags |= ECF_GIVEUNIT; if (xml_bvalue(node, "getitem", false)) - rc->ec_flags |= GETITEM; + rc->ec_flags |= ECF_GETITEM; if (xml_bvalue(node, "recruitethereal", false)) rc->ec_flags |= ECF_REC_ETHEREAL; if (xml_bvalue(node, "recruitunlimited", false)) diff --git a/src/laws.c b/src/laws.c index 1d24346e6..8e9e85ff0 100644 --- a/src/laws.c +++ b/src/laws.c @@ -3533,7 +3533,7 @@ int pay_cmd(unit * u, struct order *ord) static int reserve_i(unit * u, struct order *ord, int flags) { char token[128]; - if (u->number > 0 && (u_race(u)->ec_flags & GETITEM)) { + if (u->number > 0 && (u_race(u)->ec_flags & ECF_GETITEM)) { int use, count, para; const item_type *itype; const char *s; diff --git a/src/tests.c b/src/tests.c index ec2ac2a2f..cfcd6d0ca 100644 --- a/src/tests.c +++ b/src/tests.c @@ -42,7 +42,7 @@ struct race *test_create_race(const char *name) rc->maintenance = 10; rc->hitpoints = 20; rc->maxaura = 100; - rc->ec_flags |= GETITEM; + rc->ec_flags |= ECF_GETITEM; rc->battle_flags = BF_EQUIPMENT; return rc; } From b79db40f4183c7aed08e7fe79b0daa42f49d8c48 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 15 Jul 2017 13:59:30 +0200 Subject: [PATCH 32/57] retrofit a test for buildingcapacity. --- src/kernel/building.test.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index 588ec2937..e19d074da 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -570,11 +570,32 @@ static void test_buildingtype(CuTest *tc) { test_cleanup(); } +static void test_buildingcapacity(CuTest *tc) { + building *b; + building_type *btype; + test_setup(); + btype = test_create_buildingtype("lighthouse"); + btype->capacity = 1; + btype->maxcapacity = 4; + b = test_create_building(test_create_region(0, 0, NULL), btype); + + b->size = 1; + CuAssertIntEquals(tc, b->size*btype->capacity, buildingcapacity(b)); + b->size = 5; + CuAssertIntEquals(tc, btype->maxcapacity, buildingcapacity(b)); + + btype->capacity = -1; + CuAssertTrue(tc, building_finished(b)); + CuAssertIntEquals(tc, btype->maxcapacity, buildingcapacity(b)); + test_cleanup(); +} + CuSuite *get_building_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_buildingtype); SUITE_ADD_TEST(suite, test_largestbuilding); + SUITE_ADD_TEST(suite, test_buildingcapacity); SUITE_ADD_TEST(suite, test_cmp_castle_size); SUITE_ADD_TEST(suite, test_cmp_taxes); SUITE_ADD_TEST(suite, test_cmp_wage); From 0bf003cdc49ad5d88c15d9b7a0670252c575a052 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 13:37:40 +0200 Subject: [PATCH 33/57] add a test for btype.maxsize --- scripts/tests/e2/buildings.lua | 20 ++++++++++++++++++++ src/kernel/building.c | 1 + 2 files changed, 21 insertions(+) diff --git a/scripts/tests/e2/buildings.lua b/scripts/tests/e2/buildings.lua index 4797643e1..07b774d9c 100644 --- a/scripts/tests/e2/buildings.lua +++ b/scripts/tests/e2/buildings.lua @@ -51,3 +51,23 @@ function test_build_castle_stages() process_orders() assert_equal(250, b.size) end + +function test_build_maxsize() + local r = region.create(0,0, "plain") + local f = faction.create("human") + local u = unit.create(f, r, 100) + local b = building.create(r, "harbour") + + b.size = 20 + u:add_item("stone", 1000) + u:add_item("log", 1000) + u:add_item("money", 10000) + + u:set_skill("building", 100) + u:clear_orders() + u:add_order("MACHE BURG " .. itoa36(b.id)) + process_orders() + assert_equal(25, b.size) -- build no more than max + process_orders() + assert_equal(25, b.size) -- stop at max +end diff --git a/src/kernel/building.c b/src/kernel/building.c index bcc914cca..14e4a3e07 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -310,6 +310,7 @@ static const int watch_bonus[3] = { 0, 1, 2 }; int building_protection(const building_type * btype, int stage) { + assert(btype->flags & BTF_FORTIFICATION); if (btype->maxsize < 0) { return castle_bonus[MIN(stage, 5)]; } From 3c2754071dfcc23cf9c7d9e6ff4a6213f3c69745 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 14:01:08 +0200 Subject: [PATCH 34/57] this test fails when btype->maxsize isn't used as a limit for building. --- res/core/common/buildings.xml | 2 +- scripts/tests/e2/buildings.lua | 34 ++++++++++++++++++--------------- scripts/tests/e2/e2features.lua | 23 ---------------------- src/kernel/build.c | 3 ++- 4 files changed, 22 insertions(+), 40 deletions(-) diff --git a/res/core/common/buildings.xml b/res/core/common/buildings.xml index a799ce309..b73ab01aa 100644 --- a/res/core/common/buildings.xml +++ b/res/core/common/buildings.xml @@ -129,7 +129,7 @@ - + diff --git a/scripts/tests/e2/buildings.lua b/scripts/tests/e2/buildings.lua index 07b774d9c..02298bd97 100644 --- a/scripts/tests/e2/buildings.lua +++ b/scripts/tests/e2/buildings.lua @@ -52,22 +52,26 @@ function test_build_castle_stages() assert_equal(250, b.size) end -function test_build_maxsize() - local r = region.create(0,0, "plain") - local f = faction.create("human") - local u = unit.create(f, r, 100) - local b = building.create(r, "harbour") - - b.size = 20 - u:add_item("stone", 1000) - u:add_item("log", 1000) - u:add_item("money", 10000) - - u:set_skill("building", 100) +function test_build_harbour() +-- try to reproduce mantis bug 2221 + local r = region.create(0, 0, "plain") + local f = faction.create("human", "harbour@eressea.de", "de") + local u = unit.create(f, r) + size = 30 + u.number = 20 + u:set_skill("building", 3) + u:add_item("money", size*250) + u:add_item("stone", size*5) + u:add_item("log", size*5) u:clear_orders() - u:add_order("MACHE BURG " .. itoa36(b.id)) + u:add_order("MACHE HAFEN") process_orders() - assert_equal(25, b.size) -- build no more than max + assert_not_nil(u.building) + assert_equal("harbour", u.building.type) + assert_equal(20, u.building.size) process_orders() - assert_equal(25, b.size) -- stop at max + assert_equal(25, u.building.size) + process_orders() + assert_equal(25, u.building.size) end + diff --git a/scripts/tests/e2/e2features.lua b/scripts/tests/e2/e2features.lua index ffe3266e3..7e143c0cc 100644 --- a/scripts/tests/e2/e2features.lua +++ b/scripts/tests/e2/e2features.lua @@ -62,29 +62,6 @@ function test_dwarf_bonus() assert_equal(70, r:get_resource("iron")) end -function test_build_harbour() --- try to reproduce mantis bug 2221 - local r = region.create(0, 0, "plain") - local f = faction.create("human", "harbour@eressea.de", "de") - local u = unit.create(f, r) - size = 30 - u.number = 20 - u:set_skill("building", 3) - u:add_item("money", size*250) - u:add_item("stone", size*5) - u:add_item("log", size*5) - u:clear_orders() - u:add_order("MACHE HAFEN") - process_orders() - assert_not_nil(u.building) - assert_equal("harbour", u.building.type) - assert_equal(20, u.building.size) - process_orders() - assert_equal(25, u.building.size) - process_orders() - assert_equal(25, u.building.size) -end - local function one_unit(r, f) local u = unit.create(f, r, 1) u:add_item("money", u.number * 100) diff --git a/src/kernel/build.c b/src/kernel/build.c index 57c172905..a6e8edc77 100644 --- a/src/kernel/build.c +++ b/src/kernel/build.c @@ -717,8 +717,9 @@ build_building(unit * u, const building_type * btype, int id, int want, order * b = u->building; } - if (b) + if (b) { btype = b->type; + } if (fval(btype, BTF_UNIQUE) && buildingtype_exists(r, btype, false)) { /* only one of these per region */ From 5f463fbc4c8feda1bef919b067fc2cd5d6b68e27 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 14:05:24 +0200 Subject: [PATCH 35/57] btype->cons->maxsize does not matter if it's not a multi-stage building (castle, watch). --- res/core/common/buildings.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/res/core/common/buildings.xml b/res/core/common/buildings.xml index b73ab01aa..64edc8a34 100644 --- a/res/core/common/buildings.xml +++ b/res/core/common/buildings.xml @@ -7,14 +7,14 @@ - + - + @@ -33,7 +33,7 @@ - + @@ -44,7 +44,7 @@ - + @@ -55,7 +55,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -119,7 +119,7 @@ - + From f8de1bf29ec192282282f8acb35797c4bfd5ecd7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 16:11:00 +0200 Subject: [PATCH 36/57] remove default values from XML (capacity=1) --- res/buildings/castle-2.xml | 2 +- res/buildings/castle.xml | 2 +- res/core/common/buildings.xml | 28 ++++++++++++++-------------- res/e3a/buildings.xml | 4 ++-- res/eressea/buildings.xml | 4 ++-- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/res/buildings/castle-2.xml b/res/buildings/castle-2.xml index 7e64f88af..accb92c08 100644 --- a/res/buildings/castle-2.xml +++ b/res/buildings/castle-2.xml @@ -1,5 +1,5 @@ - + diff --git a/res/buildings/castle.xml b/res/buildings/castle.xml index 78ce7066c..ce64e8030 100644 --- a/res/buildings/castle.xml +++ b/res/buildings/castle.xml @@ -1,5 +1,5 @@ - + diff --git a/res/core/common/buildings.xml b/res/core/common/buildings.xml index 64edc8a34..932326f1c 100644 --- a/res/core/common/buildings.xml +++ b/res/core/common/buildings.xml @@ -1,9 +1,9 @@ - + - + @@ -20,7 +20,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -41,7 +41,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -72,7 +72,7 @@ - + @@ -82,7 +82,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -127,7 +127,7 @@ - + @@ -136,7 +136,7 @@ - + @@ -146,7 +146,7 @@ - + @@ -156,7 +156,7 @@ - + diff --git a/res/e3a/buildings.xml b/res/e3a/buildings.xml index 8641fd89e..069a24150 100644 --- a/res/e3a/buildings.xml +++ b/res/e3a/buildings.xml @@ -3,7 +3,7 @@ - + @@ -15,7 +15,7 @@ - + diff --git a/res/eressea/buildings.xml b/res/eressea/buildings.xml index 670ab484e..1559fd987 100644 --- a/res/eressea/buildings.xml +++ b/res/eressea/buildings.xml @@ -2,7 +2,7 @@ - - + + From 233ea9dce4e393e4a4b0ab68db0863e93f7b9fab Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 17:08:27 +0200 Subject: [PATCH 37/57] BUG 2337: lighthouse capacity is # of units, not people. --- conf/e2/config.json | 3 ++- conf/e3/config.json | 1 + src/reports.c | 9 ++++++++- src/reports.test.c | 9 +++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/conf/e2/config.json b/conf/e2/config.json index fb231e2eb..b8ca2f178 100644 --- a/conf/e2/config.json +++ b/conf/e2/config.json @@ -35,6 +35,7 @@ "rules.guard.guard_number_stop_prob": 0.001, "rules.guard.castle_stop_prob": 0.05, "rules.guard.region_type_stop_prob": 0.05, - "rules.economy.repopulate_maximum": 500 + "rules.economy.repopulate_maximum": 500, + "rules.lighthouse.unit_capacity": true } } diff --git a/conf/e3/config.json b/conf/e3/config.json index bfd1bd0fc..3305ce221 100644 --- a/conf/e3/config.json +++ b/conf/e3/config.json @@ -92,6 +92,7 @@ "rules.grow.formula": 1, "rules.tactics.formula": 1, "rules.help.mask": "fight guard money give", + "rules.lighthouse.unit_capacity": true, "movement.shipspeed.skillbonus": 6, "alliance.auto": "fight", "alliance.restricted": "fight" diff --git a/src/reports.c b/src/reports.c index 1a269caa5..e989aee40 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1405,10 +1405,12 @@ void prepare_report(report_context *ctx, faction *f) region *r; static int config; static bool rule_region_owners; + static bool rule_lighthouse_units; const struct building_type *bt_lighthouse = bt_find("lighthouse"); if (bt_lighthouse && config_changed(&config)) { rule_region_owners = config_token("rules.region_owner_pay_building", bt_lighthouse->_name); + rule_lighthouse_units = config_get_int("rules.lighthouse.unit_capacity", 0) != 0; } if (f->age <= 2) { @@ -1471,7 +1473,12 @@ void prepare_report(report_context *ctx, faction *f) c = buildingcapacity(b); br = 0; } - c -= u->number; + if (rule_lighthouse_units) { + --c; + } + else { + c -= u->number; + } if (u->faction == f && c >= 0) { /* unit is one of ours, and inside the current lighthouse */ if (br == 0) { diff --git a/src/reports.test.c b/src/reports.test.c index 74750e9b5..1efd6369a 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -496,6 +496,15 @@ void test_prepare_lighthouse_capacity(CuTest *tc) { CuAssertIntEquals(tc, seen_neighbour, r2->seen.mode); finish_reports(&ctx); + // lighthouse capacity is # of units, not people: + config_set_int("rules.lighthouse.unit_capacity", 1); + prepare_report(&ctx, u2->faction); + CuAssertPtrEquals(tc, r1, ctx.first); + CuAssertPtrEquals(tc, 0, ctx.last); + CuAssertIntEquals(tc, seen_unit, r1->seen.mode); + CuAssertIntEquals(tc, seen_lighthouse, r2->seen.mode); + finish_reports(&ctx); + test_cleanup(); } From aa2c13cffab2fc6cc6d7e11736bcee2e024e06de Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 17 Jul 2017 17:22:01 +0200 Subject: [PATCH 38/57] gcc ist pingelig --- src/reports.test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reports.test.c b/src/reports.test.c index 1efd6369a..891f7d4af 100644 --- a/src/reports.test.c +++ b/src/reports.test.c @@ -496,7 +496,7 @@ void test_prepare_lighthouse_capacity(CuTest *tc) { CuAssertIntEquals(tc, seen_neighbour, r2->seen.mode); finish_reports(&ctx); - // lighthouse capacity is # of units, not people: + /* lighthouse capacity is # of units, not people: */ config_set_int("rules.lighthouse.unit_capacity", 1); prepare_report(&ctx, u2->faction); CuAssertPtrEquals(tc, r1, ctx.first); From 3445e376e0f42a6fe8f6093bf588dbfcb4608b5b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sat, 22 Jul 2017 12:36:01 +0200 Subject: [PATCH 39/57] allow GIVE PERSON for undead race, too --- res/e3a/races.xml | 6 +++++- res/eressea/races.xml | 2 +- scripts/tests/e2/undead.lua | 4 ++-- scripts/tests/undead.lua | 10 +++++----- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/res/e3a/races.xml b/res/e3a/races.xml index cbcac8576..79d9ff9bd 100644 --- a/res/e3a/races.xml +++ b/res/e3a/races.xml @@ -700,7 +700,11 @@ - + diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 69eda9557..3ece1b325 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -732,7 +732,7 @@ - + diff --git a/scripts/tests/e2/undead.lua b/scripts/tests/e2/undead.lua index 71c14ac36..e137ce3c2 100644 --- a/scripts/tests/e2/undead.lua +++ b/scripts/tests/e2/undead.lua @@ -18,11 +18,11 @@ function test_undead_give_item() assert_equal(0, u1:get_item("log")) end -function test_undead_dont_give_person() +function test_clones_dont_give_person() local r1 = region.create(0, 0, "plain") local f1 = faction.create("human", "hodor@eressea.de", "de") local u1 = unit.create(f1, r1, 2) - u1.race = "undead" + u1.race = "clone" u1:clear_orders() u1:add_item("log", 1) u1:add_order("GIB 0 1 Person") diff --git a/scripts/tests/undead.lua b/scripts/tests/undead.lua index 420709973..0c9f609f1 100644 --- a/scripts/tests/undead.lua +++ b/scripts/tests/undead.lua @@ -21,16 +21,16 @@ function test_give_undead_to_self() local u2 = unit.create(f, r, 1, "undead") u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") process_orders() - assert_equal(2, u1.number) - assert_equal(1, u2.number) + assert_equal(1, u1.number) + assert_equal(2, u2.number) end -function test_give_self_undead_fail() +function test_give_self_clone_fail() -- disallow giving basic undead units local r = region.create(0, 0, "plain") local f = faction.create("human") - local u1 = unit.create(f, r, 2, "undead") - local u2 = unit.create(f, r, 1, "undead") + local u1 = unit.create(f, r, 2, "clone") + local u2 = unit.create(f, r, 1, "clone") u1:add_order("GIB " .. itoa36(u2.id) .. " 1 PERSON") process_orders() assert_equal(2, u1.number) From bdb30f1b82c74c8b73f434625ef1ec18d0122d03 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 23 Jul 2017 09:08:03 +0200 Subject: [PATCH 40/57] 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 475c9f8cd83292b195a7f2e45393d403d864fa1b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 23 Jul 2017 09:15:23 +0200 Subject: [PATCH 41/57] 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 4fe72b5d2823aed46a9b70d8f40233a37d6240c9 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Fri, 28 Jul 2017 09:51:28 +0200 Subject: [PATCH 42/57] BUG 2350: read studyspeed correctly and fix orcs --- res/eressea/races.xml | 2 +- res/races/orc.xml | 2 +- src/kernel/xmlreader.c | 17 +++++++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 3ece1b325..04f621526 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -1172,7 +1172,7 @@ - + diff --git a/res/races/orc.xml b/res/races/orc.xml index 4f4d96ed5..a0033759a 100644 --- a/res/races/orc.xml +++ b/res/races/orc.xml @@ -1,5 +1,5 @@ - + diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index a9d38798a..2ef54b005 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -1320,6 +1320,12 @@ static void parse_ai(race * rc, xmlNodePtr node) rc->flags |= RCF_ATTACK_MOVED; } +static void set_study_speed(race *rc, skill_t sk, int modifier){ + if (!rc->study_speed) + rc->study_speed = calloc(1, MAXSKILLS); + rc->study_speed[sk] = (char)modifier; +} + static int parse_races(xmlDocPtr doc) { xmlXPathContextPtr xpath = xmlXPathNewContext(doc); @@ -1338,6 +1344,7 @@ static int parse_races(xmlDocPtr doc) xmlXPathObjectPtr result; int k, study_speed_base, attacks; struct att *attack; + skill_t sk; propValue = xmlGetProp(node, BAD_CAST "name"); assert(propValue != NULL); @@ -1362,6 +1369,11 @@ static int parse_races(xmlDocPtr doc) rc->hitpoints = xml_ivalue(node, "hp", rc->hitpoints); rc->armor = (char)xml_ivalue(node, "ac", rc->armor); study_speed_base = xml_ivalue(node, "studyspeed", 0); + if (study_speed_base != 0) { + for (sk = 0; sk < MAXSKILLS; ++sk) { + set_study_speed(rc, sk, study_speed_base); + } + } rc->at_default = (char)xml_ivalue(node, "unarmedattack", -2); rc->df_default = (char)xml_ivalue(node, "unarmeddefense", -2); @@ -1471,7 +1483,6 @@ static int parse_races(xmlDocPtr doc) xmlNodePtr node = result->nodesetval->nodeTab[k]; int mod = xml_ivalue(node, "modifier", 0); int speed = xml_ivalue(node, "speed", study_speed_base); - skill_t sk; propValue = xmlGetProp(node, BAD_CAST "name"); assert(propValue != NULL); @@ -1479,9 +1490,7 @@ static int parse_races(xmlDocPtr doc) if (sk != NOSKILL) { rc->bonus[sk] = (char)mod; if (speed) { - if (!rc->study_speed) - rc->study_speed = calloc(1, MAXSKILLS); - rc->study_speed[sk] = (char)speed; + set_study_speed(rc, sk, speed); } } else { From 1edfb7ae8ee9a45f96b4d317051857b01e03b220 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Fri, 28 Jul 2017 09:55:39 +0200 Subject: [PATCH 43/57] use STUDYDAYS consequently --- src/battle.c | 1 + src/kernel/skills.c | 1 + src/study.c | 28 ++++++++++++++-------------- src/study.h | 1 + 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/battle.c b/src/battle.c index 343bd754a..c89753049 100644 --- a/src/battle.c +++ b/src/battle.c @@ -958,6 +958,7 @@ void drain_exp(struct unit *u, int n) skill *sv = unit_skill(u, sk); if (sv) { while (n > 0) { + /* FIXME STUDYDAYS */ if (n >= 30 * u->number) { reduce_skill(u, sv, 1); n -= 30; diff --git a/src/kernel/skills.c b/src/kernel/skills.c index b951b77ba..9dad73f2f 100644 --- a/src/kernel/skills.c +++ b/src/kernel/skills.c @@ -153,6 +153,7 @@ int rc_skillmod(const struct race *rc, const region * r, skill_t sk) int level_days(int level) { + /* FIXME STUDYDAYS * ((level + 1) * level / 2); */ return 30 * ((level + 1) * level / 2); } diff --git a/src/study.c b/src/study.c index 9ea0a860e..f05e1a914 100644 --- a/src/study.c +++ b/src/study.c @@ -176,13 +176,13 @@ const attrib_type at_learning = { static int study_days(unit * student, skill_t sk) { - int speed = 30; + int speed = STUDYDAYS; if (u_race(student)->study_speed) { speed += u_race(student)->study_speed[sk]; - if (speed < 30) { + if (speed < STUDYDAYS) { skill *sv = unit_skill(student, sk); if (sv == 0) { - speed = 30; + speed = STUDYDAYS; } } } @@ -209,7 +209,7 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, return 0; } - n = 30 * student->number; + n = STUDYDAYS * student->number; a = a_find(student->attribs, &at_learning); if (a != NULL) { teach = (teaching_info *)a->data.v; @@ -231,7 +231,7 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, * Student auch in unterschiedlichen Gebaeuden stehen duerfen */ if (academy_can_teach(teacher, student, sk)) { /* Jeder Schueler zusaetzlich +10 Tage wenn in Uni. */ - teach->value += (n / 30) * 10; /* learning erhoehen */ + teach->value += (n / STUDYDAYS) * EXPERIENCEDAYS; /* learning erhoehen */ /* Lehrer zusaetzlich +1 Tag pro Schueler. */ if (academy) { *academy += n; @@ -268,7 +268,7 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, * die Talentaenderung (enno). */ - nteaching = MAX(0, nteaching - student->number * 30); + nteaching = MAX(0, nteaching - student->number * STUDYDAYS); } return n; @@ -301,14 +301,14 @@ int teach_cmd(unit * u, struct order *ord) return 0; } - teaching = u->number * 30 * TEACHNUMBER; + teaching = u->number * STUDYDAYS * TEACHNUMBER; if ((i = get_effect(u, oldpotiontype[P_FOOL])) > 0) { /* Trank "Dumpfbackenbrot" */ i = MIN(i, u->number * TEACHNUMBER); /* Trank wirkt pro Schueler, nicht pro Lehrer */ - teaching -= i * 30; + teaching -= i * STUDYDAYS; change_effect(u, oldpotiontype[P_FOOL], -i); - j = teaching / 30; + j = teaching / STUDYDAYS; ADDMSG(&u->faction->msgs, msg_message("teachdumb", "teacher amount", u, j)); } if (teaching == 0) @@ -747,12 +747,12 @@ int study_cmd(unit * u, order * ord) if (get_effect(u, oldpotiontype[P_WISE])) { l = MIN(u->number, get_effect(u, oldpotiontype[P_WISE])); - teach->value += l * 10; + teach->value += l * EXPERIENCEDAYS; change_effect(u, oldpotiontype[P_WISE], -l); } if (get_effect(u, oldpotiontype[P_FOOL])) { l = MIN(u->number, get_effect(u, oldpotiontype[P_FOOL])); - teach->value -= l * 30; + teach->value -= l * STUDYDAYS; change_effect(u, oldpotiontype[P_FOOL], -l); } @@ -761,11 +761,11 @@ int study_cmd(unit * u, order * ord) /* p ist Kosten ohne Uni, studycost mit; wenn * p!=studycost, ist die Einheit zwangsweise * in einer Uni */ - teach->value += u->number * 10; + teach->value += u->number * EXPERIENCEDAYS; } if (is_cursed(r->attribs, C_BADLEARN, 0)) { - teach->value -= u->number * 10; + teach->value -= u->number * EXPERIENCEDAYS; } multi *= study_speedup(u, sk, speed_rule); @@ -828,7 +828,7 @@ int study_cmd(unit * u, order * ord) static int produceexp_days(void) { static int config, rule; if (config_changed(&config)) { - rule = config_get_int("study.produceexp", 10); + rule = config_get_int("study.produceexp", EXPERIENCEDAYS); } return rule; } diff --git a/src/study.h b/src/study.h index 0f8ae70f5..8362f7c55 100644 --- a/src/study.h +++ b/src/study.h @@ -39,6 +39,7 @@ extern "C" { typedef void(*learn_fun)(struct unit *u, skill_t sk, int days); #define STUDYDAYS 30 +#define EXPERIENCEDAYS 10 void learn_skill(struct unit *u, skill_t sk, int days); void produceexp(struct unit *u, skill_t sk, int n); From 160ef71d402eea5c509ec3bb45e119cfa33f7cef Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Mon, 31 Jul 2017 12:55:05 +0200 Subject: [PATCH 44/57] refactor for STUDYDAYS --- src/academy.c | 2 +- src/battle.c | 17 ++------- src/battle.test.c | 82 +++++++++++++++++++++++++++++++++++++++++++ src/items/xerewards.c | 2 ++ src/kernel/skills.c | 13 +++++++ src/kernel/skills.h | 3 +- src/randenc.c | 4 +-- src/study.c | 39 +++++++++++++------- src/study.h | 2 +- 9 files changed, 131 insertions(+), 33 deletions(-) diff --git a/src/academy.c b/src/academy.c index 496c1ef8e..9f42c0e4c 100644 --- a/src/academy.c +++ b/src/academy.c @@ -27,7 +27,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. void academy_teaching_bonus(struct unit *u, skill_t sk, int academy) { if (academy && sk != NOSKILL) { - learn_skill(u, sk, academy / STUDYDAYS); + learn_skill(u, sk, academy); } } diff --git a/src/battle.c b/src/battle.c index c89753049..84d61091a 100644 --- a/src/battle.c +++ b/src/battle.c @@ -26,6 +26,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "monsters.h" #include "move.h" #include "skill.h" +#include "study.h" #include #include @@ -955,21 +956,7 @@ void drain_exp(struct unit *u, int n) } } if (sk != NOSKILL) { - skill *sv = unit_skill(u, sk); - if (sv) { - while (n > 0) { - /* FIXME STUDYDAYS */ - if (n >= 30 * u->number) { - reduce_skill(u, sv, 1); - n -= 30; - } - else { - if (rng_int() % (30 * u->number) < n) - reduce_skill(u, sv, 1); - n = 0; - } - } - } + reduce_skill_days(u, sk, n); } } diff --git a/src/battle.test.c b/src/battle.test.c index b00d06a98..a869b4ca4 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -12,8 +12,13 @@ #include #include #include +#include +#include #include + +#include + #include "tests.h" static void test_make_fighter(CuTest * tc) @@ -494,6 +499,82 @@ static void test_battle_skilldiff_building(CuTest *tc) test_cleanup(); } +static void assert_skill(CuTest *tc, char *msg, unit *u, skill_t sk, int level, int week, int weekmax) +{ + skill *sv = unit_skill(u, sk); + char buf[256]; + if (sv) { + sprintf(buf, "%s level %d != %d", msg, sv->level, level); + CuAssertIntEquals_Msg(tc, (const char *)&buf, level, sv->level); + sprintf(buf, "%s week %d !<= %d !<= %d", msg, week, sv->weeks, weekmax); + CuAssert(tc, (const char *)&buf, sv->weeks >= week && sv->weeks <=weekmax); + } else { + CuAssertIntEquals_Msg(tc, msg, level, 0); + CuAssertIntEquals_Msg(tc, msg, week, 0); + } +} + +static void test_drain_exp(CuTest *tc) +{ + unit *u; + char *msg; + int i; + double rand; + + test_setup(); + config_set("study.random_progress", "0"); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); + set_level(u, SK_STAMINA, 3); + + CuAssertIntEquals(tc, 3, unit_skill(u, SK_STAMINA)->level); + CuAssertIntEquals(tc, 4, unit_skill(u, SK_STAMINA)->weeks); + + assert_skill(tc, msg = "base", u, SK_STAMINA, 3, 4, 4); + assert_skill(tc, msg, u, SK_STAMINA, 3, 4, 4); + assert_skill(tc, msg, u, SK_MINING, 0, 0, 0); + + for (i=0; i<10; ++i) { + set_level(u, SK_STAMINA, 3); + drain_exp(u, 0); + assert_skill(tc, msg = "0 change", u, SK_STAMINA, 3, 4, 4); + assert_skill(tc, msg, u, SK_MINING, 0, 0, 0); + + for (rand = 0.0; rand < 2.0; rand += 1) { + random_source_inject_constant(rand); + + set_level(u, SK_STAMINA, 3); + drain_exp(u, 29); + + assert_skill(tc, msg = "no change yet", u, SK_STAMINA, 3, 4, rand == 0.0?4:5); + assert_skill(tc, msg, u, SK_MINING, 0, 0, 0); + + set_level(u, SK_STAMINA, 3); + drain_exp(u, 1); + + assert_skill(tc, msg = "random change", u, SK_STAMINA, 3, 4, rand == 0.0?4:5); + assert_skill(tc, msg, u, SK_MINING, 0, 0, 0); + + set_level(u, SK_STAMINA, 3); + drain_exp(u, 30); + + assert_skill(tc, msg = "plus one", u, SK_STAMINA, 3, 5, 5); + assert_skill(tc, msg, u, SK_MINING, 0, 0, 0); + } + + set_level(u, SK_STAMINA, 3); + drain_exp(u, 90); + + assert_skill(tc, msg = "plus three", u, SK_STAMINA, 3, 7, 7); + assert_skill(tc, msg, u, SK_MINING, 0, 0, 0); + + set_level(u, SK_STAMINA, 3); + drain_exp(u, 120); + + assert_skill(tc, msg = "plus four", u, SK_STAMINA, 2, 5, 5); + assert_skill(tc, msg, u, SK_MINING, 0, 0, 0); + } +} + CuSuite *get_battle_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -508,5 +589,6 @@ CuSuite *get_battle_suite(void) SUITE_ADD_TEST(suite, test_natural_armor); SUITE_ADD_TEST(suite, test_magic_resistance); SUITE_ADD_TEST(suite, test_projectile_armor); + SUITE_ADD_TEST(suite, test_drain_exp); return suite; } diff --git a/src/items/xerewards.c b/src/items/xerewards.c index a6d1ad2ea..e39608a16 100644 --- a/src/items/xerewards.c +++ b/src/items/xerewards.c @@ -34,6 +34,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* util includes */ #include +#include + /* libc includes */ #include #include diff --git a/src/kernel/skills.c b/src/kernel/skills.c index 9dad73f2f..3bcbd0f66 100644 --- a/src/kernel/skills.c +++ b/src/kernel/skills.c @@ -203,6 +203,19 @@ int skill_weeks(int level) return level + 1; } +void increase_skill(unit * u, skill_t sk, unsigned int weeks) +{ + skill *sv = unit_skill(u, sk); + if (!sv) { + sv = add_skill(u, sk); + } + while (sv->weeks <= (int) weeks) { + weeks -= sv->weeks; + sk_set(sv, sv->level + 1); + } + sv->weeks -= weeks; +} + void reduce_skill(unit * u, skill * sv, unsigned int weeks) { sv->weeks += weeks; diff --git a/src/kernel/skills.h b/src/kernel/skills.h index 1261a7ea9..4c41109d7 100644 --- a/src/kernel/skills.h +++ b/src/kernel/skills.h @@ -52,7 +52,8 @@ extern "C" { int level(int days); #define skill_level(level) (level) - void reduce_skill(struct unit *u, skill * sv, unsigned int change); + void increase_skill(struct unit * u, skill_t sk, unsigned int weeks); + void reduce_skill(struct unit *u, skill * sv, unsigned int weeks); int skill_weeks(int level); int skill_compare(const skill * sk, const skill * sc); diff --git a/src/randenc.c b/src/randenc.c index e46d5fa24..d2099e49c 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -156,7 +156,7 @@ static bool improve_all(faction * f, skill_t sk, int by_weeks) bool result = false; for (u = f->units; u; u = u->nextF) { if (has_skill(u, sk)) { - learn_skill(u, sk, by_weeks * STUDYDAYS); + increase_skill(u, sk, by_weeks); result = true; } } @@ -242,7 +242,7 @@ void find_manual(region * r, unit * u) } if (!improve_all(u->faction, skill, 3)) { - learn_skill(u, skill, 9 * STUDYDAYS); + increase_skill(u, skill, 9); } } diff --git a/src/study.c b/src/study.c index f05e1a914..9e1668483 100644 --- a/src/study.c +++ b/src/study.c @@ -163,8 +163,8 @@ static void init_learning(struct attrib *a) static void done_learning(struct attrib *a) { - teaching_info *teach = (teaching_info *)a->data.v; - selist_free(teach->teachers); + teaching_info *teach = (teaching_info *)a->data.v; + selist_free(teach->teachers); free(a->data.v); } @@ -174,6 +174,8 @@ const attrib_type at_learning = { ATF_UNIQUE }; +#define EXPERIENCEDAYS 10 + static int study_days(unit * student, skill_t sk) { int speed = STUDYDAYS; @@ -260,14 +262,16 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, * * Ist C aber vor B dran, lehrt C 300 tage an A, und 0 tage an D, * und B lehrt auch 0 tage an A. + * (Na und? -stm) * - * Deswegen darf C D nie lehren duerfen. + * Deswegen darf C D nie lehren duerfen. (Warum? -stm) * * -> Das ist wirr. wer hat das entworfen? * Besser waere, man macht erst vorab alle zuordnungen, und dann * die Talentaenderung (enno). */ + /* FIXME: this code no effect; check if the refactoring done in 1e51d0e9e238e1e6e073cab2060777038e1acfa1 fucked this up */ nteaching = MAX(0, nteaching - student->number * STUDYDAYS); } @@ -449,7 +453,6 @@ int teach_cmd(unit * u, struct order *ord) continue; } - /* u is teacher, u2 is student */ if (effskill_study(u2, sk, 0) > effskill_study(u, sk, 0) - TEACHDIFFERENCE) { if (feedback) { @@ -480,7 +483,8 @@ int teach_cmd(unit * u, struct order *ord) free_order(new_order); /* parse_order & set_order have each increased the refcount */ } if (academy && sk_academy!=NOSKILL) { - academy_teaching_bonus(u, sk_academy, academy); + assert(academy % STUDYDAYS == 0); + academy_teaching_bonus(u, sk_academy, academy / STUDYDAYS); } return 0; } @@ -871,15 +875,24 @@ void learn_skill(unit *u, skill_t sk, int days) { ++weeks; } if (weeks > 0) { - skill *sv = unit_skill(u, sk); - if (!sv) { - sv = add_skill(u, sk); - } - while (sv->weeks <= weeks) { - weeks -= sv->weeks; - sk_set(sv, sv->level + 1); + increase_skill(u, sk, weeks); + } +} + +void reduce_skill_days(unit *u, skill_t sk, int days) { + skill *sv = unit_skill(u, sk); + if (sv) { + while (days > 0) { + if (days >= STUDYDAYS * u->number) { + reduce_skill(u, sv, 1); + days -= STUDYDAYS; + } + else { + if (chance (days / ((double) STUDYDAYS * u->number))) /* (rng_int() % (30 * u->number) < days)*/ + reduce_skill(u, sv, 1); + days = 0; + } } - sv->weeks -= weeks; } } diff --git a/src/study.h b/src/study.h index 8362f7c55..83bd65a40 100644 --- a/src/study.h +++ b/src/study.h @@ -39,8 +39,8 @@ extern "C" { typedef void(*learn_fun)(struct unit *u, skill_t sk, int days); #define STUDYDAYS 30 -#define EXPERIENCEDAYS 10 void learn_skill(struct unit *u, skill_t sk, int days); + void reduce_skill_days(struct unit *u, skill_t sk, int days); void produceexp(struct unit *u, skill_t sk, int n); void produceexp_ex(struct unit *u, skill_t sk, int n, learn_fun learn); From 80bfb5dbc6a4d510a23b66bf0d4b1097dbc367d5 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Mon, 31 Jul 2017 12:56:12 +0200 Subject: [PATCH 45/57] rename teacher variable --- src/study.c | 102 ++++++++++++++++++++++++++-------------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/study.c b/src/study.c index 9e1668483..56a9bf913 100644 --- a/src/study.c +++ b/src/study.c @@ -278,42 +278,42 @@ teach_unit(unit * teacher, unit * student, int nteaching, skill_t sk, return n; } -int teach_cmd(unit * u, struct order *ord) +int teach_cmd(unit * teacher, struct order *ord) { plane *pl; - region *r = u->region; + region *r = teacher->region; skill_t sk_academy = NOSKILL; int teaching, i, j, count, academy = 0; - if (u->region->attribs) { + if (teacher->region->attribs) { const curse_type *gbdream_ct = ct_find("gbdream"); if (gbdream_ct) { - if (get_curse(u->region->attribs, gbdream_ct)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "gbdream_noteach", "")); + if (get_curse(teacher->region->attribs, gbdream_ct)) { + ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "gbdream_noteach", "")); return 0; } } } - if ((u_race(u)->flags & RCF_NOTEACH) || fval(u, UFL_WERE)) { - cmistake(u, ord, 274, MSG_EVENT); + if ((u_race(teacher)->flags & RCF_NOTEACH) || fval(teacher, UFL_WERE)) { + cmistake(teacher, ord, 274, MSG_EVENT); return 0; } pl = rplane(r); if (pl && fval(pl, PFL_NOTEACH)) { - cmistake(u, ord, 273, MSG_EVENT); + cmistake(teacher, ord, 273, MSG_EVENT); return 0; } - teaching = u->number * STUDYDAYS * TEACHNUMBER; + teaching = teacher->number * STUDYDAYS * TEACHNUMBER; - if ((i = get_effect(u, oldpotiontype[P_FOOL])) > 0) { /* Trank "Dumpfbackenbrot" */ - i = MIN(i, u->number * TEACHNUMBER); + if ((i = get_effect(teacher, oldpotiontype[P_FOOL])) > 0) { /* Trank "Dumpfbackenbrot" */ + i = MIN(i, teacher->number * TEACHNUMBER); /* Trank wirkt pro Schueler, nicht pro Lehrer */ teaching -= i * STUDYDAYS; - change_effect(u, oldpotiontype[P_FOOL], -i); + change_effect(teacher, oldpotiontype[P_FOOL], -i); j = teaching / STUDYDAYS; - ADDMSG(&u->faction->msgs, msg_message("teachdumb", "teacher amount", u, j)); + ADDMSG(&teacher->faction->msgs, msg_message("teachdumb", "teacher amount", teacher, j)); } if (teaching == 0) return 0; @@ -323,22 +323,22 @@ int teach_cmd(unit * u, struct order *ord) init_order(ord); #if TEACH_ALL - if (getparam(u->faction->locale) == P_ANY) { + if (getparam(teacher->faction->locale) == P_ANY) { skill_t sk; unit *student; skill_t teachskill[MAXSKILLS]; int t = 0; do { - sk = getskill(u->faction->locale); - teachskill[t] = getskill(u->faction->locale); + sk = getskill(teacher->faction->locale); + teachskill[t] = getskill(teacher->faction->locale); } while (sk != NOSKILL); for (student = r->units; teaching && student; student = student->next) { if (LongHunger(student)) { continue; } - else if (student->faction == u->faction) { + else if (student->faction == teacher->faction) { if (getkeyword(student->thisorder) == K_STUDY) { /* Input ist nun von student->thisorder !! */ init_order(student->thisorder); @@ -352,20 +352,20 @@ int teach_cmd(unit * u, struct order *ord) sk = teachskill[t]; } if (sk != NOSKILL - && effskill_study(u, sk, 0) - TEACHDIFFERENCE > effskill_study(student, sk, 0)) { - teaching -= teach_unit(u, student, teaching, sk, true, &academy); + && effskill_study(teacher, sk, 0) - TEACHDIFFERENCE > effskill_study(student, sk, 0)) { + teaching -= teach_unit(teacher, student, teaching, sk, true, &academy); } } } #ifdef TEACH_FRIENDS - else if (alliedunit(u, student->faction, HELP_GUARD)) { + else if (alliedunit(teacher, student->faction, HELP_GUARD)) { if (getkeyword(student->thisorder) == K_STUDY) { /* Input ist nun von student->thisorder !! */ init_order(student->thisorder); sk = getskill(student->faction->locale); if (sk != NOSKILL - && effskill_study(u, sk, 0) - TEACHDIFFERENCE >= effskill(student, sk, 0)) { - teaching -= teach_unit(u, student, teaching, sk, true, &academy); + && effskill_study(teacher, sk, 0) - TEACHDIFFERENCE >= effskill(student, sk, 0)) { + teaching -= teach_unit(teacher, student, teaching, sk, true, &academy); } } } @@ -384,15 +384,15 @@ int teach_cmd(unit * u, struct order *ord) while (!parser_end()) { skill_t sk; - unit *u2; + unit *student; bool feedback; - getunit(r, u->faction, &u2); + getunit(r, teacher->faction, &student); ++count; /* Falls die Unit nicht gefunden wird, Fehler melden */ - if (!u2) { + if (!student) { char tbuf[20]; const char *uid; const char *token; @@ -402,30 +402,30 @@ int teach_cmd(unit * u, struct order *ord) for (j = 0; j != count - 1; ++j) { /* skip over the first 'count' units */ - getunit(r, u->faction, NULL); + getunit(r, teacher->faction, NULL); } token = getstrtoken(); /* Beginne die Fehlermeldung */ - if (isparam(token, u->faction->locale, P_TEMP)) { + if (isparam(token, teacher->faction->locale, P_TEMP)) { token = getstrtoken(); - sprintf(tbuf, "%s %s", LOC(u->faction->locale, + sprintf(tbuf, "%s %s", LOC(teacher->faction->locale, parameters[P_TEMP]), token); uid = tbuf; } else { uid = token; } - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "unitnotfound_id", + ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "unitnotfound_id", "id", uid)); parser_popstate(); continue; } - feedback = u->faction == u2->faction - || alliedunit(u2, u->faction, HELP_GUARD); + feedback = teacher->faction == student->faction + || alliedunit(student, teacher->faction, HELP_GUARD); /* Neuen Befehl zusammenbauen. TEMP-Einheiten werden automatisch in * ihre neuen Nummern uebersetzt. */ @@ -433,58 +433,58 @@ int teach_cmd(unit * u, struct order *ord) strncat(zOrder, " ", sz - 1); --sz; } - sz -= strlcpy(zOrder + 4096 - sz, itoa36(u2->no), sz); + sz -= strlcpy(zOrder + 4096 - sz, itoa36(student->no), sz); - if (getkeyword(u2->thisorder) != K_STUDY) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "teach_nolearn", "student", u2)); + if (getkeyword(student->thisorder) != K_STUDY) { + ADDMSG(&teacher->faction->msgs, + msg_feedback(teacher, ord, "teach_nolearn", "student", student)); continue; } - /* Input ist nun von u2->thisorder !! */ + /* Input ist nun von student->thisorder !! */ parser_pushstate(); - init_order(u2->thisorder); - sk = getskill(u2->faction->locale); + init_order(student->thisorder); + sk = getskill(student->faction->locale); parser_popstate(); if (sk == NOSKILL) { - ADDMSG(&u->faction->msgs, - msg_feedback(u, ord, "teach_nolearn", "student", u2)); + ADDMSG(&teacher->faction->msgs, + msg_feedback(teacher, ord, "teach_nolearn", "student", student)); continue; } - if (effskill_study(u2, sk, 0) > effskill_study(u, sk, 0) + if (effskill_study(student, sk, 0) > effskill_study(teacher, sk, 0) - TEACHDIFFERENCE) { if (feedback) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "teach_asgood", - "student", u2)); + ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, "teach_asgood", + "student", student)); } continue; } if (sk == SK_MAGIC) { /* ist der Magier schon spezialisiert, so versteht er nur noch * Lehrer seines Gebietes */ - sc_mage *mage1 = get_mage(u); - sc_mage *mage2 = get_mage(u2); + sc_mage *mage1 = get_mage(teacher); + sc_mage *mage2 = get_mage(student); if (mage2 && mage1 && mage2->magietyp != M_GRAY && mage1->magietyp != mage2->magietyp) { if (feedback) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "error_different_magic", "target", u2)); + ADDMSG(&teacher->faction->msgs, msg_feedback(teacher, ord, + "error_different_magic", "target", student)); } continue; } } sk_academy = sk; - teaching -= teach_unit(u, u2, teaching, sk, false, &academy); + teaching -= teach_unit(teacher, student, teaching, sk, false, &academy); } - new_order = create_order(K_TEACH, u->faction->locale, "%s", zOrder); - replace_order(&u->orders, ord, new_order); + new_order = create_order(K_TEACH, teacher->faction->locale, "%s", zOrder); + replace_order(&teacher->orders, ord, new_order); free_order(new_order); /* parse_order & set_order have each increased the refcount */ } if (academy && sk_academy!=NOSKILL) { assert(academy % STUDYDAYS == 0); - academy_teaching_bonus(u, sk_academy, academy / STUDYDAYS); + academy_teaching_bonus(teacher, sk_academy, academy / STUDYDAYS); } return 0; } From f0c17b01afbbbbb4487871d500770c2136bb9da7 Mon Sep 17 00:00:00 2001 From: Steffen Mecke Date: Fri, 4 Aug 2017 15:17:18 +0200 Subject: [PATCH 46/57] fixed demon_skillchange and produceexp learn_skill's argument is the number of person days, not the number of unit days as assumed! --- src/academy.c | 7 ++++--- src/items/xerewards.c | 1 + src/items/xerewards.test.c | 6 +++--- src/study.c | 7 ++++--- src/study.test.c | 12 ++++++------ 5 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/academy.c b/src/academy.c index 9f42c0e4c..c25ea2476 100644 --- a/src/academy.c +++ b/src/academy.c @@ -25,9 +25,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "academy.h" #include "study.h" -void academy_teaching_bonus(struct unit *u, skill_t sk, int academy) { - if (academy && sk != NOSKILL) { - learn_skill(u, sk, academy); +void academy_teaching_bonus(struct unit *u, skill_t sk, int student_days) { + if (student_days && sk != NOSKILL) { + /* actually days / STUDYDAYS * EXPERIENCEDAYS / MAX_STUDENTS */ + learn_skill(u, sk, student_days / STUDYDAYS); } } diff --git a/src/items/xerewards.c b/src/items/xerewards.c index e39608a16..e9a11d00d 100644 --- a/src/items/xerewards.c +++ b/src/items/xerewards.c @@ -54,6 +54,7 @@ struct order *ord) for (n = 0; n != amount; ++n) { skill *sv = u->skills; while (sv != u->skills + u->skill_size) { + /* only one person learns for 3 weeks */ learn_skill(u, (skill_t)sv->id, STUDYDAYS * 3); ++sv; } diff --git a/src/items/xerewards.test.c b/src/items/xerewards.test.c index ea9f53fde..5739141c0 100644 --- a/src/items/xerewards.test.c +++ b/src/items/xerewards.test.c @@ -31,17 +31,17 @@ static void test_skillpotion(CuTest *tc) { itype = test_create_itemtype("skillpotion"); change_resource(u, itype->rtype, 2); - learn_skill(u, SK_ENTERTAINMENT, STUDYDAYS); + learn_skill(u, SK_ENTERTAINMENT, STUDYDAYS * u->number); pSkill = unit_skill(u, SK_ENTERTAINMENT); sk_set(pSkill, 5); initialWeeks_Entertainment = pSkill->weeks = 4; - learn_skill(u, SK_STAMINA, STUDYDAYS); + learn_skill(u, SK_STAMINA, STUDYDAYS * u->number); pSkill = unit_skill(u, SK_STAMINA); sk_set(pSkill, 5); initialWeeks_Stamina = pSkill->weeks = 4; - learn_skill(u, SK_MAGIC, STUDYDAYS); + learn_skill(u, SK_MAGIC, STUDYDAYS * u->number); pSkill = unit_skill(u, SK_MAGIC); sk_set(pSkill, 5); initialWeeks_Magic = pSkill->weeks = 4; diff --git a/src/study.c b/src/study.c index 56a9bf913..ddded23cc 100644 --- a/src/study.c +++ b/src/study.c @@ -484,7 +484,7 @@ int teach_cmd(unit * teacher, struct order *ord) } if (academy && sk_academy!=NOSKILL) { assert(academy % STUDYDAYS == 0); - academy_teaching_bonus(teacher, sk_academy, academy / STUDYDAYS); + academy_teaching_bonus(teacher, sk_academy, academy); } return 0; } @@ -842,7 +842,7 @@ void produceexp_ex(struct unit *u, skill_t sk, int n, learn_fun learn) assert(u && n <= u->number); if (n > 0 && (is_monsters(u->faction) || playerrace(u_race(u)))) { int days = produceexp_days(); - learn(u, sk, days * n / u->number); + learn(u, sk, days * n); } } @@ -858,6 +858,7 @@ void inject_learn(learn_fun fun) { inject_learn_fun = fun; } #endif +/** days should be scaled by u->number; STUDYDAYS * u->number is one week worth of learning */ void learn_skill(unit *u, skill_t sk, int days) { int leveldays = STUDYDAYS * u->number; int weeks = 0; @@ -929,7 +930,7 @@ void demon_skillchange(unit *u) } } else { - learn_skill(u, sv->id, STUDYDAYS*weeks); + learn_skill(u, sv->id, STUDYDAYS * u->number * weeks); } } ++sv; diff --git a/src/study.test.c b/src/study.test.c index 74104704b..c0b58b493 100644 --- a/src/study.test.c +++ b/src/study.test.c @@ -184,12 +184,12 @@ static CuTest *g_tc; static void cb_learn_one(unit *u, skill_t sk, int days) { CuAssertIntEquals(g_tc, SK_ALCHEMY, sk); - CuAssertIntEquals(g_tc, 10, days); + CuAssertIntEquals(g_tc, 20, days); } static void cb_learn_two(unit *u, skill_t sk, int days) { CuAssertIntEquals(g_tc, SK_ALCHEMY, sk); - CuAssertIntEquals(g_tc, 20, days); + CuAssertIntEquals(g_tc, 40, days); } static void test_produceexp(CuTest *tc) { @@ -247,7 +247,7 @@ static void test_academy_building(CuTest *tc) { CuAssertPtrEquals(tc, u, log_learners[0].u); CuAssertIntEquals(tc, SK_CROSSBOW, log_learners[0].sk); - CuAssertIntEquals(tc, 15, log_learners[0].days); + CuAssertIntEquals(tc, u1->number, log_learners[0].days); test_cleanup(); } @@ -377,7 +377,7 @@ static void test_study_cost(CuTest *tc) { learn_reset(); CuAssertPtrEquals(tc, u, log_learners[0].u); CuAssertIntEquals(tc, SK_ALCHEMY, log_learners[0].sk); - CuAssertIntEquals(tc, STUDYDAYS*u->number, log_learners[0].days); + CuAssertIntEquals(tc, STUDYDAYS * u->number, log_learners[0].days); CuAssertIntEquals(tc, 0, i_get(u->items, itype)); test_cleanup(); } @@ -405,7 +405,7 @@ static void test_teach_magic(CuTest *tc) { learn_reset(); CuAssertPtrEquals(tc, u, log_learners[0].u); CuAssertIntEquals(tc, SK_MAGIC, log_learners[0].sk); - CuAssertIntEquals(tc, STUDYDAYS*2, log_learners[0].days); + CuAssertIntEquals(tc, STUDYDAYS * 2, log_learners[0].days); CuAssertIntEquals(tc, 0, i_get(u->items, itype)); test_cleanup(); } @@ -426,7 +426,7 @@ static void test_teach_cmd(CuTest *tc) { learn_reset(); CuAssertPtrEquals(tc, u, log_learners[0].u); CuAssertIntEquals(tc, SK_CROSSBOW, log_learners[0].sk); - CuAssertIntEquals(tc, STUDYDAYS*2*u->number, log_learners[0].days); + CuAssertIntEquals(tc, STUDYDAYS * 2 * u->number, log_learners[0].days); test_cleanup(); } From 4291c4de3d72bbbcdf789b633a7f671c999de4f7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Aug 2017 18:52:09 +0200 Subject: [PATCH 47/57] BUG 2353: Segen der Erde produziert zu viel Silber https://bugs.eressea.de/view.php?id=2353 In E3 gibt es legazy-attribute mit falschem Effekt, ignorieren. --- src/economy.c | 11 ++++------- src/kernel/building.c | 3 ++- src/kernel/curse.c | 19 +++++++------------ src/spells/regioncurse.c | 21 +++++++++++++++++---- src/spells/regioncurse.h | 6 +++--- 5 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/economy.c b/src/economy.c index 6fc1fea60..1cae19b1c 100644 --- a/src/economy.c +++ b/src/economy.c @@ -69,6 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include /* libs includes */ #include @@ -2653,14 +2654,10 @@ expandwork(region * r, request * work_begin, request * work_end, int maxwork) jobs = rpeasants(r); } earnings = jobs * p_wage; - if (r->attribs && rule_blessed_harvest() == HARVEST_TAXES) { + if (jobs > 0 && r->attribs && rule_blessed_harvest() == HARVEST_TAXES) { /* E3 rules */ - const curse_type *blessedharvest_ct = ct_find("blessedharvest"); - if (blessedharvest_ct) { - int happy = - (int)(jobs * curse_geteffect(get_curse(r->attribs, blessedharvest_ct))); - earnings += happy; - } + int happy = harvest_effect(r); + earnings += happy * jobs; } rsetmoney(r, money + earnings); } diff --git a/src/kernel/building.c b/src/kernel/building.c index 14e4a3e07..520807933 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -55,6 +55,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include /* attributes includes */ +#include #include typedef struct building_typelist { @@ -710,7 +711,7 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) } if (r->attribs && rule_blessed_harvest() == HARVEST_WORK) { /* E1 rules */ - wage += curse_geteffect(get_curse(r->attribs, ct_find("blessedharvest"))); + wage += harvest_effect(r); } } diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 4a3e1c045..336316159 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -596,28 +596,23 @@ curse *create_curse(unit * magician, attrib ** ap, const curse_type * ct, if (ct->mergeflags & M_DURATION) { c->duration = MAX(c->duration, duration); } - if (ct->mergeflags & M_SUMDURATION) { + else if (ct->mergeflags & M_SUMDURATION) { c->duration += duration; } - if (ct->mergeflags & M_SUMEFFECT) { - c->effect += effect; - } if (ct->mergeflags & M_MAXEFFECT) { c->effect = MAX(c->effect, effect); } + else if (ct->mergeflags & M_SUMEFFECT) { + c->effect += effect; + } if (ct->mergeflags & M_VIGOUR) { c->vigour = MAX(vigour, c->vigour); } - if (ct->mergeflags & M_VIGOUR_ADD) { + else if (ct->mergeflags & M_VIGOUR_ADD) { c->vigour = vigour + c->vigour; } - if (ct->mergeflags & M_MEN) { - switch (ct->typ) { - case CURSETYP_UNIT: - { - c->data.i += men; - } - } + if (ct->mergeflags & M_MEN && ct->typ == CURSETYP_UNIT) { + c->data.i += men; } set_curseingmagician(magician, *ap, ct); } diff --git a/src/spells/regioncurse.c b/src/spells/regioncurse.c index b10f3046f..dc9256538 100644 --- a/src/spells/regioncurse.c +++ b/src/spells/regioncurse.c @@ -24,6 +24,7 @@ #include /* util includes */ +#include #include #include #include @@ -33,10 +34,6 @@ #include #include -/* --------------------------------------------------------------------- */ -/* CurseInfo mit Spezialabfragen - */ - /* * godcursezone */ @@ -206,6 +203,22 @@ static struct curse_type ct_blessedharvest = { cinfo_simple }; +int harvest_effect(const struct region *r) { + if (r->attribs) { + curse *c = get_curse(r->attribs, &ct_blessedharvest); + if (c) { + int happy = curse_geteffect_int(c); + if (happy != 1) { + /* https://bugs.eressea.de/view.php?id=2353 detect and fix bad harvest */ + log_error("blessedharvest curse %d has effect=%d, duration=%d", c->no, happy, c->duration); + c->effect = 1.0; + } + return happy; + } + } + return 0; +} + static struct curse_type ct_drought = { "drought", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), diff --git a/src/spells/regioncurse.h b/src/spells/regioncurse.h index c261ade41..a1ee182c1 100644 --- a/src/spells/regioncurse.h +++ b/src/spells/regioncurse.h @@ -17,10 +17,10 @@ extern "C" { #endif - struct curse; - struct locale; + struct region; - extern void register_regioncurse(void); + int harvest_effect(const struct region *r); + void register_regioncurse(void); #ifdef __cplusplus } From 78f8ec0173c35555a13c38e9dfa3626cb22e7d75 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Aug 2017 19:02:57 +0200 Subject: [PATCH 48/57] Added a test for the set_email function. I'm hoping to trigger bug 2354 in a unit test. --- src/kernel/faction.test.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index 80faba3c1..7eda676f7 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -223,6 +224,21 @@ static void test_valid_race(CuTest *tc) { test_cleanup(); } +static void test_set_email(CuTest *tc) { + char * email = NULL; + test_setup(); + CuAssertIntEquals(tc, 0, set_email(&email, "enno@eressea.de")); + CuAssertStrEquals(tc, "enno@eressea.de", email); + CuAssertIntEquals(tc, 0, set_email(&email, "bugs@eressea.de")); + CuAssertStrEquals(tc, "bugs@eressea.de", email); + CuAssertIntEquals(tc, -1, set_email(&email, "bad@@eressea.de")); + CuAssertStrEquals(tc, "bugs@eressea.de", email); + CuAssertIntEquals(tc, -1, set_email(&email, "eressea.de")); + CuAssertStrEquals(tc, "bugs@eressea.de", email); + free(email); + test_cleanup(); +} + CuSuite *get_faction_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -237,5 +253,6 @@ CuSuite *get_faction_suite(void) SUITE_ADD_TEST(suite, test_set_origin_bug); SUITE_ADD_TEST(suite, test_check_passwd); SUITE_ADD_TEST(suite, test_valid_race); + SUITE_ADD_TEST(suite, test_set_email); return suite; } From faf0f48a70d0dda0e87620cd7b47af3897e74784 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Aug 2017 21:03:51 +0200 Subject: [PATCH 49/57] BUG 2354: fix email validation. https://bugs.eressea.de/view.php?id=2354 --- src/kernel/faction.test.c | 2 +- src/util/goodies.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/kernel/faction.test.c b/src/kernel/faction.test.c index 7eda676f7..7901cd96f 100644 --- a/src/kernel/faction.test.c +++ b/src/kernel/faction.test.c @@ -232,8 +232,8 @@ static void test_set_email(CuTest *tc) { CuAssertIntEquals(tc, 0, set_email(&email, "bugs@eressea.de")); CuAssertStrEquals(tc, "bugs@eressea.de", email); CuAssertIntEquals(tc, -1, set_email(&email, "bad@@eressea.de")); - CuAssertStrEquals(tc, "bugs@eressea.de", email); CuAssertIntEquals(tc, -1, set_email(&email, "eressea.de")); + CuAssertIntEquals(tc, -1, set_email(&email, "eressea@")); CuAssertStrEquals(tc, "bugs@eressea.de", email); free(email); test_cleanup(); diff --git a/src/util/goodies.c b/src/util/goodies.c index c478bcf83..0794240d5 100644 --- a/src/util/goodies.c +++ b/src/util/goodies.c @@ -82,12 +82,18 @@ static int spc_email_isvalid(const char *address) if (strchr(rfc822_specials, *c)) return 0; } + if (*c!='@') { + /* no @ symbol */ + return -1; + } + domain = ++c; + if (!*c) { + return -1; + } if (c == address || *(c - 1) == '.') return 0; /* next we validate the domain portion (name@domain) */ - if (!*(domain = ++c)) - return 0; do { if (*c == '.') { if (c == domain || *(c - 1) == '.') From 59cee972e336c7a63989056514fe3c43de02ee08 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 6 Aug 2017 21:27:20 +0200 Subject: [PATCH 50/57] BUG 2355: (temporarily) disable assert https://bugs.eressea.de/view.php?id=2355 --- src/modules/autoseed.c | 2 ++ src/study.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/autoseed.c b/src/modules/autoseed.c index ffab4ca46..6e2599763 100644 --- a/src/modules/autoseed.c +++ b/src/modules/autoseed.c @@ -161,6 +161,8 @@ newfaction *read_newfactions(const char *filename) break; if (email[0] == '\0') break; + if (email[0] == '#') + break; if (password[0] == '\0') { size_t sz; sz = strlcpy(password, itoa36(rng_int()), sizeof(password)); diff --git a/src/study.c b/src/study.c index ddded23cc..85ff0b436 100644 --- a/src/study.c +++ b/src/study.c @@ -483,7 +483,7 @@ int teach_cmd(unit * teacher, struct order *ord) free_order(new_order); /* parse_order & set_order have each increased the refcount */ } if (academy && sk_academy!=NOSKILL) { - assert(academy % STUDYDAYS == 0); + /* assert(academy % STUDYDAYS == 0); bug 2355: why? */ academy_teaching_bonus(teacher, sk_academy, academy); } return 0; From 219a3159e8f62ce4624e6f35256fe8a4cf8c0c04 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 20 Aug 2017 12:58:05 +0200 Subject: [PATCH 51/57] sort the at_keys array, binary search. --- src/attributes/key.c | 168 ++++++++++++++++++++++++++++++-------- src/attributes/key.test.c | 2 +- src/kernel/region.c | 2 +- src/util/gamedata.h | 3 +- 4 files changed, 137 insertions(+), 38 deletions(-) diff --git a/src/attributes/key.c b/src/attributes/key.c index 1bd5cd9b4..ab413755f 100644 --- a/src/attributes/key.c +++ b/src/attributes/key.c @@ -22,6 +22,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include #include #include @@ -30,38 +31,94 @@ 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) { + int n = 0; + if (keys) { + assert(keys[0] < 4096 && keys[0]>0); + n = keys[0]; + } + WRITE_INT(store, n); + for (i = 0; i < n; ++i) { WRITE_INT(store, keys[i * 2 + 1]); WRITE_INT(store, keys[i * 2 + 2]); } } +static int keys_lower_bound(int *base, int k, int l, int r) { + int km = k; + int *p = base + 1; + + while (l != r) { + int m = (l + r) / 2; + km = p[m * 2]; + if (km < k) { + if (l == m) l = r; + else l = m; + } + else { + if (r == m) r = l; + else r = m; + } + } + return l; +} + static int a_readkeys(attrib * a, void *owner, gamedata *data) { - int i, *p = 0; - READ_INT(data->store, &i); - assert(i < 4096 && i>=0); - if (i == 0) { + int i, n, *keys; + + READ_INT(data->store, &n); + assert(n < 4096 && n >= 0); + if (n == 0) { return AT_READ_FAIL; } - a->data.v = p = malloc(sizeof(int)*(i*2 + 1)); - *p++ = i; - while (i--) { - READ_INT(data->store, p++); + + keys = malloc(sizeof(int)*(n * 2 + 1)); + *keys = n; + for (i = 0; i != n; ++i) { + READ_INT(data->store, keys + i * 2 + 1); if (data->version >= KEYVAL_VERSION) { - READ_INT(data->store, p++); + READ_INT(data->store, keys + i * 2 + 2); } else { - *p++ = 1; + keys[i * 2 + 2] = 1; } } + if (data->version < SORTKEYS_VERSION) { + int e = 1; + for (i = 1; i != n; ++i) { + int k = keys[i * 2 + 1]; + int v = keys[i * 2 + 2]; + int l = keys_lower_bound(keys, k, 0, e); + if (l != e) { + int km = keys[l * 2 + 1]; + if (km == k) { + int vm = keys[l * 2 + 2]; + if (v != vm) { + log_error("key %d has values %d and %d", k, v, vm); + } + --e; + } + else { + if (e > l) { + memmove(keys + 2 * l + 3, keys + 2 * l + 1, (e - l) * 2 * sizeof(int)); + } + keys[2 * l + 1] = k; + keys[2 * l + 2] = v; + } + } + ++e; + } + if (e != n) { + keys = realloc(keys, sizeof(int)*(2 * e + 1)); + keys[0] = e; + } + } + a->data.v = keys; return AT_READ_OK; } static int a_readkey(attrib *a, void *owner, struct gamedata *data) { int res = a_readint(a, owner, data); - if (data->version>=KEYVAL_VERSION) { + if (data->version >= KEYVAL_VERSION) { return AT_READ_FAIL; } return (res != AT_READ_FAIL) ? AT_READ_DEPR : res; @@ -101,9 +158,46 @@ attrib_type at_key = { a_upgradekeys }; +static int* keys_get(int *base, int i) +{ + int n = base[0]; + assert(i >= 0 && i < n); + return base + 1 + i * 2; +} + +static int *keys_update(int *base, int key, int val) +{ + int *kv; + int n = base[0]; + int l = keys_lower_bound(base, key, 0, n); + if (l < n) { + kv = keys_get(base, l); + if (kv[0] == key) { + kv[1] = val; + } + else { + assert(kv[0] > key); + base = realloc(base, (n * 2 + 3) * sizeof(int)); + kv = keys_get(base, l); + base[0] = n + 1; + memmove(kv + 2, kv, 2 * sizeof(int) * (n - l)); + kv[0] = key; + kv[1] = val; + } + } + else { + base = realloc(base, (n * 2 + 3) * sizeof(int)); + base[0] = n + 1; + kv = keys_get(base, l); + kv[0] = key; + kv[1] = val; + } + return base; +} + void key_set(attrib ** alist, int key, int val) { - int *keys, n = 0; + int *keys; attrib *a; assert(key != 0); a = a_find(*alist, &at_keys); @@ -111,16 +205,16 @@ void key_set(attrib ** alist, int key, int val) a = a_add(alist, a_new(&at_keys)); } keys = (int *)a->data.v; - if (keys) { - n = keys[0]; + if (!keys) { + a->data.v = keys = malloc(3 * sizeof(int)); + keys[0] = 1; + keys[1] = key; + keys[2] = val; + } + else { + a->data.v = keys = keys_update(keys, key, val); + assert(keys[0] < 4096 && keys[0] >= 0); } - /* TODO: too many allocations, unsorted array */ - keys = realloc(keys, sizeof(int) *(2 * n + 3)); - 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; } void key_unset(attrib ** alist, int key) @@ -129,17 +223,19 @@ void key_unset(attrib ** alist, int key) assert(key != 0); a = a_find(*alist, &at_keys); if (a) { - int i, *keys = (int *)a->data.v; + int *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)); + int l = keys_lower_bound(keys, key, 0, n); + if (l < n) { + int *kv = keys_get(keys, l); + if (kv[0] == key) { + memmove(kv, kv + 2, (n - l - 1) * 2 * sizeof(int)); + // TODO: realloc to smaller size? keys[0]--; - break; } } + assert(keys[0] < 4096 && keys[0]>0); } } } @@ -149,12 +245,14 @@ int key_get(attrib *alist, int key) { assert(key != 0); a = a_find(alist, &at_keys); if (a) { - int i, *keys = (int *)a->data.v; + int *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]; + int n = keys[0]; + int l = keys_lower_bound(keys, key, 0, n); + if (l < n) { + int * kv = keys_get(keys, l); + if (kv[0] == key) { + return kv[1]; } } } diff --git a/src/attributes/key.test.c b/src/attributes/key.test.c index b816e1d86..79a7bde1d 100644 --- a/src/attributes/key.test.c +++ b/src/attributes/key.test.c @@ -32,8 +32,8 @@ static void test_upgrade_key(CuTest *tc) { attrib *alist = 0; key_set_orig(&alist, 40); key_set_orig(&alist, 41); - key_set_orig(&alist, 42); key_set_orig(&alist, 43); + key_set_orig(&alist, 42); key_set_orig(&alist, 44); CuAssertPtrNotNull(tc, alist->type->upgrade); alist->type->upgrade(&alist, alist); diff --git a/src/kernel/region.c b/src/kernel/region.c index b582c406e..0eabc298c 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -584,7 +584,7 @@ int rroad(const region * r, direction_t d) bool r_isforest(const region * r) { if (fval(r->terrain, FOREST_REGION)) { - /* needs to be covered with at leas 48% trees */ + /* needs to be covered with at least 48% trees */ int mincover = (int)(r->terrain->size * 0.48); int trees = rtrees(r, 2) + rtrees(r, 1); return (trees * TREESIZE >= mincover); diff --git a/src/util/gamedata.h b/src/util/gamedata.h index f4983a981..97f8416b3 100644 --- a/src/util/gamedata.h +++ b/src/util/gamedata.h @@ -35,10 +35,11 @@ #define KEYVAL_VERSION 355 /* at_keys has values */ #define NOLANDITEM_VERSION 356 /* land_region has no items */ #define NORCSPELL_VERSION 357 /* data contains no RC_SPELL units */ +#define SORTKEYS_VERSION 358 /* at_keys is sorted */ /* unfinished: */ #define CRYPT_VERSION 400 /* passwords are encrypted */ -#define RELEASE_VERSION NORCSPELL_VERSION /* current datafile */ +#define RELEASE_VERSION SORTKEYS_VERSION /* current datafile */ #define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */ #define MAX_VERSION RELEASE_VERSION /* change this if we can need to read the future datafile, and we can do so */ From ef68b8123d104729240040b8b7610bf10d667fa1 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 20 Aug 2017 17:45:03 +0200 Subject: [PATCH 52/57] smart(er) dynamic allocation of key memory. --- src/attributes/key.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/attributes/key.c b/src/attributes/key.c index ab413755f..6841bbd71 100644 --- a/src/attributes/key.c +++ b/src/attributes/key.c @@ -62,6 +62,16 @@ static int keys_lower_bound(int *base, int k, int l, int r) { return l; } +static int keys_size(int n) { + /* TODO maybe use log2 from https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog */ + assert(n > 0 && n <= 4096); + if (n <= 1) return 1; + if (n <= 4) return 4; + if (n <= 16) return 16; + if (n <= 256) return 256; + return 4096; +} + static int a_readkeys(attrib * a, void *owner, gamedata *data) { int i, n, *keys; @@ -70,8 +80,7 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) { if (n == 0) { return AT_READ_FAIL; } - - keys = malloc(sizeof(int)*(n * 2 + 1)); + keys = malloc(sizeof(int)*(keys_size(n) * 2 + 1)); *keys = n; for (i = 0; i != n; ++i) { READ_INT(data->store, keys + i * 2 + 1); @@ -108,8 +117,12 @@ static int a_readkeys(attrib * a, void *owner, gamedata *data) { ++e; } if (e != n) { - keys = realloc(keys, sizeof(int)*(2 * e + 1)); - keys[0] = e; + int sz = keys_size(n); + if (e > sz) { + sz = keys_size(e); + keys = realloc(keys, sizeof(int)*(2 * sz + 1)); + keys[0] = e; + } } } a->data.v = keys; @@ -176,9 +189,14 @@ static int *keys_update(int *base, int key, int val) kv[1] = val; } else { + int sz = keys_size(n); assert(kv[0] > key); - base = realloc(base, (n * 2 + 3) * sizeof(int)); - kv = keys_get(base, l); + if (n + 1 > sz) { + ptrdiff_t diff = kv - base; + sz = keys_size(n + 1); + base = realloc(base, (sz * 2 + 1) * sizeof(int)); + kv = base + diff; + } base[0] = n + 1; memmove(kv + 2, kv, 2 * sizeof(int) * (n - l)); kv[0] = key; @@ -186,7 +204,11 @@ static int *keys_update(int *base, int key, int val) } } else { - base = realloc(base, (n * 2 + 3) * sizeof(int)); + int sz = keys_size(n); + if (n + 1 > sz) { + sz = keys_size(n + 1); + base = realloc(base, (sz * 2 + 1) * sizeof(int)); + } base[0] = n + 1; kv = keys_get(base, l); kv[0] = key; @@ -206,7 +228,8 @@ void key_set(attrib ** alist, int key, int val) } keys = (int *)a->data.v; if (!keys) { - a->data.v = keys = malloc(3 * sizeof(int)); + int sz = keys_size(1); + a->data.v = keys = malloc((2 * sz + 1) * sizeof(int)); keys[0] = 1; keys[1] = key; keys[2] = val; @@ -230,12 +253,9 @@ void key_unset(attrib ** alist, int key) if (l < n) { int *kv = keys_get(keys, l); if (kv[0] == key) { - memmove(kv, kv + 2, (n - l - 1) * 2 * sizeof(int)); - // TODO: realloc to smaller size? - keys[0]--; + kv[1] = 0; /* do not delete, just set to 0 */ } } - assert(keys[0] < 4096 && keys[0]>0); } } } From 134ff982ba66a780633b8ea500fddf4a0999771b Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 20 Aug 2017 19:07:52 +0200 Subject: [PATCH 53/57] BUG 2358: Schiffbeschleunigung dauert laenger als eine Woche. --- src/kernel/ship.c | 2 +- src/kernel/ship.test.c | 5 ++++- src/spells.c | 2 +- src/spells/shipcurse.c | 4 ++-- src/spells/shipcurse.h | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/kernel/ship.c b/src/kernel/ship.c index 234a91631..79918806d 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -332,7 +332,7 @@ int shipspeed(const ship * sh, const unit * u) return 0; if (sh->attribs) { - if (curse_active(get_curse(sh->attribs, ct_find("stormwind")))) { + if (curse_active(get_curse(sh->attribs, &ct_stormwind))) { k *= 2; } if (curse_active(get_curse(sh->attribs, ct_find("nodrift")))) { diff --git a/src/kernel/ship.test.c b/src/kernel/ship.test.c index 541ddee9a..ea1474e56 100644 --- a/src/kernel/ship.test.c +++ b/src/kernel/ship.test.c @@ -432,8 +432,11 @@ static void test_shipspeed_stormwind(CuTest *tc) { register_shipcurse(); assert(sh && cap && crew); - create_curse(0, &sh->attribs, ct_find("stormwind"), 1, 1, 1, 0); + create_curse(0, &sh->attribs, &ct_stormwind, 1, 1, 1, 0); + CuAssertPtrNotNull(tc, sh->attribs); CuAssertIntEquals_Msg(tc, "stormwind doubles ship range", sh->type->range * 2, shipspeed(sh, cap)); + a_age(&sh->attribs, sh); + CuAssertPtrEquals(tc, NULL, sh->attribs); test_cleanup(); } diff --git a/src/spells.c b/src/spells.c index 7931be8b8..85db5d63d 100644 --- a/src/spells.c +++ b/src/spells.c @@ -2276,7 +2276,7 @@ static int sp_stormwinds(castorder * co) } /* Duration = 1, nur diese Runde */ - create_curse(mage, &sh->attribs, ct_find("stormwind"), power, 1, + create_curse(mage, &sh->attribs, &ct_stormwind, power, 1, zero_effect, 0); /* Da der Spruch nur diese Runde wirkt wird er nie im Report * erscheinen */ diff --git a/src/spells/shipcurse.c b/src/spells/shipcurse.c index 0295695a1..a6e52f3a3 100644 --- a/src/spells/shipcurse.c +++ b/src/spells/shipcurse.c @@ -72,8 +72,8 @@ static message *cinfo_shipnodrift(const void *obj, objtype_t typ, const curse * return msg_message("curseinfo::shipnodrift_0", "ship id", sh, c->no); } -static struct curse_type ct_stormwind = { "stormwind", -CURSETYP_NORM, CURSE_NOAGE, NO_MERGE, cinfo_ship +const struct curse_type ct_stormwind = { "stormwind", +CURSETYP_NORM, 0, NO_MERGE, cinfo_ship }; static struct curse_type ct_nodrift = { "nodrift", diff --git a/src/spells/shipcurse.h b/src/spells/shipcurse.h index a41f9edee..928b76771 100644 --- a/src/spells/shipcurse.h +++ b/src/spells/shipcurse.h @@ -23,6 +23,7 @@ extern "C" { struct curse; extern const struct curse_type ct_shipspeedup; + extern const struct curse_type ct_stormwind; struct message *cinfo_ship(const void *obj, objtype_t typ, const struct curse *c, int self); From c99e92db20381412e804109024afe4eb7211d05e Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 21 Aug 2017 19:43:35 +0200 Subject: [PATCH 54/57] kill curse cache logic, it was a bad idea. ct_find is almost never what we want to do. --- src/battle.c | 74 +++++++++++++++-------------------- src/battle.test.c | 4 +- src/economy.c | 4 +- src/kernel/building.c | 22 +++++------ src/kernel/curse.c | 14 ------- src/kernel/curse.h | 1 - src/kernel/curse.test.c | 19 --------- src/kernel/region.c | 5 ++- src/kernel/unit.c | 79 ++++++++++++++++---------------------- src/move.c | 12 +++--- src/report.c | 5 ++- src/spells.c | 20 +++++----- src/spells/buildingcurse.c | 6 +-- src/spells/buildingcurse.h | 3 ++ src/spells/combatspells.c | 4 +- src/spells/regioncurse.c | 12 +++--- src/spells/regioncurse.h | 12 ++++-- src/spells/unitcurse.c | 10 ++--- src/spells/unitcurse.h | 10 ++++- 19 files changed, 138 insertions(+), 178 deletions(-) diff --git a/src/battle.c b/src/battle.c index a9130f2ef..7d6df8697 100644 --- a/src/battle.c +++ b/src/battle.c @@ -55,6 +55,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include +#include /* util includes */ #include @@ -138,15 +140,10 @@ static int rule_nat_armor; static int rule_cavalry_mode; static int rule_vampire; -static const curse_type *peace_ct, *slave_ct, *calm_ct; - /** initialize rules from configuration. */ static void init_rules(void) { - peace_ct = ct_find("peacezone"); - slave_ct = ct_find("slavery"); - calm_ct = ct_find("calmmonster"); rule_nat_armor = config_get_int("rules.combat.nat_armor", 0); rule_tactics_formula = config_get_int("rules.tactics.formula", 0); rule_goblin_bonus = config_get_int("rules.combat.goblinbonus", 10); @@ -1889,14 +1886,11 @@ int skilldiff(troop at, troop dt, int dist) if (df->building) { building *b = df->building; if (b->attribs) { - const curse_type *strongwall_ct = ct_find("strongwall"); - if (strongwall_ct) { - curse *c = get_curse(b->attribs, strongwall_ct); - if (curse_active(c)) { - /* wirkt auf alle Geb�ude */ - skdiff -= curse_geteffect_int(c); - is_protected = 2; - } + curse *c = get_curse(b->attribs, &ct_strongwall); + if (curse_active(c)) { + /* wirkt auf alle Geb�ude */ + skdiff -= curse_geteffect_int(c); + is_protected = 2; } } if (b->type->flags & BTF_FORTIFICATION) { @@ -3173,14 +3167,10 @@ fighter *make_fighter(battle * b, unit * u, side * s1, bool attack) /* Effekte von Spr�chen */ if (u->attribs) { - const curse_type *speed_ct; - speed_ct = ct_find("speed"); - if (speed_ct) { - curse *c = get_curse(u->attribs, speed_ct); - if (c) { - speeded = get_cursedmen(u, c); - speed = curse_geteffect_int(c); - } + curse *c = get_curse(u->attribs, &ct_speed); + if (c) { + speeded = get_cursedmen(u, c); + speed = curse_geteffect_int(c); } } @@ -3748,6 +3738,21 @@ static void flee(const troop dt) kill_troop(dt); } +static bool is_calmed(const unit *u, const faction *f) { + attrib *a = a_find(u->attribs, &at_curse); + + while (a && a->type == &at_curse) { + curse *c = (curse *)a->data.v; + if (c->type == &ct_calmmonster && curse_geteffect_int(c) == f->subscription) { + if (curse_active(c)) { + return true; + } + } + a = a->next; + } + return false; +} + static bool start_battle(region * r, battle ** bp) { battle *b = NULL; @@ -3794,12 +3799,12 @@ static bool start_battle(region * r, battle ** bp) if (fval(u, UFL_LONGACTION)) continue; - if (peace_ct && curse_active(get_curse(r->attribs, peace_ct))) { + if (curse_active(get_curse(r->attribs, &ct_peacezone))) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "peace_active", "")); continue; } - if (slave_ct && curse_active(get_curse(u->attribs, slave_ct))) { + if (curse_active(get_curse(u->attribs, &ct_slavery))) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "slave_active", "")); continue; } @@ -3847,26 +3852,11 @@ static bool start_battle(region * r, battle ** bp) NewbieImmunity())); continue; } - /* Fehler: "Die Einheit ist mit uns alliert" */ - if (calm_ct) { - attrib *a = a_find(u->attribs, &at_curse); - bool calm = false; - while (a && a->type == &at_curse) { - curse *c = (curse *)a->data.v; - if (c->type == calm_ct - && curse_geteffect_int(c) == u2->faction->subscription) { - if (curse_active(c)) { - calm = true; - break; - } - } - a = a->next; - } - if (calm) { - cmistake(u, ord, 47, MSG_BATTLE); - continue; - } + /* Fehler: "Die Einheit ist mit uns alliert" */ + if (is_calmed(u, u2->faction)) { + cmistake(u, ord, 47, MSG_BATTLE); + continue; } /* Ende Fehlerbehandlung */ if (b == NULL) { diff --git a/src/battle.test.c b/src/battle.test.c index 290ef6d74..009c12fbf 100644 --- a/src/battle.test.c +++ b/src/battle.test.c @@ -466,11 +466,9 @@ static void test_battle_skilldiff_building(CuTest *tc) unit *ua, *ud; battle *b = NULL; building_type *btype; - const curse_type *strongwall_ct; test_setup(); btype = setup_castle(); - strongwall_ct = ct_find("strongwall"); r = test_create_region(0, 0, 0); ud = test_create_unit(test_create_faction(0), r); @@ -489,7 +487,7 @@ static void test_battle_skilldiff_building(CuTest *tc) 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); + create_curse(NULL, &ud->building->attribs, &ct_strongwall, 1, 1, 2, 1); CuAssertIntEquals(tc, -4, skilldiff(ta, td, 0)); free_battle(b); diff --git a/src/economy.c b/src/economy.c index 7dd36ae62..c64734c0a 100644 --- a/src/economy.c +++ b/src/economy.c @@ -69,6 +69,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include /* libs includes */ #include @@ -728,13 +729,12 @@ static int maintain(building * b) void maintain_buildings(region * r) { - const curse_type *nocost_ct = ct_find("nocostbuilding"); building **bp = &r->buildings; while (*bp) { building *b = *bp; int flags = BLD_MAINTAINED; - if (!curse_active(get_curse(b->attribs, nocost_ct))) { + if (!curse_active(get_curse(b->attribs, &ct_nocostbuilding))) { flags = maintain(b); } fset(b, flags); diff --git a/src/kernel/building.c b/src/kernel/building.c index bcc914cca..2a0a19dce 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -56,6 +56,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. /* attributes includes */ #include +#include typedef struct building_typelist { struct building_typelist *next; @@ -679,12 +680,7 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) building *b = largestbuilding(r, cmp_wage, false); int esize = 0; double wage; - static int ct_cache; - static const struct curse_type *drought_ct; - if (ct_changed(&ct_cache)) { - drought_ct = ct_find("drought"); - } if (b != NULL) { /* TODO: this reveals imaginary castles */ esize = buildingeffsize(b, false); @@ -709,24 +705,24 @@ default_wage(const region * r, const faction * f, const race * rc, int in_turn) } if (r->attribs && rule_blessed_harvest() == HARVEST_WORK) { /* E1 rules */ - wage += curse_geteffect(get_curse(r->attribs, ct_find("blessedharvest"))); + wage += curse_geteffect(get_curse(r->attribs, &ct_blessedharvest)); } } if (r->attribs) { attrib *a; - const struct curse_type *ctype; + curse *c; + /* Godcurse: Income -10 */ - ctype = ct_find("godcursezone"); - if (ctype && curse_active(get_curse(r->attribs, ctype))) { + c = get_curse(r->attribs, &ct_godcursezone); + if (c && curse_active(c)) { wage = MAX(0, wage - 10); } /* Bei einer D�rre verdient man nur noch ein Viertel */ - if (drought_ct) { - curse *c = get_curse(r->attribs, drought_ct); - if (curse_active(c)) - wage /= curse_geteffect(c); + c = get_curse(r->attribs, &ct_drought); + if (c && curse_active(c)) { + wage /= curse_geteffect(c); } a = a_find(r->attribs, &at_reduceproduction); diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 3d236474e..919ff2ef8 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -284,17 +284,6 @@ attrib_type at_curse = { #define MAXCTHASH 128 static selist *cursetypes[MAXCTHASH]; -static int ct_changes = 1; - -bool ct_changed(int *cache) -{ - assert(cache); - if (*cache != ct_changes) { - *cache = ct_changes; - return true; - } - return false; -} void ct_register(const curse_type * ct) { @@ -304,7 +293,6 @@ void ct_register(const curse_type * ct) assert(ct->age==NULL || (ct->flags&CURSE_NOAGE) == 0); assert((ct->flags&CURSE_ISNEW) == 0); selist_set_insert(ctlp, (void *)ct, NULL); - ++ct_changes; } void ct_remove(const char *c) @@ -320,7 +308,6 @@ void ct_remove(const char *c) if (strcmp(c, type->cname) == 0) { selist_delete(&ctl, qi); - ++ct_changes; break; } } @@ -845,5 +832,4 @@ void curses_done(void) { selist_free(cursetypes[i]); cursetypes[i] = 0; } - ++ct_changes; } diff --git a/src/kernel/curse.h b/src/kernel/curse.h index b28427fcd..5ea08fb28 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -285,7 +285,6 @@ extern "C" { struct curse *get_curse(struct attrib *ap, const curse_type * ctype); const curse_type *ct_find(const char *c); - bool ct_changed(int *cache); void ct_register(const curse_type *); void ct_remove(const char *c); void ct_checknames(void); diff --git a/src/kernel/curse.test.c b/src/kernel/curse.test.c index a9271f897..10c03a991 100644 --- a/src/kernel/curse.test.c +++ b/src/kernel/curse.test.c @@ -159,24 +159,6 @@ static void test_write_flag(CuTest *tc) { cleanup_curse(&fix); } -static void test_curse_cache(CuTest *tc) -{ - int cache = 0; - 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)); - CuAssertPtrEquals(tc, NULL, (void *)ct_find(ct_dummy.cname)); - ct_register(&ct_dummy); - CuAssertIntEquals(tc, true, ct_changed(&cache)); - CuAssertPtrEquals(tc, (void *)&ct_dummy, (void *)ct_find(ct_dummy.cname)); - ct_remove(ct_dummy.cname); - CuAssertIntEquals(tc, true, ct_changed(&cache)); - CuAssertIntEquals(tc, false, ct_changed(&cache)); - CuAssertPtrEquals(tc, NULL, (void *)ct_find(ct_dummy.cname)); - test_cleanup(); -} - static void test_curse_ids(CuTest *tc) { const curse_type ct_dummy = { "dummy", CURSETYP_NORM, 0, M_SUMEFFECT, NULL }; curse *c1, *c2; @@ -218,7 +200,6 @@ CuSuite *get_curse_suite(void) { CuSuite *suite = CuSuiteNew(); SUITE_ADD_TEST(suite, test_curse); - SUITE_ADD_TEST(suite, test_curse_cache); SUITE_ADD_TEST(suite, test_magicstreet); SUITE_ADD_TEST(suite, test_magicstreet_warning); SUITE_ADD_TEST(suite, test_good_dreams); diff --git a/src/kernel/region.c b/src/kernel/region.c index 5cb86ff47..1758927d2 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -37,6 +37,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "terrainid.h" #include "unit.h" +#include + /* util includes */ #include #include @@ -1241,8 +1243,9 @@ 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")))) + if (curse_active(get_curse(r->attribs, &ct_drought))) { p /= 2; + } return p; } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index ab5f72f35..50ebfdd5c 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -43,6 +43,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include +#include + #include "guard.h" /* util includes */ @@ -1268,52 +1271,45 @@ static int att_modification(const unit * u, skill_t sk) if (u->attribs) { curse *c; - static int cache; - static const curse_type *skillmod_ct, *worse_ct; - if (ct_changed(&cache)) { - skillmod_ct = ct_find("skillmod"); - worse_ct = ct_find("worse"); - } - c = get_curse(u->attribs, worse_ct); - if (c != NULL) + attrib *a; + + c = get_curse(u->attribs, &ct_worse); + if (c != NULL) { result += curse_geteffect(c); - if (skillmod_ct) { - attrib *a = a_find(u->attribs, &at_curse); - while (a && a->type == &at_curse) { - curse *c = (curse *)a->data.v; - if (c->type == skillmod_ct && c->data.i == sk) { - result += curse_geteffect(c); - break; - } - a = a->next; + } + + a = a_find(u->attribs, &at_curse); + while (a && a->type == &at_curse) { + c = (curse *)a->data.v; + if (c->type == &ct_skillmod && c->data.i == sk) { + result += curse_geteffect(c); + break; } + a = a->next; } } /* TODO hier kann nicht mit get/iscursed gearbeitet werden, da nur der * jeweils erste vom Typ C_GBDREAM zurueckgegen wird, wir aber alle * durchsuchen und aufaddieren muessen */ if (u->region && u->region->attribs) { - const curse_type *gbdream_ct = ct_find("gbdream"); - if (gbdream_ct) { - int bonus = 0, malus = 0; - attrib *a = a_find(u->region->attribs, &at_curse); - while (a && a->type == &at_curse) { - curse *c = (curse *)a->data.v; - - if (c->magician && curse_active(c) && c->type == gbdream_ct) { - int effect = curse_geteffect_int(c); - bool allied = alliedunit(c->magician, u->faction, HELP_GUARD); - if (allied) { - if (effect > bonus) bonus = effect; - } - else { - if (effect < malus) malus = effect; - } + int bonus = 0, malus = 0; + attrib *a = a_find(u->region->attribs, &at_curse); + while (a && a->type == &at_curse) { + curse *c = (curse *)a->data.v; + + if (c->magician && curse_active(c) && c->type == &ct_gbdream) { + int effect = curse_geteffect_int(c); + bool allied = alliedunit(c->magician, u->faction, HELP_GUARD); + if (allied) { + if (effect > bonus) bonus = effect; + } + else { + if (effect < malus) malus = effect; } - a = a->next; } - result = result + bonus + malus; + a = a->next; } + result = result + bonus + malus; } return (int)result; @@ -1738,16 +1734,9 @@ int unit_max_hp(const unit * u) /* der healing curse veraendert die maximalen hp */ if (u->region && u->region->attribs) { - static int cache; - static const curse_type *heal_ct; - if (ct_changed(&cache)) { - heal_ct = ct_find("healingzone"); - } - if (heal_ct) { - curse *c = get_curse(u->region->attribs, heal_ct); - if (c) { - h = (int)(h * (1.0 + (curse_geteffect(c) / 100))); - } + curse *c = get_curse(u->region->attribs, &ct_healing); + if (c) { + h = (int)(h * (1.0 + (curse_geteffect(c) / 100))); } } return h; diff --git a/src/move.c b/src/move.c index 8ad25bc5a..28d0fbbbe 100644 --- a/src/move.c +++ b/src/move.c @@ -50,6 +50,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include #include "teleport.h" #include "direction.h" @@ -1415,13 +1416,10 @@ static int movement_speed(unit * u) } if (u->attribs) { - const curse_type *speed_ct = ct_find("speed"); - if (speed_ct) { - curse *c = get_curse(u->attribs, speed_ct); - if (c != NULL) { - int men = get_cursedmen(u, c); - dk *= 1.0 + (double)men / (double)u->number; - } + curse *c = get_curse(u->attribs, &ct_speed); + if (c != NULL) { + int men = get_cursedmen(u, c); + dk *= 1.0 + (double)men / (double)u->number; } } diff --git a/src/report.c b/src/report.c index 188d8dfa9..1b180d8c2 100644 --- a/src/report.c +++ b/src/report.c @@ -72,6 +72,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include + /* util includes */ #include #include @@ -1390,7 +1392,6 @@ report_template(const char *filename, report_context * ctx, const char *bom) char buf[8192], *bufp; size_t size; int bytes; - const curse_type *nocost_ct = ct_find("nocostbuilding"); if (F == NULL) { perror(filename); @@ -1459,7 +1460,7 @@ report_template(const char *filename, report_context * ctx, const char *bom) WARN_STATIC_BUFFER(); if (u->building && building_owner(u->building) == u) { building *b = u->building; - if (!curse_active(get_curse(b->attribs, nocost_ct))) { + if (!curse_active(get_curse(b->attribs, &ct_nocostbuilding))) { int cost = buildingmaintenance(b, rsilver); if (cost > 0) { bytes = (int)strlcpy(bufp, ",U", size); diff --git a/src/spells.c b/src/spells.c index 85db5d63d..efda37d22 100644 --- a/src/spells.c +++ b/src/spells.c @@ -1659,7 +1659,7 @@ static int sp_great_drought(castorder * co) /* Arbeitslohn = 1/4 */ effect = 4.0; /* curses: higher is stronger */ - create_curse(mage, &r->attribs, ct_find("drought"), force, duration, effect, + create_curse(mage, &r->attribs, &ct_drought, force, duration, effect, 0); /* terraforming */ @@ -2141,7 +2141,7 @@ static int sp_drought(castorder * co) * hoch (evtl dauert dann die Duerre laenger). Ansonsten volle * Auswirkungen. */ - c = get_curse(r->attribs, ct_find("drought")); + c = get_curse(r->attribs, &ct_drought); if (c) { c->vigour = MAX(c->vigour, power); c->duration = MAX(c->duration, (int)power); @@ -2154,7 +2154,7 @@ static int sp_drought(castorder * co) rsettrees(r, 0, rtrees(r, 0) / 2); rsethorses(r, rhorses(r) / 2); - create_curse(mage, &r->attribs, ct_find("drought"), power, duration, effect, + create_curse(mage, &r->attribs, &ct_drought, power, duration, effect, 0); } return cast_level; @@ -3647,7 +3647,7 @@ static int sp_charmingsong(castorder * co) add_trigger(&mage->faction->attribs, "destroy", trigger_killunit(target)); } /* sperre ATTACKIERE, GIB PERSON und ueberspringe Migranten */ - create_curse(mage, &target->attribs, ct_find("slavery"), force, duration, zero_effect, 0); + create_curse(mage, &target->attribs, &ct_slavery, force, duration, zero_effect, 0); /* setze Partei um und loesche langen Befehl aus Sicherheitsgruenden */ u_setfaction(target, mage->faction); @@ -3921,7 +3921,7 @@ static int sp_song_of_peace(castorder * co) int duration = 2 + lovar(force / 2); message *msg[2] = { NULL, NULL }; - create_curse(mage, &r->attribs, ct_find("peacezone"), force, duration, + create_curse(mage, &r->attribs, &ct_peacezone, force, duration, zero_effect, 0); for (u = r->units; u; u = u->next) @@ -4295,7 +4295,7 @@ static int sp_calm_monster(castorder * co) } effect = mage->faction->subscription; - c = create_curse(mage, &target->attribs, ct_find("calmmonster"), force, + c = create_curse(mage, &target->attribs, &ct_calmmonster, force, (int)force, effect, 0); if (c == NULL) { report_failure(mage, co->order); @@ -5829,7 +5829,7 @@ static int sp_eternizewall(castorder * co) return 0; b = pa->param[0]->data.b; - c = create_curse(mage, &b->attribs, ct_find("nocostbuilding"), + c = create_curse(mage, &b->attribs, &ct_nocostbuilding, power * power, 1, zero_effect, 0); if (c == NULL) { /* ist bereits verzaubert */ @@ -6167,7 +6167,7 @@ static int sp_magicrunes(castorder * co) b = pa->param[0]->data.b; /* Magieresistenz der Burg erhoeht sich um 20% */ - create_curse(mage, &b->attribs, ct_find("magicrunes"), force, + create_curse(mage, &b->attribs, &ct_magicrunes, force, duration, effect, 0); /* Erfolg melden */ @@ -6181,7 +6181,7 @@ static int sp_magicrunes(castorder * co) ship *sh; sh = pa->param[0]->data.sh; /* Magieresistenz des Schiffs erhoeht sich um 20% */ - create_curse(mage, &sh->attribs, ct_find("magicrunes"), force, + create_curse(mage, &sh->attribs, &ct_magicrunes, force, duration, effect, 0); /* Erfolg melden */ @@ -6233,7 +6233,7 @@ int sp_speed2(castorder * co) men = MIN(maxmen, u->number); effect = 2; - create_curse(mage, &u->attribs, ct_find("speed"), force, dur, effect, men); + create_curse(mage, &u->attribs, &ct_speed, force, dur, effect, men); maxmen -= men; used += men; } diff --git a/src/spells/buildingcurse.c b/src/spells/buildingcurse.c index f1a3b3773..06c62e1c4 100644 --- a/src/spells/buildingcurse.c +++ b/src/spells/buildingcurse.c @@ -70,7 +70,7 @@ static message *cinfo_magicrunes(const void *obj, objtype_t typ, const curse * c return msg; } -static struct curse_type ct_magicrunes = { "magicrunes", +const struct curse_type ct_magicrunes = { "magicrunes", CURSETYP_NORM, 0, M_SUMEFFECT, cinfo_magicrunes }; @@ -80,12 +80,12 @@ CURSETYP_NORM, CURSE_ONLYONE|CURSE_NOAGE, NO_MERGE, cinfo_building }; /* Feste Mauer - Präkampfzauber, wirkt nur 1 Runde */ -static struct curse_type ct_strongwall = { "strongwall", +const struct curse_type ct_strongwall = { "strongwall", CURSETYP_NORM, 0, NO_MERGE, NULL }; /* Ewige Mauern-Zauber */ -static struct curse_type ct_nocostbuilding = { "nocostbuilding", +const struct curse_type ct_nocostbuilding = { "nocostbuilding", CURSETYP_NORM, CURSE_NOAGE | CURSE_ONLYONE, NO_MERGE, cinfo_building }; diff --git a/src/spells/buildingcurse.h b/src/spells/buildingcurse.h index 2150dc3b6..03fc46a63 100644 --- a/src/spells/buildingcurse.h +++ b/src/spells/buildingcurse.h @@ -24,6 +24,9 @@ extern "C" { struct curse_type; extern const struct curse_type ct_magicwalls; + extern const struct curse_type ct_strongwall; + extern const struct curse_type ct_magicrunes; + extern const struct curse_type ct_nocostbuilding; 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/combatspells.c b/src/spells/combatspells.c index 08f38c8ea..8f62686d6 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -879,7 +881,7 @@ int sp_strong_wall(struct castorder * co) burg = mage->building; effect = power / 4; - create_curse(mage, &burg->attribs, ct_find("strongwall"), power, 1, effect, 0); + create_curse(mage, &burg->attribs, &ct_strongwall, power, 1, effect, 0); msg = msg_message("sp_strongwalls_effect", "mage building", mage, mage->building); diff --git a/src/spells/regioncurse.c b/src/spells/regioncurse.c index 1d69574df..aafc3ed4c 100644 --- a/src/spells/regioncurse.c +++ b/src/spells/regioncurse.c @@ -55,7 +55,7 @@ static message *cinfo_cursed_by_the_gods(const void *obj, objtype_t typ, return msg_message("curseinfo::godcurse", "id", c->no); } -static struct curse_type ct_godcursezone = { +const struct curse_type ct_godcursezone = { "godcursezone", CURSETYP_NORM, CURSE_IMMUNE, (NO_MERGE), cinfo_cursed_by_the_gods, @@ -81,7 +81,7 @@ static message *cinfo_dreamcurse(const void *obj, objtype_t typ, const curse * c } } -static struct curse_type ct_gbdream = { +const struct curse_type ct_gbdream = { "gbdream", CURSETYP_NORM, 0, (NO_MERGE), cinfo_dreamcurse }; @@ -200,13 +200,13 @@ static struct curse_type ct_maelstrom = { cinfo_simple }; -static struct curse_type ct_blessedharvest = { +const struct curse_type ct_blessedharvest = { "blessedharvest", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; -static struct curse_type ct_drought = { +const struct curse_type ct_drought = { "drought", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple @@ -240,7 +240,7 @@ static struct curse_type ct_generous = { }; /* verhindert Attackiere regional */ -static struct curse_type ct_peacezone = { +const struct curse_type ct_peacezone = { "peacezone", CURSETYP_NORM, 0, NO_MERGE, cinfo_simple @@ -274,7 +274,7 @@ static struct curse_type ct_holyground = { cinfo_simple }; -static struct curse_type ct_healing = { +const struct curse_type ct_healing = { "healingzone", CURSETYP_NORM, 0, (M_VIGOUR | M_DURATION), cinfo_simple diff --git a/src/spells/regioncurse.h b/src/spells/regioncurse.h index c261ade41..c3816b25f 100644 --- a/src/spells/regioncurse.h +++ b/src/spells/regioncurse.h @@ -17,10 +17,16 @@ extern "C" { #endif - struct curse; - struct locale; + struct curse_type; - extern void register_regioncurse(void); + extern const struct curse_type ct_peacezone; + extern const struct curse_type ct_drought; + extern const struct curse_type ct_blessedharvest; + extern const struct curse_type ct_godcursezone; + extern const struct curse_type ct_gbdream; + extern const struct curse_type ct_healing; + + void register_regioncurse(void); #ifdef __cplusplus } diff --git a/src/spells/unitcurse.c b/src/spells/unitcurse.c index 0a19629f1..d959d9635 100644 --- a/src/spells/unitcurse.c +++ b/src/spells/unitcurse.c @@ -92,7 +92,7 @@ static message *cinfo_slave(const void *obj, objtype_t typ, const curse * c, return NULL; } -static struct curse_type ct_slavery = { "slavery", +const struct curse_type ct_slavery = { "slavery", CURSETYP_NORM, 0, NO_MERGE, cinfo_slave }; @@ -120,7 +120,7 @@ static message *cinfo_calm(const void *obj, objtype_t typ, const curse * c, return NULL; } -static struct curse_type ct_calmmonster = { +const struct curse_type ct_calmmonster = { "calmmonster", CURSETYP_NORM, CURSE_SPREADNEVER | CURSE_ONLYONE, NO_MERGE, cinfo_calm @@ -144,7 +144,7 @@ static message *cinfo_speed(const void *obj, objtype_t typ, const curse * c, return NULL; } -static struct curse_type ct_speed = { +const struct curse_type ct_speed = { "speed", CURSETYP_UNIT, CURSE_SPREADNEVER, M_MEN, cinfo_speed @@ -275,7 +275,7 @@ CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, cinfo_simple /* * C_ALLSKILLS (Alp) */ -static struct curse_type ct_worse = { +const struct curse_type ct_worse = { "worse", CURSETYP_UNIT, CURSE_SPREADMODULO | CURSE_NOAGE, M_MEN, cinfo_unit }; @@ -339,7 +339,7 @@ static message *cinfo_skillmod(const void *obj, objtype_t typ, const curse * c, return NULL; } -static struct curse_type ct_skillmod = { +const struct curse_type ct_skillmod = { "skillmod", CURSETYP_NORM, CURSE_SPREADMODULO, M_MEN, cinfo_skillmod, NULL, read_skill, write_skill }; diff --git a/src/spells/unitcurse.h b/src/spells/unitcurse.h index 15d535cab..2102b41e3 100644 --- a/src/spells/unitcurse.h +++ b/src/spells/unitcurse.h @@ -20,8 +20,16 @@ extern "C" { #endif struct curse; + struct curse_type; struct message; - extern struct message *cinfo_unit(const void *obj, objtype_t typ, + + extern const struct curse_type ct_slavery; + extern const struct curse_type ct_calmmonster; + extern const struct curse_type ct_speed; + extern const struct curse_type ct_worse; + extern const struct curse_type ct_skillmod; + + struct message *cinfo_unit(const void *obj, objtype_t typ, const struct curse *c, int self); extern void register_unitcurse(void); From 7985ebe51155afffaeb69547c27111283c2b1306 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 21 Aug 2017 20:18:19 +0200 Subject: [PATCH 55/57] replace ct_find calls with constants. reorder a lot of includes. --- src/battle.c | 7 ++-- src/bind_monsters.c | 4 +-- src/economy.c | 18 +++++----- src/items.c | 17 ++++++---- src/kernel/building.c | 7 ++-- src/kernel/region.c | 2 +- src/kernel/ship.c | 8 ++--- src/kernel/ship.test.c | 2 +- src/kernel/terrain.c | 8 +++-- src/kernel/unit.c | 3 +- src/laws.c | 27 +++++++-------- src/magic.c | 43 ++++++++++++------------ src/monsters.c | 7 ++-- src/move.c | 28 ++++++++-------- src/randenc.c | 54 +++++++++++++++--------------- src/report.c | 4 +-- src/reports.c | 22 ++++++------- src/spells.c | 55 ++++++++++++++----------------- src/spells.h | 7 ++-- src/spells.test.c | 4 +-- src/spells/combatspells.c | 6 ++-- src/spells/flyingship.c | 4 +-- src/spells/magicresistance.c | 2 +- src/spells/magicresistance.test.c | 4 +-- src/spells/regioncurse.c | 24 +++++++------- src/spells/regioncurse.h | 12 +++++++ src/spells/shipcurse.c | 2 +- src/spells/shipcurse.h | 2 ++ src/spells/unitcurse.c | 16 ++++----- src/spells/unitcurse.h | 8 +++++ src/study.c | 12 +++---- 31 files changed, 220 insertions(+), 199 deletions(-) diff --git a/src/battle.c b/src/battle.c index 7d6df8697..54ff2e399 100644 --- a/src/battle.c +++ b/src/battle.c @@ -27,6 +27,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "move.h" #include "skill.h" +#include +#include +#include + #include #include #include @@ -54,9 +58,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include -#include -#include -#include /* util includes */ #include diff --git a/src/bind_monsters.c b/src/bind_monsters.c index 4ac15aa24..082d940ae 100644 --- a/src/bind_monsters.c +++ b/src/bind_monsters.c @@ -2,6 +2,8 @@ #include "spells/shipcurse.h" #include "monsters.h" +#include + #include #include #include @@ -9,8 +11,6 @@ #include #include -#include - #include #include diff --git a/src/economy.c b/src/economy.c index c64734c0a..8cd87c407 100644 --- a/src/economy.c +++ b/src/economy.c @@ -36,6 +36,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "reports.h" #include "calendar.h" +#include +#include +#include +#include + /* kernel includes */ #include #include @@ -67,10 +72,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include -#include -#include - /* libs includes */ #include #include @@ -2655,12 +2656,9 @@ expandwork(region * r, request * work_begin, request * work_end, int maxwork) earnings = jobs * p_wage; if (r->attribs && rule_blessed_harvest() == HARVEST_TAXES) { /* E3 rules */ - const curse_type *blessedharvest_ct = ct_find("blessedharvest"); - if (blessedharvest_ct) { - int happy = - (int)(jobs * curse_geteffect(get_curse(r->attribs, blessedharvest_ct))); - earnings += happy; - } + int happy = + (int)(jobs * curse_geteffect(get_curse(r->attribs, &ct_blessedharvest))); + earnings += happy; } rsetmoney(r, money + earnings); } diff --git a/src/items.c b/src/items.c index e33aed1bc..dd4abe1ac 100644 --- a/src/items.c +++ b/src/items.c @@ -7,6 +7,12 @@ #include "move.h" #include "magic.h" +#include + +#include +#include +#include + #include #include #include @@ -21,9 +27,6 @@ #include #include -#include -#include - /* triggers includes */ #include #include @@ -167,7 +170,7 @@ struct order *ord) } if (force > 0) { - create_curse(u, &r->attribs, ct_find("antimagiczone"), force, duration, + create_curse(u, &r->attribs, &ct_antimagiczone, force, duration, effect, 0); } } @@ -185,7 +188,7 @@ int amount, struct order *ord) { int money; - if (get_curse(u->region->attribs, ct_find("depression"))) { + if (get_curse(u->region->attribs, &ct_depression)) { cmistake(u, ord, 58, MSG_MAGIC); return -1; } @@ -194,7 +197,7 @@ int amount, struct order *ord) change_money(u, money); rsetmoney(u->region, rmoney(u->region) - money); - create_curse(u, &u->region->attribs, ct_find("depression"), + create_curse(u, &u->region->attribs, &ct_depression, 20, BAGPIPEDURATION, 0.0, 0); ADDMSG(&u->faction->msgs, msg_message("bagpipeoffear_faction", @@ -354,7 +357,7 @@ use_tacticcrystal(unit * u, const struct item_type *itype, int amount, der vor den Antimagiezaubern passiert */ effect = (float)(rng_int() % 6 - 1); - c = create_curse(u, &u->attribs, ct_find("skillmod"), power, + c = create_curse(u, &u->attribs, &ct_skillmod, power, duration, effect, u->number); c->data.i = SK_TACTICS; UNUSED_ARG(ord); diff --git a/src/kernel/building.c b/src/kernel/building.c index 2a0a19dce..45245c53e 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -21,6 +21,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "building.h" +#include +#include + /* kernel includes */ #include "curse.h" #include "item.h" @@ -54,10 +57,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -/* attributes includes */ -#include -#include - typedef struct building_typelist { struct building_typelist *next; building_type *type; diff --git a/src/kernel/region.c b/src/kernel/region.c index 1758927d2..1fc51fce0 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -159,7 +159,7 @@ void deathcounts(region * r, int fallen) if (fallen == 0) return; if (r->attribs) { - const curse_type *ctype = ct_find("holyground"); + const curse_type *ctype = &ct_holyground; if (ctype && curse_active(get_curse(r->attribs, ctype))) return; a = a_find(r->attribs, &at_deathcount); diff --git a/src/kernel/ship.c b/src/kernel/ship.c index 79918806d..764500b50 100644 --- a/src/kernel/ship.c +++ b/src/kernel/ship.c @@ -20,6 +20,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "ship.h" +#include +#include + /* kernel includes */ #include "build.h" #include "curse.h" @@ -41,9 +44,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include -#include - #include #include #include @@ -335,7 +335,7 @@ int shipspeed(const ship * sh, const unit * u) if (curse_active(get_curse(sh->attribs, &ct_stormwind))) { k *= 2; } - if (curse_active(get_curse(sh->attribs, ct_find("nodrift")))) { + if (curse_active(get_curse(sh->attribs, &ct_nodrift))) { k += 1; } } diff --git a/src/kernel/ship.test.c b/src/kernel/ship.test.c index ea1474e56..ce55f55af 100644 --- a/src/kernel/ship.test.c +++ b/src/kernel/ship.test.c @@ -450,7 +450,7 @@ static void test_shipspeed_nodrift(CuTest *tc) { register_shipcurse(); assert(sh && cap && crew); - create_curse(0, &sh->attribs, ct_find("nodrift"), 1, 1, 1, 0); + create_curse(0, &sh->attribs, &ct_nodrift, 1, 1, 1, 0); CuAssertIntEquals_Msg(tc, "nodrift adds +1 to range", sh->type->range + 1, shipspeed(sh, cap)); test_cleanup(); } diff --git a/src/kernel/terrain.c b/src/kernel/terrain.c index 3d6f4c313..e9f448f97 100644 --- a/src/kernel/terrain.c +++ b/src/kernel/terrain.c @@ -18,14 +18,16 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include #include "terrain.h" -#include "terrainid.h" + +#include +#include /* kernel includes */ #include "curse.h" #include "region.h" #include "resources.h" +#include "terrainid.h" #include #include @@ -160,7 +162,7 @@ const char *terrain_name(const struct region *r) return r->terrain->name(r); } else if (fval(r->terrain, SEA_REGION)) { - if (curse_active(get_curse(r->attribs, ct_find("maelstrom")))) { + if (curse_active(get_curse(r->attribs, &ct_maelstrom))) { return "maelstrom"; } } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 50ebfdd5c..84e4eb06e 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -941,8 +941,7 @@ bool can_survive(const unit * u, const region * r) return false; if (r->attribs) { - const curse_type *ctype = ct_find("holyground"); - if (fval(u_race(u), RCF_UNDEAD) && curse_active(get_curse(r->attribs, ctype))) + if (fval(u_race(u), RCF_UNDEAD) && curse_active(get_curse(r->attribs, &ct_holyground))) return false; } return true; diff --git a/src/laws.c b/src/laws.c index 5c7d36b51..0d78e6d6c 100644 --- a/src/laws.c +++ b/src/laws.c @@ -42,6 +42,15 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "calendar.h" #include "guard.h" +/* attributes includes */ +#include +#include +#include + +#include +#include +#include + /* kernel includes */ #include #include @@ -66,12 +75,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include /* for volcanoes in emigration (needs a flag) */ #include -/* attributes includes */ -#include -#include -#include -#include - /* util includes */ #include #include @@ -2859,13 +2862,12 @@ static void age_stonecircle(building *b) { if (get_astralplane()) { region *rt = r_standard_to_astral(r); if (mage && rt && !fval(rt->terrain, FORBIDDEN_REGION)) { - const struct curse_type *ct_astralblock = ct_find("astralblock"); - curse *c = get_curse(rt->attribs, ct_astralblock); + curse *c = get_curse(rt->attribs, &ct_astralblock); if (!c) { int sk = effskill(mage, SK_MAGIC, 0); float effect = 100; /* the mage reactivates the circle */ - c = create_curse(mage, &rt->attribs, ct_astralblock, + c = create_curse(mage, &rt->attribs, &ct_astralblock, (float)MAX(1, sk), MAX(1, sk / 2), effect, 0); ADDMSG(&r->msgs, msg_message("astralshield_activate", "region unit", r, mage)); @@ -2923,7 +2925,7 @@ static void ageing(void) } if (is_cursed(u->attribs, C_OLDRACE, 0)) { - curse *c = get_curse(u->attribs, ct_find("oldrace")); + curse *c = get_curse(u->attribs, &ct_oldrace); if (c->duration == 1 && !(c_flags(c) & CURSE_NOAGE)) { u_setrace(u, get_race(curse_geteffect_int(c))); u->irace = NULL; @@ -3234,15 +3236,14 @@ static int use_item(unit * u, const item_type * itype, int amount, struct order void monthly_healing(void) { region *r; - const curse_type *heal_ct = ct_find("healingzone"); for (r = regions; r; r = r->next) { unit *u; double healingcurse = 0; - if (r->attribs && heal_ct) { + if (r->attribs) { /* bonus zurücksetzen */ - curse *c = get_curse(r->attribs, heal_ct); + curse *c = get_curse(r->attribs, &ct_healing); if (c != NULL) { healingcurse = curse_geteffect(c); } diff --git a/src/magic.c b/src/magic.c index 883bddffa..58222b6e7 100644 --- a/src/magic.c +++ b/src/magic.c @@ -25,6 +25,17 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "study.h" #include "helpers.h" #include "laws.h" +#include "spells.h" + +#include +#include +#include +#include +#include +#include + +#include +#include #include #include @@ -46,13 +57,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include -#include -#include -#include -#include -#include - /* util includes */ #include #include @@ -1024,7 +1028,7 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order curse *c; /* Antimagie in der Zielregion */ - c = get_curse(r->attribs, ct_find("antimagiczone")); + c = get_curse(r->attribs, &ct_antimagiczone); if (curse_active(c)) { unit *mage = c->magician; force -= curse_geteffect(c); @@ -1043,7 +1047,7 @@ spellpower(region * r, unit * u, const spell * sp, int cast_level, struct order } /* Patzerfluch-Effekt: */ - c = get_curse(r->attribs, ct_find("fumble")); + c = get_curse(r->attribs, &ct_fumble); if (curse_active(c)) { unit *mage = c->magician; force -= curse_geteffect(c); @@ -1100,21 +1104,22 @@ variant magic_resistance(unit * target) { attrib *a; curse *c; - const curse_type * ct_goodresist = 0, *ct_badresist = 0; const resource_type *rtype; const race *rc = u_race(target); variant v, prob = rc_magres(rc); const plane *pl = rplane(target->region); + bool good_resist = true; + bool bad_resist = true; if (rc == get_race(RC_HIRNTOETER) && !pl) { - prob = frac_mul(prob, frac_make(1, 2)); + prob = frac_mul(prob, frac_make(1, 2)); } assert(target->number > 0); /* Magier haben einen Resistenzbonus vom Magietalent * 5% */ prob = frac_add(prob, frac_make(effskill(target, SK_MAGIC, 0), 20)); /* Auswirkungen von Zaubern auf der Einheit */ - c = get_curse(target->attribs, ct_find("magicresistance")); + c = get_curse(target->attribs, &ct_magicresistance); if (c) { /* TODO: legacy. magicresistance-effect is an integer-percentage stored in a double */ int effect = curse_geteffect_int(c) * get_cursedmen(target, c); @@ -1132,27 +1137,23 @@ variant magic_resistance(unit * target) /* Auswirkungen von Zaubern auf der Region */ a = a_find(target->region->attribs, &at_curse); - if (a) { - ct_badresist = ct_find("badmagicresistancezone"); - ct_goodresist = ct_find("goodmagicresistancezone"); - } while (a && a->type == &at_curse) { curse *c = (curse *)a->data.v; unit *mage = c->magician; if (mage != NULL) { - if (ct_goodresist && c->type == ct_goodresist) { + if (good_resist && c->type == &ct_goodmagicresistancezone) { if (alliedunit(mage, target->faction, HELP_GUARD)) { /* TODO: legacy. magicresistance-effect is an integer-percentage stored in a double */ prob = frac_add(prob, frac_make(curse_geteffect_int(c), 100)); - ct_goodresist = 0; /* only one effect per region */ + good_resist = false; /* only one effect per region */ } } - else if (ct_badresist && c->type == ct_badresist) { + else if (bad_resist && c->type == &ct_badmagicresistancezone) { if (!alliedunit(mage, target->faction, HELP_GUARD)) { /* TODO: legacy. magicresistance-effect is an integer-percentage stored in a double */ prob = frac_sub(prob, frac_make(curse_geteffect_int(c), 100)); - ct_badresist = 0; /* only one effect per region */ + bad_resist = false; /* only one effect per region */ } } } @@ -1410,7 +1411,7 @@ static void do_fumble(castorder * co) /* temporary skill loss */ duration = MAX(rng_int() % level / 2, 2); effect = level / -2.0; - c = create_curse(u, &u->attribs, ct_find("skillmod"), level, + c = create_curse(u, &u->attribs, &ct_skillmod, level, duration, effect, 1); c->data.i = SK_MAGIC; ADDMSG(&u->faction->msgs, msg_message("patzer2", "unit region", u, r)); diff --git a/src/monsters.c b/src/monsters.c index ffc04b52e..57b557999 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -34,6 +34,8 @@ #include #include +#include + /* kernel includes */ #include #include @@ -904,13 +906,12 @@ void spawn_undead(void) { region *r; faction *monsters = get_monsters(); - const curse_type *ctype = ct_find("holyground"); for (r = regions; r; r = r->next) { int unburied = deathcount(r); - if (r->attribs && ctype) { - if (curse_active(get_curse(r->attribs, ctype))) { + if (r->attribs) { + if (curse_active(get_curse(r->attribs, &ct_holyground))) { continue; } } diff --git a/src/move.c b/src/move.c index 28d0fbbbe..de2aae7ae 100644 --- a/src/move.c +++ b/src/move.c @@ -31,6 +31,17 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "lighthouse.h" #include "piracy.h" +#include +#include +#include + +/* attributes includes */ +#include +#include +#include +#include + +/* kernel includes */ #include #include #include @@ -49,9 +60,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include -#include - #include "teleport.h" #include "direction.h" #include "calendar.h" @@ -72,12 +80,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include -/* attributes includes */ -#include -#include -#include -#include - /* libc includes */ #include #include @@ -1002,7 +1004,7 @@ bool move_blocked(const unit * u, const region * r, const region * r2) } if (r->attribs) { - const curse_type *fogtrap_ct = ct_find("fogtrap"); + const curse_type *fogtrap_ct = &ct_fogtrap; curse *c = get_curse(r->attribs, fogtrap_ct); return curse_active(c); } @@ -1254,7 +1256,7 @@ static bool roadto(const region * r, direction_t dir) return false; } if (r->attribs || r2->attribs) { - const curse_type *roads_ct = ct_find("magicstreet"); + const curse_type *roads_ct = &ct_magicstreet; if (roads_ct != NULL) { if (get_curse(r->attribs, roads_ct) != NULL) return true; @@ -1578,7 +1580,7 @@ static const region_list *travel_route(unit * u, /* illusionary units disappear in antimagic zones */ if (fval(u_race(u), RCF_ILLUSIONARY)) { - curse *c = get_curse(next->attribs, ct_find("antimagiczone")); + curse *c = get_curse(next->attribs, &ct_antimagiczone); if (curse_active(c)) { curse_changevigour(&next->attribs, c, (float)-u->number); ADDMSG(&u->faction->msgs, msg_message("illusionantimagic", "unit", u)); @@ -1892,7 +1894,7 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting) break; } - if (curse_active(get_curse(next_point->attribs, ct_find("maelstrom")))) { + if (curse_active(get_curse(next_point->attribs, &ct_maelstrom))) { if (do_maelstrom(next_point, u) == NULL) break; } diff --git a/src/randenc.c b/src/randenc.c index ab51d64b1..c0daec72c 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -27,6 +27,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "chaos.h" #include "study.h" +/* attributes includes */ +#include +#include + +#include + /* kernel includes */ #include #include @@ -44,10 +50,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -/* attributes includes */ -#include -#include - /* util includes */ #include #include @@ -692,32 +694,28 @@ static void orc_growth(void) for (u = r->units; u; u = u->next) { if (u->attribs && !has_skill(u, SK_MAGIC) && !has_skill(u, SK_ALCHEMY) && !fval(u, UFL_HERO)) { - const curse_type *ct_orcish = ct_find("orcish"); - - if (ct_orcish) { - curse *c = get_curse(u->attribs, ct_orcish); - if (c) { - int n; - int increase = 0; - int num = get_cursedmen(u, c); - double prob = curse_geteffect(c); - const item_type * it_chastity = it_find("ao_chastity"); - - if (it_chastity) { - num -= i_get(u->items, it_chastity); - } - for (n = num; n > 0; n--) { - if (chance(prob)) { - ++increase; - } + curse *c = get_curse(u->attribs, &ct_orcish); + if (c) { + int n; + int increase = 0; + int num = get_cursedmen(u, c); + double prob = curse_geteffect(c); + const item_type * it_chastity = it_find("ao_chastity"); + + if (it_chastity) { + num -= i_get(u->items, it_chastity); + } + for (n = num; n > 0; n--) { + if (chance(prob)) { + ++increase; } - if (increase) { - unit *u2 = create_unit(r, u->faction, increase, u_race(u), 0, NULL, u); - transfermen(u2, u, u2->number); + } + if (increase) { + unit *u2 = create_unit(r, u->faction, increase, u_race(u), 0, NULL, u); + transfermen(u2, u, u2->number); - ADDMSG(&u->faction->msgs, msg_message("orcgrowth", - "unit amount race", u, increase, u_race(u))); - } + ADDMSG(&u->faction->msgs, msg_message("orcgrowth", + "unit amount race", u, increase, u_race(u))); } } } diff --git a/src/report.c b/src/report.c index 1b180d8c2..b86304ffc 100644 --- a/src/report.c +++ b/src/report.c @@ -46,6 +46,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "calendar.h" #include "teleport.h" +#include + /* kernel includes */ #include #include @@ -72,8 +74,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include - /* util includes */ #include #include diff --git a/src/reports.c b/src/reports.c index 6448fa58b..0a04b7497 100644 --- a/src/reports.c +++ b/src/reports.c @@ -25,6 +25,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "lighthouse.h" #include "donations.h" +/* attributes includes */ +#include +#include +#include +#include + +#include + /* kernel includes */ #include #include @@ -68,11 +76,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -/* attributes includes */ -#include -#include -#include -#include #include "move.h" @@ -303,12 +306,9 @@ report_items(const unit *u, item * result, int size, const unit * owner, assert(size); if (u->attribs) { - const curse_type *itemcloak_ct = ct_find("itemcloak"); - if (itemcloak_ct) { - curse * cu = get_curse(u->attribs, itemcloak_ct); - if (cu && curse_active(cu)) { - return 0; - } + curse * cu = get_curse(u->attribs, &ct_itemcloak); + if (cu && curse_active(cu)) { + return 0; } } for (itm = items; itm; itm = itm->next) { diff --git a/src/spells.c b/src/spells.c index efda37d22..254546baa 100644 --- a/src/spells.c +++ b/src/spells.c @@ -825,7 +825,7 @@ static int sp_goodwinds(castorder * co) /* keine Probleme mit C_SHIP_SPEEDUP und C_SHIP_FLYING */ /* NODRIFT bewirkt auch +1 Geschwindigkeit */ - create_curse(mage, &sh->attribs, ct_find("nodrift"), power, duration, + create_curse(mage, &sh->attribs, &ct_nodrift, power, duration, zero_effect, 0); /* melden, 1x pro Partei */ @@ -872,7 +872,7 @@ static int sp_magicstreet(castorder * co) } /* wirkt schon in der Zauberrunde! */ - create_curse(mage, &r->attribs, ct_find("magicstreet"), co->force, + create_curse(mage, &r->attribs, &ct_magicstreet, co->force, co->level + 1, zero_effect, 0); /* melden, 1x pro Partei */ @@ -1022,7 +1022,7 @@ static int sp_maelstrom(castorder * co) /* Attribut auf Region. * Existiert schon ein curse, so wird dieser verstaerkt * (Max(Dauer), Max(Staerke))*/ - c = create_curse(mage, &r->attribs, ct_find("maelstrom"), co->force, duration, co->force, 0); + c = create_curse(mage, &r->attribs, &ct_maelstrom, co->force, duration, co->force, 0); /* melden, 1x pro Partei */ if (c) { @@ -1102,7 +1102,7 @@ static int sp_blessedharvest(castorder * co) * Existiert schon ein curse, so wird dieser verstaerkt * (Max(Dauer), Max(Staerke))*/ - if (create_curse(mage, &r->attribs, ct_find("blessedharvest"), co->force, + if (create_curse(mage, &r->attribs, &ct_blessedharvest, co->force, duration, 1.0, 0)) { const char * effect = co->sp->sname[0]=='b' ? "harvest_effect" : "raindance_effect"; message *seen = msg_message(effect, "mage", mage); @@ -1405,7 +1405,7 @@ static int sp_kaelteschutz(castorder * co) } effect = 1; - create_curse(mage, &u->attribs, ct_find("insectfur"), (float)cast_level, + create_curse(mage, &u->attribs, &ct_insectfur, (float)cast_level, duration, effect, men); force -= u->number; @@ -1455,7 +1455,7 @@ static int sp_sparkle(castorder * co) u = pa->param[0]->data.u; effect = (float)(rng_int() % 0xffffff); - create_curse(mage, &u->attribs, ct_find("sparkle"), (float)cast_level, + create_curse(mage, &u->attribs, &ct_sparkle, (float)cast_level, duration, effect, u->number); ADDMSG(&mage->faction->msgs, msg_message("sparkle_effect", "mage target", @@ -2036,7 +2036,7 @@ static int sp_holyground(castorder * co) report_spell(mage, r, msg); msg_release(msg); - ctype = ct_find("holyground"); + ctype = &ct_holyground; create_curse(mage, &r->attribs, ctype, power * power, 1, zero_effect, 0); a_removeall(&r->attribs, &at_deathcount); @@ -2083,7 +2083,7 @@ static int sp_homestone(castorder * co) /* Magieresistenz der Burg erhoeht sich um 50% */ effect = 50.0F; c = create_curse(mage, &mage->building->attribs, - ct_find("magicresistance"), force * force, 1, effect, 0); + &ct_magicresistance, force * force, 1, effect, 0); c_setflag(c, CURSE_NOAGE); /* melden, 1x pro Partei in der Burg */ @@ -2538,7 +2538,7 @@ static int sp_fumblecurse(castorder * co) duration = MAX(sx, rx) + 1; effect = force / 2; - c = create_curse(mage, &target->attribs, ct_find("fumble"), + c = create_curse(mage, &target->attribs, &ct_fumble, force, duration, effect, 0); if (c == NULL) { report_failure(mage, co->order); @@ -2561,7 +2561,7 @@ void patzer_fumblecurse(const castorder * co) curse *c; effect = force / 2; - c = create_curse(mage, &mage->attribs, ct_find("fumble"), force, + c = create_curse(mage, &mage->attribs, &ct_fumble, force, duration, effect, 0); if (c != NULL) { ADDMSG(&mage->faction->msgs, msg_message("magic_fumble", @@ -3231,13 +3231,6 @@ static int sp_magicboost(castorder * co) double power = co->force; double effect; trigger *tsummon; - const curse_type *ct_auraboost; - const curse_type *ct_magicboost; - - ct_auraboost = ct_find("auraboost"); - ct_magicboost = ct_find("magicboost"); - assert(ct_auraboost != NULL); - assert(ct_magicboost != NULL); /* fehler, wenn schon ein boost */ if (is_cursed(mage->attribs, C_MBOOST, 0)) { @@ -3246,13 +3239,13 @@ static int sp_magicboost(castorder * co) } effect = 6; - create_curse(mage, &mage->attribs, ct_magicboost, power, 10, effect, 1); + create_curse(mage, &mage->attribs, &ct_magicboost, power, 10, effect, 1); /* one aura boost with 200% aura now: */ effect = 200; - c = create_curse(mage, &mage->attribs, ct_auraboost, power, 4, effect, 1); + c = create_curse(mage, &mage->attribs, &ct_auraboost, power, 4, effect, 1); /* and one aura boost with 50% aura in 5 weeks: */ - tsummon = trigger_createcurse(mage, mage, ct_auraboost, power, 6, 50, 1); + tsummon = trigger_createcurse(mage, mage, &ct_auraboost, power, 6, 50, 1); add_trigger(&mage->attribs, "timer", trigger_timeout(5, tsummon)); ADDMSG(&mage->faction->msgs, msg_message("magicboost_effect", @@ -3685,7 +3678,7 @@ static int sp_song_resistmagic(castorder * co) double force = co->force; int duration = (int)force + 1; - create_curse(mage, &r->attribs, ct_find("goodmagicresistancezone"), + create_curse(mage, &r->attribs, &ct_goodmagicresistancezone, force, duration, 15, 0); /* Erfolg melden */ @@ -3714,7 +3707,7 @@ static int sp_song_susceptmagic(castorder * co) double force = co->force; int duration = (int)force + 1; - create_curse(mage, &r->attribs, ct_find("badmagicresistancezone"), + create_curse(mage, &r->attribs, &ct_badmagicresistancezone, force, duration, 15, 0); ADDMSG(&mage->faction->msgs, msg_message("regionmagic_effect", @@ -3822,7 +3815,7 @@ static int sp_raisepeasantmob(castorder * co) a->data.ca[1] = 15; /* 15% */ a_add(&u->attribs, a); - create_curse(mage, &r->attribs, ct_find("riotzone"), (float)cast_level, duration, + create_curse(mage, &r->attribs, &ct_riotzone, (float)cast_level, duration, (float)anteil, 0); msg = msg_message("sp_raisepeasantmob_effect", "mage region", mage, r); @@ -3978,7 +3971,7 @@ static int sp_generous(castorder * co) } effect = 2; - create_curse(mage, &r->attribs, ct_find("generous"), force, duration, effect, + create_curse(mage, &r->attribs, &ct_generous, force, duration, effect, 0); for (u = r->units; u; u = u->next) @@ -4443,7 +4436,7 @@ static int sp_depression(castorder * co) int duration = (int)force + 1; message *msg; - create_curse(mage, &r->attribs, ct_find("depression"), force, duration, + create_curse(mage, &r->attribs, &ct_depression, force, duration, zero_effect, 0); msg = msg_message("sp_depression_effect", "mage region", mage, r); @@ -4862,7 +4855,7 @@ int sp_sweetdreams(castorder * co) /* Nichts machen als ein entsprechendes Attribut an die Einheit legen. */ effect = 0.05f; - create_curse(mage, &u->attribs, ct_find("orcish"), power, duration, effect, men); + create_curse(mage, &u->attribs, &ct_orcish, power, duration, effect, men); msg = msg_message("sp_sweetdreams_effect", "mage unit region", mage, u, r); r_addmessage(r, mage->faction, msg); @@ -4885,7 +4878,7 @@ int sp_disturbingdreams(castorder * co) double effect; effect = 10; - create_curse(mage, &r->attribs, ct_find("badlearn"), power, duration, effect, 0); + create_curse(mage, &r->attribs, &ct_badlearn, power, duration, effect, 0); ADDMSG(&mage->faction->msgs, msg_message("sp_disturbingdreams_effect", "mage region", mage, r)); @@ -4979,7 +4972,7 @@ int sp_itemcloak(castorder * co) /* Zieleinheit */ target = pa->param[0]->data.u; - create_curse(mage, &target->attribs, ct_find("itemcloak"), power, duration, + create_curse(mage, &target->attribs, &ct_itemcloak, power, duration, zero_effect, 0); ADDMSG(&mage->faction->msgs, msg_message("itemcloak", "mage target", mage, target)); @@ -5031,7 +5024,7 @@ int sp_resist_magic_bonus(castorder * co) m = MIN(u->number, victims); victims -= m; - create_curse(mage, &u->attribs, ct_find("magicresistance"), + create_curse(mage, &u->attribs, &ct_magicresistance, power, duration, 20, m); msg = msg_message("magicresistance_effect", "unit", u); @@ -5793,7 +5786,7 @@ int sp_disruptastral(castorder * co) /* Kontakt unterbinden */ effect = 100; - create_curse(mage, &rl2->data->attribs, ct_find("astralblock"), + create_curse(mage, &rl2->data->attribs, &ct_astralblock, power, duration, effect, 0); } @@ -6107,7 +6100,7 @@ int sp_antimagiczone(castorder * co) /* Reduziert die Staerke jedes Spruchs um effect */ effect = cast_level; - create_curse(mage, &r->attribs, ct_find("antimagiczone"), power, duration, + create_curse(mage, &r->attribs, &ct_antimagiczone, power, duration, effect, 0); /* Erfolg melden */ diff --git a/src/spells.h b/src/spells.h index 275f41f7a..a2f59f231 100644 --- a/src/spells.h +++ b/src/spells.h @@ -22,14 +22,15 @@ extern "C" { #endif - struct ship; - struct curse; + struct curse_type; + struct region; struct unit; struct message; + extern const struct curse_type ct_magicresistance; + void register_magicresistance(void); void register_spells(void); - void set_spelldata(struct spell *sp); int sp_baddreams(castorder * co); int sp_gooddreams(castorder * co); diff --git a/src/spells.test.c b/src/spells.test.c index 07a980e03..075ea6da6 100644 --- a/src/spells.test.c +++ b/src/spells.test.c @@ -39,7 +39,7 @@ static void test_good_dreams(CuTest *tc) { level = sp_gooddreams(&co); CuAssertIntEquals(tc, 10, level); - curse = get_curse(r->attribs, ct_find("gbdream")); + curse = get_curse(r->attribs, &ct_gbdream); CuAssertTrue(tc, curse && curse->duration > 1); CuAssertTrue(tc, curse->effect == 1); @@ -96,7 +96,7 @@ static void test_bad_dreams(CuTest *tc) { level = sp_baddreams(&co); CuAssertIntEquals(tc, 10, level); - curse = get_curse(r->attribs, ct_find("gbdream")); + curse = get_curse(r->attribs, &ct_gbdream); CuAssertTrue(tc, curse && curse->duration > 1); CuAssertTrue(tc, curse->effect == -1); diff --git a/src/spells/combatspells.c b/src/spells/combatspells.c index 8f62686d6..0f2b2ea3a 100644 --- a/src/spells/combatspells.c +++ b/src/spells/combatspells.c @@ -12,7 +12,9 @@ #include #include "combatspells.h" -/* kernel includes */ +#include + + /* kernel includes */ #include #include #include @@ -27,8 +29,6 @@ #include #include -#include - #include #include #include diff --git a/src/spells/flyingship.c b/src/spells/flyingship.c index eac2043dd..c3fe63e73 100644 --- a/src/spells/flyingship.c +++ b/src/spells/flyingship.c @@ -1,6 +1,8 @@ #include #include "flyingship.h" +#include + #include #include #include @@ -13,8 +15,6 @@ #include -#include - #include /* libc includes */ diff --git a/src/spells/magicresistance.c b/src/spells/magicresistance.c index 7b0c1413d..6f2ec49ec 100644 --- a/src/spells/magicresistance.c +++ b/src/spells/magicresistance.c @@ -22,7 +22,7 @@ static struct message *cinfo_magicresistance(const void *obj, objtype_t typ, con return 0; } -static struct curse_type ct_magicresistance = { +const struct curse_type ct_magicresistance = { "magicresistance", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, cinfo_magicresistance }; diff --git a/src/spells/magicresistance.test.c b/src/spells/magicresistance.test.c index 621d2c3b4..7576911af 100644 --- a/src/spells/magicresistance.test.c +++ b/src/spells/magicresistance.test.c @@ -36,7 +36,7 @@ static void test_magicresistance_unit(CuTest *tc) { f2 = test_create_faction(NULL); u2 = test_create_unit(f2, r); - c = create_curse(u1, &u2->attribs, ct_find("magicresistance"), 10, 20, 30, u2->number); + c = create_curse(u1, &u2->attribs, &ct_magicresistance, 10, 20, 30, u2->number); CuAssertPtrNotNull(tc, u2->attribs); CuAssertPtrEquals(tc, (void *)&at_curse, (void *)u2->attribs->type); msg = c->type->curseinfo(u2, TYP_UNIT, c, 1); @@ -62,7 +62,7 @@ static void test_magicresistance_building(CuTest *tc) { b1 = test_create_building(r, NULL); - c = create_curse(u1, &b1->attribs, ct_find("magicresistance"), 10, 20, 30, 0); + c = create_curse(u1, &b1->attribs, &ct_magicresistance, 10, 20, 30, 0); CuAssertPtrNotNull(tc, b1->attribs); CuAssertPtrEquals(tc, (void *)&at_curse, (void *)b1->attribs->type); msg = c->type->curseinfo(b1, TYP_BUILDING, c, 1); diff --git a/src/spells/regioncurse.c b/src/spells/regioncurse.c index aafc3ed4c..fa49826d9 100644 --- a/src/spells/regioncurse.c +++ b/src/spells/regioncurse.c @@ -106,7 +106,7 @@ static message *cinfo_magicstreet(const void *obj, objtype_t typ, const curse * return msg_message("curseinfo::magicstreetwarn", "id", c->no); } -static struct curse_type ct_magicstreet = { +const struct curse_type ct_magicstreet = { "magicstreet", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_magicstreet @@ -157,7 +157,7 @@ const curse * c, int self) return self; } -static struct curse_type ct_antimagiczone = { +const struct curse_type ct_antimagiczone = { "antimagiczone", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_antimagiczone, NULL, NULL, NULL, cansee_antimagiczone @@ -188,13 +188,13 @@ static struct curse_type ct_farvision = { /* --------------------------------------------------------------------- */ -static struct curse_type ct_fogtrap = { +const struct curse_type ct_fogtrap = { "fogtrap", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; -static struct curse_type ct_maelstrom = { +const struct curse_type ct_maelstrom = { "maelstrom", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple @@ -212,28 +212,28 @@ const struct curse_type ct_drought = { cinfo_simple }; -static struct curse_type ct_badlearn = { +const struct curse_type ct_badlearn = { "badlearn", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; /* Trübsal-Zauber */ -static struct curse_type ct_depression = { +const struct curse_type ct_depression = { "depression", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_simple }; /* Astralblock, auf Astralregion */ -static struct curse_type ct_astralblock = { +const struct curse_type ct_astralblock = { "astralblock", CURSETYP_NORM, 0, NO_MERGE, cinfo_simple }; /* Unterhaltungsanteil vermehren */ -static struct curse_type ct_generous = { +const struct curse_type ct_generous = { "generous", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR | M_MAXEFFECT), cinfo_simple @@ -248,7 +248,7 @@ const struct curse_type ct_peacezone = { /* erniedigt Magieresistenz von nicht-aliierten Einheiten, wirkt nur 1x * pro Einheit */ -static struct curse_type ct_badmagicresistancezone = { +const struct curse_type ct_badmagicresistancezone = { "badmagicresistancezone", CURSETYP_NORM, 0, NO_MERGE, cinfo_simple @@ -256,19 +256,19 @@ static struct curse_type ct_badmagicresistancezone = { /* erhöht Magieresistenz von aliierten Einheiten, wirkt nur 1x pro * Einheit */ -static struct curse_type ct_goodmagicresistancezone = { +const struct curse_type ct_goodmagicresistancezone = { "goodmagicresistancezone", CURSETYP_NORM, 0, NO_MERGE, cinfo_simple }; -static struct curse_type ct_riotzone = { +const struct curse_type ct_riotzone = { "riotzone", CURSETYP_NORM, 0, (M_DURATION), cinfo_simple }; -static struct curse_type ct_holyground = { +const struct curse_type ct_holyground = { "holyground", CURSETYP_NORM, CURSE_NOAGE, (M_VIGOUR_ADD), cinfo_simple diff --git a/src/spells/regioncurse.h b/src/spells/regioncurse.h index c3816b25f..86d9b024c 100644 --- a/src/spells/regioncurse.h +++ b/src/spells/regioncurse.h @@ -25,6 +25,18 @@ extern "C" { extern const struct curse_type ct_godcursezone; extern const struct curse_type ct_gbdream; extern const struct curse_type ct_healing; + extern const struct curse_type ct_antimagiczone; + extern const struct curse_type ct_depression; + extern const struct curse_type ct_astralblock; + extern const struct curse_type ct_badmagicresistancezone; + extern const struct curse_type ct_goodmagicresistancezone; + extern const struct curse_type ct_holyground; + extern const struct curse_type ct_fogtrap; + extern const struct curse_type ct_magicstreet; + extern const struct curse_type ct_maelstrom; + extern const struct curse_type ct_riotzone; + extern const struct curse_type ct_generous; + extern const struct curse_type ct_badlearn; void register_regioncurse(void); diff --git a/src/spells/shipcurse.c b/src/spells/shipcurse.c index a6e52f3a3..180c84eea 100644 --- a/src/spells/shipcurse.c +++ b/src/spells/shipcurse.c @@ -76,7 +76,7 @@ const struct curse_type ct_stormwind = { "stormwind", CURSETYP_NORM, 0, NO_MERGE, cinfo_ship }; -static struct curse_type ct_nodrift = { "nodrift", +const struct curse_type ct_nodrift = { "nodrift", CURSETYP_NORM, 0, (M_DURATION | M_VIGOUR), cinfo_shipnodrift }; diff --git a/src/spells/shipcurse.h b/src/spells/shipcurse.h index 928b76771..8bb98bcbe 100644 --- a/src/spells/shipcurse.h +++ b/src/spells/shipcurse.h @@ -21,9 +21,11 @@ extern "C" { struct message; struct curse; + struct curse_type; extern const struct curse_type ct_shipspeedup; extern const struct curse_type ct_stormwind; + extern const struct curse_type ct_nodrift; struct message *cinfo_ship(const void *obj, objtype_t typ, const struct curse *c, int self); diff --git a/src/spells/unitcurse.c b/src/spells/unitcurse.c index d959d9635..4f8d69f64 100644 --- a/src/spells/unitcurse.c +++ b/src/spells/unitcurse.c @@ -60,14 +60,14 @@ static message *cinfo_auraboost(const void *obj, objtype_t typ, const curse * c, return NULL; } -static struct curse_type ct_auraboost = { +const struct curse_type ct_auraboost = { "auraboost", CURSETYP_NORM, CURSE_SPREADMODULO, (NO_MERGE), cinfo_auraboost }; /* Magic Boost - Gabe des Chaos */ -static struct curse_type ct_magicboost = { +const struct curse_type ct_magicboost = { "magicboost", CURSETYP_UNIT, CURSE_SPREADMODULO | CURSE_IMMUNE, M_MEN, cinfo_simple }; @@ -168,7 +168,7 @@ message *cinfo_unit(const void *obj, objtype_t typ, const curse * c, int self) return NULL; } -static struct curse_type ct_orcish = { +const struct curse_type ct_orcish = { "orcish", CURSETYP_UNIT, CURSE_SPREADMODULO, M_MEN, cinfo_unit @@ -192,7 +192,7 @@ static message *cinfo_kaelteschutz(const void *obj, objtype_t typ, const curse * return NULL; } -static struct curse_type ct_insectfur = { +const struct curse_type ct_insectfur = { "insectfur", CURSETYP_UNIT, CURSE_SPREADMODULO, (M_MEN | M_DURATION), cinfo_kaelteschutz @@ -259,7 +259,7 @@ static message *cinfo_sparkle(const void *obj, objtype_t typ, const curse * c, } } -static struct curse_type ct_sparkle = { "sparkle", +const struct curse_type ct_sparkle = { "sparkle", CURSETYP_UNIT, CURSE_SPREADMODULO, (M_MEN | M_DURATION), cinfo_sparkle }; @@ -284,20 +284,20 @@ const struct curse_type ct_worse = { /* * C_ITEMCLOAK */ -static struct curse_type ct_itemcloak = { +const struct curse_type ct_itemcloak = { "itemcloak", CURSETYP_UNIT, CURSE_SPREADNEVER, M_DURATION, cinfo_unit }; /* ------------------------------------------------------------- */ -static struct curse_type ct_fumble = { +const struct curse_type ct_fumble = { "fumble", CURSETYP_NORM, CURSE_SPREADNEVER | CURSE_ONLYONE, NO_MERGE, cinfo_unit }; /* ------------------------------------------------------------- */ -static struct curse_type ct_oldrace = { +const struct curse_type ct_oldrace = { "oldrace", CURSETYP_NORM, CURSE_SPREADALWAYS, NO_MERGE, NULL }; diff --git a/src/spells/unitcurse.h b/src/spells/unitcurse.h index 2102b41e3..681fa32de 100644 --- a/src/spells/unitcurse.h +++ b/src/spells/unitcurse.h @@ -28,6 +28,14 @@ extern "C" { extern const struct curse_type ct_speed; extern const struct curse_type ct_worse; extern const struct curse_type ct_skillmod; + extern const struct curse_type ct_oldrace; + extern const struct curse_type ct_fumble; + extern const struct curse_type ct_orcish; + extern const struct curse_type ct_itemcloak; + extern const struct curse_type ct_insectfur; + extern const struct curse_type ct_sparkle; + extern const struct curse_type ct_magicboost; + extern const struct curse_type ct_auraboost; struct message *cinfo_unit(const void *obj, objtype_t typ, const struct curse *c, int self); diff --git a/src/study.c b/src/study.c index 9ea0a860e..55bcd9b34 100644 --- a/src/study.c +++ b/src/study.c @@ -28,6 +28,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "alchemy.h" #include "academy.h" +#include + #include #include #include @@ -52,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include + #include /* libc includes */ @@ -282,12 +285,9 @@ int teach_cmd(unit * u, struct order *ord) int teaching, i, j, count, academy = 0; if (u->region->attribs) { - const curse_type *gbdream_ct = ct_find("gbdream"); - if (gbdream_ct) { - if (get_curse(u->region->attribs, gbdream_ct)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "gbdream_noteach", "")); - return 0; - } + if (get_curse(u->region->attribs, &ct_gbdream)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "gbdream_noteach", "")); + return 0; } } if ((u_race(u)->flags & RCF_NOTEACH) || fval(u, UFL_WERE)) { From fc4bde47f6546b8eb09e229bb8305b92e8680fbd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Mon, 21 Aug 2017 20:48:00 +0200 Subject: [PATCH 56/57] kill the old curses enum and oldcursename. --- src/creport.c | 6 ++- src/economy.c | 15 +++---- src/give.c | 14 ++++--- src/kernel/curse.c | 60 ++++---------------------- src/kernel/curse.h | 9 ++-- src/kernel/faction.c | 7 ++-- src/laws.c | 20 +++++---- src/magic.c | 14 +++---- src/morale.c | 4 +- src/move.c | 14 ++++--- src/randenc.c | 7 ++-- src/report.c | 7 ++-- src/spells.c | 93 ++++++++++++++++++++--------------------- src/spells/flyingship.c | 8 ++-- src/spells/flyingship.h | 3 ++ src/study.c | 2 +- 16 files changed, 127 insertions(+), 156 deletions(-) diff --git a/src/creport.c b/src/creport.c index 10dc4c323..1c18f675a 100644 --- a/src/creport.c +++ b/src/creport.c @@ -20,6 +20,8 @@ without prior permission by the authors of Eressea. #define BUFFERSIZE 32768 #define RESOURCECOMPAT +#include + /* modules include */ #include @@ -1361,7 +1363,7 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r) if (skill_enabled(SK_ENTERTAINMENT)) { fprintf(F, "%d;Unterh\n", entertainmoney(r)); } - if (is_cursed(r->attribs, C_RIOT, 0)) { + if (is_cursed(r->attribs, &ct_riotzone)) { fputs("0;Rekruten\n", F); } else { @@ -1419,7 +1421,7 @@ static void cr_output_region(FILE * F, report_context * ctx, region * r) cr_output_curses_compat(F, f, r, TYP_REGION); cr_borders(r, f, r->seen.mode, F); if (r->seen.mode == seen_unit && is_astral(r) - && !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { + && !is_cursed(r->attribs, &ct_astralblock)) { /* Sonderbehandlung Teleport-Ebene */ region_list *rl = astralregions(r, inhabitable); diff --git a/src/economy.c b/src/economy.c index 8cd87c407..c84645b02 100644 --- a/src/economy.c +++ b/src/economy.c @@ -40,6 +40,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* kernel includes */ #include @@ -118,14 +119,14 @@ int entertainmoney(const region * r) { double n; - if (is_cursed(r->attribs, C_DEPRESSION, 0)) { + if (is_cursed(r->attribs, &ct_depression)) { return 0; } n = rmoney(r) / (double)ENTERTAINFRACTION; - if (is_cursed(r->attribs, C_GENEROUS, 0)) { - n *= get_curseeffect(r->attribs, C_GENEROUS, 0); + if (is_cursed(r->attribs, &ct_generous)) { + n *= get_curseeffect(r->attribs, &ct_generous); } return (int)n; @@ -502,7 +503,7 @@ static void recruit(unit * u, struct order *ord, request ** recruitorders) return; } } - if (is_cursed(r->attribs, C_RIOT, 0)) { + if (is_cursed(r->attribs, &ct_riotzone)) { /* Die Region befindet sich in Aufruhr */ cmistake(u, ord, 237, MSG_EVENT); return; @@ -652,7 +653,7 @@ static int forget_cmd(unit * u, order * ord) skill_t sk; const char *s; - if (is_cursed(u->attribs, C_SLAVE, 0)) { + if (is_cursed(u->attribs, &ct_slavery)) { /* charmed units shouldn't be losing their skills */ return 0; } @@ -2589,7 +2590,7 @@ void entertain_cmd(unit * u, struct order *ord) cmistake(u, ord, 69, MSG_INCOME); return; } - if (is_cursed(r->attribs, C_DEPRESSION, 0)) { + if (is_cursed(r->attribs, &ct_depression)) { cmistake(u, ord, 28, MSG_INCOME); return; } @@ -3028,7 +3029,7 @@ void produce(struct region *r) continue; if (u_race(u) == rc_insect && r_insectstalled(r) && - !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + !is_cursed(u->attribs, &ct_insectfur)) continue; if (fval(u, UFL_LONGACTION) && u->thisorder == NULL) { diff --git a/src/give.c b/src/give.c index 060ecbbb9..28f47acd7 100644 --- a/src/give.c +++ b/src/give.c @@ -17,7 +17,12 @@ #include "economy.h" #include "laws.h" -/* kernel includes */ +#include + + /* attributes includes */ +#include + + /* kernel includes */ #include #include #include @@ -33,9 +38,6 @@ #include #include -/* attributes includes */ -#include - /* util includes */ #include #include @@ -286,7 +288,7 @@ static bool can_give_men(const unit *u, const unit *dst, order *ord, message **m /* hungry people cannot be given away */ if (msg) *msg = msg_error(u, ord, 73); } - else if (fval(u, UFL_LOCKED) || is_cursed(u->attribs, C_SLAVE, 0)) { + else if (fval(u, UFL_LOCKED) || is_cursed(u->attribs, &ct_slavery)) { if (msg) *msg = msg_error(u, ord, 74); } else { @@ -329,7 +331,7 @@ message * give_men(int n, unit * u, unit * u2, struct order *ord) else if (unit_has_cursed_item(u2)) { error = 78; } - else if (fval(u2, UFL_LOCKED) || is_cursed(u2->attribs, C_SLAVE, 0)) { + else if (fval(u2, UFL_LOCKED) || is_cursed(u2->attribs, &ct_slavery)) { error = 75; } else if (!ucontact(u2, u)) { diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 919ff2ef8..968269962 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -141,10 +141,11 @@ static int read_ccompat(const char *cursename, struct storage *store) struct compat { const char *name; const char *tokens; - } *seek, old_curses[] = { { - "disorientationzone", "" }, { - "shipdisorientation", "" }, { - NULL, NULL } }; + } *seek, old_curses[] = { + { "disorientationzone", "" }, + { "shipdisorientation", "" }, + { NULL, NULL } + }; for (seek = old_curses; seek->name; ++seek) { if (strcmp(seek->tokens, cursename) == 0) { const char *p; @@ -232,7 +233,7 @@ int curse_read(attrib * a, void *owner, gamedata *data) if (c->type->typ == CURSETYP_REGION) { int rr = read_reference(&c->data.v, data, read_region_reference, - RESOLVE_REGION(data->version)); + RESOLVE_REGION(data->version)); if (ur == 0 && rr == 0 && !c->data.v) { return AT_READ_FAIL; } @@ -290,7 +291,7 @@ void ct_register(const curse_type * ct) unsigned int hash = tolower(ct->cname[0]) & 0xFF; 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); } @@ -466,7 +467,7 @@ int curse_geteffect_int(const curse * c) /* ------------------------------------------------------------- */ static void set_curseingmagician(struct unit *magician, struct attrib *ap_target, -const curse_type * ct) + const curse_type * ct) { curse *c = get_curse(ap_target, ct); if (c) { @@ -723,51 +724,6 @@ bool is_cursed_with(const attrib * ap, const curse * c) return false; } -/* ------------------------------------------------------------- */ -/* cursedata */ -/* ------------------------------------------------------------- */ - -static const char *oldnames[MAXCURSE] = { - /* OBS: when removing curses, remember to update read_ccompat() */ - "fogtrap", - "antimagiczone", - "farvision", - "gbdream", - "auraboost", - "maelstrom", - "blessedharvest", - "drought", - "badlearn", - "stormwind", - "flyingship", - "nodrift", - "depression", - "magicwalls", - "strongwall", - "astralblock", - "generous", - "peacezone", - "magicstreet", - "magicrunes", - "badmagicresistancezone", - "goodmagicresistancezone", - "slavery", - "calmmonster", - "oldrace", - "fumble", - "riotzone", - "godcursezone", - "speed", - "orcish", - "magicboost", - "insectfur" -}; - -const char *oldcursename(int id) -{ - return oldnames[id]; -} - /* ------------------------------------------------------------- */ message *cinfo_simple(const void *obj, objtype_t typ, const struct curse * c, int self) diff --git a/src/kernel/curse.h b/src/kernel/curse.h index 5ea08fb28..9f330fdd6 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -303,14 +303,13 @@ extern "C" { bool curse_active(const struct curse *c); /*** COMPATIBILITY MACROS. DO NOT USE FOR NEW CODE, REPLACE IN OLD CODE: */ - const char *oldcursename(int id); struct message *cinfo_simple(const void *obj, objtype_t typ, const struct curse *c, int self); int curse_cansee(const struct curse *c, const struct faction *viewer, objtype_t typ, const void *obj, int self); -#define is_cursed(a, id, id2) \ - (a && curse_active(get_curse(a, ct_find(oldcursename(id))))) -#define get_curseeffect(a, id, id2) \ - curse_geteffect(get_curse(a, ct_find(oldcursename(id)))) +#define is_cursed(a, ctype) \ + (a && curse_active(get_curse(a, ctype))) +#define get_curseeffect(a, ctype) \ + curse_geteffect(get_curse(a, ctype)) /* eressea-defined attribute-type flags */ #define ATF_CURSE ATF_USER_DEFINED diff --git a/src/kernel/faction.c b/src/kernel/faction.c index 0b099df0f..16788c3b5 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -33,6 +33,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "terrain.h" #include "unit.h" +#include +#include + /* util includes */ #include #include @@ -49,8 +52,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -#include - #include #include @@ -730,7 +731,7 @@ int count_faction(const faction * f, int flags) } } else if (flags&COUNT_MIGRANTS) { - if (!is_cursed(u->attribs, C_SLAVE, 0)) { + if (!is_cursed(u->attribs, &ct_slavery)) { n += x; } } diff --git a/src/laws.c b/src/laws.c index 0d78e6d6c..47f1dd9e9 100644 --- a/src/laws.c +++ b/src/laws.c @@ -430,7 +430,7 @@ static void horses(region * r) maxhorses = MAX(0, maxhorses); horses = rhorses(r); if (horses > 0) { - if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { + if (is_cursed(r->attribs, &ct_godcursezone)) { rsethorses(r, (int)(horses * 0.9)); } else if (maxhorses) { @@ -583,7 +583,7 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) a_removeall(&r->attribs, &at_germs); } - if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { + if (is_cursed(r->attribs, &ct_godcursezone)) { rsettrees(r, 1, (int)(rtrees(r, 1) * 0.9)); rsettrees(r, 2, (int)(rtrees(r, 2) * 0.9)); return; @@ -640,7 +640,7 @@ growing_trees(region * r, const int current_season, const int last_weeks_season) } else if (current_season == SEASON_SPRING) { - if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) + if (is_cursed(r->attribs, &ct_godcursezone)) return; /* in at_germs merken uns die Zahl der Samen und Sprößlinge, die @@ -2924,11 +2924,13 @@ static void ageing(void) change_effect(u, oldpotiontype[P_BERSERK], -1 * MIN(u->number, i)); } - if (is_cursed(u->attribs, C_OLDRACE, 0)) { - curse *c = get_curse(u->attribs, &ct_oldrace); - if (c->duration == 1 && !(c_flags(c) & CURSE_NOAGE)) { - u_setrace(u, get_race(curse_geteffect_int(c))); - u->irace = NULL; + if (u->attribs) { + curse * c = get_curse(u->attribs, &ct_oldrace); + if (c && curse_active(c)) { + if (c->duration == 1 && !(c_flags(c) & CURSE_NOAGE)) { + u_setrace(u, get_race(curse_geteffect_int(c))); + u->irace = NULL; + } } } } @@ -3789,7 +3791,7 @@ void process(void) } else if (u_race(u) == get_race(RC_INSECT) && r_insectstalled(r) - && !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) { + && !is_cursed(u->attribs, &ct_insectfur)) { ord = NULL; } else if (LongHunger(u)) { diff --git a/src/magic.c b/src/magic.c index 58222b6e7..dde298ed0 100644 --- a/src/magic.c +++ b/src/magic.c @@ -35,6 +35,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include +#include #include #include @@ -699,7 +700,7 @@ int max_spellpoints(const region * r, const unit * u) if (rtype && i_get(u->items, rtype->itype) > 0) { msp += use_item_aura(r, u); } - n = get_curseeffect(u->attribs, C_AURA, 0); + n = get_curseeffect(u->attribs, &ct_auraboost); if (n > 0) { msp = (msp * n) / 100; } @@ -1251,8 +1252,7 @@ target_resists_magic(unit * magician, void *obj, int objtyp, int t_bonus) } if (a) { - const struct curse_type *ct_resist = ct_find(oldcursename(C_RESIST_MAGIC)); - curse * c = get_curse(a, ct_resist); + curse * c = get_curse(a, &ct_magicrunes); int effect = curse_geteffect_int(c); prob = frac_add(prob, frac_make(effect, 100)); } @@ -1320,10 +1320,10 @@ bool fumble(region * r, unit * u, const spell * sp, int cast_grade) if (mage->magietyp == M_DRAIG) { fumble_chance += CHAOSPATZERCHANCE; } - if (is_cursed(u->attribs, C_MBOOST, 0)) { + if (is_cursed(u->attribs, &ct_magicboost)) { fumble_chance += CHAOSPATZERCHANCE; } - if (is_cursed(u->attribs, C_FUMBLE, 0)) { + if (is_cursed(u->attribs, &ct_fumble)) { fumble_chance += CHAOSPATZERCHANCE; } @@ -1503,7 +1503,7 @@ void regenerate_aura(void) reg_aura *= btype->auraregen; /* Bonus/Malus durch Zauber */ - mod = get_curseeffect(u->attribs, C_AURA, 0); + mod = get_curseeffect(u->attribs, &ct_auraboost); if (mod > 0) { reg_aura = (reg_aura * mod) / 100.0; } @@ -2795,7 +2795,7 @@ void magic(void) continue; if (u_race(u) == rc_insect && r_insectstalled(r) && - !is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + !is_cursed(u->attribs, &ct_insectfur)) continue; if (fval(u, UFL_WERE | UFL_LONGACTION)) { diff --git a/src/morale.c b/src/morale.c index 8b0a8c6ee..a8a7cc9d9 100644 --- a/src/morale.c +++ b/src/morale.c @@ -20,6 +20,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include "morale.h" +#include + #include #include #include @@ -53,7 +55,7 @@ void morale_update(region *r) { if (stability > MORALE_COOLDOWN && r->land->ownership->owner && morale < MORALE_MAX) { double ch = popularity(); - if (is_cursed(r->attribs, C_GENEROUS, 0)) { + if (is_cursed(r->attribs, &ct_generous)) { ch *= 1.2; /* 20% improvement */ } if (stability >= MORALE_AVERAGE * 2 || chance(ch)) { diff --git a/src/move.c b/src/move.c index de2aae7ae..33ed38126 100644 --- a/src/move.c +++ b/src/move.c @@ -34,6 +34,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include +#include /* attributes includes */ #include @@ -673,7 +674,7 @@ static bool is_freezing(const unit * u) { if (u_race(u) != get_race(RC_INSECT)) return false; - if (is_cursed(u->attribs, C_KAELTESCHUTZ, 0)) + if (is_cursed(u->attribs, &ct_insectfur)) return false; return true; } @@ -832,7 +833,7 @@ static void drifting_ships(region * r) } /* Schiff schon abgetrieben oder durch Zauber geschützt? */ - if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { + if (!drift || fval(sh, SF_DRIFTED) || is_cursed(sh->attribs, &ct_nodrift)) { shp = &sh->next; continue; } @@ -1803,7 +1804,7 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting) } if (rng_int() % 10000 < stormchance * sh->type->storm && fval(current_point->terrain, SEA_REGION)) { - if (!is_cursed(sh->attribs, C_SHIP_NODRIFT, 0)) { + if (!is_cursed(sh->attribs, &ct_nodrift)) { region *rnext = NULL; bool storm = true; int d_offset = rng_int() % MAXDIRECTIONS; @@ -1920,9 +1921,10 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting) last_point = current_point; current_point = next_point; - if (!fval(current_point->terrain, SEA_REGION) - && !is_cursed(sh->attribs, C_SHIP_FLYING, 0)) + if (!fval(next_point->terrain, SEA_REGION) + && !is_cursed(sh->attribs, &ct_flyingship)) { break; + } token = getstrtoken(); error = movewhere(u, token, current_point, &next_point); if (error || next_point == NULL) { @@ -1958,7 +1960,7 @@ static void sail(unit * u, order * ord, region_list ** routep, bool drifting) set_order(&u->thisorder, NULL); set_coast(sh, last_point, current_point); - if (is_cursed(sh->attribs, C_SHIP_FLYING, 0)) { + if (is_cursed(sh->attribs, &ct_flyingship)) { ADDMSG(&f->msgs, msg_message("shipfly", "ship from to", sh, starting_point, current_point)); } diff --git a/src/randenc.c b/src/randenc.c index c0daec72c..ba986ffe1 100644 --- a/src/randenc.c +++ b/src/randenc.c @@ -27,12 +27,13 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "chaos.h" #include "study.h" +#include +#include + /* attributes includes */ #include #include -#include - /* kernel includes */ #include #include @@ -651,7 +652,7 @@ static void godcurse(void) region *r; for (r = regions; r; r = r->next) { - if (is_cursed(r->attribs, C_CURSED_BY_THE_GODS, 0)) { + if (is_cursed(r->attribs, &ct_godcursezone)) { unit *u; for (u = r->units; u; u = u->next) { skill *sv = u->skills; diff --git a/src/report.c b/src/report.c index b86304ffc..4b462d9ff 100644 --- a/src/report.c +++ b/src/report.c @@ -29,6 +29,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "monsters.h" #include "travelthru.h" +#include +#include + /* modules includes */ #include @@ -46,8 +49,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include "calendar.h" #include "teleport.h" -#include - /* kernel includes */ #include #include @@ -1187,7 +1188,7 @@ void report_region(struct stream *out, const region * r, faction * f) paragraph(out, buf, 0, 0, 0); if (r->seen.mode == seen_unit && is_astral(r) && - !is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { + !is_cursed(r->attribs, &ct_astralblock)) { /* Sonderbehandlung Teleport-Ebene */ region_list *rl = astralregions(r, inhabitable); region_list *rl2; diff --git a/src/spells.c b/src/spells.c index 254546baa..734648204 100644 --- a/src/spells.c +++ b/src/spells.c @@ -1785,7 +1785,7 @@ static int sp_treewalkenter(castorder * co) } rt = r_standard_to_astral(r); - if (rt == NULL || is_cursed(rt->attribs, C_ASTRALBLOCK, 0) + if (rt == NULL || is_cursed(rt->attribs, &ct_astralblock) || fval(rt->terrain, FORBIDDEN_REGION)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralblock", "")); @@ -1901,7 +1901,7 @@ static int sp_treewalkexit(castorder * co) "spellfail_astralonly", "")); return 0; } - if (is_cursed(r->attribs, C_ASTRALBLOCK, 0)) { + if (is_cursed(r->attribs, &ct_astralblock)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralblock", "")); return 0; @@ -2264,12 +2264,12 @@ static int sp_stormwinds(castorder * co) sh = pa->param[n]->data.sh; /* mit C_SHIP_NODRIFT haben wir kein Problem */ - if (is_cursed(sh->attribs, C_SHIP_FLYING, 0)) { + if (is_cursed(sh->attribs, &ct_flyingship)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "error_spell_on_flying_ship", "ship", sh)) continue; } - if (is_cursed(sh->attribs, C_SHIP_SPEEDUP, 0)) { + if (is_cursed(sh->attribs, &ct_shipspeedup)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "error_spell_on_ship_already", "ship", sh)) continue; @@ -2338,7 +2338,7 @@ static int sp_earthquake(castorder * co) while (*blist) { building *burg = *blist; - if (burg->size != 0 && !is_cursed(burg->attribs, C_MAGICWALLS, 0)) { + if (burg->size != 0 && !is_cursed(burg->attribs, &ct_magicwalls)) { /* Magieresistenz */ if (!target_resists_magic(mage, burg, TYP_BUILDING, 0)) { kaputt = MIN(10 * cast_level, burg->size / 4); @@ -2798,7 +2798,7 @@ static int sp_unholypower(castorder * co) * korrekt abgefangen wird. Besser (aber nicht gerade einfach) * waere es, eine solche Konstruktion irgendwie zu kapseln. */ if (fval(u, UFL_LOCKED) || fval(u, UFL_HUNGER) - || is_cursed(u->attribs, C_SLAVE, 0)) { + || is_cursed(u->attribs, &ct_slavery)) { cmistake(mage, co->order, 74, MSG_MAGIC); continue; } @@ -3186,7 +3186,7 @@ static int sp_chaossuction(castorder * co) cmistake(mage, co->order, 216, MSG_MAGIC); return 0; } - else if (is_cursed(rt->attribs, C_ASTRALBLOCK, 0)) { + else if (is_cursed(rt->attribs, &ct_astralblock)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralblock", "")); return 0; @@ -3233,7 +3233,7 @@ static int sp_magicboost(castorder * co) trigger *tsummon; /* fehler, wenn schon ein boost */ - if (is_cursed(mage->attribs, C_MBOOST, 0)) { + if (is_cursed(mage->attribs, &ct_magicboost)) { report_failure(mage, co->order); return 0; } @@ -3748,7 +3748,7 @@ static int sp_rallypeasantmob(castorder * co) } } - c = get_curse(r->attribs, ct_find(oldcursename(C_RIOT))); + c = get_curse(r->attribs, &ct_riotzone); if (c != NULL) { remove_curse(&r->attribs, c); } @@ -3964,7 +3964,7 @@ static int sp_generous(castorder * co) double effect; message *msg[2] = { NULL, NULL }; - if (is_cursed(r->attribs, C_DEPRESSION, 0)) { + if (is_cursed(r->attribs, &ct_depression)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_generous", "")); return 0; @@ -4662,7 +4662,29 @@ int sp_analysedream(castorder * co) return cast_level; } -static int sp_gbdreams(castorder * co, const char *curse_name, int effect); +static int sp_gbdreams(castorder * co, int effect) +{ + int duration; + unit *mage = co->magician.u; + int cast_level = co->level; + double power = co->force; + region *r = co_get_region(co); + + /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken, + * also duration+2 */ + duration = (int)MAX(1, power / 2); /* Stufe 1 macht sonst mist */ + duration = 2 + rng_int() % duration; + + /* Nichts machen als ein entsprechendes Attribut in die Region legen. */ + create_curse(mage, &r->attribs, &ct_gbdream, power, duration, effect, 0); + + /* Erfolg melden */ + ADDMSG(&mage->faction->msgs, msg_message("regionmagic_effect", + "unit region command", mage, mage->region, co->order)); + + return cast_level; +} + /* ------------------------------------------------------------- */ /* Name: Schlechte Traeume @@ -4679,7 +4701,7 @@ static int sp_gbdreams(castorder * co, const char *curse_name, int effect); * */ int sp_baddreams(castorder * co) { - return sp_gbdreams(co, "gbdream", -1); + return sp_gbdreams(co, -1); } /* ------------------------------------------------------------- */ @@ -4696,30 +4718,7 @@ int sp_baddreams(castorder * co) */ int sp_gooddreams(castorder * co) { - return sp_gbdreams(co, "gbdream", 1); -} - -static int sp_gbdreams(castorder * co, const char *curse_name, int effect) -{ - int duration; - unit *mage = co->magician.u; - int cast_level = co->level; - double power = co->force; - region *r = co_get_region(co); - - /* wirkt erst in der Folgerunde, soll mindestens eine Runde wirken, - * also duration+2 */ - duration = (int)MAX(1, power / 2); /* Stufe 1 macht sonst mist */ - duration = 2 + rng_int() % duration; - - /* Nichts machen als ein entsprechendes Attribut in die Region legen. */ - create_curse(mage, &r->attribs, ct_find(curse_name), power, duration, effect, 0); - - /* Erfolg melden */ - ADDMSG(&mage->faction->msgs, msg_message("regionmagic_effect", - "unit region command", mage, mage->region, co->order)); - - return cast_level; + return sp_gbdreams(co, 1); } /* ------------------------------------------------------------- */ @@ -5075,8 +5074,8 @@ int sp_enterastral(castorder * co) return 0; } - if (is_cursed(rt->attribs, C_ASTRALBLOCK, 0) - || is_cursed(ro->attribs, C_ASTRALBLOCK, 0)) { + if (is_cursed(rt->attribs, &ct_astralblock) + || is_cursed(ro->attribs, &ct_astralblock)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralblock", "")); return 0; @@ -5202,8 +5201,8 @@ int sp_pullastral(castorder * co) return 0; } - if (is_cursed(rt->attribs, C_ASTRALBLOCK, 0) - || is_cursed(ro->attribs, C_ASTRALBLOCK, 0)) { + if (is_cursed(rt->attribs, &ct_astralblock) + || is_cursed(ro->attribs, &ct_astralblock)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralblock", "")); return 0; @@ -5346,8 +5345,8 @@ int sp_leaveastral(castorder * co) return 0; } - if (ro == NULL || is_cursed(ro->attribs, C_ASTRALBLOCK, 0) - || is_cursed(rt->attribs, C_ASTRALBLOCK, 0)) { + if (ro == NULL || is_cursed(ro->attribs, &ct_astralblock) + || is_cursed(rt->attribs, &ct_astralblock)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralblock", "")); return 0; @@ -5486,7 +5485,7 @@ int sp_fetchastral(castorder * co) ro = u->region; } - if (is_cursed(ro->attribs, C_ASTRALBLOCK, 0)) { + if (is_cursed(ro->attribs, &ct_astralblock)) { ADDMSG(&mage->faction->msgs, msg_feedback(mage, co->order, "spellfail_astralblock", "")); continue; @@ -5599,7 +5598,7 @@ int sp_showastral(castorder * co) for (rl2 = rl; rl2; rl2 = rl2->next) { region *r2 = rl2->data; - if (!is_cursed(r2->attribs, C_ASTRALBLOCK, 0)) { + if (!is_cursed(r2->attribs, &ct_astralblock)) { for (u = r2->units; u; u = u->next) { if (u_race(u) != get_race(RC_SPECIAL) && u_race(u) != get_race(RC_SPELL)) n++; @@ -5619,7 +5618,7 @@ int sp_showastral(castorder * co) "Nebel zu erkennen sind ", unitname(mage)); for (rl2 = rl; rl2; rl2 = rl2->next) { - if (!is_cursed(rl2->data->attribs, C_ASTRALBLOCK, 0)) { + if (!is_cursed(rl2->data->attribs, &ct_astralblock)) { for (u = rl2->data->units; u; u = u->next) { if (u_race(u) != get_race(RC_SPECIAL) && u_race(u) != get_race(RC_SPELL)) { c++; @@ -5677,7 +5676,7 @@ int sp_viewreality(castorder * co) /* Irgendwann mal auf Curses u/o Attribut umstellen. */ for (rl2 = rl; rl2; rl2 = rl2->next) { region *rt = rl2->data; - if (!is_cursed(rt->attribs, C_ASTRALBLOCK, 0)) { + if (!is_cursed(rt->attribs, &ct_astralblock)) { u = create_unit(rt, mage->faction, 1, get_race(RC_SPELL), 0, "spell/viewreality", NULL); @@ -5735,7 +5734,7 @@ int sp_disruptastral(castorder * co) int inhab_regions = 0; region_list *trl = NULL; - if (is_cursed(r2->attribs, C_ASTRALBLOCK, 0)) + if (is_cursed(r2->attribs, &ct_astralblock)) continue; if (r2->units != NULL) { diff --git a/src/spells/flyingship.c b/src/spells/flyingship.c index c3fe63e73..e23f6906b 100644 --- a/src/spells/flyingship.c +++ b/src/spells/flyingship.c @@ -66,11 +66,11 @@ int sp_flying_ship(castorder * co) cno = levitate_ship(sh, mage, power, 1); if (cno == 0) { - if (is_cursed(sh->attribs, C_SHIP_FLYING, 0)) { + if (is_cursed(sh->attribs, &ct_flyingship)) { /* Auf dem Schiff befindet liegt bereits so ein Zauber. */ cmistake(mage, co->order, 211, MSG_MAGIC); } - else if (is_cursed(sh->attribs, C_SHIP_SPEEDUP, 0)) { + else if (is_cursed(sh->attribs, &ct_shipspeedup)) { /* Es ist zu gefaehrlich, ein sturmgepeitschtes Schiff fliegen zu lassen. */ cmistake(mage, co->order, 210, MSG_MAGIC); } @@ -127,7 +127,7 @@ static int flyingship_age(curse * c) return 0; } -static struct curse_type ct_flyingship = { "flyingship", +const struct curse_type ct_flyingship = { "flyingship", CURSETYP_NORM, 0, NO_MERGE, cinfo_ship, NULL, flyingship_read, flyingship_write, NULL, flyingship_age }; @@ -153,7 +153,7 @@ static curse *shipcurse_flyingship(ship * sh, unit * mage, double power, int dur if (curse_active(get_curse(sh->attribs, &ct_flyingship))) { return NULL; } - if (is_cursed(sh->attribs, C_SHIP_SPEEDUP, 0)) { + if (is_cursed(sh->attribs, &ct_shipspeedup)) { return NULL; } } diff --git a/src/spells/flyingship.h b/src/spells/flyingship.h index 52013ac13..4a03e6b71 100644 --- a/src/spells/flyingship.h +++ b/src/spells/flyingship.h @@ -12,6 +12,9 @@ extern "C" { struct castorder; struct ship; struct unit; + struct curse_type; + + extern const struct curse_type ct_flyingship; int sp_flying_ship(struct castorder * co); diff --git a/src/study.c b/src/study.c index 55bcd9b34..882a3040b 100644 --- a/src/study.c +++ b/src/study.c @@ -764,7 +764,7 @@ int study_cmd(unit * u, order * ord) teach->value += u->number * 10; } - if (is_cursed(r->attribs, C_BADLEARN, 0)) { + if (is_cursed(r->attribs, &ct_badlearn)) { teach->value -= u->number * 10; } From b70f0e9977eb9f4b20c10cbc5e6db9c21504abe4 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Thu, 24 Aug 2017 16:57:02 +0200 Subject: [PATCH 57/57] do not allow install from the wrong branch --- s/install | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/s/install b/s/install index 27cf185af..5115ca8ee 100755 --- a/s/install +++ b/s/install @@ -1,18 +1,25 @@ #!/bin/sh -ROOT=$(pwd) -while [ ! -d $ROOT/.git ]; do - ROOT=$(dirname $ROOT) - if [ "/" = "$ROOT" ]; then - echo "could not find root, are you in the git repository?" - exit - fi + +FORCE=0 +while getopts f o; do + case "${o}" in + f) usage ; FORCE=yes ;; + esac done +if [ "$FORCE" != "yes" ] ; then + BRANCH=$(git status -s -b | head -1 | cut -d\ -f 2 | sed 's/\..*//') + if [ "$BRANCH" != "master" ] ; then + echo "you should only install stable versions from the master branch" + exit + fi +fi [ -z "$CC" ] && [ ! -z `which clang` ] && CC="clang" [ -z "$CC" ] && [ ! -z `which gcc` ] && CC="gcc" [ -z "$CC" ] && [ ! -z `which tcc` ] && CC="tcc" [ -z "$CC" ] && [ ! -z `which cc` ] && CC="cc" BIN_DIR="Debug" +ROOT=$(git rev-parse --show-toplevel) cd $ROOT/$BIN_DIR make install