diff --git a/src/creport.c b/src/creport.c index 9829f7e7c..2bb96f65f 100644 --- a/src/creport.c +++ b/src/creport.c @@ -685,13 +685,16 @@ static void fwriteorder(FILE * F, const struct order *ord, const struct locale *lang, bool escape) { - char ebuf[1024]; + char ebuf[1025]; char obuf[1024]; const char *str = obuf; fputc('"', F); write_order(ord, obuf, sizeof(obuf)); if (escape) { str = escape_string(obuf, ebuf, sizeof(ebuf)); + if (str == ebuf) { + ebuf[1024] = 0; + } } if (str[0]) fputs(str, F); diff --git a/src/give.c b/src/give.c index c2ddfdf6c..6e7c0f060 100644 --- a/src/give.c +++ b/src/give.c @@ -165,7 +165,7 @@ struct order *ord) return -1; } else if (n == 0) { - int reserve = get_reservation(src, itype->rtype); + int reserve = get_reservation(src, itype); if (reserve) { msg_feedback(src, ord, "nogive_reserved", "resource reservation", itype->rtype, reserve); @@ -187,7 +187,7 @@ struct order *ord) i_change(&dest->items, itype, r); #ifdef RESERVE_GIVE #ifdef RESERVE_DONATIONS - change_reservation(dest, item2resource(itype), r); + change_reservation(dest, itype, r); #else if (src->faction == dest->faction) { change_reservation(dest, item2resource(itype), r); @@ -516,7 +516,7 @@ void give_unit(unit * u, unit * u2, order * ord) cmistake(u, ord, 156, MSG_COMMERCE); return; } -// TODO: add_give(u, u2, 1, 1, get_resourcetype(R_UNIT), ord, 0); + add_give(u, u2, n, n, get_resourcetype(R_PERSON), ord, 0); u_setfaction(u, u2->faction); u2->faction->newbies += n; } @@ -680,8 +680,8 @@ void give_cmd(unit * u, order * ord) item *itm = *itmp; const item_type *itype = itm->type; if (itm->number > 0 - && itm->number - get_reservation(u, itype->rtype) > 0) { - n = itm->number - get_reservation(u, itype->rtype); + && itm->number - get_reservation(u, itype) > 0) { + n = itm->number - get_reservation(u, itype); if (give_item(n, itype, u, u2, ord) == 0) { if (*itmp != itm) continue; @@ -719,7 +719,7 @@ void give_cmd(unit * u, order * ord) item *i = *i_find(&u->items, itype); if (i != NULL) { if (can_give(u, u2, itype, 0)) { - n = i->number - get_reservation(u, itype->rtype); + n = i->number - get_reservation(u, itype); give_item(n, itype, u, u2, ord); } else { diff --git a/src/kernel/item.c b/src/kernel/item.c index 42f58fa22..320864122 100644 --- a/src/kernel/item.c +++ b/src/kernel/item.c @@ -604,7 +604,7 @@ static const char *resourcenames[MAX_RESOURCES] = { "aurafocus", "sphereofinv", "magicbag", "magicherbbag", "dreameye", "p2", "seed", "mallornseed", "money", "aura", "permaura", - "hp", "peasant" + "hp", "peasant", "person" }; const resource_type *get_resourcetype(resource_t type) { @@ -949,6 +949,8 @@ void init_resources(void) { resource_type *rtype; + rtype = rt_get_or_create(resourcenames[R_PERSON]); // lousy hack + rtype = rt_get_or_create(resourcenames[R_PEASANT]); rtype->uchange = res_changepeasants; diff --git a/src/kernel/item.h b/src/kernel/item.h index d0986e41f..b3ea13bfc 100644 --- a/src/kernel/item.h +++ b/src/kernel/item.h @@ -298,6 +298,7 @@ extern "C" { R_PERMAURA, /* Permanente Aura */ R_LIFE, R_PEASANT, + R_PERSON, MAX_RESOURCES, /* do not use outside item.c ! */ NORESOURCE = -1 diff --git a/src/kernel/pool.c b/src/kernel/pool.c index f524616f6..bad3d1d80 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -84,34 +84,34 @@ int change_resource(unit * u, const resource_type * rtype, int change) return i; } -int get_reservation(const unit * u, const resource_type * rtype) +int get_reservation(const unit * u, const item_type * itype) { reservation *res = u->reservations; - if (rtype == get_resourcetype(R_STONE) && (u_race(u)->flags & RCF_STONEGOLEM)) + if (itype->rtype == get_resourcetype(R_STONE) && (u_race(u)->flags & RCF_STONEGOLEM)) return (u->number * GOLEM_STONE); - if (rtype == get_resourcetype(R_IRON) && (u_race(u)->flags & RCF_IRONGOLEM)) + if (itype->rtype == get_resourcetype(R_IRON) && (u_race(u)->flags & RCF_IRONGOLEM)) return (u->number * GOLEM_IRON); - while (res && res->type != rtype) + while (res && res->type != itype) res = res->next; if (res) return res->value; return 0; } -int change_reservation(unit * u, const resource_type * rtype, int value) +int change_reservation(unit * u, const item_type * itype, int value) { reservation *res, **rp = &u->reservations; if (!value) return 0; - while (*rp && (*rp)->type != rtype) + while (*rp && (*rp)->type != itype) rp = &(*rp)->next; res = *rp; if (!res) { *rp = res = calloc(sizeof(reservation), 1); - res->type = rtype; + res->type = itype; res->value = value; } else if (res && res->value + value <= 0) { @@ -125,18 +125,18 @@ int change_reservation(unit * u, const resource_type * rtype, int value) return res->value; } -int set_resvalue(unit * u, const resource_type * rtype, int value) +int set_resvalue(unit * u, const item_type * itype, int value) { reservation *res, **rp = &u->reservations; - assert(rtype->itype); - while (*rp && (*rp)->type != rtype) + + while (*rp && (*rp)->type != itype) rp = &(*rp)->next; res = *rp; if (!res) { if (!value) return 0; *rp = res = calloc(sizeof(reservation), 1); - res->type = rtype; + res->type = itype; res->value = value; } else if (res && value <= 0) { @@ -166,8 +166,8 @@ int count) if ((mode & GET_SLACK) && (mode & GET_RESERVE)) use = have; - else if (mode & (GET_SLACK|GET_RESERVE)) { - int reserve = get_reservation(u, rtype); + else if (rtype->itype && mode & (GET_SLACK | GET_RESERVE)) { + int reserve = get_reservation(u, rtype->itype); int slack = _max(0, have - reserve); if (mode & GET_RESERVE) use = have - slack; @@ -211,13 +211,13 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) if ((mode & GET_SLACK) && (mode & GET_RESERVE)) { n = _min(use, have); } - else { - int reserve = get_reservation(u, rtype); + else if (rtype->itype) { + int reserve = get_reservation(u, rtype->itype); int slack = _max(0, have - reserve); if (mode & GET_RESERVE) { n = have - slack; n = _min(use, n); - change_reservation(u, rtype, -n); + change_reservation(u, rtype->itype, -n); } else if (mode & GET_SLACK) { n = _min(use, slack); @@ -229,23 +229,24 @@ use_pooled(unit * u, const resource_type * rtype, unsigned int mode, int count) } if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK | GET_RESERVE)) { - for (v = r->units; use > 0 && v != NULL; v = v->next) + for (v = r->units; use > 0 && v != NULL; v = v->next) { if (u != v) { - int mask; - if ((urace(v)->ec_flags & GIVEITEM) == 0) - continue; - if (v->items == NULL && rtype->uget == NULL) - continue; + int mask; + if ((urace(v)->ec_flags & GIVEITEM) == 0) + continue; + if (v->items == NULL && rtype->uget == NULL) + continue; - if (v->faction == f) { - mask = (mode >> 3) & (GET_SLACK | GET_RESERVE); - } - else if (alliedunit(v, f, HELP_MONEY)) - mask = (mode >> 6) & (GET_SLACK | GET_RESERVE); - else - continue; - use -= use_pooled(v, rtype, mask, use); + if (v->faction == f) { + mask = (mode >> 3) & (GET_SLACK | GET_RESERVE); + } + else if (alliedunit(v, f, HELP_MONEY)) + mask = (mode >> 6) & (GET_SLACK | GET_RESERVE); + else + continue; + use -= use_pooled(v, rtype, mask, use); } + } } return count - use; } diff --git a/src/kernel/pool.h b/src/kernel/pool.h index 6c47a5c14..695dfb28c 100644 --- a/src/kernel/pool.h +++ b/src/kernel/pool.h @@ -24,6 +24,7 @@ extern "C" { struct unit; struct resource_type; + struct item_type; struct region; /* bitfield values for get/use/change operations */ @@ -54,11 +55,11 @@ extern "C" { int change_resource(struct unit *u, const struct resource_type *res, int change); - int get_reservation(const struct unit *u, const struct resource_type *res); - int change_reservation(struct unit *u, const struct resource_type *res, + int get_reservation(const struct unit *u, const struct item_type *res); + int change_reservation(struct unit *u, const struct item_type *res, int value); - int set_resvalue(struct unit * u, const struct resource_type * rtype, int value); + int set_resvalue(struct unit * u, const struct item_type * rtype, int value); #ifdef __cplusplus } diff --git a/src/kernel/pool.test.c b/src/kernel/pool.test.c index b82304d25..711803970 100644 --- a/src/kernel/pool.test.c +++ b/src/kernel/pool.test.c @@ -30,10 +30,10 @@ void test_reservation(CuTest *tc) { assert(u); i_change(&u->items, rtype->itype, 100); CuAssertIntEquals(tc, 100, get_resource(u, rtype)); - CuAssertIntEquals(tc, 0, get_reservation(u, rtype)); - CuAssertIntEquals(tc, 50, change_reservation(u, rtype, 50)); - CuAssertIntEquals(tc, 100, change_reservation(u, rtype, 50)); - CuAssertIntEquals(tc, 50, set_resvalue(u, rtype, 50)); + CuAssertIntEquals(tc, 0, get_reservation(u, rtype->itype)); + CuAssertIntEquals(tc, 50, change_reservation(u, rtype->itype, 50)); + CuAssertIntEquals(tc, 100, change_reservation(u, rtype->itype, 50)); + CuAssertIntEquals(tc, 50, set_resvalue(u, rtype->itype, 50)); CuAssertIntEquals(tc, 100, get_resource(u, rtype)); CuAssertIntEquals(tc, 200, change_resource(u, rtype, 100)); CuAssertIntEquals(tc, 200, get_resource(u, rtype)); @@ -61,11 +61,11 @@ void test_pool(CuTest *tc) { u3 = test_create_unit(test_create_faction(0), r); assert(u1 && u2); i_change(&u1->items, rtype->itype, 100); - set_resvalue(u1, rtype, 50); + set_resvalue(u1, rtype->itype, 50); i_change(&u2->items, rtype->itype, 200); - set_resvalue(u2, rtype, 100); + set_resvalue(u2, rtype->itype, 100); i_change(&u3->items, rtype->itype, 400); - set_resvalue(u3, rtype, 200); + set_resvalue(u3, rtype->itype, 200); CuAssertIntEquals(tc, 50, get_pooled(u1, rtype, GET_SLACK, 40)); CuAssertIntEquals(tc, 50, get_pooled(u1, rtype, GET_SLACK, INT_MAX)); @@ -112,46 +112,45 @@ void test_pool_use(CuTest *tc) { unit *u1, *u2, *u3; faction *f; region *r; - struct resource_type *rtype; + struct item_type *itype; ally *al; test_cleanup(); test_create_world(); - rtype = rt_get_or_create("money"); - it_get_or_create(rtype); + itype = it_get_or_create(rt_get_or_create("money")); f = test_create_faction(0); r = findregion(0, 0); - assert(r && f && rtype && rtype->itype); + assert(r && f && itype); u1 = test_create_unit(f, r); u2 = test_create_unit(f, r); u3 = test_create_unit(test_create_faction(0), r); assert(u1 && u2); - i_change(&u1->items, rtype->itype, 100); - set_resvalue(u1, rtype, 50); - i_change(&u2->items, rtype->itype, 200); - set_resvalue(u2, rtype, 100); - i_change(&u3->items, rtype->itype, 400); - set_resvalue(u3, rtype, 200); + i_change(&u1->items, itype, 100); + set_resvalue(u1, itype, 50); + i_change(&u2->items, itype, 200); + set_resvalue(u2, itype, 100); + i_change(&u3->items, itype, 400); + set_resvalue(u3, itype, 200); al = ally_add(&u3->faction->allies, f); al->status = HELP_MONEY; - CuAssertIntEquals(tc, 10, use_pooled(u1, rtype, GET_SLACK, 10)); - CuAssertIntEquals(tc, 40, use_pooled(u1, rtype, GET_SLACK, 50)); - CuAssertIntEquals(tc, 50, i_get(u1->items, rtype->itype)); + CuAssertIntEquals(tc, 10, use_pooled(u1, itype->rtype, GET_SLACK, 10)); + CuAssertIntEquals(tc, 40, use_pooled(u1, itype->rtype, GET_SLACK, 50)); + CuAssertIntEquals(tc, 50, i_get(u1->items, itype)); - CuAssertIntEquals(tc, 50, get_reservation(u1, rtype)); - CuAssertIntEquals(tc, 10, use_pooled(u1, rtype, GET_RESERVE, 10)); - CuAssertIntEquals(tc, 40, i_get(u1->items, rtype->itype)); - CuAssertIntEquals(tc, 40, get_reservation(u1, rtype)); - CuAssertIntEquals(tc, 40, use_pooled(u1, rtype, GET_RESERVE, 50)); + CuAssertIntEquals(tc, 50, get_reservation(u1, itype)); + CuAssertIntEquals(tc, 10, use_pooled(u1, itype->rtype, GET_RESERVE, 10)); + CuAssertIntEquals(tc, 40, i_get(u1->items, itype)); + CuAssertIntEquals(tc, 40, get_reservation(u1, itype)); + CuAssertIntEquals(tc, 40, use_pooled(u1, itype->rtype, GET_RESERVE, 50)); - CuAssertIntEquals(tc, 10, use_pooled(u1, rtype, GET_POOLED_SLACK, 10)); - CuAssertIntEquals(tc, 90, use_pooled(u1, rtype, GET_POOLED_SLACK, 100)); - CuAssertIntEquals(tc, 100, i_get(u2->items, rtype->itype)); - CuAssertIntEquals(tc, 10, use_pooled(u1, rtype, GET_POOLED_RESERVE, 10)); - CuAssertIntEquals(tc, 90, get_reservation(u2, rtype)); - CuAssertIntEquals(tc, 90, use_pooled(u1, rtype, GET_POOLED_RESERVE, 100)); - CuAssertIntEquals(tc, 0, i_get(u2->items, rtype->itype)); + CuAssertIntEquals(tc, 10, use_pooled(u1, itype->rtype, GET_POOLED_SLACK, 10)); + CuAssertIntEquals(tc, 90, use_pooled(u1, itype->rtype, GET_POOLED_SLACK, 100)); + CuAssertIntEquals(tc, 100, i_get(u2->items, itype)); + CuAssertIntEquals(tc, 10, use_pooled(u1, itype->rtype, GET_POOLED_RESERVE, 10)); + CuAssertIntEquals(tc, 90, get_reservation(u2, itype)); + CuAssertIntEquals(tc, 90, use_pooled(u1, itype->rtype, GET_POOLED_RESERVE, 100)); + CuAssertIntEquals(tc, 0, i_get(u2->items, itype)); } void test_change_resource(CuTest * tc) diff --git a/src/kernel/race.c b/src/kernel/race.c index 7452fe79d..627882d8b 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -154,6 +154,9 @@ static race *rc_find_i(const char *name) while (rc && !strcmp(rname, rc->_name) == 0) { rc = rc->next; } + if (!rc && strcmp(name, "uruk") == 0) { + rc = rc_find_i("orc"); + } return rc; } diff --git a/src/kernel/save.c b/src/kernel/save.c index 153829ace..9b6f23e12 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -401,25 +401,25 @@ void read_items(struct storage *store, item ** ilist) { for (;;) { char ibuf[32]; - const resource_type *rtype; + const item_type *itype; int i; READ_STR(store, ibuf, sizeof(ibuf)); if (!strcmp("end", ibuf)) { break; } - rtype = rt_find(ibuf); + itype = it_find(ibuf); READ_INT(store, &i); if (i <= 0) { - log_error("data contains an entry with %d %s\n", i, resourcename(rtype, NMF_PLURAL)); + log_error("data contains an entry with %d %s\n", i, resourcename(itype->rtype, NMF_PLURAL)); } else { - if (rtype && rtype->itype) { - i_change(ilist, rtype->itype, i); + if (itype && itype->rtype) { + i_change(ilist, itype, i); } else { log_error("data contains unknown item type %s.\n", ibuf); } - assert(rtype && rtype->itype); + assert(itype && itype->rtype); } } } diff --git a/src/kernel/unit.h b/src/kernel/unit.h index bd5ffd493..bb1d5d54c 100644 --- a/src/kernel/unit.h +++ b/src/kernel/unit.h @@ -73,7 +73,7 @@ extern "C" { typedef struct reservation { struct reservation *next; - const struct resource_type *type; + const struct item_type *type; int value; } reservation; diff --git a/src/kernel/version.h b/src/kernel/version.h index e21c2c74b..e92d23aa6 100644 --- a/src/kernel/version.h +++ b/src/kernel/version.h @@ -74,7 +74,7 @@ #define SAVEGAMEID_VERSION 343 /* instead of XMLNAME, save the game.id parameter from the config */ #define BUILDNO_VERSION 344 /* storing the build number in the save */ #define AUTO_RACENAME_VERSION 345 /* NPC units with name==NULL will automatically get their race for a name */ -#define MIN_VERSION CURSETYPE_VERSION /* minimal datafile we support */ +#define MIN_VERSION INTPAK_VERSION /* minimal datafile we support */ #define RELEASE_VERSION AUTO_RACENAME_VERSION /* current datafile */ #define STREAM_VERSION 2 /* internal encoding of binary files */ diff --git a/src/laws.c b/src/laws.c index ea7423670..44bec3642 100755 --- a/src/laws.c +++ b/src/laws.c @@ -1972,7 +1972,7 @@ int mail_cmd(unit * u, struct order *ord) case P_REGION: /* können alle Einheiten in der Region sehen */ s = getstrtoken(); - if (!s[0]) { + if (!s || !s[0]) { cmistake(u, ord, 30, MSG_MESSAGE); break; } @@ -3850,7 +3850,7 @@ static int reserve_i(unit * u, struct order *ord, int flags) { if (u->number > 0 && (urace(u)->ec_flags & GETITEM)) { int use, count, para; - const resource_type *rtype; + const item_type *itype; const char *s; init_order(ord); @@ -3862,19 +3862,19 @@ static int reserve_i(unit * u, struct order *ord, int flags) count = getint() * u->number; } s = getstrtoken(); - rtype = s ? findresourcetype(s, u->faction->locale) : 0; - if (rtype == NULL) + itype = s ? finditemtype(s, u->faction->locale) : 0; + if (itype == NULL) return 0; - set_resvalue(u, rtype, 0); /* make sure the pool is empty */ + set_resvalue(u, itype, 0); /* make sure the pool is empty */ if (count == 0 && para == P_ANY) { - count = get_resource(u, rtype); + count = get_resource(u, itype->rtype); } - use = use_pooled(u, rtype, flags, count); + use = use_pooled(u, itype->rtype, flags, count); if (use) { - set_resvalue(u, rtype, use); - change_resource(u, rtype, use); + set_resvalue(u, itype, use); + change_resource(u, itype->rtype, use); return use; } } diff --git a/src/skill.c b/src/skill.c index acd6ba89a..d7ca2fee5 100644 --- a/src/skill.c +++ b/src/skill.c @@ -95,13 +95,18 @@ skill_t get_skill(const char *s, const struct locale * lang) if (s) { char * str = transliterate(buffer, sizeof(buffer) - sizeof(int), s); - int i; - const void * match; - void **tokens = get_translations(lang, UT_SKILLS); - struct critbit_tree *cb = (critbit_tree *)*tokens; - if (cb && cb_find_prefix(cb, str, strlen(str), &match, 1, 0)) { - cb_get_kv(match, &i, sizeof(int)); - result = (skill_t)i; + if (str) { + int i; + const void * match; + void **tokens = get_translations(lang, UT_SKILLS); + struct critbit_tree *cb = (critbit_tree *)*tokens; + if (cb && cb_find_prefix(cb, str, strlen(str), &match, 1, 0)) { + cb_get_kv(match, &i, sizeof(int)); + result = (skill_t)i; + } + } + else { + log_warning("could not transliterate skill: %s", s); } } return result; diff --git a/src/util/strings.c b/src/util/strings.c index a2e137042..4c72e0913 100644 --- a/src/util/strings.c +++ b/src/util/strings.c @@ -42,9 +42,13 @@ const char *escape_string(const char *str, char *buffer, char *o; size_t skip = start - str; + if (skip > len) { + skip = len; + } memcpy(buffer, str, skip); o = buffer + skip; p = str + skip; + len -= skip; do { if (*p == '\"' || *p == '\\') { if (len < 2) { diff --git a/src/util/strings.test.c b/src/util/strings.test.c index ada78d206..c8dd63147 100644 --- a/src/util/strings.test.c +++ b/src/util/strings.test.c @@ -7,6 +7,9 @@ static void test_escape_string(CuTest * tc) { char scratch[64]; + CuAssertStrEquals(tc, "12345678901234567890", escape_string("12345678901234567890", scratch, 16)); + CuAssertStrEquals(tc, "123456789\\\"12345", escape_string("123456789\"1234567890", scratch, 16)); + CuAssertStrEquals(tc, "1234567890123456", escape_string("1234567890123456\"890", scratch, 16)); CuAssertStrEquals(tc, "hello world", escape_string("hello world", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "hello \\\"world\\\"", escape_string("hello \"world\"", scratch, sizeof(scratch))); CuAssertStrEquals(tc, "\\\"\\\\", escape_string("\"\\", scratch, sizeof(scratch)));