From 915a924fcbbf65e4e55dfde37202fe5f9ca34f33 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 09:17:01 +0100 Subject: [PATCH 01/14] start removing dependencies on potion_type. use item_type where we can. does not compile, is WIP. --- src/alchemy.c | 137 ++++++++++++++++++++++++++++------------ src/alchemy.h | 20 +++--- src/battle.c | 4 +- src/bind_unit.c | 5 +- src/creport.c | 17 +++-- src/economy.c | 21 +++--- src/helpers.c | 2 +- src/items.c | 10 +-- src/kernel/build.test.c | 4 +- src/kernel/item.c | 39 +----------- src/kernel/item.h | 14 +--- src/kernel/unit.c | 6 +- src/kernel/unit.h | 9 ++- src/kernel/unit.test.c | 4 +- src/laws.c | 47 +++++++------- src/report.c | 15 ++--- src/study.c | 13 +--- src/upkeep.c | 14 ++-- src/volcano.c | 4 +- 19 files changed, 191 insertions(+), 194 deletions(-) diff --git a/src/alchemy.c b/src/alchemy.c index 83b4ffcd0..29db8ce85 100644 --- a/src/alchemy.c +++ b/src/alchemy.c @@ -48,7 +48,41 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -/* ------------------------------------------------------------- */ +typedef struct potion_type { + struct potion_type *next; + const struct item_type *itype; + int level; +} potion_type; + +static potion_type *potiontypes; + +static void pt_register(potion_type * ptype) +{ + ptype->next = potiontypes; + potiontypes = ptype; +} + +void new_potiontype(item_type * itype, int level) +{ + potion_type *ptype; + + ptype = (potion_type *)calloc(sizeof(potion_type), 1); + itype->flags |= ITF_POTION; + ptype->itype = itype; + ptype->level = level; + pt_register(ptype); +} + +int potion_level(const item_type *itype) +{ + potion_type *ptype; + for (ptype = potiontypes; ptype; ptype = ptype->next) { + if (ptype->itype == itype) { + return ptype->level; + } + } + return 0; +} void herbsearch(unit * u, int max_take) { @@ -95,33 +129,37 @@ void herbsearch(unit * u, int max_take) } } -static int begin_potion(unit * u, const potion_type * ptype, struct order *ord) +static int begin_potion(unit * u, const item_type * itype, struct order *ord) { - bool rule_multipotion; - assert(ptype != NULL); + static int config; + static bool rule_multipotion; + + assert(itype); + if (config_changed(&config)) { + /* should we allow multiple different potions to be used the same turn? */ + rule_multipotion = config_get_int("rules.magic.multipotion", 0) != 0; + } - /* should we allow multiple different potions to be used the same turn? */ - rule_multipotion = config_get_int("rules.magic.multipotion", 0) != 0; if (!rule_multipotion) { - const potion_type *use = ugetpotionuse(u); - if (use != NULL && use != ptype) { + const item_type *use = ugetpotionuse(u); + if (use != NULL && use != itype) { ADDMSG(&u->faction->msgs, msg_message("errusingpotion", "unit using command", - u, use->itype->rtype, ord)); + u, use->rtype, ord)); return ECUSTOM; } } return 0; } -static void end_potion(unit * u, const potion_type * ptype, int amount) +static void end_potion(unit * u, const item_type * itype, int amount) { - use_pooled(u, ptype->itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, + use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", - "unit potion", u, ptype->itype->rtype)); + "unit potion", u, itype->rtype)); } static int potion_water_of_life(unit * u, region *r, int amount) { @@ -157,6 +195,22 @@ static int potion_water_of_life(unit * u, region *r, int amount) { return amount; } +void show_potions(faction *f, int sklevel) +{ + const potion_type *ptype; + for (ptype = potiontypes; ptype; ptype = ptype->next) { + if (ptype->level > 0 && sklevel == ptype->level * 2) { + attrib *a = a_find(f->attribs, &at_showitem); + while (a && a->type == &at_showitem && a->data.v != ptype) + a = a->next; + if (a == NULL || a->type != &at_showitem) { + a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)ptype->itype; + } + } + } +} + static int potion_healing(unit * u, int amount) { int maxhp = unit_max_hp(u) * u->number; u->hp = u->hp + 400 * amount; @@ -185,42 +239,40 @@ static int potion_power(unit *u, int amount) { return amount; } -static int do_potion(unit * u, region *r, const potion_type * ptype, int amount) +static int do_potion(unit * u, region *r, const item_type * itype, int amount) { - if (ptype == oldpotiontype[P_LIFE]) { + if (itype == oldpotiontype[P_LIFE]) { return potion_water_of_life(u, r, amount); } - else if (ptype == oldpotiontype[P_HEILWASSER]) { + else if (itype == oldpotiontype[P_HEILWASSER]) { return potion_healing(u, amount); } - else if (ptype == oldpotiontype[P_PEOPLE]) { + else if (itype == oldpotiontype[P_PEOPLE]) { return potion_luck(u, r, &at_peasantluck, amount); } - else if (ptype == oldpotiontype[P_HORSE]) { + else if (itype == oldpotiontype[P_HORSE]) { return potion_luck(u, r, &at_horseluck, amount); } - else if (ptype == oldpotiontype[P_MACHT]) { + else if (itype == oldpotiontype[P_MACHT]) { return potion_power(u, amount); } else { - change_effect(u, ptype, 10 * amount); + change_effect(u, itype, 10 * amount); } return amount; } int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) { - const potion_type *ptype = resource2potion(itype->rtype); - - if (oldpotiontype[P_HEAL] && ptype == oldpotiontype[P_HEAL]) { + if (oldpotiontype[P_HEAL] && itype == oldpotiontype[P_HEAL]) { return EUNUSABLE; } else { - int result = begin_potion(u, ptype, ord); + int result = begin_potion(u, itype, ord); if (result) return result; - amount = do_potion(u, u->region, ptype, amount); - end_potion(u, ptype, amount); + amount = do_potion(u, u->region, itype, amount); + end_potion(u, itype, amount); } return 0; } @@ -228,7 +280,7 @@ int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) typedef struct potiondelay { unit *u; region *r; - const potion_type *ptype; + const item_type *itype; int amount; } potiondelay; @@ -245,7 +297,7 @@ static int age_potiondelay(attrib * a, void *owner) { potiondelay *pd = (potiondelay *)a->data.v; UNUSED_ARG(owner); - pd->amount = do_potion(pd->u, pd->r, pd->ptype, pd->amount); + pd->amount = do_potion(pd->u, pd->r, pd->itype, pd->amount); return AT_AGE_REMOVE; } @@ -256,13 +308,13 @@ attrib_type at_potiondelay = { age_potiondelay, 0, 0 }; -static attrib *make_potiondelay(unit * u, const potion_type * ptype, int amount) +static attrib *make_potiondelay(unit * u, const item_type * itype, int amount) { attrib *a = a_new(&at_potiondelay); potiondelay *pd = (potiondelay *)a->data.v; pd->u = u; pd->r = u->region; - pd->ptype = ptype; + pd->itype = itype; pd->amount = amount; return a; } @@ -271,14 +323,13 @@ int use_potion_delayed(unit * u, const item_type * itype, int amount, struct order *ord) { - const potion_type *ptype = resource2potion(itype->rtype); - int result = begin_potion(u, ptype, ord); + int result = begin_potion(u, itype, ord); if (result) return result; - a_add(&u->attribs, make_potiondelay(u, ptype, amount)); + a_add(&u->attribs, make_potiondelay(u, itype, amount)); - end_potion(u, ptype, amount); + end_potion(u, itype, amount); return 0; } @@ -301,7 +352,7 @@ a_writeeffect(const attrib * a, const void *owner, struct storage *store) { effect_data *edata = (effect_data *)a->data.v; UNUSED_ARG(owner); - WRITE_TOK(store, resourcename(edata->type->itype->rtype, 0)); + WRITE_TOK(store, resourcename(edata->type->rtype, 0)); WRITE_INT(store, edata->value); } @@ -318,14 +369,16 @@ static int a_readeffect(attrib * a, void *owner, struct gamedata *data) rtype = rt_find(zText); READ_INT(store, &power); - if (rtype == NULL || rtype->ptype == NULL || power <= 0) { + if (rtype == NULL || rtype->itype == NULL || power <= 0) { return AT_READ_FAIL; } - if (rtype->ptype==oldpotiontype[P_HEAL]) { - /* healing potions used to have long-term effects */ - return AT_READ_FAIL; + if (data->version < NOLANDITEM_VERSION) { + if (rtype->itype == oldpotiontype[P_HEAL]) { + /* healing potions used to have long-term effects */ + return AT_READ_FAIL; + } } - edata->type = rtype->ptype; + edata->type = rtype->itype; edata->value = power; return AT_READ_OK; } @@ -339,7 +392,7 @@ attrib_type at_effect = { a_readeffect, }; -int get_effect(const unit * u, const potion_type * effect) +int get_effect(const unit * u, const item_type * effect) { const attrib *a; for (a = a_find(u->attribs, &at_effect); a != NULL && a->type == &at_effect; @@ -351,7 +404,7 @@ int get_effect(const unit * u, const potion_type * effect) return 0; } -int change_effect(unit * u, const potion_type * effect, int delta) +int change_effect(unit * u, const item_type * effect, int delta) { if (delta != 0) { attrib *a = a_find(u->attribs, &at_effect); diff --git a/src/alchemy.h b/src/alchemy.h index b89d1c27f..f8cebd3db 100644 --- a/src/alchemy.h +++ b/src/alchemy.h @@ -26,9 +26,12 @@ extern "C" { struct potion_type; struct unit; struct region; + struct faction; struct item_type; struct order; + extern struct attrib_type at_effect; + enum { /* Stufe 1 */ P_FAST, @@ -52,22 +55,23 @@ extern "C" { MAX_POTIONS }; + void new_potiontype(struct item_type * itype, int level); + int potion_level(const struct item_type *itype); + void show_potions(struct faction *f, int sklevel); + void herbsearch(struct unit *u, int max); - extern int use_potion(struct unit *u, const struct item_type *itype, + int use_potion(struct unit *u, const struct item_type *itype, int amount, struct order *); - extern int use_potion_delayed(struct unit *u, const struct item_type *itype, + int use_potion_delayed(struct unit *u, const struct item_type *itype, int amount, struct order *); - extern void init_potions(void); - - extern int get_effect(const struct unit *u, const struct potion_type *effect); - extern int change_effect(struct unit *u, const struct potion_type *effect, + int get_effect(const struct unit *u, const struct item_type *effect); + int change_effect(struct unit *u, const struct item_type *effect, int value); - extern struct attrib_type at_effect; /* rausnehmen, sobald man attribute splitten kann: */ typedef struct effect_data { - const struct potion_type *type; + const struct item_type *type; int value; } effect_data; diff --git a/src/battle.c b/src/battle.c index ab5fa2ca1..04cc1904d 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1298,11 +1298,11 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile) } if (oldpotiontype[P_HEAL] && !fval(&df->person[dt.index], FL_HEALING_USED)) { - if (i_get(du->items, oldpotiontype[P_HEAL]->itype) > 0) { + if (i_get(du->items, oldpotiontype[P_HEAL]) > 0) { message *m = msg_message("potionsave", "unit", du); battle_message_faction(b, du->faction, m); msg_release(m); - i_change(&du->items, oldpotiontype[P_HEAL]->itype, -1); + i_change(&du->items, oldpotiontype[P_HEAL], -1); fset(&df->person[dt.index], FL_HEALING_USED); df->person[dt.index].hp = u_race(du)->hitpoints * 5; /* give the person a buffer */ return false; diff --git a/src/bind_unit.c b/src/bind_unit.c index a681a201d..aea404597 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -366,13 +366,10 @@ static int tolua_unit_get_effect(lua_State * L) const unit *self = (unit *)tolua_tousertype(L, 1, 0); const char *potion_name = tolua_tostring(L, 2, 0); int result = -1; - const potion_type *pt_potion; const item_type *it_potion = it_find(potion_name); if (it_potion != NULL) { - pt_potion = it_potion->rtype->ptype; - if (pt_potion != NULL) - result = get_effect(self, pt_potion); + result = get_effect(self, it_potion); } lua_pushinteger(L, result); diff --git a/src/creport.c b/src/creport.c index 4e8fe95b6..912011911 100644 --- a/src/creport.c +++ b/src/creport.c @@ -276,7 +276,7 @@ cr_output_curses(struct stream *out, const faction * viewer, const void *obj, ob else if (a->type == &at_effect && self) { effect_data *data = (effect_data *)a->data.v; if (data->value > 0) { - const char *key = resourcename(data->type->itype->rtype, 0); + const char *key = resourcename(data->type->rtype, 0); if (!header) { header = 1; stream_printf(out, "EFFECTS\n"); @@ -1652,27 +1652,26 @@ report_computer(const char *filename, report_context * ctx, const char *bom) } for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; a = a->next) { - const potion_type *ptype = - resource2potion(((const item_type *)a->data.v)->rtype); + const item_type *itype = (const item_type *)a->data.v; const char *ch; const char *description = NULL; - if (ptype == NULL) + if (itype == NULL) continue; - ch = resourcename(ptype->itype->rtype, 0); + ch = resourcename(itype->rtype, 0); fprintf(F, "TRANK %d\n", str_hash(ch)); fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch))); - fprintf(F, "%d;Stufe\n", ptype->level); + fprintf(F, "%d;Stufe\n", potion_level(itype)); if (description == NULL) { - const char *pname = resourcename(ptype->itype->rtype, 0); + const char *pname = resourcename(itype->rtype, 0); const char *potiontext = mkname("potion", pname); description = LOC(f->locale, potiontext); } fprintf(F, "\"%s\";Beschr\n", description); - if (ptype->itype->construction) { - requirement *m = ptype->itype->construction->materials; + if (itype->construction) { + requirement *m = itype->construction->materials; fprintf(F, "ZUTATEN\n"); diff --git a/src/economy.c b/src/economy.c index ef38ef8af..fcba85955 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1233,14 +1233,14 @@ void split_allocations(region * r) allocations = NULL; } -static void create_potion(unit * u, const potion_type * ptype, int want) +static void create_potion(unit * u, const item_type * itype, int want) { int built; if (want == 0) { - want = maxbuild(u, ptype->itype->construction); + want = maxbuild(u, itype->construction); } - built = build(u, ptype->itype->construction, 0, want, 0); + built = build(u, itype->construction, 0, want, 0); switch (built) { case ELOWSKILL: case ENEEDSKILL: @@ -1253,16 +1253,16 @@ static void create_potion(unit * u, const potion_type * ptype, int want) case ENOMATERIALS: /* something missing from the list of materials */ ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, - ptype->itype->construction, want)); + itype->construction, want)); return; break; default: - i_change(&u->items, ptype->itype, built); + i_change(&u->items, itype, built); if (want == INT_MAX) want = built; ADDMSG(&u->faction->msgs, msg_message("produce", "unit region amount wanted resource", u, u->region, built, want, - ptype->itype->rtype)); + itype->rtype)); break; } } @@ -1277,11 +1277,12 @@ void make_item(unit * u, const item_type * itype, int want) allocate_resource(u, itype->rtype, want); } else { - const potion_type *ptype = resource2potion(itype->rtype); - if (ptype != NULL) - create_potion(u, ptype, want); - else if (itype->construction && itype->construction->materials) + if (itype->flags & ITF_POTION) { + create_potion(u, itype, want); + } + else if (itype->construction && itype->construction->materials) { manufacture(u, itype, want); + } else { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_cannotmake", "")); diff --git a/src/helpers.c b/src/helpers.c index 5015fe401..b5c4c05ba 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -281,7 +281,7 @@ use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord) return result; } lua_pop(L, 1); - if (itype->rtype->ptype) { + if (itype->flags & ITF_POTION) { return use_potion(u, itype, amount, ord); } else { log_error("no such callout: %s", fname); diff --git a/src/items.c b/src/items.c index 94afd8ca1..2a2248279 100644 --- a/src/items.c +++ b/src/items.c @@ -268,7 +268,7 @@ static int use_foolpotion(unit *u, const item_type *itype, int amount, ADDMSG(&u->faction->msgs, msg_message("givedumb", "unit recipient amount", u, target, amount)); - change_effect(target, itype->rtype->ptype, amount); + change_effect(target, itype, amount); use_pooled(u, itype->rtype, GET_DEFAULT, amount); return 0; } @@ -278,7 +278,7 @@ use_bloodpotion(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { if (u->number == 0 || u_race(u) == get_race(RC_DAEMON)) { - change_effect(u, itype->rtype->ptype, 100 * amount); + change_effect(u, itype, 100 * amount); } else { const race *irace = u_irace(u); @@ -302,7 +302,7 @@ struct order *ord) } use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, itype->rtype->ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", "unit potion", u, itype->rtype)); @@ -335,7 +335,7 @@ struct order *ord) } use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(user, itype->rtype->ptype); + usetpotionuse(user, itype); ADDMSG(&user->faction->msgs, msg_message("usepotion", "unit potion", user, itype->rtype)); @@ -408,7 +408,7 @@ static int use_warmthpotion(unit *u, const item_type *itype, } use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, itype->rtype->ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", "unit potion", u, itype->rtype)); diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index 88b1bab8c..6d6c6079f 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -160,12 +160,12 @@ static void test_build_with_ring(CuTest *tc) { static void test_build_with_potion(CuTest *tc) { build_fixture bf = { 0 }; unit *u; - const potion_type *ptype; + const item_type *ptype; const struct resource_type *rtype; u = setup_build(&bf); rtype = bf.cons.materials[0].rtype; - oldpotiontype[P_DOMORE] = ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1); + oldpotiontype[P_DOMORE] = ptype = it_get_or_create(rt_get_or_create("hodor")); assert(rtype && ptype); i_change(&u->items, rtype->itype, 20); diff --git a/src/kernel/item.c b/src/kernel/item.c index 2eabd4aa5..f7ce28835 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -60,7 +60,6 @@ static critbit_tree inames[MAXLOCALES]; static critbit_tree rnames[MAXLOCALES]; static critbit_tree cb_resources; luxury_type *luxurytypes; -potion_type *potiontypes; #define RTYPENAMELEN 24 typedef struct rt_entry { @@ -315,28 +314,8 @@ armor_type *new_armortype(item_type * itype, double penalty, variant magres, return atype; } -static void pt_register(potion_type * ptype) +void it_set_appearance(item_type *itype, const char *appearance) { - ptype->itype->rtype->ptype = ptype; - ptype->next = potiontypes; - potiontypes = ptype; -} - -potion_type *new_potiontype(item_type * itype, int level) -{ - potion_type *ptype; - - assert(resource2potion(itype->rtype) == NULL); - - ptype = (potion_type *)calloc(sizeof(potion_type), 1); - ptype->itype = itype; - ptype->level = level; - pt_register(ptype); - - return ptype; -} - -void it_set_appearance(item_type *itype, const char *appearance) { assert(itype); assert(itype->rtype); if (appearance) { @@ -377,18 +356,6 @@ const luxury_type *resource2luxury(const resource_type * rtype) #endif } -const potion_type *resource2potion(const resource_type * rtype) -{ -#ifdef AT_PTYPE - attrib *a = a_find(rtype->attribs, &at_ptype); - if (a) - return (const potion_type *)a->data.v; - return NULL; -#else - return rtype->ptype; -#endif -} - resource_type *rt_find(const char *name) { const void *match; @@ -573,7 +540,7 @@ item *i_new(const item_type * itype, int size) return i; } -const potion_type *oldpotiontype[MAX_POTIONS + 1]; +const item_type *oldpotiontype[MAX_POTIONS + 1]; /*** alte items ***/ @@ -677,7 +644,7 @@ static void init_oldpotions(void) for (p = 0; p != MAX_POTIONS; ++p) { item_type *itype = it_find(potionnames[p]); if (itype != NULL) { - oldpotiontype[p] = itype->rtype->ptype; + oldpotiontype[p] = itype; } } } diff --git a/src/kernel/item.h b/src/kernel/item.h index cc5991ed6..c289005df 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -80,7 +80,6 @@ extern "C" { struct resource_mod *modifiers; /* --- pointers --- */ struct item_type *itype; - struct potion_type *ptype; struct luxury_type *ltype; struct weapon_type *wtype; struct armor_type *atype; @@ -99,6 +98,7 @@ extern "C" { #define ITF_ANIMAL 0x0010 /* an animal */ #define ITF_VEHICLE 0x0020 /* a vehicle, drawn by two animals */ #define ITF_CANUSE 0x0040 /* can be used with use_item_fun callout */ +#define ITF_POTION 0x0080 /* is a potion (for use_potion) */ /* error codes for item_type::use */ #define ECUSTOM -1 @@ -128,13 +128,6 @@ extern "C" { } luxury_type; extern luxury_type *luxurytypes; - typedef struct potion_type { - struct potion_type *next; - const item_type *itype; - int level; - } potion_type; - extern potion_type *potiontypes; - #define WMF_WALKING 0x0001 #define WMF_RIDING 0x0002 #define WMF_ANYONE 0x000F /* convenience */ @@ -206,7 +199,6 @@ extern "C" { const resource_type *item2resource(const item_type * i); const weapon_type *resource2weapon(const resource_type * i); - const potion_type *resource2potion(const resource_type * i); const luxury_type *resource2luxury(const resource_type * i); item **i_find(item ** pi, const item_type * it); @@ -234,8 +226,6 @@ extern "C" { skill_t sk); armor_type *new_armortype(item_type * itype, double penalty, variant magres, int prot, unsigned int flags); - potion_type *new_potiontype(item_type * itype, int level); - /* these constants are used with get_resourcetype. * The order of the enum is not important for stored data. @@ -285,7 +275,7 @@ extern "C" { NORESOURCE = -1 } resource_t; - extern const struct potion_type *oldpotiontype[]; + extern const struct item_type *oldpotiontype[]; const struct resource_type *get_resourcetype(resource_t rt); struct item *item_spoil(const struct race *rc, int size); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 28f227ff5..fb07d782e 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -585,7 +585,7 @@ attrib_type at_potionuser = { NO_READ }; -void usetpotionuse(unit * u, const potion_type * ptype) +void usetpotionuse(unit * u, const item_type * ptype) { attrib *a = a_find(u->attribs, &at_potionuser); if (!a) @@ -593,12 +593,12 @@ void usetpotionuse(unit * u, const potion_type * ptype) a->data.v = (void *)ptype; } -const potion_type *ugetpotionuse(const unit * u) +const item_type *ugetpotionuse(const unit * u) { attrib *a = a_find(u->attribs, &at_potionuser); if (!a) return NULL; - return (const potion_type *)a->data.v; + return (const item_type *)a->data.v; } /*********************/ diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 53f9836db..91a3ec930 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -28,11 +28,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif -#define MAXUNITS 1048573 /* must be prime for hashing. 524287 was >90% full */ struct skill; struct item; struct sc_mage; struct gamedata; + struct item_type; + +#define MAXUNITS 1048573 /* should be prime for hashing. 524287 was >90% full */ + #define UFL_DEAD (1<<0) #define UFL_ISNEW (1<<1) /* 2 */ #define UFL_LONGACTION (1<<2) /* 4 */ @@ -147,8 +150,8 @@ extern "C" { const char *uprivate(const struct unit *u); void usetprivate(struct unit *u, const char *c); - const struct potion_type *ugetpotionuse(const struct unit *u); /* benutzt u einein trank? */ - void usetpotionuse(struct unit *u, const struct potion_type *p); /* u benutzt trank p (es darf halt nur einer pro runde) */ + const struct item_type *ugetpotionuse(const struct unit *u); /* benutzt u einein trank? */ + void usetpotionuse(struct unit *u, const struct item_type *p); /* u benutzt trank p (es darf halt nur einer pro runde) */ bool ucontact(const struct unit *u, const struct unit *u2); void usetcontact(struct unit *u, const struct unit *c); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 5694fb79d..b75d6829d 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -101,11 +101,11 @@ static void test_remove_units_with_dead_faction(CuTest *tc) { static void test_scale_number(CuTest *tc) { unit *u; - const struct potion_type *ptype; + const struct item_type *ptype; test_setup(); test_create_world(); - ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1); + ptype = it_get_or_create(rt_get_or_create("hodor")); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); change_effect(u, ptype, 1); u->hp = 35; diff --git a/src/laws.c b/src/laws.c index bccefab20..faf680272 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2252,17 +2252,17 @@ static void display_item(unit * u, const item_type * itype) itype->weight, itype->rtype, info)); } -static void display_potion(unit * u, const potion_type * ptype) +static void display_potion(unit * u, const item_type * itype) { faction * f = u->faction; attrib *a; a = a_find(f->attribs, &at_showitem); - while (a && a->data.v != ptype) + while (a && a->data.v != itype) a = a->next; if (!a) { a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; + a->data.v = (void *)itype; } } @@ -2429,21 +2429,16 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { err = 36; /* we do not have this item? */ if (i <= 0) { /* we don't have the item, but it may be a potion that we know */ - const potion_type *ptype = resource2potion(item2resource(itype)); - if (ptype) { - if (2 * ptype->level > effskill(u, SK_ALCHEMY, 0)) { - itype = NULL; - } - } else { + int level = potion_level(itype); + if (2 * level > effskill(u, SK_ALCHEMY, 0)) { itype = NULL; } } } if (itype) { - const potion_type *ptype = itype->rtype->ptype; - if (ptype) { - display_potion(u, ptype); + if (itype->flags & ITF_POTION) { + display_potion(u, itype); } else { display_item(u, itype); @@ -2471,26 +2466,30 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { cmistake(u, ord, err, MSG_EVENT); } +bool display_potions(unit *u) +{ + int skill = effskill(u, SK_ALCHEMY, 0); + int c = 0; + const potion_type *ptype; + for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { + if (ptype->level * 2 <= skill) { + display_potion(u, ptype); + ++c; + } + } + return (c > 0); +} + static void reshow(unit * u, struct order *ord, const char *s, param_t p) { - int skill, c; - const potion_type *ptype; - switch (p) { case P_ZAUBER: a_removeall(&u->faction->attribs, &at_seenspell); break; case P_POTIONS: - skill = effskill(u, SK_ALCHEMY, 0); - c = 0; - for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { - if (ptype->level * 2 <= skill) { - display_potion(u, ptype); - ++c; - } - } - if (c == 0) + if (!display_potions(u)) { cmistake(u, ord, 285, MSG_EVENT); + } break; case NOPARAM: reshow_other(u, ord, s); diff --git a/src/report.c b/src/report.c index e154ab045..25a92ede2 100644 --- a/src/report.c +++ b/src/report.c @@ -578,7 +578,7 @@ nr_curses_i(struct stream *out, int indent, const faction *viewer, objtype_t typ effect_data *data = (effect_data *)a->data.v; if (data->value > 0) { msg = msg_message("nr_potion_effect", "potion left", - data->type->itype->rtype, data->value); + data->type->rtype, data->value); } } if (msg) { @@ -2198,11 +2198,10 @@ report_plaintext(const char *filename, report_context * ctx, CHECK_ERRNO(); for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; a = a->next) { - const potion_type *ptype = - resource2potion(((const item_type *)a->data.v)->rtype); + const item_type *itype = (const item_type *)a->data.v; const char *description = NULL; - if (ptype != NULL) { - const char *pname = resourcename(ptype->itype->rtype, 0); + if (itype) { + const char *pname = resourcename(itype->rtype, 0); if (ch == 0) { newline(out); @@ -2213,7 +2212,7 @@ report_plaintext(const char *filename, report_context * ctx, newline(out); centre(out, LOC(f->locale, pname), true); snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"), - ptype->level); + potion_level(itype)); centre(out, buf, true); newline(out); @@ -2223,8 +2222,8 @@ report_plaintext(const char *filename, report_context * ctx, if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - if (ptype->itype->construction) { - requirement *rm = ptype->itype->construction->materials; + if (itype->construction) { + requirement *rm = itype->construction->materials; while (rm->number) { bytes = (int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size); diff --git a/src/study.c b/src/study.c index c5d657c48..f446e34ab 100644 --- a/src/study.c +++ b/src/study.c @@ -779,21 +779,10 @@ int study_cmd(unit * u, order * ord) /* Spruchlistenaktualiesierung ist in Regeneration */ if (sk == SK_ALCHEMY) { - const potion_type *ptype; faction *f = u->faction; int skill = effskill(u, SK_ALCHEMY, 0); if (skill > maxalchemy) { - for (ptype = potiontypes; ptype; ptype = ptype->next) { - if (skill == ptype->level * 2) { - a = a_find(f->attribs, &at_showitem); - while (a && a->type == &at_showitem && a->data.v != ptype) - a = a->next; - if (a == NULL || a->type != &at_showitem) { - a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; - } - } - } + show_potions(f, skill); } } else if (sk == SK_MAGIC) { diff --git a/src/upkeep.c b/src/upkeep.c index 3bd77710e..6748d620c 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -245,26 +245,22 @@ void get_food(region * r) int hungry = u->number; /* use peasantblood before eating the peasants themselves */ - const struct potion_type *pt_blood = 0; - const resource_type *rt_blood = rt_find("peasantblood"); - if (rt_blood) { - pt_blood = rt_blood->ptype; - } - if (pt_blood) { + const struct item_type *it_blood = it_find("peasantblood"); + if (it_blood) { /* always start with the unit itself, then the first known unit that may have some blood */ unit *donor = u; while (donor != NULL && hungry > 0) { - int blut = get_effect(donor, pt_blood); + int blut = get_effect(donor, it_blood); if (hungry < blut) blut = hungry; if (blut > 0) { - change_effect(donor, pt_blood, -blut); + change_effect(donor, it_blood, -blut); hungry -= blut; } if (donor == u) donor = r->units; while (donor != NULL) { if (u_race(donor) == rc_demon && donor != u) { - if (get_effect(donor, pt_blood)) { + if (get_effect(donor, it_blood)) { /* if he's in our faction, drain him: */ if (donor->faction == u->faction) break; diff --git a/src/volcano.c b/src/volcano.c index d90ef47ee..df70a864f 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -133,8 +133,8 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic) change_effect(u, oldpotiontype[P_HEAL], -1); heiltrank = 1; } - else if (i_get(u->items, oldpotiontype[P_HEAL]->itype) > 0) { - i_change(&u->items, oldpotiontype[P_HEAL]->itype, -1); + else if (i_get(u->items, oldpotiontype[P_HEAL]) > 0) { + i_change(&u->items, oldpotiontype[P_HEAL], -1); change_effect(u, oldpotiontype[P_HEAL], 3); heiltrank = 1; } From 4ef7009de7e613a0174e75d99332f8621c5c71e5 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 10:01:06 +0100 Subject: [PATCH 02/14] compiles, test fails, xmlreader includes need fixing --- src/alchemy.c | 14 ++++++++++++++ src/alchemy.h | 5 ++++- src/kernel/item.c | 15 +++++++++++++++ src/kernel/item.h | 6 ++++-- src/kernel/xmlreader.c | 9 +++++---- src/laws.c | 32 ++++---------------------------- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/alchemy.c b/src/alchemy.c index 29db8ce85..cf3d2b376 100644 --- a/src/alchemy.c +++ b/src/alchemy.c @@ -434,3 +434,17 @@ int change_effect(unit * u, const item_type * effect, int delta) log_error("change effect with delta==0 for unit %s\n", itoa36(u->no)); return 0; } + +bool display_potions(struct unit *u) +{ + int skill = effskill(u, SK_ALCHEMY, 0); + int c = 0; + const potion_type *ptype; + for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { + if (ptype->level * 2 <= skill) { + show_item(u, ptype->itype); + ++c; + } + } + return (c > 0); +} diff --git a/src/alchemy.h b/src/alchemy.h index f8cebd3db..d183cacd0 100644 --- a/src/alchemy.h +++ b/src/alchemy.h @@ -19,6 +19,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef H_KRNL_ALCHEMY_H #define H_KRNL_ALCHEMY_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -68,8 +70,9 @@ extern "C" { int get_effect(const struct unit *u, const struct item_type *effect); int change_effect(struct unit *u, const struct item_type *effect, int value); + bool display_potions(struct unit *u); - /* rausnehmen, sobald man attribute splitten kann: */ + /* TODO: rausnehmen, sobald man attribute splitten kann: */ typedef struct effect_data { const struct item_type *type; int value; diff --git a/src/kernel/item.c b/src/kernel/item.c index f7ce28835..74951895a 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -980,3 +980,18 @@ void register_resources(void) register_function((pf_generic)res_changehp, "changehp"); register_function((pf_generic)res_changeaura, "changeaura"); } + +void show_item(unit * u, const item_type * itype) +{ + faction * f = u->faction; + attrib *a; + + a = a_find(f->attribs, &at_showitem); + while (a && a->data.v != itype) + a = a->next; + if (!a) { + a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)itype; + } +} + diff --git a/src/kernel/item.h b/src/kernel/item.h index c289005df..e7bfef7cc 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -276,6 +276,10 @@ extern "C" { } resource_t; extern const struct item_type *oldpotiontype[]; + extern struct attrib_type at_showitem; /* show this potion's description */ + + void show_item(struct unit * u, const struct item_type * itype); + const struct resource_type *get_resourcetype(resource_t rt); struct item *item_spoil(const struct race *rc, int size); @@ -285,8 +289,6 @@ extern "C" { int set_money(struct unit *, int); int change_money(struct unit *, int); - extern struct attrib_type at_showitem; /* show this potion's description */ - void register_resources(void); void init_resources(void); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index f086af3ef..1ef17b2e7 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -32,6 +32,8 @@ without prior permission by the authors of Eressea. #include "prefix.h" #include "move.h" +/* TODO: core code should not include these files: */ +#include "alchemy.h" #include "vortex.h" #include @@ -483,12 +485,11 @@ static int parse_ships(xmlDocPtr doc) return 0; } -static potion_type *xml_readpotion(xmlXPathContextPtr xpath, item_type * itype) +static void xml_readpotion(xmlXPathContextPtr xpath, item_type * itype) { int level = xml_ivalue(xpath->node, "level", 0); - assert(level > 0); - return new_potiontype(itype, level); + new_potiontype(itype, level); } static luxury_type *xml_readluxury(xmlXPathContextPtr xpath, item_type * itype) @@ -741,7 +742,7 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype) itype->flags |= ITF_CANUSE; } xpath->node = result->nodesetval->nodeTab[0]; - rtype->ptype = xml_readpotion(xpath, itype); + xml_readpotion(xpath, itype); } xmlXPathFreeObject(result); diff --git a/src/laws.c b/src/laws.c index faf680272..47577d461 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2234,6 +2234,10 @@ int send_cmd(unit * u, struct order *ord) return 0; } +static void display_potion(unit * u, const item_type * itype) { + show_item(u, itype); +} + static void display_item(unit * u, const item_type * itype) { faction * f = u->faction; @@ -2252,20 +2256,6 @@ static void display_item(unit * u, const item_type * itype) itype->weight, itype->rtype, info)); } -static void display_potion(unit * u, const item_type * itype) -{ - faction * f = u->faction; - attrib *a; - - a = a_find(f->attribs, &at_showitem); - while (a && a->data.v != itype) - a = a->next; - if (!a) { - a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)itype; - } -} - static void display_race(unit * u, const race * rc) { faction * f = u->faction; @@ -2466,20 +2456,6 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { cmistake(u, ord, err, MSG_EVENT); } -bool display_potions(unit *u) -{ - int skill = effskill(u, SK_ALCHEMY, 0); - int c = 0; - const potion_type *ptype; - for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { - if (ptype->level * 2 <= skill) { - display_potion(u, ptype); - ++c; - } - } - return (c > 0); -} - static void reshow(unit * u, struct order *ord, const char *s, param_t p) { switch (p) { From 4d38a40e96541cf00cdacd81e1e079084a76a9b7 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 10:06:13 +0100 Subject: [PATCH 03/14] better testing for is_potion (should be a function) --- src/laws.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/laws.c b/src/laws.c index 47577d461..75ab7372a 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2417,10 +2417,10 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { int i = i_get(u->items, itype); err = 36; /* we do not have this item? */ - if (i <= 0) { - /* we don't have the item, but it may be a potion that we know */ + if (i <= 0 && (itype->flags & ITF_POTION)) { + /* we don't have the item, but it is a potion. do we know it? */ int level = potion_level(itype); - if (2 * level > effskill(u, SK_ALCHEMY, 0)) { + if (level > 0 && 2 * level > effskill(u, SK_ALCHEMY, 0)) { itype = NULL; } } @@ -2452,8 +2452,9 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { found = true; } } - if (!found) - cmistake(u, ord, err, MSG_EVENT); + if (!found) { + cmistake(u, ord, err, MSG_EVENT); + } } static void reshow(unit * u, struct order *ord, const char *s, param_t p) From efec41ca56e99e99d7954ac31175f0da352f9120 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 20:45:59 +0100 Subject: [PATCH 04/14] Fix broken SHOW logic for potions. --- src/laws.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/laws.c b/src/laws.c index 75ab7372a..dbb99adc1 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2414,26 +2414,22 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { if (itype) { /* if this is a potion, we need the right alchemy skill */ - int i = i_get(u->items, itype); - err = 36; /* we do not have this item? */ - if (i <= 0 && (itype->flags & ITF_POTION)) { + if (itype->flags & ITF_POTION) { /* we don't have the item, but it is a potion. do we know it? */ int level = potion_level(itype); - if (level > 0 && 2 * level > effskill(u, SK_ALCHEMY, 0)) { - itype = NULL; + if (level > 0 && 2 * level <= effskill(u, SK_ALCHEMY, 0)) { + display_potion(u, itype); + found = true; } } - } - - if (itype) { - if (itype->flags & ITF_POTION) { - display_potion(u, itype); - } else { - display_item(u, itype); + int i = i_get(u->items, itype); + if (i > 0) { + found = true; + display_item(u, itype); + } } - found = true; } if (sp) { From 3d69f4e372b6658ff28e762fd330bb6aab0cd350 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 09:17:01 +0100 Subject: [PATCH 05/14] start removing dependencies on potion_type. use item_type where we can. does not compile, is WIP. --- src/alchemy.c | 137 ++++++++++++++++++++++++++++------------ src/alchemy.h | 20 +++--- src/battle.c | 4 +- src/bind_unit.c | 5 +- src/creport.c | 17 +++-- src/economy.c | 21 +++--- src/helpers.c | 2 +- src/items.c | 10 +-- src/kernel/build.test.c | 4 +- src/kernel/item.c | 39 +----------- src/kernel/item.h | 14 +--- src/kernel/unit.c | 6 +- src/kernel/unit.h | 9 ++- src/kernel/unit.test.c | 4 +- src/laws.c | 47 +++++++------- src/report.c | 15 ++--- src/study.c | 13 +--- src/upkeep.c | 14 ++-- src/volcano.c | 4 +- 19 files changed, 191 insertions(+), 194 deletions(-) diff --git a/src/alchemy.c b/src/alchemy.c index 83b4ffcd0..29db8ce85 100644 --- a/src/alchemy.c +++ b/src/alchemy.c @@ -48,7 +48,41 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include -/* ------------------------------------------------------------- */ +typedef struct potion_type { + struct potion_type *next; + const struct item_type *itype; + int level; +} potion_type; + +static potion_type *potiontypes; + +static void pt_register(potion_type * ptype) +{ + ptype->next = potiontypes; + potiontypes = ptype; +} + +void new_potiontype(item_type * itype, int level) +{ + potion_type *ptype; + + ptype = (potion_type *)calloc(sizeof(potion_type), 1); + itype->flags |= ITF_POTION; + ptype->itype = itype; + ptype->level = level; + pt_register(ptype); +} + +int potion_level(const item_type *itype) +{ + potion_type *ptype; + for (ptype = potiontypes; ptype; ptype = ptype->next) { + if (ptype->itype == itype) { + return ptype->level; + } + } + return 0; +} void herbsearch(unit * u, int max_take) { @@ -95,33 +129,37 @@ void herbsearch(unit * u, int max_take) } } -static int begin_potion(unit * u, const potion_type * ptype, struct order *ord) +static int begin_potion(unit * u, const item_type * itype, struct order *ord) { - bool rule_multipotion; - assert(ptype != NULL); + static int config; + static bool rule_multipotion; + + assert(itype); + if (config_changed(&config)) { + /* should we allow multiple different potions to be used the same turn? */ + rule_multipotion = config_get_int("rules.magic.multipotion", 0) != 0; + } - /* should we allow multiple different potions to be used the same turn? */ - rule_multipotion = config_get_int("rules.magic.multipotion", 0) != 0; if (!rule_multipotion) { - const potion_type *use = ugetpotionuse(u); - if (use != NULL && use != ptype) { + const item_type *use = ugetpotionuse(u); + if (use != NULL && use != itype) { ADDMSG(&u->faction->msgs, msg_message("errusingpotion", "unit using command", - u, use->itype->rtype, ord)); + u, use->rtype, ord)); return ECUSTOM; } } return 0; } -static void end_potion(unit * u, const potion_type * ptype, int amount) +static void end_potion(unit * u, const item_type * itype, int amount) { - use_pooled(u, ptype->itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, + use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", - "unit potion", u, ptype->itype->rtype)); + "unit potion", u, itype->rtype)); } static int potion_water_of_life(unit * u, region *r, int amount) { @@ -157,6 +195,22 @@ static int potion_water_of_life(unit * u, region *r, int amount) { return amount; } +void show_potions(faction *f, int sklevel) +{ + const potion_type *ptype; + for (ptype = potiontypes; ptype; ptype = ptype->next) { + if (ptype->level > 0 && sklevel == ptype->level * 2) { + attrib *a = a_find(f->attribs, &at_showitem); + while (a && a->type == &at_showitem && a->data.v != ptype) + a = a->next; + if (a == NULL || a->type != &at_showitem) { + a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)ptype->itype; + } + } + } +} + static int potion_healing(unit * u, int amount) { int maxhp = unit_max_hp(u) * u->number; u->hp = u->hp + 400 * amount; @@ -185,42 +239,40 @@ static int potion_power(unit *u, int amount) { return amount; } -static int do_potion(unit * u, region *r, const potion_type * ptype, int amount) +static int do_potion(unit * u, region *r, const item_type * itype, int amount) { - if (ptype == oldpotiontype[P_LIFE]) { + if (itype == oldpotiontype[P_LIFE]) { return potion_water_of_life(u, r, amount); } - else if (ptype == oldpotiontype[P_HEILWASSER]) { + else if (itype == oldpotiontype[P_HEILWASSER]) { return potion_healing(u, amount); } - else if (ptype == oldpotiontype[P_PEOPLE]) { + else if (itype == oldpotiontype[P_PEOPLE]) { return potion_luck(u, r, &at_peasantluck, amount); } - else if (ptype == oldpotiontype[P_HORSE]) { + else if (itype == oldpotiontype[P_HORSE]) { return potion_luck(u, r, &at_horseluck, amount); } - else if (ptype == oldpotiontype[P_MACHT]) { + else if (itype == oldpotiontype[P_MACHT]) { return potion_power(u, amount); } else { - change_effect(u, ptype, 10 * amount); + change_effect(u, itype, 10 * amount); } return amount; } int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) { - const potion_type *ptype = resource2potion(itype->rtype); - - if (oldpotiontype[P_HEAL] && ptype == oldpotiontype[P_HEAL]) { + if (oldpotiontype[P_HEAL] && itype == oldpotiontype[P_HEAL]) { return EUNUSABLE; } else { - int result = begin_potion(u, ptype, ord); + int result = begin_potion(u, itype, ord); if (result) return result; - amount = do_potion(u, u->region, ptype, amount); - end_potion(u, ptype, amount); + amount = do_potion(u, u->region, itype, amount); + end_potion(u, itype, amount); } return 0; } @@ -228,7 +280,7 @@ int use_potion(unit * u, const item_type * itype, int amount, struct order *ord) typedef struct potiondelay { unit *u; region *r; - const potion_type *ptype; + const item_type *itype; int amount; } potiondelay; @@ -245,7 +297,7 @@ static int age_potiondelay(attrib * a, void *owner) { potiondelay *pd = (potiondelay *)a->data.v; UNUSED_ARG(owner); - pd->amount = do_potion(pd->u, pd->r, pd->ptype, pd->amount); + pd->amount = do_potion(pd->u, pd->r, pd->itype, pd->amount); return AT_AGE_REMOVE; } @@ -256,13 +308,13 @@ attrib_type at_potiondelay = { age_potiondelay, 0, 0 }; -static attrib *make_potiondelay(unit * u, const potion_type * ptype, int amount) +static attrib *make_potiondelay(unit * u, const item_type * itype, int amount) { attrib *a = a_new(&at_potiondelay); potiondelay *pd = (potiondelay *)a->data.v; pd->u = u; pd->r = u->region; - pd->ptype = ptype; + pd->itype = itype; pd->amount = amount; return a; } @@ -271,14 +323,13 @@ int use_potion_delayed(unit * u, const item_type * itype, int amount, struct order *ord) { - const potion_type *ptype = resource2potion(itype->rtype); - int result = begin_potion(u, ptype, ord); + int result = begin_potion(u, itype, ord); if (result) return result; - a_add(&u->attribs, make_potiondelay(u, ptype, amount)); + a_add(&u->attribs, make_potiondelay(u, itype, amount)); - end_potion(u, ptype, amount); + end_potion(u, itype, amount); return 0; } @@ -301,7 +352,7 @@ a_writeeffect(const attrib * a, const void *owner, struct storage *store) { effect_data *edata = (effect_data *)a->data.v; UNUSED_ARG(owner); - WRITE_TOK(store, resourcename(edata->type->itype->rtype, 0)); + WRITE_TOK(store, resourcename(edata->type->rtype, 0)); WRITE_INT(store, edata->value); } @@ -318,14 +369,16 @@ static int a_readeffect(attrib * a, void *owner, struct gamedata *data) rtype = rt_find(zText); READ_INT(store, &power); - if (rtype == NULL || rtype->ptype == NULL || power <= 0) { + if (rtype == NULL || rtype->itype == NULL || power <= 0) { return AT_READ_FAIL; } - if (rtype->ptype==oldpotiontype[P_HEAL]) { - /* healing potions used to have long-term effects */ - return AT_READ_FAIL; + if (data->version < NOLANDITEM_VERSION) { + if (rtype->itype == oldpotiontype[P_HEAL]) { + /* healing potions used to have long-term effects */ + return AT_READ_FAIL; + } } - edata->type = rtype->ptype; + edata->type = rtype->itype; edata->value = power; return AT_READ_OK; } @@ -339,7 +392,7 @@ attrib_type at_effect = { a_readeffect, }; -int get_effect(const unit * u, const potion_type * effect) +int get_effect(const unit * u, const item_type * effect) { const attrib *a; for (a = a_find(u->attribs, &at_effect); a != NULL && a->type == &at_effect; @@ -351,7 +404,7 @@ int get_effect(const unit * u, const potion_type * effect) return 0; } -int change_effect(unit * u, const potion_type * effect, int delta) +int change_effect(unit * u, const item_type * effect, int delta) { if (delta != 0) { attrib *a = a_find(u->attribs, &at_effect); diff --git a/src/alchemy.h b/src/alchemy.h index b89d1c27f..f8cebd3db 100644 --- a/src/alchemy.h +++ b/src/alchemy.h @@ -26,9 +26,12 @@ extern "C" { struct potion_type; struct unit; struct region; + struct faction; struct item_type; struct order; + extern struct attrib_type at_effect; + enum { /* Stufe 1 */ P_FAST, @@ -52,22 +55,23 @@ extern "C" { MAX_POTIONS }; + void new_potiontype(struct item_type * itype, int level); + int potion_level(const struct item_type *itype); + void show_potions(struct faction *f, int sklevel); + void herbsearch(struct unit *u, int max); - extern int use_potion(struct unit *u, const struct item_type *itype, + int use_potion(struct unit *u, const struct item_type *itype, int amount, struct order *); - extern int use_potion_delayed(struct unit *u, const struct item_type *itype, + int use_potion_delayed(struct unit *u, const struct item_type *itype, int amount, struct order *); - extern void init_potions(void); - - extern int get_effect(const struct unit *u, const struct potion_type *effect); - extern int change_effect(struct unit *u, const struct potion_type *effect, + int get_effect(const struct unit *u, const struct item_type *effect); + int change_effect(struct unit *u, const struct item_type *effect, int value); - extern struct attrib_type at_effect; /* rausnehmen, sobald man attribute splitten kann: */ typedef struct effect_data { - const struct potion_type *type; + const struct item_type *type; int value; } effect_data; diff --git a/src/battle.c b/src/battle.c index ab5fa2ca1..04cc1904d 100644 --- a/src/battle.c +++ b/src/battle.c @@ -1298,11 +1298,11 @@ terminate(troop dt, troop at, int type, const char *damage, bool missile) } if (oldpotiontype[P_HEAL] && !fval(&df->person[dt.index], FL_HEALING_USED)) { - if (i_get(du->items, oldpotiontype[P_HEAL]->itype) > 0) { + if (i_get(du->items, oldpotiontype[P_HEAL]) > 0) { message *m = msg_message("potionsave", "unit", du); battle_message_faction(b, du->faction, m); msg_release(m); - i_change(&du->items, oldpotiontype[P_HEAL]->itype, -1); + i_change(&du->items, oldpotiontype[P_HEAL], -1); fset(&df->person[dt.index], FL_HEALING_USED); df->person[dt.index].hp = u_race(du)->hitpoints * 5; /* give the person a buffer */ return false; diff --git a/src/bind_unit.c b/src/bind_unit.c index a681a201d..aea404597 100644 --- a/src/bind_unit.c +++ b/src/bind_unit.c @@ -366,13 +366,10 @@ static int tolua_unit_get_effect(lua_State * L) const unit *self = (unit *)tolua_tousertype(L, 1, 0); const char *potion_name = tolua_tostring(L, 2, 0); int result = -1; - const potion_type *pt_potion; const item_type *it_potion = it_find(potion_name); if (it_potion != NULL) { - pt_potion = it_potion->rtype->ptype; - if (pt_potion != NULL) - result = get_effect(self, pt_potion); + result = get_effect(self, it_potion); } lua_pushinteger(L, result); diff --git a/src/creport.c b/src/creport.c index 4e8fe95b6..912011911 100644 --- a/src/creport.c +++ b/src/creport.c @@ -276,7 +276,7 @@ cr_output_curses(struct stream *out, const faction * viewer, const void *obj, ob else if (a->type == &at_effect && self) { effect_data *data = (effect_data *)a->data.v; if (data->value > 0) { - const char *key = resourcename(data->type->itype->rtype, 0); + const char *key = resourcename(data->type->rtype, 0); if (!header) { header = 1; stream_printf(out, "EFFECTS\n"); @@ -1652,27 +1652,26 @@ report_computer(const char *filename, report_context * ctx, const char *bom) } for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; a = a->next) { - const potion_type *ptype = - resource2potion(((const item_type *)a->data.v)->rtype); + const item_type *itype = (const item_type *)a->data.v; const char *ch; const char *description = NULL; - if (ptype == NULL) + if (itype == NULL) continue; - ch = resourcename(ptype->itype->rtype, 0); + ch = resourcename(itype->rtype, 0); fprintf(F, "TRANK %d\n", str_hash(ch)); fprintf(F, "\"%s\";Name\n", translate(ch, LOC(f->locale, ch))); - fprintf(F, "%d;Stufe\n", ptype->level); + fprintf(F, "%d;Stufe\n", potion_level(itype)); if (description == NULL) { - const char *pname = resourcename(ptype->itype->rtype, 0); + const char *pname = resourcename(itype->rtype, 0); const char *potiontext = mkname("potion", pname); description = LOC(f->locale, potiontext); } fprintf(F, "\"%s\";Beschr\n", description); - if (ptype->itype->construction) { - requirement *m = ptype->itype->construction->materials; + if (itype->construction) { + requirement *m = itype->construction->materials; fprintf(F, "ZUTATEN\n"); diff --git a/src/economy.c b/src/economy.c index ef38ef8af..fcba85955 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1233,14 +1233,14 @@ void split_allocations(region * r) allocations = NULL; } -static void create_potion(unit * u, const potion_type * ptype, int want) +static void create_potion(unit * u, const item_type * itype, int want) { int built; if (want == 0) { - want = maxbuild(u, ptype->itype->construction); + want = maxbuild(u, itype->construction); } - built = build(u, ptype->itype->construction, 0, want, 0); + built = build(u, itype->construction, 0, want, 0); switch (built) { case ELOWSKILL: case ENEEDSKILL: @@ -1253,16 +1253,16 @@ static void create_potion(unit * u, const potion_type * ptype, int want) case ENOMATERIALS: /* something missing from the list of materials */ ADDMSG(&u->faction->msgs, msg_materials_required(u, u->thisorder, - ptype->itype->construction, want)); + itype->construction, want)); return; break; default: - i_change(&u->items, ptype->itype, built); + i_change(&u->items, itype, built); if (want == INT_MAX) want = built; ADDMSG(&u->faction->msgs, msg_message("produce", "unit region amount wanted resource", u, u->region, built, want, - ptype->itype->rtype)); + itype->rtype)); break; } } @@ -1277,11 +1277,12 @@ void make_item(unit * u, const item_type * itype, int want) allocate_resource(u, itype->rtype, want); } else { - const potion_type *ptype = resource2potion(itype->rtype); - if (ptype != NULL) - create_potion(u, ptype, want); - else if (itype->construction && itype->construction->materials) + if (itype->flags & ITF_POTION) { + create_potion(u, itype, want); + } + else if (itype->construction && itype->construction->materials) { manufacture(u, itype, want); + } else { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "error_cannotmake", "")); diff --git a/src/helpers.c b/src/helpers.c index 5015fe401..b5c4c05ba 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -281,7 +281,7 @@ use_item_lua(unit *u, const item_type *itype, int amount, struct order *ord) return result; } lua_pop(L, 1); - if (itype->rtype->ptype) { + if (itype->flags & ITF_POTION) { return use_potion(u, itype, amount, ord); } else { log_error("no such callout: %s", fname); diff --git a/src/items.c b/src/items.c index 94afd8ca1..2a2248279 100644 --- a/src/items.c +++ b/src/items.c @@ -268,7 +268,7 @@ static int use_foolpotion(unit *u, const item_type *itype, int amount, ADDMSG(&u->faction->msgs, msg_message("givedumb", "unit recipient amount", u, target, amount)); - change_effect(target, itype->rtype->ptype, amount); + change_effect(target, itype, amount); use_pooled(u, itype->rtype, GET_DEFAULT, amount); return 0; } @@ -278,7 +278,7 @@ use_bloodpotion(struct unit *u, const struct item_type *itype, int amount, struct order *ord) { if (u->number == 0 || u_race(u) == get_race(RC_DAEMON)) { - change_effect(u, itype->rtype->ptype, 100 * amount); + change_effect(u, itype, 100 * amount); } else { const race *irace = u_irace(u); @@ -302,7 +302,7 @@ struct order *ord) } use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, itype->rtype->ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", "unit potion", u, itype->rtype)); @@ -335,7 +335,7 @@ struct order *ord) } use_pooled(user, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(user, itype->rtype->ptype); + usetpotionuse(user, itype); ADDMSG(&user->faction->msgs, msg_message("usepotion", "unit potion", user, itype->rtype)); @@ -408,7 +408,7 @@ static int use_warmthpotion(unit *u, const item_type *itype, } use_pooled(u, itype->rtype, GET_SLACK | GET_RESERVE | GET_POOLED_SLACK, amount); - usetpotionuse(u, itype->rtype->ptype); + usetpotionuse(u, itype); ADDMSG(&u->faction->msgs, msg_message("usepotion", "unit potion", u, itype->rtype)); diff --git a/src/kernel/build.test.c b/src/kernel/build.test.c index eab2a6f00..ece28f4eb 100644 --- a/src/kernel/build.test.c +++ b/src/kernel/build.test.c @@ -161,12 +161,12 @@ static void test_build_with_ring(CuTest *tc) { static void test_build_with_potion(CuTest *tc) { build_fixture bf = { 0 }; unit *u; - const potion_type *ptype; + const item_type *ptype; const struct resource_type *rtype; u = setup_build(&bf); rtype = bf.cons.materials[0].rtype; - oldpotiontype[P_DOMORE] = ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1); + oldpotiontype[P_DOMORE] = ptype = it_get_or_create(rt_get_or_create("hodor")); assert(rtype && ptype); i_change(&u->items, rtype->itype, 20); diff --git a/src/kernel/item.c b/src/kernel/item.c index 2eabd4aa5..f7ce28835 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -60,7 +60,6 @@ static critbit_tree inames[MAXLOCALES]; static critbit_tree rnames[MAXLOCALES]; static critbit_tree cb_resources; luxury_type *luxurytypes; -potion_type *potiontypes; #define RTYPENAMELEN 24 typedef struct rt_entry { @@ -315,28 +314,8 @@ armor_type *new_armortype(item_type * itype, double penalty, variant magres, return atype; } -static void pt_register(potion_type * ptype) +void it_set_appearance(item_type *itype, const char *appearance) { - ptype->itype->rtype->ptype = ptype; - ptype->next = potiontypes; - potiontypes = ptype; -} - -potion_type *new_potiontype(item_type * itype, int level) -{ - potion_type *ptype; - - assert(resource2potion(itype->rtype) == NULL); - - ptype = (potion_type *)calloc(sizeof(potion_type), 1); - ptype->itype = itype; - ptype->level = level; - pt_register(ptype); - - return ptype; -} - -void it_set_appearance(item_type *itype, const char *appearance) { assert(itype); assert(itype->rtype); if (appearance) { @@ -377,18 +356,6 @@ const luxury_type *resource2luxury(const resource_type * rtype) #endif } -const potion_type *resource2potion(const resource_type * rtype) -{ -#ifdef AT_PTYPE - attrib *a = a_find(rtype->attribs, &at_ptype); - if (a) - return (const potion_type *)a->data.v; - return NULL; -#else - return rtype->ptype; -#endif -} - resource_type *rt_find(const char *name) { const void *match; @@ -573,7 +540,7 @@ item *i_new(const item_type * itype, int size) return i; } -const potion_type *oldpotiontype[MAX_POTIONS + 1]; +const item_type *oldpotiontype[MAX_POTIONS + 1]; /*** alte items ***/ @@ -677,7 +644,7 @@ static void init_oldpotions(void) for (p = 0; p != MAX_POTIONS; ++p) { item_type *itype = it_find(potionnames[p]); if (itype != NULL) { - oldpotiontype[p] = itype->rtype->ptype; + oldpotiontype[p] = itype; } } } diff --git a/src/kernel/item.h b/src/kernel/item.h index cc5991ed6..c289005df 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -80,7 +80,6 @@ extern "C" { struct resource_mod *modifiers; /* --- pointers --- */ struct item_type *itype; - struct potion_type *ptype; struct luxury_type *ltype; struct weapon_type *wtype; struct armor_type *atype; @@ -99,6 +98,7 @@ extern "C" { #define ITF_ANIMAL 0x0010 /* an animal */ #define ITF_VEHICLE 0x0020 /* a vehicle, drawn by two animals */ #define ITF_CANUSE 0x0040 /* can be used with use_item_fun callout */ +#define ITF_POTION 0x0080 /* is a potion (for use_potion) */ /* error codes for item_type::use */ #define ECUSTOM -1 @@ -128,13 +128,6 @@ extern "C" { } luxury_type; extern luxury_type *luxurytypes; - typedef struct potion_type { - struct potion_type *next; - const item_type *itype; - int level; - } potion_type; - extern potion_type *potiontypes; - #define WMF_WALKING 0x0001 #define WMF_RIDING 0x0002 #define WMF_ANYONE 0x000F /* convenience */ @@ -206,7 +199,6 @@ extern "C" { const resource_type *item2resource(const item_type * i); const weapon_type *resource2weapon(const resource_type * i); - const potion_type *resource2potion(const resource_type * i); const luxury_type *resource2luxury(const resource_type * i); item **i_find(item ** pi, const item_type * it); @@ -234,8 +226,6 @@ extern "C" { skill_t sk); armor_type *new_armortype(item_type * itype, double penalty, variant magres, int prot, unsigned int flags); - potion_type *new_potiontype(item_type * itype, int level); - /* these constants are used with get_resourcetype. * The order of the enum is not important for stored data. @@ -285,7 +275,7 @@ extern "C" { NORESOURCE = -1 } resource_t; - extern const struct potion_type *oldpotiontype[]; + extern const struct item_type *oldpotiontype[]; const struct resource_type *get_resourcetype(resource_t rt); struct item *item_spoil(const struct race *rc, int size); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 28f227ff5..fb07d782e 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -585,7 +585,7 @@ attrib_type at_potionuser = { NO_READ }; -void usetpotionuse(unit * u, const potion_type * ptype) +void usetpotionuse(unit * u, const item_type * ptype) { attrib *a = a_find(u->attribs, &at_potionuser); if (!a) @@ -593,12 +593,12 @@ void usetpotionuse(unit * u, const potion_type * ptype) a->data.v = (void *)ptype; } -const potion_type *ugetpotionuse(const unit * u) +const item_type *ugetpotionuse(const unit * u) { attrib *a = a_find(u->attribs, &at_potionuser); if (!a) return NULL; - return (const potion_type *)a->data.v; + return (const item_type *)a->data.v; } /*********************/ diff --git a/src/kernel/unit.h b/src/kernel/unit.h index 53f9836db..91a3ec930 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -28,11 +28,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif -#define MAXUNITS 1048573 /* must be prime for hashing. 524287 was >90% full */ struct skill; struct item; struct sc_mage; struct gamedata; + struct item_type; + +#define MAXUNITS 1048573 /* should be prime for hashing. 524287 was >90% full */ + #define UFL_DEAD (1<<0) #define UFL_ISNEW (1<<1) /* 2 */ #define UFL_LONGACTION (1<<2) /* 4 */ @@ -147,8 +150,8 @@ extern "C" { const char *uprivate(const struct unit *u); void usetprivate(struct unit *u, const char *c); - const struct potion_type *ugetpotionuse(const struct unit *u); /* benutzt u einein trank? */ - void usetpotionuse(struct unit *u, const struct potion_type *p); /* u benutzt trank p (es darf halt nur einer pro runde) */ + const struct item_type *ugetpotionuse(const struct unit *u); /* benutzt u einein trank? */ + void usetpotionuse(struct unit *u, const struct item_type *p); /* u benutzt trank p (es darf halt nur einer pro runde) */ bool ucontact(const struct unit *u, const struct unit *u2); void usetcontact(struct unit *u, const struct unit *c); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 9391e7012..20d23e7a8 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -101,11 +101,11 @@ static void test_remove_units_with_dead_faction(CuTest *tc) { static void test_scale_number(CuTest *tc) { unit *u; - const struct potion_type *ptype; + const struct item_type *ptype; test_setup(); test_create_world(); - ptype = new_potiontype(it_get_or_create(rt_get_or_create("hodor")), 1); + ptype = it_get_or_create(rt_get_or_create("hodor")); u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); change_effect(u, ptype, 1); u->hp = 35; diff --git a/src/laws.c b/src/laws.c index bccefab20..faf680272 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2252,17 +2252,17 @@ static void display_item(unit * u, const item_type * itype) itype->weight, itype->rtype, info)); } -static void display_potion(unit * u, const potion_type * ptype) +static void display_potion(unit * u, const item_type * itype) { faction * f = u->faction; attrib *a; a = a_find(f->attribs, &at_showitem); - while (a && a->data.v != ptype) + while (a && a->data.v != itype) a = a->next; if (!a) { a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; + a->data.v = (void *)itype; } } @@ -2429,21 +2429,16 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { err = 36; /* we do not have this item? */ if (i <= 0) { /* we don't have the item, but it may be a potion that we know */ - const potion_type *ptype = resource2potion(item2resource(itype)); - if (ptype) { - if (2 * ptype->level > effskill(u, SK_ALCHEMY, 0)) { - itype = NULL; - } - } else { + int level = potion_level(itype); + if (2 * level > effskill(u, SK_ALCHEMY, 0)) { itype = NULL; } } } if (itype) { - const potion_type *ptype = itype->rtype->ptype; - if (ptype) { - display_potion(u, ptype); + if (itype->flags & ITF_POTION) { + display_potion(u, itype); } else { display_item(u, itype); @@ -2471,26 +2466,30 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { cmistake(u, ord, err, MSG_EVENT); } +bool display_potions(unit *u) +{ + int skill = effskill(u, SK_ALCHEMY, 0); + int c = 0; + const potion_type *ptype; + for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { + if (ptype->level * 2 <= skill) { + display_potion(u, ptype); + ++c; + } + } + return (c > 0); +} + static void reshow(unit * u, struct order *ord, const char *s, param_t p) { - int skill, c; - const potion_type *ptype; - switch (p) { case P_ZAUBER: a_removeall(&u->faction->attribs, &at_seenspell); break; case P_POTIONS: - skill = effskill(u, SK_ALCHEMY, 0); - c = 0; - for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { - if (ptype->level * 2 <= skill) { - display_potion(u, ptype); - ++c; - } - } - if (c == 0) + if (!display_potions(u)) { cmistake(u, ord, 285, MSG_EVENT); + } break; case NOPARAM: reshow_other(u, ord, s); diff --git a/src/report.c b/src/report.c index e154ab045..25a92ede2 100644 --- a/src/report.c +++ b/src/report.c @@ -578,7 +578,7 @@ nr_curses_i(struct stream *out, int indent, const faction *viewer, objtype_t typ effect_data *data = (effect_data *)a->data.v; if (data->value > 0) { msg = msg_message("nr_potion_effect", "potion left", - data->type->itype->rtype, data->value); + data->type->rtype, data->value); } } if (msg) { @@ -2198,11 +2198,10 @@ report_plaintext(const char *filename, report_context * ctx, CHECK_ERRNO(); for (a = a_find(f->attribs, &at_showitem); a && a->type == &at_showitem; a = a->next) { - const potion_type *ptype = - resource2potion(((const item_type *)a->data.v)->rtype); + const item_type *itype = (const item_type *)a->data.v; const char *description = NULL; - if (ptype != NULL) { - const char *pname = resourcename(ptype->itype->rtype, 0); + if (itype) { + const char *pname = resourcename(itype->rtype, 0); if (ch == 0) { newline(out); @@ -2213,7 +2212,7 @@ report_plaintext(const char *filename, report_context * ctx, newline(out); centre(out, LOC(f->locale, pname), true); snprintf(buf, sizeof(buf), "%s %d", LOC(f->locale, "nr_level"), - ptype->level); + potion_level(itype)); centre(out, buf, true); newline(out); @@ -2223,8 +2222,8 @@ report_plaintext(const char *filename, report_context * ctx, if (wrptr(&bufp, &size, bytes) != 0) WARN_STATIC_BUFFER(); - if (ptype->itype->construction) { - requirement *rm = ptype->itype->construction->materials; + if (itype->construction) { + requirement *rm = itype->construction->materials; while (rm->number) { bytes = (int)str_strlcpy(bufp, LOC(f->locale, resourcename(rm->rtype, 0)), size); diff --git a/src/study.c b/src/study.c index c5d657c48..f446e34ab 100644 --- a/src/study.c +++ b/src/study.c @@ -779,21 +779,10 @@ int study_cmd(unit * u, order * ord) /* Spruchlistenaktualiesierung ist in Regeneration */ if (sk == SK_ALCHEMY) { - const potion_type *ptype; faction *f = u->faction; int skill = effskill(u, SK_ALCHEMY, 0); if (skill > maxalchemy) { - for (ptype = potiontypes; ptype; ptype = ptype->next) { - if (skill == ptype->level * 2) { - a = a_find(f->attribs, &at_showitem); - while (a && a->type == &at_showitem && a->data.v != ptype) - a = a->next; - if (a == NULL || a->type != &at_showitem) { - a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)ptype->itype; - } - } - } + show_potions(f, skill); } } else if (sk == SK_MAGIC) { diff --git a/src/upkeep.c b/src/upkeep.c index 3bd77710e..6748d620c 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -245,26 +245,22 @@ void get_food(region * r) int hungry = u->number; /* use peasantblood before eating the peasants themselves */ - const struct potion_type *pt_blood = 0; - const resource_type *rt_blood = rt_find("peasantblood"); - if (rt_blood) { - pt_blood = rt_blood->ptype; - } - if (pt_blood) { + const struct item_type *it_blood = it_find("peasantblood"); + if (it_blood) { /* always start with the unit itself, then the first known unit that may have some blood */ unit *donor = u; while (donor != NULL && hungry > 0) { - int blut = get_effect(donor, pt_blood); + int blut = get_effect(donor, it_blood); if (hungry < blut) blut = hungry; if (blut > 0) { - change_effect(donor, pt_blood, -blut); + change_effect(donor, it_blood, -blut); hungry -= blut; } if (donor == u) donor = r->units; while (donor != NULL) { if (u_race(donor) == rc_demon && donor != u) { - if (get_effect(donor, pt_blood)) { + if (get_effect(donor, it_blood)) { /* if he's in our faction, drain him: */ if (donor->faction == u->faction) break; diff --git a/src/volcano.c b/src/volcano.c index d90ef47ee..df70a864f 100644 --- a/src/volcano.c +++ b/src/volcano.c @@ -133,8 +133,8 @@ damage_unit(unit * u, const char *dam, bool physical, bool magic) change_effect(u, oldpotiontype[P_HEAL], -1); heiltrank = 1; } - else if (i_get(u->items, oldpotiontype[P_HEAL]->itype) > 0) { - i_change(&u->items, oldpotiontype[P_HEAL]->itype, -1); + else if (i_get(u->items, oldpotiontype[P_HEAL]) > 0) { + i_change(&u->items, oldpotiontype[P_HEAL], -1); change_effect(u, oldpotiontype[P_HEAL], 3); heiltrank = 1; } From 2b2a79620c87257a9061b11c924c5b5f9bf21c93 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 10:01:06 +0100 Subject: [PATCH 06/14] compiles, test fails, xmlreader includes need fixing --- src/alchemy.c | 14 ++++++++++++++ src/alchemy.h | 5 ++++- src/kernel/item.c | 15 +++++++++++++++ src/kernel/item.h | 6 ++++-- src/kernel/xmlreader.c | 9 +++++---- src/laws.c | 32 ++++---------------------------- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/src/alchemy.c b/src/alchemy.c index 29db8ce85..cf3d2b376 100644 --- a/src/alchemy.c +++ b/src/alchemy.c @@ -434,3 +434,17 @@ int change_effect(unit * u, const item_type * effect, int delta) log_error("change effect with delta==0 for unit %s\n", itoa36(u->no)); return 0; } + +bool display_potions(struct unit *u) +{ + int skill = effskill(u, SK_ALCHEMY, 0); + int c = 0; + const potion_type *ptype; + for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { + if (ptype->level * 2 <= skill) { + show_item(u, ptype->itype); + ++c; + } + } + return (c > 0); +} diff --git a/src/alchemy.h b/src/alchemy.h index f8cebd3db..d183cacd0 100644 --- a/src/alchemy.h +++ b/src/alchemy.h @@ -19,6 +19,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef H_KRNL_ALCHEMY_H #define H_KRNL_ALCHEMY_H +#include + #ifdef __cplusplus extern "C" { #endif @@ -68,8 +70,9 @@ extern "C" { int get_effect(const struct unit *u, const struct item_type *effect); int change_effect(struct unit *u, const struct item_type *effect, int value); + bool display_potions(struct unit *u); - /* rausnehmen, sobald man attribute splitten kann: */ + /* TODO: rausnehmen, sobald man attribute splitten kann: */ typedef struct effect_data { const struct item_type *type; int value; diff --git a/src/kernel/item.c b/src/kernel/item.c index f7ce28835..74951895a 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -980,3 +980,18 @@ void register_resources(void) register_function((pf_generic)res_changehp, "changehp"); register_function((pf_generic)res_changeaura, "changeaura"); } + +void show_item(unit * u, const item_type * itype) +{ + faction * f = u->faction; + attrib *a; + + a = a_find(f->attribs, &at_showitem); + while (a && a->data.v != itype) + a = a->next; + if (!a) { + a = a_add(&f->attribs, a_new(&at_showitem)); + a->data.v = (void *)itype; + } +} + diff --git a/src/kernel/item.h b/src/kernel/item.h index c289005df..e7bfef7cc 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -276,6 +276,10 @@ extern "C" { } resource_t; extern const struct item_type *oldpotiontype[]; + extern struct attrib_type at_showitem; /* show this potion's description */ + + void show_item(struct unit * u, const struct item_type * itype); + const struct resource_type *get_resourcetype(resource_t rt); struct item *item_spoil(const struct race *rc, int size); @@ -285,8 +289,6 @@ extern "C" { int set_money(struct unit *, int); int change_money(struct unit *, int); - extern struct attrib_type at_showitem; /* show this potion's description */ - void register_resources(void); void init_resources(void); diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index f086af3ef..1ef17b2e7 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -32,6 +32,8 @@ without prior permission by the authors of Eressea. #include "prefix.h" #include "move.h" +/* TODO: core code should not include these files: */ +#include "alchemy.h" #include "vortex.h" #include @@ -483,12 +485,11 @@ static int parse_ships(xmlDocPtr doc) return 0; } -static potion_type *xml_readpotion(xmlXPathContextPtr xpath, item_type * itype) +static void xml_readpotion(xmlXPathContextPtr xpath, item_type * itype) { int level = xml_ivalue(xpath->node, "level", 0); - assert(level > 0); - return new_potiontype(itype, level); + new_potiontype(itype, level); } static luxury_type *xml_readluxury(xmlXPathContextPtr xpath, item_type * itype) @@ -741,7 +742,7 @@ static item_type *xml_readitem(xmlXPathContextPtr xpath, resource_type * rtype) itype->flags |= ITF_CANUSE; } xpath->node = result->nodesetval->nodeTab[0]; - rtype->ptype = xml_readpotion(xpath, itype); + xml_readpotion(xpath, itype); } xmlXPathFreeObject(result); diff --git a/src/laws.c b/src/laws.c index faf680272..47577d461 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2234,6 +2234,10 @@ int send_cmd(unit * u, struct order *ord) return 0; } +static void display_potion(unit * u, const item_type * itype) { + show_item(u, itype); +} + static void display_item(unit * u, const item_type * itype) { faction * f = u->faction; @@ -2252,20 +2256,6 @@ static void display_item(unit * u, const item_type * itype) itype->weight, itype->rtype, info)); } -static void display_potion(unit * u, const item_type * itype) -{ - faction * f = u->faction; - attrib *a; - - a = a_find(f->attribs, &at_showitem); - while (a && a->data.v != itype) - a = a->next; - if (!a) { - a = a_add(&f->attribs, a_new(&at_showitem)); - a->data.v = (void *)itype; - } -} - static void display_race(unit * u, const race * rc) { faction * f = u->faction; @@ -2466,20 +2456,6 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { cmistake(u, ord, err, MSG_EVENT); } -bool display_potions(unit *u) -{ - int skill = effskill(u, SK_ALCHEMY, 0); - int c = 0; - const potion_type *ptype; - for (ptype = potiontypes; ptype != NULL; ptype = ptype->next) { - if (ptype->level * 2 <= skill) { - display_potion(u, ptype); - ++c; - } - } - return (c > 0); -} - static void reshow(unit * u, struct order *ord, const char *s, param_t p) { switch (p) { From 7a64053dc9120b9b30ba672ff7f851e084ee7252 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 10:06:13 +0100 Subject: [PATCH 07/14] better testing for is_potion (should be a function) --- src/laws.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/laws.c b/src/laws.c index 47577d461..75ab7372a 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2417,10 +2417,10 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { int i = i_get(u->items, itype); err = 36; /* we do not have this item? */ - if (i <= 0) { - /* we don't have the item, but it may be a potion that we know */ + if (i <= 0 && (itype->flags & ITF_POTION)) { + /* we don't have the item, but it is a potion. do we know it? */ int level = potion_level(itype); - if (2 * level > effskill(u, SK_ALCHEMY, 0)) { + if (level > 0 && 2 * level > effskill(u, SK_ALCHEMY, 0)) { itype = NULL; } } @@ -2452,8 +2452,9 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { found = true; } } - if (!found) - cmistake(u, ord, err, MSG_EVENT); + if (!found) { + cmistake(u, ord, err, MSG_EVENT); + } } static void reshow(unit * u, struct order *ord, const char *s, param_t p) From 71c9b5adefb64ba18cc280fca608137bfab6a0f0 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Jan 2018 20:45:59 +0100 Subject: [PATCH 08/14] Fix broken SHOW logic for potions. --- src/laws.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/laws.c b/src/laws.c index 75ab7372a..dbb99adc1 100644 --- a/src/laws.c +++ b/src/laws.c @@ -2414,26 +2414,22 @@ static void reshow_other(unit * u, struct order *ord, const char *s) { if (itype) { /* if this is a potion, we need the right alchemy skill */ - int i = i_get(u->items, itype); - err = 36; /* we do not have this item? */ - if (i <= 0 && (itype->flags & ITF_POTION)) { + if (itype->flags & ITF_POTION) { /* we don't have the item, but it is a potion. do we know it? */ int level = potion_level(itype); - if (level > 0 && 2 * level > effskill(u, SK_ALCHEMY, 0)) { - itype = NULL; + if (level > 0 && 2 * level <= effskill(u, SK_ALCHEMY, 0)) { + display_potion(u, itype); + found = true; } } - } - - if (itype) { - if (itype->flags & ITF_POTION) { - display_potion(u, itype); - } else { - display_item(u, itype); + int i = i_get(u->items, itype); + if (i > 0) { + found = true; + display_item(u, itype); + } } - found = true; } if (sp) { From 010ff35c4ac3ff5dcac81e128d27297306016abd Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 14 Jan 2018 17:43:10 +0100 Subject: [PATCH 09/14] test_setup_world is deprecated. --- src/items/xerewards.test.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/items/xerewards.test.c b/src/items/xerewards.test.c index 27c34b812..c0d20079e 100644 --- a/src/items/xerewards.test.c +++ b/src/items/xerewards.test.c @@ -20,7 +20,7 @@ static void test_manacrystal(CuTest *tc) { test_setup(); test_inject_messagetypes(); - u = test_create_unit(test_create_faction(NULL), test_create_region(0, 0, NULL)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); itype = test_create_itemtype("manacrystal"); change_resource(u, itype->rtype, 1); CuAssertIntEquals(tc, -1, use_manacrystal(u, itype, 1, NULL)); @@ -50,8 +50,7 @@ static void test_skillpotion(CuTest *tc) { test_setup(); test_inject_messagetypes(); - test_create_world(); - u = test_create_unit(test_create_faction(NULL), findregion(0, 0)); + u = test_create_unit(test_create_faction(NULL), test_create_plain(0, 0)); itype = test_create_itemtype("skillpotion"); change_resource(u, itype->rtype, 2); From 0435c9ee8be39cd4a1eaf2e4c55b8df4530edfb3 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 14 Jan 2018 17:50:54 +0100 Subject: [PATCH 10/14] jsonconf reads game rules outside of kernel, so move it out. --- src/CMakeLists.txt | 2 ++ src/bind_config.c | 16 ++++++------- src/{kernel => }/jsonconf.c | 39 ++++++++++++++++---------------- src/{kernel => }/jsonconf.h | 0 src/{kernel => }/jsonconf.test.c | 0 src/kernel/CMakeLists.txt | 2 -- src/kernel/xmlreader.c | 1 - 7 files changed, 29 insertions(+), 31 deletions(-) rename src/{kernel => }/jsonconf.c (99%) rename src/{kernel => }/jsonconf.h (100%) rename src/{kernel => }/jsonconf.test.c (100%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4708caf6d..48ba117e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,6 +100,7 @@ set (ERESSEA_SRC reports.c teleport.c guard.c + jsonconf.c prefix.c donations.c eressea.c @@ -212,6 +213,7 @@ set(TESTS_SRC give.test.c guard.test.c json.test.c + jsonconf.test.c keyword.test.c laws.test.c lighthouse.test.c diff --git a/src/bind_config.c b/src/bind_config.c index 871d53dce..83c65364d 100644 --- a/src/bind_config.c +++ b/src/bind_config.c @@ -4,8 +4,15 @@ #include "bind_config.h" +#include "jsonconf.h" + #include -#include +#include +#include +#include +#include +#include +#include #include #include @@ -20,13 +27,6 @@ #include #include -#include "kernel/building.h" -#include "kernel/race.h" -#include "kernel/ship.h" -#include "kernel/spell.h" -#include "kernel/spellbook.h" -#include "kernel/terrain.h" - void config_reset(void) { free_config(); free_nrmesssages(); diff --git a/src/kernel/jsonconf.c b/src/jsonconf.c similarity index 99% rename from src/kernel/jsonconf.c rename to src/jsonconf.c index 052f7a8c8..3c5411b9d 100644 --- a/src/kernel/jsonconf.c +++ b/src/jsonconf.c @@ -15,26 +15,17 @@ without prior permission by the authors of Eressea. #include "jsonconf.h" /* kernel includes */ -#include "building.h" -#include "direction.h" -#include "keyword.h" -#include "equipment.h" -#include "item.h" -#include "messages.h" -#include "race.h" -#include "region.h" -#include "resources.h" -#include "ship.h" -#include "terrain.h" -#include "skill.h" -#include "spell.h" -#include "spellbook.h" -#include "calendar.h" - -/* game modules */ -#include "prefix.h" -#include "move.h" -#include "calendar.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* util includes */ #include @@ -48,6 +39,14 @@ without prior permission by the authors of Eressea. #include #include +/* game modules */ +#include "calendar.h" +#include "direction.h" +#include "keyword.h" +#include "move.h" +#include "prefix.h" +#include "skill.h" + /* external libraries */ #include diff --git a/src/kernel/jsonconf.h b/src/jsonconf.h similarity index 100% rename from src/kernel/jsonconf.h rename to src/jsonconf.h diff --git a/src/kernel/jsonconf.test.c b/src/jsonconf.test.c similarity index 100% rename from src/kernel/jsonconf.test.c rename to src/jsonconf.test.c diff --git a/src/kernel/CMakeLists.txt b/src/kernel/CMakeLists.txt index 99db2db27..3458d6947 100644 --- a/src/kernel/CMakeLists.txt +++ b/src/kernel/CMakeLists.txt @@ -32,7 +32,6 @@ spellbook.test.c spell.test.c # terrain.test.c unit.test.c -jsonconf.test.c # xmlreader.test.c ) @@ -80,7 +79,6 @@ spell.c terrain.c unit.c xmlreader.c -jsonconf.c ) SET(VERSION_SRC ${PROJECT_NAME}/version.c PARENT_SCOPE) diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c index 1ef17b2e7..cfdee7513 100644 --- a/src/kernel/xmlreader.c +++ b/src/kernel/xmlreader.c @@ -34,7 +34,6 @@ without prior permission by the authors of Eressea. /* TODO: core code should not include these files: */ #include "alchemy.h" -#include "vortex.h" #include #include From 5b099e27f61ba02e94c443b54b07d50d2c467b55 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 14 Jan 2018 18:02:30 +0100 Subject: [PATCH 11/14] fix broken includes --- src/jsonconf.test.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/jsonconf.test.c b/src/jsonconf.test.c index ea6c733f5..29c68e600 100644 --- a/src/jsonconf.test.c +++ b/src/jsonconf.test.c @@ -1,24 +1,28 @@ +#ifdef _MSC_VER #include -#include "types.h" +#endif + +#include "kernel/types.h" + #include "jsonconf.h" -#include "config.h" -#include "building.h" -#include "direction.h" -#include "item.h" -#include "keyword.h" -#include "race.h" -#include "ship.h" -#include "spell.h" -#include "order.h" -#include "terrain.h" - -#include "move.h" -#include "calendar.h" -#include "prefix.h" +#include "kernel/config.h" +#include "kernel/building.h" +#include "kernel/item.h" +#include "kernel/race.h" +#include "kernel/ship.h" +#include "kernel/spell.h" +#include "kernel/order.h" +#include "kernel/terrain.h" #include "util/language.h" +#include "calendar.h" +#include "direction.h" +#include "keyword.h" +#include "move.h" +#include "prefix.h" + #include #include #include From 0291d85529b4ff7cc6ef617f0ee08f63e122ec10 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 19 Jan 2018 16:59:52 +0100 Subject: [PATCH 12/14] make sure that jewels are what is sold in tests. --- src/economy.test.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/economy.test.c b/src/economy.test.c index ff21f4622..282c9fc64 100644 --- a/src/economy.test.c +++ b/src/economy.test.c @@ -206,15 +206,16 @@ static region *setup_trade_region(CuTest *tc, const struct terrain_type *terrain item_type *it_luxury; struct locale * lang = default_locale; - new_luxurytype(it_luxury = test_create_itemtype("jewel"), 5); - locale_setstring(lang, it_luxury->rtype->_name, it_luxury->rtype->_name); - CuAssertStrEquals(tc, it_luxury->rtype->_name, LOC(lang, resourcename(it_luxury->rtype, 0))); - new_luxurytype(it_luxury = test_create_itemtype("balm"), 5); locale_setstring(lang, it_luxury->rtype->_name, it_luxury->rtype->_name); CuAssertStrEquals(tc, it_luxury->rtype->_name, LOC(lang, resourcename(it_luxury->rtype, 0))); + new_luxurytype(it_luxury = test_create_itemtype("jewel"), 5); + locale_setstring(lang, it_luxury->rtype->_name, it_luxury->rtype->_name); + CuAssertStrEquals(tc, it_luxury->rtype->_name, LOC(lang, resourcename(it_luxury->rtype, 0))); + r = test_create_region(0, 0, terrain); + setluxuries(r, it_luxury->rtype->ltype); return r; } From d78b21c1c36987f1b9aac5192483884116a22bd2 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 Jan 2018 10:32:39 +0100 Subject: [PATCH 13/14] BUG 2413: renumber parsing caused f->no == 0 --- src/kernel/save.c | 3 ++- src/renumber.c | 12 ++++++++---- src/renumber.test.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/kernel/save.c b/src/kernel/save.c index 926de1bb1..227304339 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1149,7 +1149,8 @@ void write_faction(gamedata *data, const faction * f) ursprung *ur; assert(f->_alive); - write_faction_reference(f, data->store); + assert(f->no > 0 && f->no <= MAX_UNIT_NR); + WRITE_INT(data->store, f->no); WRITE_INT(data->store, f->subscription); #if RELEASE_VERSION >= SPELL_LEVEL_VERSION WRITE_INT(data->store, f->max_spelllevel); diff --git a/src/renumber.c b/src/renumber.c index 30769403f..5f1fc3537 100644 --- a/src/renumber.c +++ b/src/renumber.c @@ -88,11 +88,15 @@ int renumber_cmd(unit * u, order * ord) s = gettoken(token, sizeof(token)); if (s && *s) { int id = atoi36((const char *)s); - attrib *a = a_find(f->attribs, &at_number); - if (!a) - a = a_add(&f->attribs, a_new(&at_number)); - a->data.i = id; + if (id > 0 && id <= MAX_UNIT_NR) { + attrib *a = a_find(f->attribs, &at_number); + if (!a) + a = a_add(&f->attribs, a_new(&at_number)); + a->data.i = id; + break; + } } + cmistake(u, ord, 114, MSG_EVENT); break; case P_UNIT: diff --git a/src/renumber.test.c b/src/renumber.test.c index 8f6f91a59..c512367b8 100644 --- a/src/renumber.test.c +++ b/src/renumber.test.c @@ -49,6 +49,37 @@ static void test_renumber_faction_duplicate(CuTest *tc) { test_cleanup(); } +static void test_renumber_faction_invalid(CuTest *tc) { + unit *u; + faction *f; + int no; + const struct locale *lang; + + test_setup_ex(tc); + u = test_create_unit(f = test_create_faction(0), test_create_region(0, 0, 0)); + no = f->no; + lang = f->locale; + u->thisorder = create_order(K_NUMBER, lang, "%s [halima]", LOC(lang, parameters[P_FACTION])); + renumber_cmd(u, u->thisorder); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error114")); + renumber_factions(); + CuAssertIntEquals(tc, no, f->no); + + test_clear_messages(f); + free_order(u->thisorder); + u->thisorder = create_order(K_NUMBER, lang, "%s 10000", LOC(lang, parameters[P_FACTION])); + renumber_cmd(u, u->thisorder); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error114")); + + test_clear_messages(f); + free_order(u->thisorder); + u->thisorder = create_order(K_NUMBER, lang, "%s 0", LOC(lang, parameters[P_FACTION])); + renumber_cmd(u, u->thisorder); + CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error114")); + + test_cleanup(); +} + static void test_renumber_building(CuTest *tc) { unit *u; int uno, no; @@ -230,5 +261,6 @@ CuSuite *get_renumber_suite(void) SUITE_ADD_TEST(suite, test_renumber_ship_duplicate); SUITE_ADD_TEST(suite, test_renumber_faction); SUITE_ADD_TEST(suite, test_renumber_faction_duplicate); + SUITE_ADD_TEST(suite, test_renumber_faction_invalid); return suite; } From 0bf5e3bd5716c5ead9eb68186b668ebfe3d1d6e9 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Sun, 21 Jan 2018 11:02:20 +0100 Subject: [PATCH 14/14] fix test_cleanup -> test_teardown name change --- src/renumber.test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renumber.test.c b/src/renumber.test.c index 11fb022aa..0c2030379 100644 --- a/src/renumber.test.c +++ b/src/renumber.test.c @@ -79,7 +79,7 @@ static void test_renumber_faction_invalid(CuTest *tc) { renumber_cmd(u, u->thisorder); CuAssertPtrNotNull(tc, test_find_messagetype(f->msgs, "error114")); - test_cleanup(); + test_teardown(); } static void test_renumber_building(CuTest *tc) {