diff --git a/src/kernel/curse.c b/src/kernel/curse.c index 01e77eace..4a3e1c045 100644 --- a/src/kernel/curse.c +++ b/src/kernel/curse.c @@ -493,7 +493,7 @@ const curse_type * ct) /* ------------------------------------------------------------- */ /* gibt bei Personenbeschränkten Verzauberungen die Anzahl der * betroffenen Personen zurück. Ansonsten wird 0 zurückgegeben. */ -int get_cursedmen(unit * u, const curse * c) +int get_cursedmen(const unit * u, const curse * c) { int cursedmen = u->number; @@ -631,7 +631,7 @@ curse *create_curse(unit * magician, attrib ** ap, const curse_type * ct, /* hier müssen alle c-typen, die auf Einheiten gezaubert werden können, * berücksichtigt werden */ -static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) +static void do_transfer_curse(curse * c, const unit * u, unit * u2, int n) { int cursedmen = 0; int men = get_cursedmen(u, c); @@ -678,7 +678,7 @@ static void do_transfer_curse(curse * c, unit * u, unit * u2, int n) } } -void transfer_curse(unit * u, unit * u2, int n) +void transfer_curse(const unit * u, unit * u2, int n) { attrib *a; diff --git a/src/kernel/curse.h b/src/kernel/curse.h index 543755c2b..a4fd1c430 100644 --- a/src/kernel/curse.h +++ b/src/kernel/curse.h @@ -267,7 +267,7 @@ extern "C" { /* gibt bei Personenbeschränkten Verzauberungen die Anzahl der * betroffenen Personen zurück. Ansonsten wird 0 zurückgegeben. */ - int get_cursedmen(struct unit *u, const struct curse *c); + int get_cursedmen(const struct unit *u, const struct curse *c); /* setzt/loescht Spezialflag einer Verzauberung (zB 'dauert ewig') */ void c_setflag(curse * c, unsigned int flag); @@ -277,7 +277,7 @@ extern "C" { * korrekt gehandhabt werden. Je nach internen Flag kann dies * unterschiedlich gewünscht sein * */ - void transfer_curse(struct unit *u, struct unit *u2, int n); + void transfer_curse(const struct unit *u, struct unit *u2, int n); /* gibt pointer auf die erste curse-struct zurück, deren Typ ctype ist, * oder einen NULL-pointer diff --git a/src/kernel/messages.c b/src/kernel/messages.c index d3cd4f99b..b8d33f08c 100644 --- a/src/kernel/messages.c +++ b/src/kernel/messages.c @@ -258,15 +258,14 @@ message * msg_error(const unit * u, struct order *ord, int mno) { return msg_feedback(u, ord, msgname, ""); } -message * cmistake(const unit * u, struct order *ord, int mno, int mtype) +void cmistake(const unit * u, struct order *ord, int mno, int mtype) { - message * result; + message * msg; UNUSED_ARG(mtype); - result = msg_error(u, ord, mno); - if (result) { - ADDMSG(&u->faction->msgs, result); + msg = msg_error(u, ord, mno); + if (msg) { + ADDMSG(&u->faction->msgs, msg); } - return result; } void syntax_error(const struct unit *u, struct order *ord) diff --git a/src/kernel/messages.h b/src/kernel/messages.h index a42342153..4eca65fc1 100644 --- a/src/kernel/messages.h +++ b/src/kernel/messages.h @@ -60,7 +60,7 @@ extern "C" { #define ADDMSG(msgs, mcreate) { message * mx = mcreate; if (mx) { assert(mx->refcount>=1); add_message(msgs, mx); msg_release(mx); } } void syntax_error(const struct unit *u, struct order *ord); - struct message * cmistake(const struct unit *u, struct order *ord, int mno, int mtype); + void cmistake(const struct unit *u, struct order *ord, int mno, int mtype); struct message * msg_error(const struct unit * u, struct order *ord, int mno); #ifdef __cplusplus } diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 7b6f135fc..bdd5ac232 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -981,10 +981,9 @@ void move_unit(unit * u, region * r, unit ** ulist) /* ist mist, aber wegen nicht skalierender attribute notwendig: */ #include "alchemy.h" -void clone_men(unit * u, unit * dst, int n) +void clone_men(const unit * u, unit * dst, int n) { const attrib *a; - int hp = u->hp; region *r = u->region; if (n == 0) @@ -1073,11 +1072,9 @@ void clone_men(unit * u, unit * dst, int n) if (u->attribs) { transfer_curse(u, dst, n); } - } - if (dst) { set_number(dst, dst->number + n); - hp -= u->hp; - dst->hp += hp; + dst->hp += u->hp * dst->number / u->number; + assert(dst->hp >= dst->number); /* TODO: Das ist schnarchlahm! und gehoert nicht hierhin */ a = a_find(dst->attribs, &at_effect); while (a && a->type == &at_effect) { @@ -1530,7 +1527,9 @@ unit *create_unit(region * r, faction * f, int number, const struct race *urace, /* u->race muss bereits gesetzt sein, wird fuer default-hp gebraucht */ /* u->region auch */ - u->hp = unit_max_hp(u) * number; + if (number > 0) { + u->hp = unit_max_hp(u) * number; + } if (dname) { u->_name = strdup(dname); diff --git a/src/kernel/unit.h b/src/kernel/unit.h index beea74ee7..dede956b5 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -166,7 +166,7 @@ extern "C" { void set_level(struct unit *u, skill_t id, int level); int get_level(const struct unit *u, skill_t id); void transfermen(struct unit *src, struct unit *dst, int n); - void clone_men(struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */ + void clone_men(const struct unit *src, struct unit *dst, int n); /* like transfer, but do not subtract from src */ int eff_skill(const struct unit *u, const struct skill *sv, const struct region *r); int effskill_study(const struct unit *u, skill_t sk, const struct region *r); diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index 54b07b63f..6ab8ee21a 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -525,6 +525,29 @@ static void test_unlimited_units(CuTest *tc) { test_cleanup(); } +static void test_clone_men(CuTest *tc) { + unit *u1, *u2; + region *r; + faction *f; + test_setup(); + r = test_create_region(0, 0, NULL); + f = test_create_faction(NULL); + u1 = test_create_unit(f, r); + scale_number(u1, 10); + u2 = test_create_unit(f, r); + scale_number(u2, 0); + CuAssertIntEquals(tc, 10, u1->number); + CuAssertIntEquals(tc, 200, u1->hp); + CuAssertIntEquals(tc, 0, u2->number); + CuAssertIntEquals(tc, 0, u2->hp); + clone_men(u1, u2, 1); + CuAssertIntEquals(tc, 10, u1->number); + CuAssertIntEquals(tc, 200, u1->hp); + CuAssertIntEquals(tc, 1, u2->number); + CuAssertIntEquals(tc, 20, u2->hp); + test_cleanup(); +} + CuSuite *get_unit_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -533,6 +556,7 @@ CuSuite *get_unit_suite(void) SUITE_ADD_TEST(suite, test_unit_name); SUITE_ADD_TEST(suite, test_unit_name_from_race); SUITE_ADD_TEST(suite, test_update_monster_name); + SUITE_ADD_TEST(suite, test_clone_men); SUITE_ADD_TEST(suite, test_remove_unit); SUITE_ADD_TEST(suite, test_remove_empty_units); SUITE_ADD_TEST(suite, test_remove_units_without_faction); diff --git a/src/reports.c b/src/reports.c index 8287e41f7..1a269caa5 100644 --- a/src/reports.c +++ b/src/reports.c @@ -161,15 +161,15 @@ size_t report_status(const unit * u, const struct locale *lang, char *fsbuf, siz const char *lname = locale_name(lang); struct locale *wloc = get_locale(lname); log_warning("no translation for combat status %s in %s", combatstatus[u->status], lname); - locale_setstring(wloc, combatstatus[u->status], combatstatus[u->status]+7); - len = strlcpy(fsbuf, combatstatus[u->status]+7, buflen); + locale_setstring(wloc, combatstatus[u->status], combatstatus[u->status] + 7); + len = strlcpy(fsbuf, combatstatus[u->status] + 7, buflen); } else { len = strlcpy(fsbuf, status, buflen); } if (fval(u, UFL_NOAID)) { - len += strlcat(fsbuf+len, ", ", buflen-len); - len += strlcat(fsbuf+len, LOC(lang, "status_noaid"), buflen-len); + len += strlcat(fsbuf + len, ", ", buflen - len); + len += strlcat(fsbuf + len, LOC(lang, "status_noaid"), buflen - len); } return len; @@ -201,7 +201,7 @@ const char *hp_status(const unit * u) void report_item(const unit * owner, const item * i, const faction * viewer, -const char **name, const char **basename, int *number, bool singular) + const char **name, const char **basename, int *number, bool singular) { const resource_type *rsilver = get_resourcetype(R_SILVER); @@ -251,7 +251,7 @@ const char **name, const char **basename, int *number, bool singular) if (name) *name = LOC(viewer->locale, resourcename(i->type->rtype, - NMF_APPEARANCE | ((i->number != 1 && !singular) ? GR_PLURAL : 0))); + NMF_APPEARANCE | ((i->number != 1 && !singular) ? GR_PLURAL : 0))); if (basename) *basename = resourcename(i->type->rtype, NMF_APPEARANCE); if (number) { @@ -286,7 +286,7 @@ static size_t buforder(char *buffer, size_t size, const order * ord, int mode) WARN_STATIC_BUFFER(); } - return bufp-buffer; + return bufp - buffer; } /** create a report of a list of items to a non-owner. @@ -349,7 +349,7 @@ report_items(const unit *u, item * result, int size, const unit * owner, return n; } -static void report_resource(resource_report * result, const resource_type *rtype, +static void report_resource(resource_report * result, const resource_type *rtype, int number, int level) { assert(rtype); @@ -381,7 +381,7 @@ void report_race(const struct unit *u, const char **name, const char **illusion) void report_building(const struct building *b, const char **name, -const char **illusion) + const char **illusion) { if (name) { *name = buildingtype(b->type, b, b->size); @@ -400,7 +400,7 @@ const char **illusion) int report_resources(const region * r, resource_report * result, int size, -const faction * viewer, bool see_unit) + const faction * viewer, bool see_unit) { int n = 0; @@ -487,7 +487,7 @@ const faction * viewer, bool see_unit) int bufunit(const faction * f, const unit * u, unsigned int indent, seen_mode mode, char *buf, -size_t size) + size_t size) { int i, dh; int getarnt = fval(u, UFL_ANON_FACTION); @@ -626,7 +626,7 @@ size_t size) skill *sv; for (sv = u->skills; sv != u->skills + u->skill_size; ++sv) { size_t bytes = spskill(bufp, size, f->locale, u, sv, &dh, 1); - assert(bytes <=INT_MAX); + assert(bytes <= INT_MAX); if (wrptr(&bufp, &size, (int)bytes) != 0) WARN_STATIC_BUFFER(); } @@ -796,7 +796,7 @@ size_t size) size_t spskill(char *buffer, size_t size, const struct locale * lang, -const struct unit * u, struct skill * sv, int *dh, int days) + const struct unit * u, struct skill * sv, int *dh, int days) { char *bufp = buffer; int i, effsk; @@ -856,7 +856,7 @@ const struct unit * u, struct skill * sv, int *dh, int days) WARN_STATIC_BUFFER(); } } - return bufp-buffer; + return bufp - buffer; } void split_paragraph(strlist ** SP, const char *s, unsigned int indent, unsigned int width, char mark) @@ -927,7 +927,7 @@ void lparagraph(struct strlist **SP, char *s, unsigned int indent, char mark) void spunit(struct strlist **SP, const struct faction *f, const unit * u, unsigned int indent, -seen_mode mode) + seen_mode mode) { char buf[DISPLAYSIZE]; int dh = bufunit(f, u, indent, mode, buf, sizeof(buf)); @@ -1013,7 +1013,7 @@ static void cb_add_address(region *r, unit *ut, void *cbdata) { address_data *data = (address_data *)cbdata; faction *f = data->f; - if (ut->faction==f) { + if (ut->faction == f) { unit *u; for (u = r->units; u; u = u->next) { faction *sf = visible_faction(f, u); @@ -1140,8 +1140,8 @@ void reports_done(void) { int get_regions_distance_arr(region *rc, int radius, region *result[], int size) { int n = 0, i; - - if (size>n) { + + if (size > n) { result[n++] = rc; fset(rc, RF_MARK); } @@ -1151,7 +1151,7 @@ int get_regions_distance_arr(region *rc, int radius, region *result[], int size) r = result[i]; dist = distance(rc, r); - if (distseen.modeseen.mode < seen_neighbour) { rn->seen.mode = seen_neighbour; - if (first->index>rn->index) first = rn; - if (last->indexindex) last = rn; + if (first->index > rn->index) first = rn; + if (last->index < rn->index) last = rn; } } } @@ -1370,6 +1370,9 @@ void reorder_units(region * r) static region *lastregion(faction * f) { + if (!f->units) { + return NULL; + } return f->last ? f->last->next : NULL; } @@ -1387,14 +1390,14 @@ static region *firstregion(faction * f) static void cb_add_seen(region *r, unit *u, void *cbdata) { faction *f = (faction *)cbdata; - if (u->faction==f) { + if (u->faction == f) { add_seen_nb(f, r, seen_travel); } } /** set region.seen based on visibility by one faction. * - * this function may also update ctx->last and ctx->first for potential + * this function may also update ctx->last and ctx->first for potential * lighthouses and travelthru reports */ void prepare_report(report_context *ctx, faction *f) @@ -1408,8 +1411,8 @@ void prepare_report(report_context *ctx, faction *f) rule_region_owners = config_token("rules.region_owner_pay_building", bt_lighthouse->_name); } - if (f->age<=2) { - if ((f->flags&FFL_PWMSG)==0) { + if (f->age <= 2) { + if ((f->flags&FFL_PWMSG) == 0) { /* TODO: this assumes unencrypted passwords */ f->flags |= FFL_PWMSG; ADDMSG(&f->msgs, msg_message("changepasswd", "value", f->_password)); @@ -1421,72 +1424,74 @@ void prepare_report(report_context *ctx, faction *f) ctx->addresses = NULL; ctx->userdata = NULL; /* [first,last) interval of regions with a unit in it: */ - ctx->first = firstregion(f); - ctx->last = lastregion(f); + if (f->units) { + ctx->first = firstregion(f); + ctx->last = lastregion(f); - for (r = ctx->first; r!=ctx->last; r = r->next) { - unit *u; - building *b; - int br = 0, c = 0, range = 0; - if (fval(r, RF_OBSERVER)) { - int skill = get_observer(r, f); - if (skill >= 0) { - add_seen_nb(f, r, seen_spell); + for (r = ctx->first; r != ctx->last; r = r->next) { + unit *u; + building *b; + int br = 0, c = 0, range = 0; + if (fval(r, RF_OBSERVER)) { + int skill = get_observer(r, f); + if (skill >= 0) { + add_seen_nb(f, r, seen_spell); + } } - } - if (fval(r, RF_LIGHTHOUSE)) { - /* region owners get the report from lighthouses */ - if (rule_region_owners && f == region_get_owner(r)) { - for (b = rbuildings(r); b; b = b->next) { - if (b && b->type == bt_lighthouse) { - /* region owners get maximm range */ - int br = lighthouse_range(b, NULL, NULL); - if (br > range) range = br; + if (fval(r, RF_LIGHTHOUSE)) { + /* region owners get the report from lighthouses */ + if (rule_region_owners && f == region_get_owner(r)) { + for (b = rbuildings(r); b; b = b->next) { + if (b && b->type == bt_lighthouse) { + /* region owners get maximm range */ + int br = lighthouse_range(b, NULL, NULL); + if (br > range) range = br; + } } } } - } - b = NULL; - for (u = r->units; u; u = u->next) { - /* if we have any unit in this region, then we get seen_unit access */ - if (u->faction == f) { - add_seen_nb(f, r, seen_unit); - /* units inside the lighthouse get range based on their perception - * or the size, if perception is not a skill - */ - if (!fval(r, RF_LIGHTHOUSE)) { - /* it's enough to add the region once, and if there are - * no lighthouses, there is no need to look at more units */ - break; - } - } - if (range == 0 && u->building && u->building->type == bt_lighthouse) { - if (u->building && b != u->building) { - b = u->building; - c = buildingcapacity(b); - br = 0; - } - c -= u->number; - if (u->faction == f && c >= 0) { - /* unit is one of ours, and inside the current lighthouse */ - if (br == 0) { - /* lazy-calculate the range */ - br = lighthouse_range(u->building, f, u); + b = NULL; + for (u = r->units; u; u = u->next) { + /* if we have any unit in this region, then we get seen_unit access */ + if (u->faction == f) { + add_seen_nb(f, r, seen_unit); + /* units inside the lighthouse get range based on their perception + * or the size, if perception is not a skill + */ + if (!fval(r, RF_LIGHTHOUSE)) { + /* it's enough to add the region once, and if there are + * no lighthouses, there is no need to look at more units */ + break; } - if (br > range) { - range = br; + } + if (range == 0 && u->building && u->building->type == bt_lighthouse) { + if (u->building && b != u->building) { + b = u->building; + c = buildingcapacity(b); + br = 0; + } + c -= u->number; + if (u->faction == f && c >= 0) { + /* unit is one of ours, and inside the current lighthouse */ + if (br == 0) { + /* lazy-calculate the range */ + br = lighthouse_range(u->building, f, u); + } + if (br > range) { + range = br; + } } } } - } - if (range > 0) { - /* we are in at least one lighthouse. add the regions we can see from here! */ - prepare_lighthouse(f, r, range); - } + if (range > 0) { + /* we are in at least one lighthouse. add the regions we can see from here! */ + prepare_lighthouse(f, r, range); + } - if (fval(r, RF_TRAVELUNIT) && r->seen.modeseen.mode < seen_travel) { + travelthru_map(r, cb_add_seen, f); + } } } /* [fast,last) interval of seen regions (with lighthouses and travel) @@ -1697,7 +1702,7 @@ const char *trailinto(const region * r, const struct locale *lang) size_t sz; sz = strlcpy(ref, tname, sizeof(ref)); - sz += strlcat(ref+sz, "_trail", sizeof(ref)-sz); + sz += strlcat(ref + sz, "_trail", sizeof(ref) - sz); s = LOC(lang, ref); if (s && *s) { if (strstr(s, "%s")) diff --git a/src/upkeep.c b/src/upkeep.c index 8494d7f25..c4a937a45 100644 --- a/src/upkeep.c +++ b/src/upkeep.c @@ -191,6 +191,7 @@ void get_food(region * r) int need = lifestyle(u); faction *f = u->faction; + assert(u->hp > 0); need -= MAX(0, get_money(u)); if (need > 0) {