From 481275aef1295cf4ffb503d53a81134eb51dc34d Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Dec 2014 20:53:39 +0100 Subject: [PATCH 1/3] refactor: eliminate the getunitpeasants global variable. bugfix: it was possible to uncover stealth units with GIVE CONTROL. --- src/battle.c | 2 +- src/economy.c | 16 ++++++-------- src/give.c | 54 +++++++++++++++++++++------------------------ src/give.h | 1 + src/give.test.c | 2 -- src/kernel/config.c | 31 +++++++++++++++++++++----- src/kernel/config.h | 9 ++++++-- src/laws.c | 2 +- src/move.c | 12 +++++----- src/spy.c | 2 +- src/study.c | 4 ++-- 11 files changed, 76 insertions(+), 59 deletions(-) diff --git a/src/battle.c b/src/battle.c index c7ccf2ae8..c43ea2989 100644 --- a/src/battle.c +++ b/src/battle.c @@ -4004,7 +4004,7 @@ static bool start_battle(region * r, battle ** bp) init_order(ord); /* attackierte Einheit ermitteln */ - u2 = getunit(r, u->faction); + getunit(r, u->faction, &u2); /* Beginn Fehlerbehandlung */ /* Fehler: "Die Einheit wurde nicht gefunden" */ diff --git a/src/economy.c b/src/economy.c index 5de7fde59..566536f07 100644 --- a/src/economy.c +++ b/src/economy.c @@ -629,20 +629,18 @@ int give_control_cmd(unit * u, order * ord) region *r = u->region; unit *u2; const char *s; - param_t p; init_order(ord); - u2 = getunit(r, u->faction); - s = getstrtoken(); - p = findparam(s, u->faction->locale); + getunit(r, u->faction, &u2); - /* first, do all the ones that do not require HELP_GIVE or CONTACT */ - if (p == P_CONTROL) { + s = getstrtoken(); + if (isparam(s, u->faction->locale, P_CONTROL)) { message *msg = 0; - if (!u2 || u2->number == 0) { - msg = msg_feedback(u, ord, "feedback_unit_not_found", ""); - ADDMSG(&u->faction->msgs, msg); + if (!can_give_to(u, u2)) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "feedback_unit_not_found", "")); + return; } else if (!u->building && !u->ship) { msg = cmistake(u, ord, 140, MSG_EVENT); diff --git a/src/give.c b/src/give.c index b76e735e8..7a17b2da3 100644 --- a/src/give.c +++ b/src/give.c @@ -434,7 +434,7 @@ void give_unit(unit * u, unit * u2, order * ord) cmistake(u, ord, 152, MSG_COMMERCE); } } - else if (getunitpeasants) { + else { unit *u3; for (u3 = r->units; u3; u3 = u3->next) @@ -461,10 +461,6 @@ void give_unit(unit * u, unit * u2, order * ord) cmistake(u, ord, 153, MSG_COMMERCE); } } - else { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - } return; } @@ -520,12 +516,25 @@ void give_unit(unit * u, unit * u2, order * ord) u2->faction->newbies += n; } +bool can_give_to(unit *u, unit *u2) { + /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ + if (!u2 || u2->number == 0) { + return false; + } + if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) + && !cansee(u->faction, u->region, u2, 0) && !ucontact(u2, u) + && !fval(u2, UFL_TAKEALL)) { + return false; + } + return true; +} + void give_cmd(unit * u, order * ord) { region *r = u->region; unit *u2; const char *s; - int n; + int err, n; const item_type *itype; param_t p; plane *pl; @@ -534,7 +543,7 @@ void give_cmd(unit * u, order * ord) kwd = init_order(ord); assert(kwd == K_GIVE); - u2 = getunit(r, u->faction); + err = getunit(r, u->faction, &u2); s = getstrtoken(); n = s ? atoip(s) : 0; p = (n > 0) ? NOPARAM : findparam(s, u->faction->locale); @@ -545,9 +554,13 @@ void give_cmd(unit * u, order * ord) return; } - if (!u2 && !getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); + if (err == GET_NOTFOUND || (err != GET_PEASANTS && !can_give_to(u, u2))) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, ord, "feedback_unit_not_found", "")); + return; + } + if (u == u2) { + cmistake(u, ord, 8, MSG_COMMERCE); return; } @@ -557,19 +570,6 @@ void give_cmd(unit * u, order * ord) return; } - /* Damit Tarner nicht durch die Fehlermeldung enttarnt werden können */ - if (u2 && !alliedunit(u2, u->faction, HELP_GIVE) - && !cansee(u->faction, r, u2, 0) && !ucontact(u2, u) - && !fval(u2, UFL_TAKEALL)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", - "")); - return; - } - if (u == u2) { - cmistake(u, ord, 8, MSG_COMMERCE); - return; - } - /* UFL_TAKEALL ist ein grober Hack. Generalisierung tut not, ist aber nicht * wirklich einfach. */ pl = rplane(r); @@ -605,11 +605,6 @@ void give_cmd(unit * u, order * ord) msg_feedback(u, ord, "race_notake", "race", u_race(u2))); return; } - if (!u2 && !getunitpeasants) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, - "feedback_unit_not_found", "")); - return; - } if (u->items) { item **itmp = &u->items; while (*itmp) { @@ -628,8 +623,9 @@ void give_cmd(unit * u, order * ord) itmp = &itm->next; } } - if (!given) + if (!given) { cmistake(u, ord, 38, MSG_COMMERCE); + } return; } diff --git a/src/give.h b/src/give.h index dfd53cddc..7a579d3df 100644 --- a/src/give.h +++ b/src/give.h @@ -29,6 +29,7 @@ extern "C" { void give_unit(struct unit *u, struct unit *u2, struct order *ord); void give_cmd(struct unit * u, struct order * ord); struct message * check_give(const struct unit * u, const struct unit * u2, struct order *ord); + bool can_give_to(struct unit *u, struct unit *u2); #ifdef __cplusplus } diff --git a/src/give.test.c b/src/give.test.c index 517675e4a..f4d929c31 100644 --- a/src/give.test.c +++ b/src/give.test.c @@ -43,7 +43,6 @@ static void test_give_unit_to_peasants(CuTest * tc) { env.f2 = 0; setup_give(&env); rsetpeasants(env.r, 0); - getunitpeasants = true; give_unit(env.src, NULL, NULL); CuAssertIntEquals(tc, 0, env.src->number); CuAssertIntEquals(tc, 1, env.r->land->peasants); @@ -57,7 +56,6 @@ static void test_give_unit_in_ocean(CuTest * tc) { env.f2 = 0; setup_give(&env); env.r->terrain = test_create_terrain("ocean", SEA_REGION); - getunitpeasants = true; give_unit(env.src, NULL, NULL); CuAssertIntEquals(tc, 0, env.src->number); test_cleanup(); diff --git a/src/kernel/config.c b/src/kernel/config.c index 3dd22b159..5a68597d4 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1015,19 +1015,38 @@ int read_unitid(const faction * f, const region * r) return atoi36((const char *)s); } -/* exported symbol */ -bool getunitpeasants; - -unit *getunit(const region * r, const faction * f) +int getunit(const region * r, const faction * f, unit **uresult) +{ + int n = read_unitid(f, r); + unit *u2; + + if (n == 0) { + *uresult = 0; + return GET_PEASANTS; + } + if (n < 0) + return 0; + + *uresult = u2 = findunit(n); + if (u2 != NULL && u2->region == r) { + /* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition + * here, but it got removed because of a bug that made units disappear: + * http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172 + */ + return GET_UNIT; + } + + return GET_NOTFOUND; +} + +unit *getunit_deprecated(const region * r, const faction * f) { int n = read_unitid(f, r); unit *u2; if (n == 0) { - getunitpeasants = 1; return NULL; } - getunitpeasants = 0; if (n < 0) return 0; diff --git a/src/kernel/config.h b/src/kernel/config.h index 0a1f5b242..da94ae072 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -60,6 +60,11 @@ extern "C" { #define PLAGUE_HEALCHANCE 0.25F /* Wahrscheinlichkeit Heilung */ #define PLAGUE_HEALCOST 30 /* Heilkosten */ + + /* getunit results: */ +#define GET_UNIT 0 +#define GET_NOTFOUND 1 +#define GET_PEASANTS 2 /* Bewegungsweiten: */ #define BP_WALKING 4 #define BP_RIDING 6 @@ -163,7 +168,8 @@ extern "C" { struct unit *createunit(struct region *r, struct faction *f, int number, const struct race *rc); void create_unitid(struct unit *u, int id); - struct unit *getunit(const struct region *r, const struct faction *f); + struct unit *getunit_deprecated(const struct region *r, const struct faction *f); + int getunit(const struct region * r, const struct faction * f, struct unit **uresult); int read_unitid(const struct faction *f, const struct region *r); @@ -371,7 +377,6 @@ extern "C" { extern int turn; extern int verbosity; - extern bool getunitpeasants; /** report options **/ extern const char *options[MAXOPTIONS]; diff --git a/src/laws.c b/src/laws.c index 44bec3642..6b0b229ab 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1830,7 +1830,7 @@ int name_cmd(struct unit *u, struct order *ord) case P_UNIT: if (foreign) { - unit *u2 = getunit(r, u->faction); + unit *u2 = getunit_deprecated(r, u->faction); if (!u2 || !cansee(u->faction, r, u2, 0)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, diff --git a/src/move.c b/src/move.c index b7fa6feb4..f51884937 100644 --- a/src/move.c +++ b/src/move.c @@ -1248,7 +1248,7 @@ static bool transport(unit * ut, unit * u) for (ord = ut->orders; ord; ord = ord->next) { if (getkeyword(ord) == K_TRANSPORT) { init_order(ord); - if (getunit(ut->region, ut->faction) == u) { + if (getunit_deprecated(ut->region, ut->faction) == u) { return true; } } @@ -1281,7 +1281,7 @@ static void init_transportation(void) unit *ut; init_order(u->thisorder); - ut = getunit(r, u->faction); + ut = getunit_deprecated(r, u->faction); if (ut == NULL) { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "feedback_unit_not_found", "")); @@ -1312,14 +1312,14 @@ static void init_transportation(void) if (getkeyword(ord) == K_TRANSPORT) { init_order(ord); for (;;) { - unit *ut = getunit(r, u->faction); + unit *ut = getunit_deprecated(r, u->faction); if (ut == NULL) break; if (getkeyword(ut->thisorder) == K_DRIVE && can_move(ut) && !fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { init_order(ut->thisorder); - if (getunit(r, ut->faction) == u) { + if (getunit_deprecated(r, ut->faction) == u) { w += weight(ut); } } @@ -2204,7 +2204,7 @@ static const region_list *travel_i(unit * u, const region_list * route_begin, continue; init_order(ord); - ut = getunit(r, u->faction); + ut = getunit_deprecated(r, u->faction); if (ut != NULL) { if (getkeyword(ut->thisorder) == K_DRIVE) { if (ut->building && !can_leave(ut)) { @@ -2219,7 +2219,7 @@ static const region_list *travel_i(unit * u, const region_list * route_begin, if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { init_order(ut->thisorder); - if (getunit(u->region, ut->faction) == u) { + if (getunit_deprecated(u->region, ut->faction) == u) { const region_list *route_to = travel_route(ut, route_begin, route_end, ord, TRAVEL_TRANSPORTED); diff --git a/src/spy.c b/src/spy.c index 00616a47e..438cc29df 100644 --- a/src/spy.c +++ b/src/spy.c @@ -121,7 +121,7 @@ int spy_cmd(unit * u, struct order *ord) region *r = u->region; init_order(ord); - target = getunit(r, u->faction); + target = getunit_deprecated(r, u->faction); if (!target) { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, diff --git a/src/study.c b/src/study.c index 6bc889a59..d76fd0353 100644 --- a/src/study.c +++ b/src/study.c @@ -390,7 +390,7 @@ int teach_cmd(unit * u, struct order *ord) init_order(ord); while (!parser_end()) { - unit *u2 = getunit(r, u->faction); + unit *u2 = getunit_deprecated(r, u->faction); bool feedback; ++count; @@ -406,7 +406,7 @@ 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); + getunit_deprecated(r, u->faction); } token = getstrtoken(); From 98994f233dd1059971f2538ee3bac3a7e55cb0df Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Dec 2014 21:06:47 +0100 Subject: [PATCH 2/3] remove the deprecated getunit function. fix the build, missing return value from give_control_cmd. --- src/economy.c | 2 +- src/kernel/config.c | 34 +- src/kernel/config.h | 1 - src/laws.c | 3 +- src/move.c | 32 +- src/spy.c | 779 ++++++++++++++++++++++---------------------- src/study.c | 6 +- 7 files changed, 429 insertions(+), 428 deletions(-) diff --git a/src/economy.c b/src/economy.c index 566536f07..6938be4c3 100644 --- a/src/economy.c +++ b/src/economy.c @@ -640,7 +640,7 @@ int give_control_cmd(unit * u, order * ord) if (!can_give_to(u, u2)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", "")); - return; + return 0; } else if (!u->building && !u->ship) { msg = cmistake(u, ord, 140, MSG_EVENT); diff --git a/src/kernel/config.c b/src/kernel/config.c index 5a68597d4..9cb6ee7ef 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1021,13 +1021,18 @@ int getunit(const region * r, const faction * f, unit **uresult) unit *u2; if (n == 0) { - *uresult = 0; + if (uresult) { + *uresult = 0; + } return GET_PEASANTS; } if (n < 0) - return 0; + return GET_NOTFOUND; - *uresult = u2 = findunit(n); + u2 = findunit(n); + if (uresult) { + *uresult = u2; + } if (u2 != NULL && u2->region == r) { /* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition * here, but it got removed because of a bug that made units disappear: @@ -1039,29 +1044,6 @@ int getunit(const region * r, const faction * f, unit **uresult) return GET_NOTFOUND; } -unit *getunit_deprecated(const region * r, const faction * f) -{ - int n = read_unitid(f, r); - unit *u2; - - if (n == 0) { - return NULL; - } - if (n < 0) - return 0; - - u2 = findunit(n); - if (u2 != NULL && u2->region == r) { - /* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition - * here, but it got removed because of a bug that made units disappear: - * http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172 - */ - return u2; - } - - return NULL; -} - /* - String Listen --------------------------------------------- */ void addstrlist(strlist ** SP, const char *s) { diff --git a/src/kernel/config.h b/src/kernel/config.h index da94ae072..0e00110a6 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -168,7 +168,6 @@ extern "C" { struct unit *createunit(struct region *r, struct faction *f, int number, const struct race *rc); void create_unitid(struct unit *u, int id); - struct unit *getunit_deprecated(const struct region *r, const struct faction *f); int getunit(const struct region * r, const struct faction * f, struct unit **uresult); int read_unitid(const struct faction *f, const struct region *r); diff --git a/src/laws.c b/src/laws.c index 6b0b229ab..253a17167 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1830,8 +1830,9 @@ int name_cmd(struct unit *u, struct order *ord) case P_UNIT: if (foreign) { - unit *u2 = getunit_deprecated(r, u->faction); + unit *u2 = 0; + getunit(r, u->faction, &u2); if (!u2 || !cansee(u->faction, r, u2, 0)) { ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "feedback_unit_not_found", "")); diff --git a/src/move.c b/src/move.c index f51884937..5ace63929 100644 --- a/src/move.c +++ b/src/move.c @@ -1247,8 +1247,10 @@ static bool transport(unit * ut, unit * u) for (ord = ut->orders; ord; ord = ord->next) { if (getkeyword(ord) == K_TRANSPORT) { + unit *u2; init_order(ord); - if (getunit_deprecated(ut->region, ut->faction) == u) { + getunit(ut->region, ut->faction, &u2); + if (u2 == u) { return true; } } @@ -1278,11 +1280,10 @@ static void init_transportation(void) for (u = r->units; u; u = u->next) { if (getkeyword(u->thisorder) == K_DRIVE && can_move(u) && !fval(u, UFL_NOTMOVING) && !LongHunger(u)) { - unit *ut; + unit *ut = 0; init_order(u->thisorder); - ut = getunit_deprecated(r, u->faction); - if (ut == NULL) { + if (getunit(r, u->faction, &ut) != GET_UNIT) { ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, "feedback_unit_not_found", "")); continue; @@ -1312,14 +1313,18 @@ static void init_transportation(void) if (getkeyword(ord) == K_TRANSPORT) { init_order(ord); for (;;) { - unit *ut = getunit_deprecated(r, u->faction); + unit *ut = 0; - if (ut == NULL) + if (getunit(r, u->faction, &ut) != GET_UNIT) { break; - if (getkeyword(ut->thisorder) == K_DRIVE && can_move(ut) - && !fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { + } + if (getkeyword(ut->thisorder) == K_DRIVE && + can_move(ut) && !fval(ut, UFL_NOTMOVING) && + !LongHunger(ut)) { + unit *u2; init_order(ut->thisorder); - if (getunit_deprecated(r, ut->faction) == u) { + getunit(r, ut->faction, &u2); + if (u2 == u) { w += weight(ut); } } @@ -2198,14 +2203,13 @@ static const region_list *travel_i(unit * u, const region_list * route_begin, /* transportation */ for (ord = u->orders; ord; ord = ord->next) { - unit *ut; + unit *ut = 0; if (getkeyword(ord) != K_TRANSPORT) continue; init_order(ord); - ut = getunit_deprecated(r, u->faction); - if (ut != NULL) { + if (getunit(r, u->faction, &ut) == GET_UNIT) { if (getkeyword(ut->thisorder) == K_DRIVE) { if (ut->building && !can_leave(ut)) { cmistake(ut, ut->thisorder, 150, MSG_MOVE); @@ -2218,8 +2222,10 @@ static const region_list *travel_i(unit * u, const region_list * route_begin, bool found = false; if (!fval(ut, UFL_NOTMOVING) && !LongHunger(ut)) { + unit *u2; init_order(ut->thisorder); - if (getunit_deprecated(u->region, ut->faction) == u) { + getunit(u->region, ut->faction, &u2); + if (u2 == u) { const region_list *route_to = travel_route(ut, route_begin, route_end, ord, TRAVEL_TRANSPORTED); diff --git a/src/spy.c b/src/spy.c index 438cc29df..5b96849c5 100644 --- a/src/spy.c +++ b/src/spy.c @@ -1,7 +1,7 @@ /* Copyright (c) 1998-2010, Enno Rehling - Katja Zedel +Katja Zedel Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -58,453 +58,464 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * Spionage des Spions */ void spy_message(int spy, const unit * u, const unit * target) { - const char *str = report_kampfstatus(target, u->faction->locale); + const char *str = report_kampfstatus(target, u->faction->locale); - ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u, - target, str)); - if (spy > 20) { - sc_mage *mage = get_mage(target); - /* for mages, spells and magic school */ - if (mage) { - ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "target type", - target, magic_school[mage->magietyp])); - } - } - if (spy > 6) { - faction *fv = visible_faction(u->faction, target); - if (fv && fv != target->faction) { - /* true faction */ - ADDMSG(&u->faction->msgs, msg_message("spyreport_faction", - "target faction", target, target->faction)); - add_seen_faction(u->faction, target->faction); - } - } - if (spy > 0) { - int first = 1; - int found = 0; - skill *sv; - char buf[4096]; - - buf[0] = 0; - for (sv = target->skills; sv != target->skills + target->skill_size; ++sv) { - if (sv->level > 0) { - found++; - if (first == 1) { - first = 0; - } else { - strncat(buf, ", ", sizeof(buf)-1); + ADDMSG(&u->faction->msgs, msg_message("spyreport", "spy target status", u, + target, str)); + if (spy > 20) { + sc_mage *mage = get_mage(target); + /* for mages, spells and magic school */ + if (mage) { + ADDMSG(&u->faction->msgs, msg_message("spyreport_mage", "target type", + target, magic_school[mage->magietyp])); } - strncat(buf, (const char *)skillname((skill_t)sv->id, u->faction->locale), - sizeof(buf)-1); - strncat(buf, " ", sizeof(buf)-1); - strncat(buf, itoa10(eff_skill(target, (skill_t)sv->id, target->region)), - sizeof(buf)-1); - } } - if (found) { - ADDMSG(&u->faction->msgs, msg_message("spyreport_skills", "target skills", - target, buf)); + if (spy > 6) { + faction *fv = visible_faction(u->faction, target); + if (fv && fv != target->faction) { + /* true faction */ + ADDMSG(&u->faction->msgs, msg_message("spyreport_faction", + "target faction", target, target->faction)); + add_seen_faction(u->faction, target->faction); + } } + if (spy > 0) { + int first = 1; + int found = 0; + skill *sv; + char buf[4096]; - if (target->items) { - ADDMSG(&u->faction->msgs, msg_message("spyreport_items", "target items", - target, target->items)); + buf[0] = 0; + for (sv = target->skills; sv != target->skills + target->skill_size; ++sv) { + if (sv->level > 0) { + found++; + if (first == 1) { + first = 0; + } + else { + strncat(buf, ", ", sizeof(buf) - 1); + } + strncat(buf, (const char *)skillname((skill_t)sv->id, u->faction->locale), + sizeof(buf) - 1); + strncat(buf, " ", sizeof(buf) - 1); + strncat(buf, itoa10(eff_skill(target, (skill_t)sv->id, target->region)), + sizeof(buf) - 1); + } + } + if (found) { + ADDMSG(&u->faction->msgs, msg_message("spyreport_skills", "target skills", + target, buf)); + } + + if (target->items) { + ADDMSG(&u->faction->msgs, msg_message("spyreport_items", "target items", + target, target->items)); + } } - } } int spy_cmd(unit * u, struct order *ord) { - unit *target; - int spy, observe; - double spychance, observechance; - region *r = u->region; + unit *target; + int spy, observe; + double spychance, observechance; + region *r = u->region; - init_order(ord); - target = getunit_deprecated(r, u->faction); + init_order(ord); + getunit(r, u->faction, &target); - if (!target) { - ADDMSG(&u->faction->msgs, msg_feedback(u, u->thisorder, - "feedback_unit_not_found", "")); + if (!target) { + ADDMSG(&u->faction->msgs, + msg_feedback(u, u->thisorder, "feedback_unit_not_found", "")); + return 0; + } + if (!can_contact(r, u, target)) { + cmistake(u, u->thisorder, 24, MSG_EVENT); + return 0; + } + if (eff_skill(u, SK_SPY, r) < 1) { + cmistake(u, u->thisorder, 39, MSG_EVENT); + return 0; + } + /* Die Grundchance fuer einen erfolgreichen Spionage-Versuch ist 10%. + * Fuer jeden Talentpunkt, den das Spionagetalent das Tarnungstalent + * des Opfers uebersteigt, erhoeht sich dieses um 5%*/ + spy = eff_skill(u, SK_SPY, r) - eff_skill(target, SK_STEALTH, r); + spychance = 0.1 + _max(spy * 0.05, 0.0); + + if (chance(spychance)) { + produceexp(u, SK_SPY, u->number); + spy_message(spy, u, target); + } + else { + ADDMSG(&u->faction->msgs, msg_message("spyfail", "spy target", u, target)); + } + + /* der Spion kann identifiziert werden, wenn das Opfer bessere + * Wahrnehmung als das Ziel Tarnung + Spionage/2 hat */ + observe = eff_skill(target, SK_PERCEPTION, r) + - (effskill(u, SK_STEALTH) + eff_skill(u, SK_SPY, r) / 2); + + if (invisible(u, target) >= u->number) { + observe = _min(observe, 0); + } + + /* Anschliessend wird - unabhaengig vom Erfolg - gewuerfelt, ob der + * Spionageversuch bemerkt wurde. Die Wahrscheinlich dafuer ist (100 - + * SpionageSpion*5 + WahrnehmungOpfer*2)%. */ + observechance = 1.0 - (eff_skill(u, SK_SPY, r) * 0.05) + + (eff_skill(target, SK_PERCEPTION, r) * 0.02); + + if (chance(observechance)) { + ADDMSG(&target->faction->msgs, msg_message("spydetect", + "spy target", observe > 0 ? u : NULL, target)); + } return 0; - } - if (!can_contact(r, u, target)) { - cmistake(u, u->thisorder, 24, MSG_EVENT); - return 0; - } - if (eff_skill(u, SK_SPY, r) < 1) { - cmistake(u, u->thisorder, 39, MSG_EVENT); - return 0; - } - /* Die Grundchance fuer einen erfolgreichen Spionage-Versuch ist 10%. - * Fuer jeden Talentpunkt, den das Spionagetalent das Tarnungstalent - * des Opfers uebersteigt, erhoeht sich dieses um 5%*/ - spy = eff_skill(u, SK_SPY, r) - eff_skill(target, SK_STEALTH, r); - spychance = 0.1 + _max(spy * 0.05, 0.0); - - if (chance(spychance)) { - produceexp(u, SK_SPY, u->number); - spy_message(spy, u, target); - } else { - ADDMSG(&u->faction->msgs, msg_message("spyfail", "spy target", u, target)); - } - - /* der Spion kann identifiziert werden, wenn das Opfer bessere - * Wahrnehmung als das Ziel Tarnung + Spionage/2 hat */ - observe = eff_skill(target, SK_PERCEPTION, r) - - (effskill(u, SK_STEALTH) + eff_skill(u, SK_SPY, r) / 2); - - if (invisible(u, target) >= u->number) { - observe = _min(observe, 0); - } - - /* Anschliessend wird - unabhaengig vom Erfolg - gewuerfelt, ob der - * Spionageversuch bemerkt wurde. Die Wahrscheinlich dafuer ist (100 - - * SpionageSpion*5 + WahrnehmungOpfer*2)%. */ - observechance = 1.0 - (eff_skill(u, SK_SPY, r) * 0.05) - + (eff_skill(target, SK_PERCEPTION, r) * 0.02); - - if (chance(observechance)) { - ADDMSG(&target->faction->msgs, msg_message("spydetect", - "spy target", observe > 0 ? u : NULL, target)); - } - return 0; } void set_factionstealth(unit * u, faction * f) { - region *lastr = NULL; - /* for all units mu of our faction, check all the units in the region - * they are in, if their visible faction is f, it's ok. use lastr to - * avoid testing the same region twice in a row. */ - unit *mu = u->faction->units; - while (mu != NULL) { - if (mu->number && mu->region != lastr) { - unit *ru = mu->region->units; - lastr = mu->region; - while (ru != NULL) { - if (ru->number) { - faction *fv = visible_faction(f, ru); - if (fv == f) { - if (cansee(f, lastr, ru, 0)) - break; - } + region *lastr = NULL; + /* for all units mu of our faction, check all the units in the region + * they are in, if their visible faction is f, it's ok. use lastr to + * avoid testing the same region twice in a row. */ + unit *mu = u->faction->units; + while (mu != NULL) { + if (mu->number && mu->region != lastr) { + unit *ru = mu->region->units; + lastr = mu->region; + while (ru != NULL) { + if (ru->number) { + faction *fv = visible_faction(f, ru); + if (fv == f) { + if (cansee(f, lastr, ru, 0)) + break; + } + } + ru = ru->next; + } + if (ru != NULL) + break; } - ru = ru->next; - } - if (ru != NULL) - break; + mu = mu->nextF; + } + if (mu != NULL) { + attrib *a = a_find(u->attribs, &at_otherfaction); + if (!a) + a = a_add(&u->attribs, make_otherfaction(f)); + else + a->data.v = f; } - mu = mu->nextF; - } - if (mu != NULL) { - attrib *a = a_find(u->attribs, &at_otherfaction); - if (!a) - a = a_add(&u->attribs, make_otherfaction(f)); - else - a->data.v = f; - } } int setstealth_cmd(unit * u, struct order *ord) { - const char *s; - int level, rule; - const race *trace; + const char *s; + int level, rule; + const race *trace; - init_order(ord); - s = getstrtoken(); + init_order(ord); + s = getstrtoken(); - /* Tarne ohne Parameter: Setzt maximale Tarnung */ + /* Tarne ohne Parameter: Setzt maximale Tarnung */ - if (s == NULL || *s == 0) { - u_seteffstealth(u, -1); - return 0; - } - - if (isdigit(s[0])) { - /* Tarnungslevel setzen */ - level = atoi((const char *)s); - if (level > effskill(u, SK_STEALTH)) { - ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_lowstealth", "")); - return 0; - } - u_seteffstealth(u, level); - return 0; - } - - trace = findrace(s, u->faction->locale); - if (trace) { - /* demons can cloak as other player-races */ - if (u_race(u) == get_race(RC_DAEMON)) { - race_t allowed[] = { RC_DWARF, RC_ELF, RC_ORC, RC_GOBLIN, RC_HUMAN, - RC_TROLL, RC_DAEMON, RC_INSECT, RC_HALFLING, RC_CAT, RC_AQUARIAN, - NORACE - }; - int i; - for (i = 0; allowed[i] != NORACE; ++i) - if (get_race(allowed[i]) == trace) - break; - if (get_race(allowed[i]) == trace) { - u->irace = trace; - if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) - set_racename(&u->attribs, NULL); - } - return 0; + if (s == NULL || *s == 0) { + u_seteffstealth(u, -1); + return 0; } - /* Singdrachen koennen sich nur als Drachen tarnen */ - if (u_race(u) == get_race(RC_SONGDRAGON) - || u_race(u) == get_race(RC_BIRTHDAYDRAGON)) { - if (trace == get_race(RC_SONGDRAGON) || trace == get_race(RC_FIREDRAGON) - || trace == get_race(RC_DRAGON) || trace == get_race(RC_WYRM)) { - u->irace = trace; - if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) - set_racename(&u->attribs, NULL); - } - return 0; - } - - /* Daemomen und Illusionsparteien koennen sich als andere race tarnen */ - if (u_race(u)->flags & RCF_SHAPESHIFT) { - if (playerrace(trace)) { - u->irace = trace; - if ((u_race(u)->flags & RCF_SHAPESHIFTANY) && get_racename(u->attribs)) - set_racename(&u->attribs, NULL); - } - } - return 0; - } - - switch (findparam(s, u->faction->locale)) { - case P_FACTION: - /* TARNE PARTEI [NICHT|NUMMER abcd] */ - rule = rule_stealth_faction(); - if (!rule) { - /* TARNE PARTEI is disabled */ - break; - } - s = getstrtoken(); - if (rule&1) { - if (!s || *s == 0) { - fset(u, UFL_ANON_FACTION); - break; - } else if (findparam(s, u->faction->locale) == P_NOT) { - freset(u, UFL_ANON_FACTION); - break; + if (isdigit(s[0])) { + /* Tarnungslevel setzen */ + level = atoi((const char *)s); + if (level > effskill(u, SK_STEALTH)) { + ADDMSG(&u->faction->msgs, msg_feedback(u, ord, "error_lowstealth", "")); + return 0; } - } - if (rule&2) { - if (get_keyword(s, u->faction->locale) == K_NUMBER) { - const char *s2 = getstrtoken(); - int nr = -1; + u_seteffstealth(u, level); + return 0; + } - if (s2) { - nr = atoi36(s2); - } - if (!s2 || *s2 == 0 || nr == u->faction->no) { - a_removeall(&u->attribs, &at_otherfaction); - break; - } else { - struct faction *f = findfaction(nr); - if (f == NULL) { - cmistake(u, ord, 66, MSG_EVENT); - break; - } else { - set_factionstealth(u, f); - break; + trace = findrace(s, u->faction->locale); + if (trace) { + /* demons can cloak as other player-races */ + if (u_race(u) == get_race(RC_DAEMON)) { + race_t allowed[] = { RC_DWARF, RC_ELF, RC_ORC, RC_GOBLIN, RC_HUMAN, + RC_TROLL, RC_DAEMON, RC_INSECT, RC_HALFLING, RC_CAT, RC_AQUARIAN, + NORACE + }; + int i; + for (i = 0; allowed[i] != NORACE; ++i) + if (get_race(allowed[i]) == trace) + break; + if (get_race(allowed[i]) == trace) { + u->irace = trace; + if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) + set_racename(&u->attribs, NULL); } - } + return 0; } - } - cmistake(u, ord, 289, MSG_EVENT); - break; + + /* Singdrachen koennen sich nur als Drachen tarnen */ + if (u_race(u) == get_race(RC_SONGDRAGON) + || u_race(u) == get_race(RC_BIRTHDAYDRAGON)) { + if (trace == get_race(RC_SONGDRAGON) || trace == get_race(RC_FIREDRAGON) + || trace == get_race(RC_DRAGON) || trace == get_race(RC_WYRM)) { + u->irace = trace; + if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) + set_racename(&u->attribs, NULL); + } + return 0; + } + + /* Daemomen und Illusionsparteien koennen sich als andere race tarnen */ + if (u_race(u)->flags & RCF_SHAPESHIFT) { + if (playerrace(trace)) { + u->irace = trace; + if ((u_race(u)->flags & RCF_SHAPESHIFTANY) && get_racename(u->attribs)) + set_racename(&u->attribs, NULL); + } + } + return 0; + } + + switch (findparam(s, u->faction->locale)) { + case P_FACTION: + /* TARNE PARTEI [NICHT|NUMMER abcd] */ + rule = rule_stealth_faction(); + if (!rule) { + /* TARNE PARTEI is disabled */ + break; + } + s = getstrtoken(); + if (rule & 1) { + if (!s || *s == 0) { + fset(u, UFL_ANON_FACTION); + break; + } + else if (findparam(s, u->faction->locale) == P_NOT) { + freset(u, UFL_ANON_FACTION); + break; + } + } + if (rule & 2) { + if (get_keyword(s, u->faction->locale) == K_NUMBER) { + const char *s2 = getstrtoken(); + int nr = -1; + + if (s2) { + nr = atoi36(s2); + } + if (!s2 || *s2 == 0 || nr == u->faction->no) { + a_removeall(&u->attribs, &at_otherfaction); + break; + } + else { + struct faction *f = findfaction(nr); + if (f == NULL) { + cmistake(u, ord, 66, MSG_EVENT); + break; + } + else { + set_factionstealth(u, f); + break; + } + } + } + } + cmistake(u, ord, 289, MSG_EVENT); + break; case P_ANY: case P_NOT: - /* TARNE ALLES (was nicht so alles geht?) */ - u_seteffstealth(u, -1); - break; + /* TARNE ALLES (was nicht so alles geht?) */ + u_seteffstealth(u, -1); + break; default: - if (u_race(u)->flags & RCF_SHAPESHIFTANY) { - set_racename(&u->attribs, s); - } else { - cmistake(u, ord, 289, MSG_EVENT); - } - } - return 0; + if (u_race(u)->flags & RCF_SHAPESHIFTANY) { + set_racename(&u->attribs, s); + } + else { + cmistake(u, ord, 289, MSG_EVENT); + } + } + return 0; } static int crew_skill(region * r, faction * f, ship * sh, skill_t sk) { - int value = 0; - unit *u; + int value = 0; + unit *u; - for (u = r->units; u; u = u->next) { - if (u->ship == sh && u->faction == f) { - int s = eff_skill(u, sk, r); - value = _max(s, value); + for (u = r->units; u; u = u->next) { + if (u->ship == sh && u->faction == f) { + int s = eff_skill(u, sk, r); + value = _max(s, value); + } } - } - return value; + return value; } static int try_destruction(unit * u, unit * u2, const ship * sh, int skilldiff) { - const char *destruction_success_msg = "destroy_ship_0"; - const char *destruction_failed_msg = "destroy_ship_1"; - const char *destruction_detected_msg = "destroy_ship_2"; - const char *detect_failure_msg = "destroy_ship_3"; - const char *object_destroyed_msg = "destroy_ship_4"; + const char *destruction_success_msg = "destroy_ship_0"; + const char *destruction_failed_msg = "destroy_ship_1"; + const char *destruction_detected_msg = "destroy_ship_2"; + const char *detect_failure_msg = "destroy_ship_3"; + const char *object_destroyed_msg = "destroy_ship_4"; - if (skilldiff == 0) { - /* tell the unit that the attempt failed: */ - ADDMSG(&u->faction->msgs, msg_message(destruction_failed_msg, "ship unit", - sh, u)); - /* tell the enemy about the attempt: */ - if (u2) { - ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh)); + if (skilldiff == 0) { + /* tell the unit that the attempt failed: */ + ADDMSG(&u->faction->msgs, msg_message(destruction_failed_msg, "ship unit", + sh, u)); + /* tell the enemy about the attempt: */ + if (u2) { + ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh)); + } + return 0; } - return 0; - } else if (skilldiff < 0) { - /* tell the unit that the attempt was detected: */ - ADDMSG(&u2->faction->msgs, msg_message(destruction_detected_msg, - "ship unit", sh, u)); - /* tell the enemy whodunit: */ - if (u2) { - ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh)); + else if (skilldiff < 0) { + /* tell the unit that the attempt was detected: */ + ADDMSG(&u2->faction->msgs, msg_message(destruction_detected_msg, + "ship unit", sh, u)); + /* tell the enemy whodunit: */ + if (u2) { + ADDMSG(&u2->faction->msgs, msg_message(detect_failure_msg, "ship", sh)); + } + return 0; } - return 0; - } else { - /* tell the unit that the attempt succeeded */ - ADDMSG(&u->faction->msgs, msg_message(destruction_success_msg, "ship unit", - sh, u)); - if (u2) { - ADDMSG(&u2->faction->msgs, msg_message(object_destroyed_msg, "ship", sh)); + else { + /* tell the unit that the attempt succeeded */ + ADDMSG(&u->faction->msgs, msg_message(destruction_success_msg, "ship unit", + sh, u)); + if (u2) { + ADDMSG(&u2->faction->msgs, msg_message(object_destroyed_msg, "ship", sh)); + } } - } - return 1; /* success */ + return 1; /* success */ } static void sink_ship(region * r, ship * sh, const char *name, unit * saboteur) { - unit **ui, *u; - region *safety = r; - int i; - direction_t d; - double probability = 0.0; - message *sink_msg = NULL; - faction *f; + unit **ui, *u; + region *safety = r; + int i; + direction_t d; + double probability = 0.0; + message *sink_msg = NULL; + faction *f; - for (f = NULL, u = r->units; u; u = u->next) { - /* slight optimization to avoid dereferencing u->faction each time */ - if (f != u->faction) { - f = u->faction; - freset(f, FFL_SELECT); - } - } - - /* figure out what a unit's chances of survival are: */ - if (!fval(r->terrain, SEA_REGION)) { - probability = CANAL_SWIMMER_CHANCE; - } else { - for (d = 0; d != MAXDIRECTIONS; ++d) { - region *rn = rconnect(r, d); - if (!fval(rn->terrain, SEA_REGION) && !move_blocked(NULL, r, rn)) { - safety = rn; - probability = OCEAN_SWIMMER_CHANCE; - break; - } - } - } - for (ui = &r->units; *ui; ui = &(*ui)->next) { - unit *u = *ui; - - /* inform this faction about the sinking ship: */ - if (!fval(u->faction, FFL_SELECT)) { - fset(u->faction, FFL_SELECT); - if (sink_msg == NULL) { - sink_msg = msg_message("sink_msg", "ship region", sh, r); - } - add_message(&f->msgs, sink_msg); + for (f = NULL, u = r->units; u; u = u->next) { + /* slight optimization to avoid dereferencing u->faction each time */ + if (f != u->faction) { + f = u->faction; + freset(f, FFL_SELECT); + } } - if (u->ship == sh) { - int dead = 0; - message *msg; - - /* if this fails, I misunderstood something: */ - for (i = 0; i != u->number; ++i) - if (chance(probability)) - ++dead; - - if (dead != u->number) { - /* she will live. but her items get stripped */ - if (dead > 0) { - msg = - msg_message("sink_lost_msg", "dead region unit", dead, safety, u); - } else { - msg = msg_message("sink_saved_msg", "region unit", safety, u); - } - leave_ship(u); - if (r != safety) { - setguard(u, GUARD_NONE); - } - while (u->items) { - i_remove(&u->items, u->items); - } - move_unit(u, safety, NULL); - } else { - msg = msg_message("sink_lost_msg", "dead region unit", dead, NULL, u); - } - add_message(&u->faction->msgs, msg); - msg_release(msg); - if (dead == u->number) { - /* the poor creature, she dies */ - if (remove_unit(ui, u) != 0) { - ui = &u->next; - } - } + /* figure out what a unit's chances of survival are: */ + if (!fval(r->terrain, SEA_REGION)) { + probability = CANAL_SWIMMER_CHANCE; } - } - if (sink_msg) - msg_release(sink_msg); - /* finally, get rid of the ship */ - remove_ship(&sh->region->ships, sh); + else { + for (d = 0; d != MAXDIRECTIONS; ++d) { + region *rn = rconnect(r, d); + if (!fval(rn->terrain, SEA_REGION) && !move_blocked(NULL, r, rn)) { + safety = rn; + probability = OCEAN_SWIMMER_CHANCE; + break; + } + } + } + for (ui = &r->units; *ui; ui = &(*ui)->next) { + unit *u = *ui; + + /* inform this faction about the sinking ship: */ + if (!fval(u->faction, FFL_SELECT)) { + fset(u->faction, FFL_SELECT); + if (sink_msg == NULL) { + sink_msg = msg_message("sink_msg", "ship region", sh, r); + } + add_message(&f->msgs, sink_msg); + } + + if (u->ship == sh) { + int dead = 0; + message *msg; + + /* if this fails, I misunderstood something: */ + for (i = 0; i != u->number; ++i) + if (chance(probability)) + ++dead; + + if (dead != u->number) { + /* she will live. but her items get stripped */ + if (dead > 0) { + msg = + msg_message("sink_lost_msg", "dead region unit", dead, safety, u); + } + else { + msg = msg_message("sink_saved_msg", "region unit", safety, u); + } + leave_ship(u); + if (r != safety) { + setguard(u, GUARD_NONE); + } + while (u->items) { + i_remove(&u->items, u->items); + } + move_unit(u, safety, NULL); + } + else { + msg = msg_message("sink_lost_msg", "dead region unit", dead, NULL, u); + } + add_message(&u->faction->msgs, msg); + msg_release(msg); + if (dead == u->number) { + /* the poor creature, she dies */ + if (remove_unit(ui, u) != 0) { + ui = &u->next; + } + } + } + } + if (sink_msg) + msg_release(sink_msg); + /* finally, get rid of the ship */ + remove_ship(&sh->region->ships, sh); } int sabotage_cmd(unit * u, struct order *ord) { - const char *s; - int i; - ship *sh; - unit *u2; - char buffer[DISPLAYSIZE]; - region *r = u->region; - int skdiff; + const char *s; + int i; + ship *sh; + unit *u2; + char buffer[DISPLAYSIZE]; + region *r = u->region; + int skdiff; - init_order(ord); - s = getstrtoken(); + init_order(ord); + s = getstrtoken(); - i = findparam(s, u->faction->locale); + i = findparam(s, u->faction->locale); - switch (i) { + switch (i) { case P_SHIP: - sh = u->ship; - if (!sh) { - cmistake(u, u->thisorder, 144, MSG_EVENT); - return 0; - } - u2 = ship_owner(sh); - skdiff = - eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION); - if (try_destruction(u, u2, sh, skdiff)) { - sink_ship(r, sh, buffer, u); - } - break; + sh = u->ship; + if (!sh) { + cmistake(u, u->thisorder, 144, MSG_EVENT); + return 0; + } + u2 = ship_owner(sh); + skdiff = + eff_skill(u, SK_SPY, r) - crew_skill(r, u2->faction, sh, SK_PERCEPTION); + if (try_destruction(u, u2, sh, skdiff)) { + sink_ship(r, sh, buffer, u); + } + break; default: - cmistake(u, u->thisorder, 9, MSG_EVENT); - return 0; - } + cmistake(u, u->thisorder, 9, MSG_EVENT); + return 0; + } - return 0; + return 0; } diff --git a/src/study.c b/src/study.c index d76fd0353..be189970c 100644 --- a/src/study.c +++ b/src/study.c @@ -390,8 +390,10 @@ int teach_cmd(unit * u, struct order *ord) init_order(ord); while (!parser_end()) { - unit *u2 = getunit_deprecated(r, u->faction); + unit *u2; bool feedback; + + getunit(r, u->faction, &u2); ++count; /* Falls die Unit nicht gefunden wird, Fehler melden */ @@ -406,7 +408,7 @@ int teach_cmd(unit * u, struct order *ord) for (j = 0; j != count - 1; ++j) { /* skip over the first 'count' units */ - getunit_deprecated(r, u->faction); + getunit(r, u->faction, NULL); } token = getstrtoken(); From 63f69ec1cf5527d6b54deddab4bd9d33b43bbc98 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 12 Dec 2014 21:55:44 +0100 Subject: [PATCH 3/3] add the test coverage for getunit. fix a bug where NULL was not returned when unit is in the wrong region. --- src/kernel/config.c | 35 ++++++++++++------------ src/kernel/config.test.c | 59 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/src/kernel/config.c b/src/kernel/config.c index 9cb6ee7ef..4d6f18059 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -1018,30 +1018,29 @@ int read_unitid(const faction * f, const region * r) int getunit(const region * r, const faction * f, unit **uresult) { int n = read_unitid(f, r); - unit *u2; + int result = GET_NOTFOUND; + unit *u2 = NULL; if (n == 0) { - if (uresult) { - *uresult = 0; - } - return GET_PEASANTS; + result = GET_PEASANTS; + } + else if (n>0) { + u2 = findunit(n); + if (u2 != NULL && u2->region == r) { + /* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition + * here, but it got removed because of a bug that made units disappear: + * http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172 + */ + result = GET_UNIT; + } + else { + u2 = NULL; + } } - if (n < 0) - return GET_NOTFOUND; - - u2 = findunit(n); if (uresult) { *uresult = u2; } - if (u2 != NULL && u2->region == r) { - /* there used to be a 'u2->flags & UFL_ISNEW || u2->number>0' condition - * here, but it got removed because of a bug that made units disappear: - * http://eressea.upb.de/mantis/bug_view_page.php?bug_id=0000172 - */ - return GET_UNIT; - } - - return GET_NOTFOUND; + return result; } /* - String Listen --------------------------------------------- */ diff --git a/src/kernel/config.test.c b/src/kernel/config.test.c index 78562f5dd..79643106c 100644 --- a/src/kernel/config.test.c +++ b/src/kernel/config.test.c @@ -2,10 +2,68 @@ #include #include +#include +#include +#include +#include +#include +#include #include #include +struct critbit_tree; + +static void test_getunit(CuTest *tc) { + unit *u, *u2; + order *ord; + attrib *a; + struct region *r; + struct locale *lang; + struct terrain_type *t_plain; + struct critbit_tree ** cb; + + test_cleanup(); + lang = get_or_create_locale("de"); + cb = (struct critbit_tree **)get_translations(lang, UT_PARAMS); + add_translation(cb, "TEMP", P_TEMP); + /* note that the english order is FIGHT, not COMBAT, so this is a poor example */ + t_plain = test_create_terrain("plain", LAND_REGION); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, t_plain)); + a = a_add(&u->attribs, a_new(&at_alias)); + a->data.i = atoi36("42"); /* this unit is also TEMP 42 */ + r = test_create_region(1, 0, t_plain); + + ord = create_order(K_GIVE, lang, itoa36(u->no)); + init_order(ord); + CuAssertIntEquals(tc, GET_UNIT, getunit(u->region, u->faction, &u2)); + CuAssertPtrEquals(tc, u, u2); + init_order(ord); + CuAssertIntEquals(tc, GET_NOTFOUND, getunit(r, u->faction, &u2)); + CuAssertPtrEquals(tc, NULL, u2); + free_order(ord); + + ord = create_order(K_GIVE, lang, itoa36(u->no+1)); + init_order(ord); + CuAssertIntEquals(tc, GET_NOTFOUND, getunit(u->region, u->faction, &u2)); + CuAssertPtrEquals(tc, NULL, u2); + free_order(ord); + + ord = create_order(K_GIVE, lang, "0"); + init_order(ord); + CuAssertIntEquals(tc, GET_PEASANTS, getunit(u->region, u->faction, &u2)); + CuAssertPtrEquals(tc, NULL, u2); + free_order(ord); + + ord = create_order(K_GIVE, lang, "TEMP 42"); + init_order(ord); + CuAssertIntEquals(tc, GET_UNIT, getunit(u->region, u->faction, &u2)); + CuAssertPtrEquals(tc, u, u2); + free_order(ord); + + test_cleanup(); +} + static void test_get_set_param(CuTest * tc) { struct param *par = 0; @@ -42,6 +100,7 @@ static void test_param_flt(CuTest * tc) CuSuite *get_config_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_getunit); SUITE_ADD_TEST(suite, test_get_set_param); SUITE_ADD_TEST(suite, test_param_int); SUITE_ADD_TEST(suite, test_param_flt);