diff --git a/res/eressea/races.xml b/res/eressea/races.xml index 6deefacc9..986e2b85f 100644 --- a/res/eressea/races.xml +++ b/res/eressea/races.xml @@ -701,7 +701,7 @@ - + diff --git a/scripts/tests/e2/e2features.lua b/scripts/tests/e2/e2features.lua index 3576b7349..eb118c931 100644 --- a/scripts/tests/e2/e2features.lua +++ b/scripts/tests/e2/e2features.lua @@ -254,7 +254,7 @@ function test_can_give_person() end function test_no_uruk() - local f1 = faction.create("uruk", "noreply@eressea.de", "de") + local f1 = faction.create("uruk") assert_equal(f1.race, "orc") end @@ -349,7 +349,7 @@ end function test_stonegolems() local r0 = region.create(0, 0, "plain") - local f1 = faction.create("stonegolem", "noreply@eressea.de", "de") + local f1 = faction.create("stonegolem") local u1 = unit.create(f1, r0, 1) local u2 = unit.create(f1, r0, 2) local c1 = building.create(r0, "castle") @@ -378,10 +378,29 @@ end function test_birthdaycake() r = region.create(0,0, "plain") - f = faction.create("human", "cake@eressea.de", "de") + f = faction.create("human") u = unit.create(f, r, 1) u:add_item("birthdaycake", 1) u:clear_orders() u:add_order("ZEIGE Geburtstagstorte") process_orders() end + +function test_demonstealth() + local desc, r, f, u + r = region.create(0, 0, "plain") + f = faction.create("demon") + u = unit.create(f, r, 1) + + u:clear_orders() + u:add_order("TARNE Zwerg") + process_orders() + desc = u:show() + assert_not_nil(string.find(desc, "Zwerg")) + + u:clear_orders() + u:add_order("TARNE Drache") + process_orders() + desc = u:show() + assert_equal(nil, string.find(desc, "Drache")) +end diff --git a/src/kernel/config.c b/src/kernel/config.c index 1d005c9c1..02ed9894d 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -365,13 +365,26 @@ void init_options_translation(const struct locale * lang) { } } -void init_locale(struct locale *lang) +void init_races(struct locale *lang) { - variant var; - int i; const struct race *rc; void **tokens; + tokens = get_translations(lang, UT_RACES); + for (rc = races; rc; rc = rc->next) { + const char *name; + variant var; + var.v = (void *)rc; + name = locale_string(lang, rc_name_s(rc, NAME_PLURAL), false); + if (name) addtoken((struct tnode **)tokens, name, var); + name = locale_string(lang, rc_name_s(rc, NAME_SINGULAR), false); + if (name) addtoken((struct tnode **)tokens, name, var); + } +} + +static void init_magic(struct locale *lang) +{ + void **tokens; tokens = get_translations(lang, UT_MAGIC); if (tokens) { const char *str = config_get("rules.magic.playerschools"); @@ -383,7 +396,9 @@ void init_locale(struct locale *lang) sstr = strdup(str); tok = strtok(sstr, " "); while (tok) { + variant var; const char *name; + int i; for (i = 0; i != MAXMAGIETYP; ++i) { if (strcmp(tok, magic_school[i]) == 0) break; } @@ -400,21 +415,14 @@ void init_locale(struct locale *lang) } free(sstr); } - +} +void init_locale(struct locale *lang) +{ + init_magic(lang); init_directions(lang); init_keywords(lang); init_skills(lang); - - tokens = get_translations(lang, UT_RACES); - for (rc = races; rc; rc = rc->next) { - const char *name; - var.v = (void *)rc; - name = locale_string(lang, rc_name_s(rc, NAME_PLURAL), false); - if (name) addtoken((struct tnode **)tokens, name, var); - name = locale_string(lang, rc_name_s(rc, NAME_SINGULAR), false); - if (name) addtoken((struct tnode **)tokens, name, var); - } - + init_races(lang); init_parameters(lang); init_options_translation(lang); diff --git a/src/kernel/config.h b/src/kernel/config.h index a4378332d..f80214fde 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -56,6 +56,7 @@ extern "C" { /* returns a value between [0..xpct_2], generated with two dice */ void init_locale(struct locale *lang); + void init_races(struct locale *lang); int forbiddenid(int id); int newcontainerid(void); diff --git a/src/kernel/race.c b/src/kernel/race.c index 8a8cc906e..a2c37d87d 100644 --- a/src/kernel/race.c +++ b/src/kernel/race.c @@ -65,7 +65,7 @@ race *races; int num_races = 0; static int rc_changes = 1; -static const char *racenames[MAXRACES] = { +const char *racenames[MAXRACES] = { "dwarf", "elf", NULL, "goblin", "human", "troll", "demon", "insect", "halfling", "cat", "aquarian", "orc", "snotling", "undead", NULL, "youngdragon", "dragon", "wyrm", "ent", "catdragon", "dracoid", @@ -168,6 +168,7 @@ const struct race *findrace(const char *s, const struct locale *lang) const struct race *get_race(race_t rt) { const char * name; + assert(rt >= 0); assert(rt < MAXRACES); name = racenames[rt]; if (!name) { @@ -484,11 +485,9 @@ void rc_set_param(struct race *rc, const char *key, const char *value) { } } -const char* rc_name(const race * rc, name_t n, char *name, size_t size) { +const char* rc_key(const char *rcname, name_t n, char *name, size_t size) +{ const char * postfix = 0; - if (!rc) { - return NULL; - } switch (n) { case NAME_SINGULAR: postfix = ""; break; case NAME_PLURAL: postfix = "_p"; break; @@ -497,12 +496,20 @@ const char* rc_name(const race * rc, name_t n, char *name, size_t size) { default: assert(!"invalid name_t enum in rc_name_s"); } if (postfix) { - snprintf(name, size, "race::%s%s", rc->_name, postfix); + snprintf(name, size, "race::%s%s", rcname, postfix); return name; } return NULL; } +const char* rc_name(const race * rc, name_t n, char *name, size_t size) +{ + if (!rc) { + return NULL; + } + return rc_key(rc->_name, n, name, size); +} + const char *rc_name_s(const race * rc, name_t n) { static char name[64]; /* FIXME: static return value */ diff --git a/src/kernel/race.h b/src/kernel/race.h index fcd78ae19..5c320ea05 100644 --- a/src/kernel/race.h +++ b/src/kernel/race.h @@ -50,8 +50,6 @@ extern "C" { struct rcoption; struct item_type; - extern int num_races; - typedef enum { RC_DWARF, /* 0 - Zwerg */ RC_ELF, @@ -103,6 +101,9 @@ extern "C" { NORACE = -1 } race_t; + extern int num_races; + extern const char *racenames[MAXRACES]; + typedef struct att { int type; union { @@ -180,6 +181,7 @@ extern "C" { typedef enum name_t { NAME_SINGULAR, NAME_PLURAL, NAME_DEFINITIVE, NAME_CATEGORY } name_t; const char * rc_name_s(const race *rc, name_t n); + const char * rc_key(const char *rcname, name_t n, char *name, size_t size); const char * rc_name(const race *rc, name_t n, char *name, size_t size); void rc_set_param(struct race *rc, const char *key, const char *value); diff --git a/src/kernel/region.c b/src/kernel/region.c index 2a54a2eaa..0e45c59bb 100644 --- a/src/kernel/region.c +++ b/src/kernel/region.c @@ -1505,6 +1505,7 @@ int owner_change(const region * r) bool is_mourning(const region * r, int in_turn) { int change = owner_change(r); - return (change == in_turn - 1 && r->land->ownership->last_owner && r->land->ownership->owner - && r->land->ownership->last_owner != r->land->ownership->owner); + return (change == in_turn - 1 && r->land && + r->land->ownership->last_owner && r->land->ownership->owner && + r->land->ownership->last_owner != r->land->ownership->owner); } diff --git a/src/kernel/unit.test.c b/src/kernel/unit.test.c index d8aaae6ec..096da9d62 100644 --- a/src/kernel/unit.test.c +++ b/src/kernel/unit.test.c @@ -153,42 +153,37 @@ static void test_unit_name(CuTest *tc) { static void test_unit_name_from_race(CuTest *tc) { unit *u; - struct locale *lang; - test_cleanup(); - test_create_world(); - u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); + test_setup(); + u = test_create_unit(test_create_faction(test_create_race("human")), test_create_region(0, 0, NULL)); renumber_unit(u, 666); unit_setname(u, NULL); - lang = get_or_create_locale("de"); - locale_setstring(lang, rc_name_s(u->_race, NAME_SINGULAR), "Mensch"); - locale_setstring(lang, rc_name_s(u->_race, NAME_PLURAL), "Menschen"); - CuAssertStrEquals(tc, "Mensch (ii)", unitname(u)); - CuAssertStrEquals(tc, "Mensch", unit_getname(u)); + CuAssertStrEquals(tc, "human (ii)", unitname(u)); + CuAssertStrEquals(tc, "human", unit_getname(u)); u->number = 2; - CuAssertStrEquals(tc, "Menschen (ii)", unitname(u)); - CuAssertStrEquals(tc, "Menschen", unit_getname(u)); + CuAssertStrEquals(tc, "human_p (ii)", unitname(u)); + CuAssertStrEquals(tc, "human_p", unit_getname(u)); test_cleanup(); } static void test_update_monster_name(CuTest *tc) { unit *u; - struct locale *lang; + race *rc; - test_cleanup(); - test_create_world(); - u = test_create_unit(test_create_faction(test_create_race("human")), findregion(0, 0)); - lang = get_or_create_locale("de"); - locale_setstring(lang, rc_name_s(u->_race, NAME_SINGULAR), "Mensch"); - locale_setstring(lang, rc_name_s(u->_race, NAME_PLURAL), "Menschen"); + test_setup(); + rc = test_create_race("human"); + u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, NULL)); unit_setname(u, "Hodor"); CuAssertTrue(tc, !unit_name_equals_race(u)); - unit_setname(u, "Menschling"); + unit_setname(u, "humanitarian"); + CuAssertTrue(tc, !unit_name_equals_race(u)); + + unit_setname(u, "huma"); CuAssertTrue(tc, !unit_name_equals_race(u)); unit_setname(u, rc_name_s(u->_race, NAME_SINGULAR)); @@ -197,12 +192,6 @@ static void test_update_monster_name(CuTest *tc) { unit_setname(u, rc_name_s(u->_race, NAME_PLURAL)); CuAssertTrue(tc, unit_name_equals_race(u)); - unit_setname(u, "Mensch"); - CuAssertTrue(tc, unit_name_equals_race(u)); - - unit_setname(u, "Menschen"); - CuAssertTrue(tc, unit_name_equals_race(u)); - test_cleanup(); } diff --git a/src/laws.c b/src/laws.c index adf8b9f11..af96a309c 100644 --- a/src/laws.c +++ b/src/laws.c @@ -1584,7 +1584,9 @@ int display_cmd(unit * u, struct order *ord) free(*s); if (s2) { char * str = strdup(s2); - unicode_utf8_trim(str); + if (unicode_utf8_trim(str) != 0) { + log_info("trimming info: %s", s2); + } if (strlen(str) >= DISPLAYSIZE) { str[DISPLAYSIZE-1] = 0; } @@ -1626,7 +1628,9 @@ static int rename_cmd(unit * u, order * ord, char **s, const char *s2) /* TODO: Validate to make sure people don't have illegal characters in * names, phishing-style? () come to mind. */ strlcpy(name, s2, sizeof(name)); - unicode_utf8_trim(name); + if (unicode_utf8_trim(name) != 0) { + log_info("trimming name: %s", s2); + } free(*s); *s = strdup(name); diff --git a/src/monsters.c b/src/monsters.c index 4edaeedea..21a3583af 100644 --- a/src/monsters.c +++ b/src/monsters.c @@ -738,7 +738,7 @@ void plan_monsters(faction * f) order *long_order = NULL; /* Ab hier nur noch Befehle für NPC-Einheiten. */ - if (!is_monsters(u->faction)) + if (u->faction!=f) continue; /* Befehle müssen jede Runde neu gegeben werden: */ diff --git a/src/spy.c b/src/spy.c index 08662ea8e..837bc28ee 100644 --- a/src/spy.c +++ b/src/spy.c @@ -247,24 +247,16 @@ int setstealth_cmd(unit * u, struct order *ord) 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) { + if (playerrace(trace)) { u->irace = trace; - if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) + if (u_race(u)->flags & RCF_SHAPESHIFTANY && get_racename(u->attribs)) { set_racename(&u->attribs, NULL); + } } return 0; } - /* Singdrachen koennen sich nur als Drachen tarnen */ - if (u_race(u) == get_race(RC_SONGDRAGON) + else 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)) { diff --git a/src/spy.test.c b/src/spy.test.c index 190cb09a5..11c8c1ff1 100644 --- a/src/spy.test.c +++ b/src/spy.test.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -130,21 +131,55 @@ static void test_sabotage_other_fail(CuTest *tc) { static void test_setstealth_cmd(CuTest *tc) { unit *u; const struct locale *lang; - + test_setup(); - u = test_create_unit(test_create_faction(0), test_create_region(0,0,0)); + u = test_create_unit(test_create_faction(0), test_create_region(0, 0, 0)); lang = u->faction->locale; - u->flags = UFL_ANON_FACTION|UFL_SIEGE; + u->flags = UFL_ANON_FACTION | UFL_SIEGE; u->thisorder = create_order(K_SETSTEALTH, lang, "%s %s", - LOC(lang, parameters[P_FACTION]), - LOC(lang, parameters[P_NOT])); + LOC(lang, parameters[P_FACTION]), + LOC(lang, parameters[P_NOT])); setstealth_cmd(u, u->thisorder); CuAssertIntEquals(tc, UFL_SIEGE, u->flags); free_order(u->thisorder); u->thisorder = create_order(K_SETSTEALTH, lang, "%s", - LOC(lang, parameters[P_FACTION])); + LOC(lang, parameters[P_FACTION])); setstealth_cmd(u, u->thisorder); - CuAssertIntEquals(tc, UFL_SIEGE|UFL_ANON_FACTION, u->flags); + CuAssertIntEquals(tc, UFL_SIEGE | UFL_ANON_FACTION, u->flags); + test_cleanup(); +} + +static void test_setstealth_demon(CuTest *tc) { + unit *u; + struct locale *lang; + struct race *rc; + + test_setup(); + lang = test_create_locale(); + rc = test_create_race("demon"); + u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0)); + rc = test_create_race("dwarf"); + init_races(lang); + u->thisorder = create_order(K_SETSTEALTH, lang, racename(lang, u, rc)); + setstealth_cmd(u, u->thisorder); + CuAssertPtrEquals(tc, (void *)rc, (void *)u->irace); + test_cleanup(); +} + +static void test_setstealth_demon_bad(CuTest *tc) { + unit *u; + struct locale *lang; + struct race *rc; + + test_setup(); + lang = test_create_locale(); + rc = test_create_race("demon"); + u = test_create_unit(test_create_faction(rc), test_create_region(0, 0, 0)); + rc = test_create_race("smurf"); + init_races(lang); + u->thisorder = create_order(K_SETSTEALTH, lang, racename(lang, u, rc)); + setstealth_cmd(u, u->thisorder); + CuAssertPtrEquals(tc, NULL, (void *)u->irace); test_cleanup(); } @@ -180,6 +215,8 @@ CuSuite *get_spy_suite(void) SUITE_ADD_TEST(suite, test_all_spy_message); SUITE_ADD_TEST(suite, test_sabotage_self); SUITE_ADD_TEST(suite, test_setstealth_cmd); + SUITE_ADD_TEST(suite, test_setstealth_demon); + SUITE_ADD_TEST(suite, test_setstealth_demon_bad); SUITE_ADD_TEST(suite, test_sabotage_other_fail); SUITE_ADD_TEST(suite, test_sabotage_other_success); return suite; diff --git a/src/tests.c b/src/tests.c index faa8f6e2e..a9b4878b6 100644 --- a/src/tests.c +++ b/src/tests.c @@ -96,8 +96,19 @@ struct locale * test_create_locale(void) { locale_setstring(loc, "stone_p", "Steine"); locale_setstring(loc, "plain", "Ebene"); locale_setstring(loc, "ocean", "Ozean"); - locale_setstring(loc, "race::human", "Mensch"); - locale_setstring(loc, "race::human_p", "Menschen"); + for (i = 0; i < MAXRACES; ++i) { + if (racenames[i]) { + char name[64]; + rc_key(racenames[i], NAME_PLURAL, name, sizeof(name)); + if (!locale_getstring(loc, name)) { + locale_setstring(loc, name, name + 6); + } + rc_key(racenames[i], NAME_SINGULAR, name, sizeof(name)); + if (!locale_getstring(loc, name)) { + locale_setstring(loc, name, name + 6); + } + } + } for (i = 0; i < MAXSKILLS; ++i) { if (!locale_getstring(loc, mkname("skill", skillnames[i]))) locale_setstring(loc, mkname("skill", skillnames[i]), skillnames[i]);