diff --git a/conf/e2/config.json b/conf/e2/config.json new file mode 100644 index 000000000..b2acffcb3 --- /dev/null +++ b/conf/e2/config.json @@ -0,0 +1,5 @@ +{ + "include": [ + "keywords.json" + ] +} diff --git a/conf/e3/config.json b/conf/e3/config.json new file mode 100644 index 000000000..b2acffcb3 --- /dev/null +++ b/conf/e3/config.json @@ -0,0 +1,5 @@ +{ + "include": [ + "keywords.json" + ] +} diff --git a/conf/e4/config.json b/conf/e4/config.json new file mode 100644 index 000000000..b2acffcb3 --- /dev/null +++ b/conf/e4/config.json @@ -0,0 +1,5 @@ +{ + "include": [ + "keywords.json" + ] +} diff --git a/conf/keywords.json b/conf/keywords.json new file mode 100644 index 000000000..bc5538810 --- /dev/null +++ b/conf/keywords.json @@ -0,0 +1,65 @@ +{ + "keywords": { + "de": { + "//" : "//", + "banner": "BANNER", + "work": [ "ARBEITE", "ARBEITEN" ], + "attack": ["ATTACKIERE", "ATTACKIEREN"], + "steal": [ "BEKLAUE", "BEKLAUEN" ], + "besiege": ["BELAGERE", "BELAGERN" ], + "name": [ "BENENNE", "BENENNEN" ], + "use": [ "BENUTZE", "BENUTZEN" ], + "describe": [ "BESCHREIBE", "BESCHREIBEN" ], + "enter": ["BETRETE", "BETRETEN"], + "guard": ["BEWACHE", "BEWACHEN"], + "message": "BOTSCHAFT", + "end": "ENDE", + "ride": ["REITE", "REITEN"], + "number": "NUMMER", + "follow": ["FOLGE","FOLGEN"], + "research": ["FORSCHE", "FORSCHEN"], + "give": "GIB", + "help": [ "HELFE", "HELFEN" ], + "combat": [ "KÄMPFE", "KÄMPFEN" ], + "ready" : "KAMPFZAUBER", + "buy" : [ "KAUFE", "KAUFEN"], + "contact": [ "KONTAKT", "KONTAKTIEREN"], + "teach": ["LEHRE", "LEHREN"], + "study": ["LERNE", "LERNEN"], + "make": ["MACHE", "MACHEN"], + "maketemp": ["MACHE TEMP", "MACHETEMP"], + "move" : "NACH", + "password" : "PASSWORD", + "recruit": ["REKRUTIERE", "REKRUTIEREN"], + "reserve": ["RESERVIERE", "RESERVIEREN"], + "route": "ROUTE", + "sabotage": ["SABOTIERE", "SABOTIEREN"], + "option": "OPTION", + "spy": ["SPIONIERE", "SPIONIEREN"], + "quit": "STIRB", + "hide": ["TARNE", "TARNEN"], + "carry": ["TRANSPORTIERE", "TRANSPORTIEREN"], + "tax": ["TREIBE", "TREIBEN", "STEUERN"], + "entertain": ["UNTERHALTE", "UNTERHALTEN"], + "sell": ["VERKAUFE", "VERKAUFEN"], + "leave": ["VERLASSE", "VERLASSEN"], + "forget": ["VERGISS", "VERGESSEN"], + "cast": ["ZAUBERE", "ZAUBERN"], + "show": ["ZEIGE", "ZEIGEN"], + "destroy": ["ZERSTÖRE", "ZERSTÖREN"], + "grow": ["ZÃœCHTE", "ZÃœCHTEN"], + "default": "DEFAULT", + "origin": "URSPRUNG", + "email": "EMAIL", + "piracy": "PIRATERIE", + "group": "GRUPPE", + "sort": ["SORTIERE", "SORTIEREN"], + "prefix": "PRÄFIX", + "plant": ["PFLANZE", "PFLANZEN"], + "alliance": "ALLIANZ", + "claim": ["BEANSPRUCHE", "BEANSPRUCHEN"], + "promote": ["BEFÖRDERE", "BEFÖRDERUNG"], + "pay": ["BEZAHLE", "BEZAHLEN"] + } + } +} diff --git a/res/core/de/strings.xml b/res/core/de/strings.xml index cd408f9ea..ddf8ced6d 100644 --- a/res/core/de/strings.xml +++ b/res/core/de/strings.xml @@ -2111,199 +2111,6 @@ - - - - // - - - BANNER - - - ARBEITEN - - - ATTACKIEREN - - - BEANSPRUCHEN - - - BEKLAUEN - - - BELAGERE - - - BENENNEN - - - BENUTZEN - - - BESCHREIBEN - - - BETRETEN - - - GIB - - - BEWACHEN - - - BOTSCHAFT - - - ENDE - - - FAHREN - - - NUMMER - - - FOLGEN - - - FORSCHEN - - - HELFEN - - - KÄMPFEN - - - KAMPFZAUBER - - - KAUFEN - - - KONTAKTIEREN - - - LEHREN - - - LERNEN - - - LOCALE - - - MACHEN - - - MACHETEMP - - - NACH - - - ALLIANZ - - - BEFÖRDERUNG - - - BEZAHLEN - - - PFLANZEN - - - PRÄFIX - - - INFO - - - PASSWORT - - - REKRUTIEREN - - - RESERVIEREN - - - ROUTE - - - SABOTIEREN - - - OPTION - - - SPIONIEREN - - - STIRB - - - TARNEN - - - TRANSPORTIEREN - - - TREIBEN - - - UNTERHALTEN - - - VERKAUFEN - - - VERLASSEN - - - VERGESSEN - - - ZAUBERE - - - ZEIGEN - - - ZERSTÖREN - - - ZÃœCHTEN - - - DEFAULT - - - REPORT - - - URSPRUNG - - - EMAIL - - - PIRATERIE - - - LOCALE - - - GRUPPE - - - SORTIEREN - - - Optionen diff --git a/res/core/en/strings.xml b/res/core/en/strings.xml index a85bb5a4f..98bfaf310 100644 --- a/res/core/en/strings.xml +++ b/res/core/en/strings.xml @@ -1451,9 +1451,6 @@ HELP - - FIGHT - COMBATSPELL diff --git a/res/core/messages.xml b/res/core/messages.xml index fd601adf0..52951dc88 100644 --- a/res/core/messages.xml +++ b/res/core/messages.xml @@ -3767,8 +3767,9 @@ "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann nicht bewachen, da sie versucht zu fliehen." - "$unit($unit) in $region($region): '$order($command)' - The unit cannot guard the region because it's trying to flee." - "$unit($unit) in $region($region): '$order($command)' - The unit cannot guard the region because it's trying to flee." + "$unit($unit) in $region($region): + '$order($command)' - The unit cannot guard the region because it + is trying to flee." @@ -3778,7 +3779,6 @@ "$unit($unit) in $region($region): '$order($command)' - Die Einheit kann den Befehl in dieser Runde nicht ausführen, da sie an einem Kampf teilgenommen hat." - "$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has been in combat." "$unit($unit) in $region($region): '$order($command)' - The unit cannot execute this command because it has been in combat." @@ -8364,8 +8364,9 @@ - "$unit($unit) in $region($region): '$order($command)' - Es ist so schön friedlich, man möchte hier niemanden angreifen." - "$unit($unit) in $region($region): '$order($command)' - It's so quiet and peaceful, nobody wants to attack anybody right now." + "$unit($unit) in $region($region): '$order($command)' - Es ist so schön friedlich, man möchte hier niemanden angreifen." + "$unit($unit) in $region($region): + '$order($command)' - It is so quiet and peaceful, nobody wants to attack anybody right now." diff --git a/scripts/eressea/xmlconf.lua b/scripts/eressea/xmlconf.lua index 1aaa39bdd..8ddd09539 100644 --- a/scripts/eressea/xmlconf.lua +++ b/scripts/eressea/xmlconf.lua @@ -1,8 +1,10 @@ local confdir = 'conf/' -if config.rules then - confdir = confdir .. config.rules .. '/' -end if config.install then confdir = config.install .. '/' .. confdir end -read_xml(confdir .. 'config.xml', confdir .. 'catalog.xml') +rules='' +if config.rules then + rules = config.rules .. '/' +end +read_xml(confdir .. rules .. 'config.xml', confdir .. rules .. 'catalog.xml') +eressea.config.read(rules .. 'config.json', confdir) diff --git a/src/bind_config.c b/src/bind_config.c index e0930481f..e87f65fb5 100644 --- a/src/bind_config.c +++ b/src/bind_config.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "kernel/building.h" #include "kernel/race.h" @@ -48,8 +50,34 @@ int config_parse(const char *json) return 1; } -int config_read(const char *filename) +int config_read(const char *filename, const char * relpath) { + char name[MAX_PATH]; + FILE *F; + + json_relpath = relpath; + if (relpath) { + _snprintf(name, sizeof(name), "%s/%s", relpath, filename); + F = fopen(name, "rt"); + } + else { + F = fopen(filename, "rt"); + } + if (F) { + int result; + char *data; + size_t sz; + + fseek(F, 0, SEEK_END); + sz = ftell(F); + rewind(F); + data = malloc(sz); + fread(data, 1, sz, F); + fclose(F); + result = config_parse(data); + free(data); + return result; + } return 1; } diff --git a/src/bind_config.h b/src/bind_config.h index 27f59f853..aa6efde05 100644 --- a/src/bind_config.h +++ b/src/bind_config.h @@ -6,7 +6,7 @@ extern "C" { void config_reset(void); int config_parse(const char *json); -int config_read(const char *filename); +int config_read(const char *filename, const char * relpath); #ifdef __cplusplus } diff --git a/src/bindings.c b/src/bindings.c index 94caa2d42..1446dac15 100755 --- a/src/bindings.c +++ b/src/bindings.c @@ -68,6 +68,7 @@ without prior permission by the authors of Eressea. #include #include #include +#include #include @@ -1001,6 +1002,21 @@ static int tolua_get_spells(lua_State * L) return tolua_quicklist_push(L, "spell_list", "spell", spells); } +static int init_data(const char *filename, const char *catalog) +{ + int l; + l = read_xml(filename, catalog); + reset_locales(); + if (l) { + return l; + } + if (turn < 0) { + turn = first_turn; + } + return 0; +} + + int tolua_read_xml(lua_State * L) { const char *filename = tolua_tostring(L, 1, "config.xml"); diff --git a/src/build.h b/src/build.h index bb1b13a0c..f69bc269f 100644 --- a/src/build.h +++ b/src/build.h @@ -1,3 +1,3 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 3 -#define VERSION_BUILD 685 +#define VERSION_BUILD 687 diff --git a/src/config.pkg b/src/config.pkg index 33f94bed8..d0cb3f905 100644 --- a/src/config.pkg +++ b/src/config.pkg @@ -5,7 +5,7 @@ $#include "bind_config.h" module eressea { module config { void config_reset @ reset(void); - int config_read @ read(const char *filename); + int config_read @ read(const char *filename, const char *relpath); int config_parse @ parse(const char *json); } } diff --git a/src/config.pkg.c b/src/config.pkg.c index c4225ff7b..cc4bb6965 100644 --- a/src/config.pkg.c +++ b/src/config.pkg.c @@ -57,16 +57,18 @@ static int tolua_config_eressea_config_read00(lua_State* tolua_S) #ifndef TOLUA_RELEASE tolua_Error tolua_err; if ( - !tolua_isstring(tolua_S,1,0,&tolua_err) || - !tolua_isnoobj(tolua_S,2,&tolua_err) + !tolua_isstring(tolua_S, 1, 0, &tolua_err) || + !tolua_isstring(tolua_S, 2, 0, &tolua_err) || + !tolua_isnoobj(tolua_S,3,&tolua_err) ) goto tolua_lerror; else #endif { - const char* filename = ((const char*) tolua_tostring(tolua_S,1,0)); + const char* filename = ((const char*)tolua_tostring(tolua_S, 1, 0)); + const char* relpath = ((const char*)tolua_tostring(tolua_S, 2, 0)); { - int tolua_ret = (int) config_read(filename); + int tolua_ret = (int) config_read(filename, relpath); tolua_pushnumber(tolua_S,(lua_Number)tolua_ret); } } diff --git a/src/economy.c b/src/economy.c index bb24fd5e5..bf7e4f288 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1039,12 +1039,10 @@ static bool maintain(building * b, bool first) u = building_owner(b); if (u == NULL) return false; - /* If the owner is the region owner, check if biggest castle has the dontpay flag */ + /* If the owner is the region owner, check if dontpay flag is set for the building where he is in */ if (check_param(global.parameters, "rules.region_owner_pay_building", b->type->_name)) { - if (u == building_owner(largestbuilding(r, &cmp_taxes, false))) { - if (fval(u->building, BLD_DONTPAY)) { - return false; - } + if (fval(u->building, BLD_DONTPAY)) { + return false; } } for (c = 0; b->type->maintenance[c].number; ++c) { diff --git a/src/kernel/CMakeLists.txt b/src/kernel/CMakeLists.txt index 9566317e7..a1ea20a64 100644 --- a/src/kernel/CMakeLists.txt +++ b/src/kernel/CMakeLists.txt @@ -3,6 +3,7 @@ project(kernel C) SET(_TEST_FILES build.test.c config.test.c +group.test.c faction.test.c unit.test.c save.test.c diff --git a/src/kernel/ally.c b/src/kernel/ally.c index cf5772fd6..ed53cbce4 100644 --- a/src/kernel/ally.c +++ b/src/kernel/ally.c @@ -4,36 +4,36 @@ #include ally * ally_find(ally *al, const struct faction *f) { - for (;al;al=al->next) { - if (al->faction==f) return al; - } - return 0; + for (; al; al = al->next) { + if (al->faction == f) return al; + } + return 0; } ally * ally_add(ally **al_p, struct faction *f) { - ally * al; - while (*al_p) { - al = *al_p; - if (al->faction==f) return al; - al_p = &al->next; - } - al = (ally *)malloc(sizeof(ally)); - al->faction = f; - al->status = 0; - al->next = 0; - *al_p = al; - return al; + ally * al; + while (*al_p) { + al = *al_p; + if (f && al->faction == f) return al; + al_p = &al->next; + } + al = (ally *)malloc(sizeof(ally)); + al->faction = f; + al->status = 0; + al->next = 0; + *al_p = al; + return al; } void ally_remove(ally **al_p, struct faction *f) { - ally * al; - while (*al_p) { - al = *al_p; - if (al->faction==f) { - *al_p = al->next; - free(al); - break; + ally * al; + while (*al_p) { + al = *al_p; + if (al->faction == f) { + *al_p = al->next; + free(al); + break; + } + al_p = &al->next; } - al_p = &al->next; - } } diff --git a/src/kernel/ally.test.c b/src/kernel/ally.test.c index 7a3155159..c5c47298f 100644 --- a/src/kernel/ally.test.c +++ b/src/kernel/ally.test.c @@ -7,22 +7,37 @@ static void test_ally(CuTest * tc) { - ally * al = 0; - struct faction * f1 = test_create_faction(0); + ally * al = 0; + struct faction * f1 = test_create_faction(0); - ally_add(&al, f1); - CuAssertPtrNotNull(tc, al); - CuAssertPtrEquals(tc, f1, ally_find(al, f1)->faction); + ally_add(&al, f1); + CuAssertPtrNotNull(tc, al); + CuAssertPtrEquals(tc, f1, ally_find(al, f1)->faction); - ally_remove(&al, f1); - CuAssertPtrEquals(tc, 0, al); - CuAssertPtrEquals(tc, 0, ally_find(al, f1)); + ally_remove(&al, f1); + CuAssertPtrEquals(tc, 0, al); + CuAssertPtrEquals(tc, 0, ally_find(al, f1)); +} + +static void test_ally_null(CuTest * tc) +{ + ally *a1 = 0, *a2 = 0; + + a1 = ally_add(&a1, 0); + a2 = ally_add(&a1, 0); + CuAssertPtrNotNull(tc, a1); + CuAssertPtrNotNull(tc, a2); + CuAssertPtrEquals(tc, a2, a1->next); + CuAssertPtrEquals(tc, 0, a2->next); + free(a1); + free(a2); } CuSuite *get_ally_suite(void) { - CuSuite *suite = CuSuiteNew(); - SUITE_ADD_TEST(suite, test_ally); - return suite; + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_ally); + SUITE_ADD_TEST(suite, test_ally_null); + return suite; } diff --git a/src/kernel/config.c b/src/kernel/config.c index 67e145258..15e77b987 100644 --- a/src/kernel/config.c +++ b/src/kernel/config.c @@ -673,7 +673,7 @@ static void init_gms(void) faction *f; for (f = factions; f; f = f->next) { - const attrib *a = a_findc(f->attribs, &at_gm); + attrib *a = a_find(f->attribs, &at_gm); if (a != NULL) fset(f, FFL_GM); @@ -1961,20 +1961,6 @@ void kernel_done(void) gc_done(); } -const char *localenames[] = { - "de", "en", - NULL -}; - -void init_locales(void) -{ - int l; - for (l = 0; localenames[l]; ++l) { - struct locale *lang = get_or_create_locale(localenames[l]); - init_locale(lang); - } -} - /* TODO: soll hier weg */ extern struct attrib_type at_shiptrail; diff --git a/src/kernel/config.h b/src/kernel/config.h index 13c552c84..c7fd0f225 100644 --- a/src/kernel/config.h +++ b/src/kernel/config.h @@ -101,7 +101,6 @@ extern "C" { /* ------------------------------------------------------------- */ void add_translation(struct critbit_tree **cb, const char *str, int i); void init_translations(const struct locale *lang, int ut, const char * (*string_cb)(int i), int maxstrings); - void init_locales(void); int shipspeed(const struct ship *sh, const struct unit *u); #define i2b(i) ((bool)((i)?(true):(false))) @@ -171,7 +170,6 @@ extern "C" { /* returns a value between [0..xpct_2], generated with two dice */ int distribute(int old, int new_value, int n); - void init_locales(void); void init_locale(struct locale *lang); int newunitid(void); diff --git a/src/kernel/faction.c b/src/kernel/faction.c index de9ba6ed1..5cb152e47 100755 --- a/src/kernel/faction.c +++ b/src/kernel/faction.c @@ -430,10 +430,8 @@ void set_alliance(faction * a, faction * b, int status) sfp = &sf->next; } if (*sfp == NULL) { - ally *sf = *sfp = malloc(sizeof(ally)); - sf->next = NULL; + ally *sf = ally_add(sfp, b); sf->status = status; - sf->faction = b; return; } (*sfp)->status |= status; diff --git a/src/kernel/group.c b/src/kernel/group.c index 99e2a1a61..510c327ac 100755 --- a/src/kernel/group.c +++ b/src/kernel/group.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 @@ -50,203 +50,200 @@ static int maxgid; static group *new_group(faction * f, const char *name, int gid) { - group **gp = &f->groups; - int index = gid % GMAXHASH; - group *g = calloc(sizeof(group), 1); + group **gp = &f->groups; + int index = gid % GMAXHASH; + group *g = calloc(sizeof(group), 1); - while (*gp) - gp = &(*gp)->next; - *gp = g; + while (*gp) + gp = &(*gp)->next; + *gp = g; - maxgid = _max(gid, maxgid); - g->name = _strdup(name); - g->gid = gid; + maxgid = _max(gid, maxgid); + g->name = _strdup(name); + g->gid = gid; - g->nexthash = ghash[index]; - return ghash[index] = g; + g->nexthash = ghash[index]; + return ghash[index] = g; } static void init_group(faction * f, group * g) { - ally *a, **an; + ally *a, **an; - an = &g->allies; - for (a = f->allies; a; a = a->next) - if (a->faction) { - ally *ga = calloc(sizeof(ally), 1); - *ga = *a; - *an = ga; - an = &ga->next; - } + an = &g->allies; + for (a = f->allies; a; a = a->next) + if (a->faction) { + ally *ga = ally_add(an, a->faction); + ga->status = a->status; + an = &ga->next; + } } static group *find_groupbyname(group * g, const char *name) { - while (g && unicode_utf8_strcasecmp(name, g->name) != 0) - g = g->next; - return g; + while (g && unicode_utf8_strcasecmp(name, g->name) != 0) + g = g->next; + return g; } static group *find_group(int gid) { - int index = gid % GMAXHASH; - group *g = ghash[index]; - while (g && g->gid != gid) - g = g->nexthash; - return g; + int index = gid % GMAXHASH; + group *g = ghash[index]; + while (g && g->gid != gid) + g = g->nexthash; + return g; } static int read_group(attrib * a, void *owner, struct storage *store) { - group *g; - int gid; + group *g; + int gid; - READ_INT(store, &gid); - a->data.v = g = find_group(gid); - if (g != 0) { - g->members++; - return AT_READ_OK; - } - return AT_READ_FAIL; + READ_INT(store, &gid); + a->data.v = g = find_group(gid); + if (g != 0) { + g->members++; + return AT_READ_OK; + } + return AT_READ_FAIL; } static void write_group(const attrib * a, const void *owner, struct storage *store) { - group *g = (group *) a->data.v; - WRITE_INT(store, g->gid); + group *g = (group *)a->data.v; + WRITE_INT(store, g->gid); } attrib_type at_group = { /* attribute for units assigned to a group */ -"grp", + "grp", DEFAULT_INIT, - DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, ATF_UNIQUE}; + DEFAULT_FINALIZE, DEFAULT_AGE, write_group, read_group, ATF_UNIQUE }; void free_group(group * g) { - int index = g->gid % GMAXHASH; - group **g_ptr = ghash + index; - while (*g_ptr && (*g_ptr)->gid != g->gid) - g_ptr = &(*g_ptr)->nexthash; - assert(*g_ptr == g); - *g_ptr = g->nexthash; + int index = g->gid % GMAXHASH; + group **g_ptr = ghash + index; + while (*g_ptr && (*g_ptr)->gid != g->gid) + g_ptr = &(*g_ptr)->nexthash; + assert(*g_ptr == g); + *g_ptr = g->nexthash; - while (g->allies) { - ally *a = g->allies; - g->allies = a->next; - free(a); - } - free(g->name); - free(g); + while (g->allies) { + ally *a = g->allies; + g->allies = a->next; + free(a); + } + free(g->name); + free(g); } group * get_group(const struct unit *u) { - if (fval(u, UFL_GROUP)) { - attrib * a = a_find(u->attribs, &at_group); - if (a) { - return (group *) a->data.v; + if (fval(u, UFL_GROUP)) { + attrib * a = a_find(u->attribs, &at_group); + if (a) { + return (group *)a->data.v; + } } - } - return 0; + return 0; } void set_group(struct unit *u, struct group *g) { - attrib *a = NULL; + attrib *a = NULL; - if (fval(u, UFL_GROUP)) { - a = a_find(u->attribs, &at_group); - } - - if (a) { - group *og = (group *) a->data.v; - if (og == g) - return; - --og->members; - } - - if (g) { - if (!a) { - a = a_add(&u->attribs, a_new(&at_group)); - fset(u, UFL_GROUP); + if (fval(u, UFL_GROUP)) { + a = a_find(u->attribs, &at_group); + } + + if (a) { + group *og = (group *)a->data.v; + if (og == g) + return; + --og->members; + } + + if (g) { + if (!a) { + a = a_add(&u->attribs, a_new(&at_group)); + fset(u, UFL_GROUP); + } + a->data.v = g; + g->members++; + } + else if (a) { + a_remove(&u->attribs, a); + freset(u, UFL_GROUP); } - a->data.v = g; - g->members++; - } else if (a) { - a_remove(&u->attribs, a); - freset(u, UFL_GROUP); - } } bool join_group(unit * u, const char *name) { - group *g = NULL; + group *g = NULL; - if (name && name[0]) { - g = find_groupbyname(u->faction->groups, name); - if (g == NULL) { - g = new_group(u->faction, name, ++maxgid); - init_group(u->faction, g); + if (name && name[0]) { + g = find_groupbyname(u->faction->groups, name); + if (g == NULL) { + g = new_group(u->faction, name, ++maxgid); + init_group(u->faction, g); + } } - } - set_group(u, g); - return true; + set_group(u, g); + return true; } void write_groups(struct storage *store, group * g) { - while (g) { - ally *a; - WRITE_INT(store, g->gid); - WRITE_STR(store, g->name); - for (a = g->allies; a; a = a->next) { - if (a->faction) { - write_faction_reference(a->faction, store); - WRITE_INT(store, a->status); - } + while (g) { + ally *a; + WRITE_INT(store, g->gid); + WRITE_STR(store, g->name); + for (a = g->allies; a; a = a->next) { + if (a->faction) { + write_faction_reference(a->faction, store); + WRITE_INT(store, a->status); + } + } + WRITE_INT(store, 0); + a_write(store, g->attribs, g); + WRITE_SECTION(store); + g = g->next; } WRITE_INT(store, 0); - a_write(store, g->attribs, g); - WRITE_SECTION(store); - g = g->next; - } - WRITE_INT(store, 0); } void read_groups(struct storage *store, faction * f) { - for (;;) { - ally **pa; - group *g; - int gid; - char buf[1024]; - - READ_INT(store, &gid); - if (gid == 0) - break; - READ_STR(store, buf, sizeof(buf)); - g = new_group(f, buf, gid); - pa = &g->allies; for (;;) { - ally *a; - variant fid; - READ_INT(store, &fid.i); - if (fid.i <= 0) - break; - if (global.data_version < STORAGE_VERSION && fid.i == 0) - break; - a = malloc(sizeof(ally)); - *pa = a; - pa = &a->next; - READ_INT(store, &a->status); + ally **pa; + group *g; + int gid; + char buf[1024]; - a->faction = findfaction(fid.i); - if (!a->faction) - ur_add(fid, &a->faction, resolve_faction); + READ_INT(store, &gid); + if (gid == 0) + break; + READ_STR(store, buf, sizeof(buf)); + g = new_group(f, buf, gid); + pa = &g->allies; + for (;;) { + ally *a; + variant fid; + + READ_INT(store, &fid.i); + if (fid.i <= 0) + break; + if (global.data_version < STORAGE_VERSION && fid.i == 0) + break; + a = ally_add(pa, findfaction(fid.i)); + READ_INT(store, &a->status); + if (!a->faction) + ur_add(fid, &a->faction, resolve_faction); + } + *pa = 0; + a_read(store, &g->attribs, g); } - *pa = 0; - a_read(store, &g->attribs, g); - } } diff --git a/src/kernel/group.h b/src/kernel/group.h index ea312542c..076761d98 100755 --- a/src/kernel/group.h +++ b/src/kernel/group.h @@ -22,9 +22,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern "C" { #endif -/* bitfield value for group::flags */ -#define GFL_ALIVE 0x01 /* There is at least one struct unit in the group */ - struct gamedata; typedef struct group { @@ -34,7 +31,6 @@ extern "C" { struct attrib *attribs; char *name; struct ally *allies; - int flags; int gid; int members; } group; diff --git a/src/kernel/group.test.c b/src/kernel/group.test.c new file mode 100644 index 000000000..c1bd01d59 --- /dev/null +++ b/src/kernel/group.test.c @@ -0,0 +1,45 @@ +#include +#include "types.h" +#include "group.h" +#include "faction.h" +#include "unit.h" +#include "region.h" + +#include +#include +#include + +static void test_group(CuTest * tc) +{ + unit *u; + region *r; + faction *f; + group *g; + + test_cleanup(); + test_create_world(); + r = findregion(0, 0); + f = test_create_faction(0); + assert(r && f); + u = test_create_unit(f, r); + assert(u); + CuAssertTrue(tc, join_group(u, "hodor")); + CuAssertPtrNotNull(tc, (g = get_group(u))); + CuAssertStrEquals(tc, "hodor", g->name); + CuAssertIntEquals(tc, 1, g->members); + set_group(u, 0); + CuAssertIntEquals(tc, 0, g->members); + CuAssertPtrEquals(tc, 0, get_group(u)); + set_group(u, g); + CuAssertIntEquals(tc, 1, g->members); + CuAssertPtrEquals(tc, g, get_group(u)); + test_cleanup(); +} + +CuSuite *get_group_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_group); + return suite; +} + diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c index d8a0e59e6..d09aaf6ff 100644 --- a/src/kernel/jsonconf.c +++ b/src/kernel/jsonconf.c @@ -627,29 +627,69 @@ static void json_keywords(cJSON *json) { static void json_races(cJSON *json) { cJSON *child; - if (json->type!=cJSON_Object) { + if (json->type != cJSON_Object) { log_error("races is not a json object: %d", json->type); return; } - for (child=json->child;child;child=child->next) { + for (child = json->child; child; child = child->next) { json_race(child, rc_get_or_create(child->string)); } } +const char * json_relpath; + +static void json_include(cJSON *json) { + cJSON *child; + if (json->type != cJSON_Array) { + log_error("config is not a json array: %d", json->type); + return; + } + for (child = json->child; child; child = child->next) { + FILE *F; + if (json_relpath) { + char name[MAX_PATH]; + _snprintf(name, sizeof(name), "%s/%s", json_relpath, child->valuestring); + F = fopen(name, "rt"); + } + else { + F = fopen(child->valuestring, "rt"); + } + if (F) { + cJSON *config; + char *data; + size_t sz; + fseek(F, 0, SEEK_END); + sz = ftell(F); + rewind(F); + data = malloc(sz); + fread(data, 1, sz, F); + fclose(F); + config = cJSON_Parse(data); + free(data); + json_config(config); + cJSON_Delete(config); + } + } +} + void json_config(cJSON *json) { cJSON *child; if (json->type!=cJSON_Object) { log_error("config is not a json object: %d", json->type); return; } + reset_locales(); for (child=json->child;child;child=child->next) { if (strcmp(child->string, "races")==0) { json_races(child); } - else if (strcmp(child->string, "items")==0) { + else if (strcmp(child->string, "items") == 0) { json_items(child); } - else if (strcmp(child->string, "ships")==0) { + else if (strcmp(child->string, "include") == 0) { + json_include(child); + } + else if (strcmp(child->string, "ships") == 0) { json_ships(child); } else if (strcmp(child->string, "strings")==0) { @@ -676,6 +716,5 @@ void json_config(cJSON *json) { log_error("config contains unknown attribute %s", child->string); } } - init_locales(); } diff --git a/src/kernel/jsonconf.h b/src/kernel/jsonconf.h index 9d0f1467e..6940386e9 100644 --- a/src/kernel/jsonconf.h +++ b/src/kernel/jsonconf.h @@ -18,7 +18,8 @@ extern "C" { struct cJSON; void json_config(struct cJSON *str); - + extern const char * json_relpath; + #ifdef __cplusplus } #endif diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c index 42505f0bb..6c555bfc6 100644 --- a/src/kernel/jsonconf.test.c +++ b/src/kernel/jsonconf.test.c @@ -10,11 +10,13 @@ #include "race.h" #include "ship.h" #include "spell.h" +#include "order.h" #include "terrain.h" #include "util/language.h" #include #include #include +#include #include static const struct race * race_with_flag(const char * name) { @@ -101,7 +103,7 @@ static void test_races(CuTest * tc) static void test_findrace(CuTest *tc) { const char * data = "{\"races\": { \"dwarf\": {} }, \"strings\": { \"de\" : { \"race::dwarf\" : \"Zwerg\" } } }"; cJSON *json = cJSON_Parse(data); - const struct locale *lang; + struct locale *lang; const race *rc; CuAssertPtrNotNull(tc, json); @@ -110,6 +112,7 @@ static void test_findrace(CuTest *tc) { CuAssertPtrEquals(tc, 0, (void *)findrace("Zwerg", lang)); json_config(json); + init_locale(lang); rc = findrace("Zwerg", lang); CuAssertPtrNotNull(tc, rc); CuAssertStrEquals(tc, "dwarf", rc->_name); @@ -228,29 +231,29 @@ static void test_spells(CuTest * tc) CuAssertPtrEquals(tc, 0, find_spell("fireball")); } +static const char * building_data = "{\"buildings\": { " +"\"house\" : { " +"\"maintenance\" : " +"{ \"type\" : \"iron\", \"amount\" : 1, \"flags\" : [ \"required\", \"variable\" ] }" +"," +"\"construction\" : {" +"\"maxsize\" : 20," +"\"reqsize\" : 10," +"\"minskill\" : 1," +"\"materials\" : {" +"\"stone\" : 2," +"\"iron\" : 1" +"}}}," +"\"shed\" : {" +"\"maintenance\" : [" +"{ \"type\" : \"iron\", \"amount\" : 1 }," +"{ \"type\" : \"stone\", \"amount\" : 2 }" +"]}" +"}}"; + static void test_buildings(CuTest * tc) { - const char * data = "{\"buildings\": { " - "\"house\" : { " - "\"maintenance\" : " - "{ \"type\" : \"iron\", \"amount\" : 1, \"flags\" : [ \"required\", \"variable\" ] }" - "," - "\"construction\" : {" - "\"maxsize\" : 20," - "\"reqsize\" : 10," - "\"minskill\" : 1," - "\"materials\" : {" - "\"stone\" : 2," - "\"iron\" : 1" - "}}}," - "\"shed\" : {" - "\"maintenance\" : [" - "{ \"type\" : \"iron\", \"amount\" : 1 }," - "{ \"type\" : \"stone\", \"amount\" : 2 }" - "]}" - "}}"; - - cJSON *json = cJSON_Parse(data); + cJSON *json = cJSON_Parse(building_data); const building_type *bt; test_cleanup(); @@ -292,6 +295,25 @@ static void test_buildings(CuTest * tc) test_cleanup(); } +static void test_configs(CuTest * tc) +{ + const char * data = "{\"include\": [ \"test.json\" ] }"; + FILE *F; + cJSON *json = cJSON_Parse(data); + + test_cleanup(); + + F = fopen("test.json", "wt"); + fwrite(building_data, 1, strlen(building_data), F); + fclose(F); + CuAssertPtrNotNull(tc, json); + CuAssertPtrEquals(tc, 0, buildingtypes); + json_config(json); + CuAssertPtrNotNull(tc, buildingtypes); + unlink("test.json"); + test_cleanup(); +} + static void test_terrains(CuTest * tc) { const char * data = "{\"terrains\": { \"plain\" : { \"flags\" : [ \"land\", \"fly\", \"walk\" ] } }}"; @@ -374,6 +396,7 @@ static void test_keywords(CuTest * tc) CuAssertIntEquals(tc, K_MOVE, get_keyword("nach", lang)); CuAssertStrEquals(tc, "LERNEN", locale_string(lang, "keyword::study")); + CuAssertStrEquals(tc, "NACH", locale_string(lang, "keyword::move")); test_cleanup(); } @@ -395,6 +418,26 @@ static void test_strings(CuTest * tc) CuAssertStrEquals(tc, "LERNEN", locale_string(lang, "study")); } +static void test_infinitive_from_config(CuTest *tc) { + char buffer[32]; + struct locale *lang; + struct order *ord; + const char * data = "{\"keywords\": { \"de\" : { \"study\" : [ \"LERNE\", \"LERNEN\" ] }}}"; + + cJSON *json = cJSON_Parse(data); + CuAssertPtrNotNull(tc, json); + json_config(json); + + lang = get_or_create_locale("de"); + CuAssertIntEquals(tc, K_STUDY, get_keyword("LERN", lang)); + CuAssertIntEquals(tc, K_STUDY, get_keyword("LERNE", lang)); + CuAssertIntEquals(tc, K_STUDY, get_keyword("LERNEN", lang)); + + ord = create_order(K_STUDY, lang, ""); + CuAssertStrEquals(tc, "LERNE", get_command(ord, buffer, sizeof(buffer))); + test_cleanup(); +} + CuSuite *get_jsonconf_suite(void) { CuSuite *suite = CuSuiteNew(); @@ -404,6 +447,7 @@ CuSuite *get_jsonconf_suite(void) SUITE_ADD_TEST(suite, test_items); SUITE_ADD_TEST(suite, test_ships); SUITE_ADD_TEST(suite, test_buildings); + SUITE_ADD_TEST(suite, test_configs); SUITE_ADD_TEST(suite, test_castles); SUITE_ADD_TEST(suite, test_terrains); SUITE_ADD_TEST(suite, test_races); @@ -411,6 +455,7 @@ CuSuite *get_jsonconf_suite(void) SUITE_ADD_TEST(suite, test_strings); SUITE_ADD_TEST(suite, test_spells); SUITE_ADD_TEST(suite, test_flags); + SUITE_ADD_TEST(suite, test_infinitive_from_config); return suite; } diff --git a/src/kernel/order.test.c b/src/kernel/order.test.c index 1d556c622..0ae35d0bc 100644 --- a/src/kernel/order.test.c +++ b/src/kernel/order.test.c @@ -32,6 +32,7 @@ static void test_parse_order(CuTest *tc) { struct locale * lang = get_or_create_locale("en"); locale_setstring(lang, "keyword::move", "MOVE"); + init_keyword(lang, K_MOVE, "MOVE"); ord = parse_order("MOVE NORTH", lang); CuAssertPtrNotNull(tc, ord); CuAssertIntEquals(tc, K_MOVE, getkeyword(ord)); diff --git a/src/kernel/pool.c b/src/kernel/pool.c index e38c31011..6706ed80c 100644 --- a/src/kernel/pool.c +++ b/src/kernel/pool.c @@ -167,7 +167,7 @@ int count) if ((mode & GET_SLACK) && (mode & GET_RESERVE)) use = have; - else { + else if (mode & (GET_SLACK|GET_RESERVE)) { int reserve = get_reservation(u, rtype); int slack = _max(0, have - reserve); if (mode & GET_RESERVE) @@ -177,11 +177,9 @@ int count) } if (rtype->flags & RTF_POOLED && mode & ~(GET_SLACK | GET_RESERVE)) { for (v = r->units; v && use < count; v = v->next) - if (u != v) { + if (u != v && (u->items || rtype->uget)) { int mask; - if (v->items == NULL && rtype->uget == NULL) - continue; if ((urace(v)->ec_flags & GIVEITEM) == 0) continue; diff --git a/src/kernel/pool.h b/src/kernel/pool.h index 6de15bf3c..d6f4766c6 100644 --- a/src/kernel/pool.h +++ b/src/kernel/pool.h @@ -29,8 +29,8 @@ extern "C" { #define GET_POOLED_SLACK 0x08 #define GET_POOLED_RESERVE 0x10 #define GET_POOLED_FORCE 0x20 /* ignore f->options pools */ -#define GET_ALLIED_SLACK 0x30 -#define GET_ALLIED_RESERVE 0x40 +#define GET_ALLIED_SLACK 0x40 +#define GET_ALLIED_RESERVE 0x80 /* for convenience: */ #define GET_DEFAULT (GET_RESERVE|GET_SLACK|GET_POOLED_SLACK) diff --git a/src/kernel/pool.test.c b/src/kernel/pool.test.c index ad700f6a8..e6594bfac 100644 --- a/src/kernel/pool.test.c +++ b/src/kernel/pool.test.c @@ -1,47 +1,172 @@ #include #include +#include "ally.h" #include "pool.h" #include "magic.h" #include "unit.h" #include "item.h" +#include "faction.h" #include "region.h" #include "skill.h" #include #include +#include +#include + +void test_reservation(CuTest *tc) { + unit *u; + faction *f; + region *r; + struct resource_type *rtype; + test_cleanup(); + test_create_world(); + rtype = rt_get_or_create("money"); + it_get_or_create(rtype); + f = test_create_faction(0); + r = findregion(0, 0); + assert(r && f && rtype && rtype->itype); + u = test_create_unit(f, r); + 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, 100, get_resource(u, rtype)); + CuAssertIntEquals(tc, 200, change_resource(u, rtype, 100)); + CuAssertIntEquals(tc, 200, get_resource(u, rtype)); + CuAssertIntEquals(tc, 200, i_get(u->items, rtype->itype)); + + test_cleanup(); +} + +void test_pool(CuTest *tc) { + unit *u1, *u2, *u3; + faction *f; + region *r; + struct resource_type *rtype; + ally *al; + + test_cleanup(); + test_create_world(); + rtype = rt_get_or_create("money"); + it_get_or_create(rtype); + f = test_create_faction(0); + r = findregion(0, 0); + assert(r && f && rtype && rtype->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); + + CuAssertIntEquals(tc, 50, get_pooled(u1, rtype, GET_SLACK, 40)); + CuAssertIntEquals(tc, 50, get_pooled(u1, rtype, GET_SLACK, INT_MAX)); + CuAssertIntEquals(tc, 100, get_pooled(u1, rtype, GET_SLACK | GET_RESERVE, INT_MAX)); + CuAssertIntEquals(tc, 150, get_pooled(u1, rtype, GET_SLACK | GET_POOLED_SLACK, INT_MAX)); + CuAssertIntEquals(tc, 100, get_pooled(u1, rtype, GET_POOLED_SLACK, INT_MAX)); + CuAssertIntEquals(tc, 200, get_pooled(u1, rtype, GET_POOLED_SLACK | GET_POOLED_RESERVE, INT_MAX)); + + al = ally_add(&u3->faction->allies, f); + al->status = HELP_GUARD; + CuAssertIntEquals(tc, 0, get_pooled(u1, rtype, GET_ALLIED_SLACK | GET_ALLIED_RESERVE, INT_MAX)); + al->status = HELP_MONEY; + CuAssertIntEquals(tc, 200, get_pooled(u1, rtype, GET_ALLIED_SLACK, INT_MAX)); + CuAssertIntEquals(tc, 200, get_pooled(u1, rtype, GET_ALLIED_RESERVE, INT_MAX)); + CuAssertIntEquals(tc, 400, get_pooled(u1, rtype, GET_ALLIED_SLACK | GET_ALLIED_RESERVE, INT_MAX)); + + CuAssertIntEquals(tc, 100, get_pooled(u1, rtype, GET_ALL, 50)); + CuAssertIntEquals(tc, 300, get_pooled(u1, rtype, GET_ALL, 150)); + CuAssertIntEquals(tc, 300, get_pooled(u1, rtype, GET_ALL, INT_MAX)); +} + +void test_pool_use(CuTest *tc) { + unit *u1, *u2, *u3; + faction *f; + region *r; + struct resource_type *rtype; + ally *al; + + test_cleanup(); + test_create_world(); + rtype = rt_get_or_create("money"); + it_get_or_create(rtype); + f = test_create_faction(0); + r = findregion(0, 0); + assert(r && f && rtype && rtype->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); + 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, 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, 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)); +} void test_change_resource(CuTest * tc) { - struct unit * u; - struct faction * f; - struct region * r; - const char * names[] = { "money", "aura", "permaura", "horse", "hp", 0 }; - int i; + struct unit * u; + struct faction * f; + struct region * r; + const char * names[] = { "money", "aura", "permaura", "horse", "hp", 0 }; + int i; - test_cleanup(); - test_create_world(); - enable_skill(SK_MAGIC, true); + test_cleanup(); + test_create_world(); + enable_skill(SK_MAGIC, true); - r = findregion(0, 0); - f = test_create_faction(0); - u = test_create_unit(f, r); - CuAssertPtrNotNull(tc, u); - set_level(u, SK_MAGIC, 5); - create_mage(u, M_DRAIG); + r = findregion(0, 0); + f = test_create_faction(0); + u = test_create_unit(f, r); + CuAssertPtrNotNull(tc, u); + set_level(u, SK_MAGIC, 5); + create_mage(u, M_DRAIG); - for (i=0;names[i];++i) { - const struct resource_type *rtype = rt_find(names[i]); - int have = get_resource(u, rtype); - CuAssertIntEquals(tc, have+1, change_resource(u, rtype, 1)); - CuAssertIntEquals(tc, have+1, get_resource(u, rtype)); - } + for (i = 0; names[i]; ++i) { + const struct resource_type *rtype = rt_find(names[i]); + int have = get_resource(u, rtype); + CuAssertIntEquals(tc, have + 1, change_resource(u, rtype, 1)); + CuAssertIntEquals(tc, have + 1, get_resource(u, rtype)); + } } CuSuite *get_pool_suite(void) { - CuSuite *suite = CuSuiteNew(); -/* SUITE_ADD_TEST(suite, test_pool); */ - SUITE_ADD_TEST(suite, test_change_resource); - return suite; + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_reservation); + SUITE_ADD_TEST(suite, test_pool); + SUITE_ADD_TEST(suite, test_pool_use); + SUITE_ADD_TEST(suite, test_change_resource); + return suite; } diff --git a/src/kernel/save.c b/src/kernel/save.c index c52eae383..f6fb4c540 100644 --- a/src/kernel/save.c +++ b/src/kernel/save.c @@ -1119,8 +1119,11 @@ static ally **addally(const faction * f, ally ** sfp, int aid, int state) if (state == 0) return sfp; - sf = calloc(1, sizeof(ally)); - sf->faction = af; + while (*sfp) { + sfp = &(*sfp)->next; + } + + sf = ally_add(sfp, af); if (!sf->faction) { variant id; id.i = aid; @@ -1128,9 +1131,6 @@ static ally **addally(const faction * f, ally ** sfp, int aid, int state) } sf->status = state & HELP_ALL; - while (*sfp) - sfp = &(*sfp)->next; - *sfp = sf; return &sf->next; } @@ -1460,6 +1460,7 @@ int readgame(const char *filename, int backup) storage store; FILE *F; + init_locales(); log_printf(stdout, "- reading game data from %s\n", filename); sprintf(path, "%s/%s", datapath(), filename); diff --git a/src/kernel/unit.c b/src/kernel/unit.c index 27dff7f0c..6e7f1eaa0 100644 --- a/src/kernel/unit.c +++ b/src/kernel/unit.c @@ -702,6 +702,7 @@ void set_level(unit * u, skill_t sk, int value) { skill *sv = u->skills; + assert(sk != SK_MAGIC || is_monsters(u->faction) || u->number == 1); if (!skill_enabled(sk)) return; @@ -1161,10 +1162,13 @@ skill *add_skill(unit * u, skill_t id) ++u->skill_size; u->skills = realloc(u->skills, u->skill_size * sizeof(skill)); sv = (u->skills + u->skill_size - 1); - sv->level = (unsigned char)0; - sv->weeks = (unsigned char)1; - sv->old = (unsigned char)0; - sv->id = (unsigned char)id; + sv->level = 0; + sv->weeks = 1; + sv->old = 0; + sv->id = id; + if (id == SK_MAGIC && u->faction && !is_monsters(u->faction)) { + assert(u->number==1 && max_magicians(u->faction) >= u->number); + } return sv; } diff --git a/src/keyword.c b/src/keyword.c index 23f55a609..25ace155b 100644 --- a/src/keyword.c +++ b/src/keyword.c @@ -103,7 +103,7 @@ const char *keywords[MAXKEYWORDS] = { "research", "give", "help", - "fight", + "combat", "ready", "buy", "contact", diff --git a/src/keyword.test.c b/src/keyword.test.c index f2cde5ab1..3f6828c76 100644 --- a/src/keyword.test.c +++ b/src/keyword.test.c @@ -1,6 +1,7 @@ #include #include "kernel/types.h" #include "kernel/config.h" +#include "kernel/order.h" #include "keyword.h" #include "util/language.h" #include "tests.h" @@ -19,6 +20,25 @@ static void test_init_keywords(CuTest *tc) { test_cleanup(); } +static void test_infinitive(CuTest *tc) { + char buffer[32]; + struct locale *lang; + struct order *ord; + test_cleanup(); + + lang = get_or_create_locale("de"); + locale_setstring(lang, "keyword::study", "LERNE"); + init_keyword(lang, K_STUDY, "LERNE"); + init_keyword(lang, K_STUDY, "LERNEN"); + CuAssertIntEquals(tc, K_STUDY, get_keyword("LERN", lang)); + CuAssertIntEquals(tc, K_STUDY, get_keyword("LERNE", lang)); + CuAssertIntEquals(tc, K_STUDY, get_keyword("LERNEN", lang)); + + ord = create_order(K_STUDY, lang, ""); + CuAssertStrEquals(tc, "LERNE", get_command(ord, buffer, sizeof(buffer))); + test_cleanup(); +} + static void test_init_keyword(CuTest *tc) { struct locale *lang; test_cleanup(); @@ -76,6 +96,7 @@ static void test_get_shortest_match(CuTest *tc) { CuSuite *get_keyword_suite(void) { CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_infinitive); SUITE_ADD_TEST(suite, test_init_keyword); SUITE_ADD_TEST(suite, test_init_keywords); SUITE_ADD_TEST(suite, test_findkeyword); @@ -83,4 +104,3 @@ CuSuite *get_keyword_suite(void) SUITE_DISABLE_TEST(suite, test_get_keyword_default); return suite; } - diff --git a/src/laws.c b/src/laws.c index 999f553a5..ed319023e 100755 --- a/src/laws.c +++ b/src/laws.c @@ -83,7 +83,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #include #include #include -#include #include @@ -1349,10 +1348,8 @@ int ally_cmd(unit * u, struct order *ord) return 0; } else { - sf = calloc(1, sizeof(ally)); - sf->faction = f; + sf = ally_add(sfp, f); sf->status = 0; - addlist(sfp, sf); } } switch (keyword) { @@ -2585,7 +2582,7 @@ int reshow_cmd(unit * u, struct order *ord) init_order(ord); s = getstrtoken(); - if (isparam(s, u->faction->locale, P_ANY)) { + if (s && isparam(s, u->faction->locale, P_ANY)) { p = getparam(u->faction->locale); s = NULL; } @@ -4557,17 +4554,3 @@ void update_subscriptions(void) } fclose(F); } - -int init_data(const char *filename, const char *catalog) -{ - int l; - l = read_xml(filename, catalog); - if (l) { - return l; - } - init_locales(); - if (turn < 0) { - turn = first_turn; - } - return 0; -} diff --git a/src/laws.h b/src/laws.h index 3ffc35f08..c9fdc095f 100755 --- a/src/laws.h +++ b/src/laws.h @@ -24,13 +24,10 @@ extern "C" { extern int writepasswd(void); void demographics(void); - void last_orders(void); - void find_address(void); void update_guards(void); void update_subscriptions(void); void deliverMail(struct faction *f, struct region *r, struct unit *u, const char *s, struct unit *receiver); - int init_data(const char *filename, const char *catalog); bool renamed_building(const struct building * b); int rename_building(struct unit * u, struct order * ord, struct building * b, const char *name); diff --git a/src/laws.test.c b/src/laws.test.c index 48283b017..6549d1bf6 100644 --- a/src/laws.test.c +++ b/src/laws.test.c @@ -2,6 +2,7 @@ #include #include "laws.h" +#include #include #include #include @@ -57,14 +58,15 @@ static void test_rename_building(CuTest * tc) rename_building(u, NULL, b, "Villa Nagel"); CuAssertStrEquals(tc, "Villa Nagel", b->name); + CuAssertTrue(tc, renamed_building(b)); } static void test_rename_building_twice(CuTest * tc) { region *r; - building *b; unit *u; faction *f; + building *b; building_type *btype; test_cleanup(); @@ -85,6 +87,37 @@ static void test_rename_building_twice(CuTest * tc) CuAssertStrEquals(tc, "Villa Kunterbunt", b->name); } +static void test_contact(CuTest * tc) +{ + region *r; + unit *u1, *u2, *u3; + building *b; + building_type *btype; + ally *al; + + test_cleanup(); + test_create_world(); + + btype = bt_get_or_create("castle"); + r = findregion(0, 0); + b = new_building(btype, r, default_locale); + u1 = test_create_unit(test_create_faction(0), r); + u2 = test_create_unit(test_create_faction(0), r); + u3 = test_create_unit(test_create_faction(0), r); + set_level(u3, SK_PERCEPTION, 2); + usetsiege(u3, b); + b->besieged = 1; + CuAssertIntEquals(tc, 1, can_contact(r, u1, u2)); + + u_set_building(u1, b); + CuAssertIntEquals(tc, 0, can_contact(r, u1, u2)); + al = ally_add(&u1->faction->allies, u2->faction); + al->status = HELP_ALL; + CuAssertIntEquals(tc, HELP_GIVE, can_contact(r, u1, u2)); + u_set_building(u2, b); + CuAssertIntEquals(tc, 1, can_contact(r, u1, u2)); +} + static void test_fishing_feeds_2_people(CuTest * tc) { const resource_type *rtype; @@ -412,5 +445,6 @@ CuSuite *get_laws_suite(void) SUITE_ADD_TEST(suite, test_reserve_cmd); SUITE_ADD_TEST(suite, test_new_units); SUITE_ADD_TEST(suite, test_cannot_create_unit_above_limit); + SUITE_ADD_TEST(suite, test_contact); return suite; } diff --git a/src/modules/gmcmd.c b/src/modules/gmcmd.c index 9a5085ecf..d98ae9dbe 100644 --- a/src/modules/gmcmd.c +++ b/src/modules/gmcmd.c @@ -45,9 +45,9 @@ static int read_permissions(attrib * a, void *owner, struct storage *store) { - attrib *attr = NULL; - a_read(store, &attr, owner); - a_remove(&attr, a); + assert(!a); + a_read(store, &a, owner); + a_remove(&a, a); return AT_READ_OK; } diff --git a/src/reports.c b/src/reports.c index 1939fa972..e7ca9c314 100644 --- a/src/reports.c +++ b/src/reports.c @@ -1183,7 +1183,7 @@ link_seen(seen_region * seehash[], const region * first, const region * last) } r = r->next; } - sr->next = 0; + if (sr) sr->next = 0; } seen_region *find_seen(struct seen_region *seehash[], const region * r) diff --git a/src/skill.test.c b/src/skill.test.c index 00c884edc..48b293e04 100644 --- a/src/skill.test.c +++ b/src/skill.test.c @@ -11,8 +11,8 @@ static void test_init_skills(CuTest *tc) { test_cleanup(); lang = get_or_create_locale("de"); - locale_setstring(lang, "alchemy", "Alchemie"); - init_skills(lang); +// locale_setstring(lang, "alchemy", "Alchemie"); + init_skill(lang, SK_ALCHEMY, "Alchemie"); CuAssertIntEquals(tc, SK_ALCHEMY, get_skill("alchemie", lang)); test_cleanup(); } diff --git a/src/test_eressea.c b/src/test_eressea.c index 94f8d6c67..17958c7b2 100644 --- a/src/test_eressea.c +++ b/src/test_eressea.c @@ -35,10 +35,12 @@ int RunAllTests(void) ADD_TESTS(suite, bsdstring); ADD_TESTS(suite, functions); ADD_TESTS(suite, umlaut); + ADD_TESTS(suite, unicode); ADD_TESTS(suite, strings); /* kernel */ ADD_TESTS(suite, unit); ADD_TESTS(suite, faction); + ADD_TESTS(suite, group); ADD_TESTS(suite, build); ADD_TESTS(suite, pool); ADD_TESTS(suite, curse); diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 51ceadac7..a9fde29a8 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -7,6 +7,7 @@ strings.test.c bsdstring.test.c functions.test.c umlaut.test.c +unicode.test.c ) SET(_FILES diff --git a/src/util/attrib.test.c b/src/util/attrib.test.c index 2e15c8321..479809d1d 100644 --- a/src/util/attrib.test.c +++ b/src/util/attrib.test.c @@ -69,6 +69,13 @@ static void test_attrib_nexttype(CuTest * tc) CuAssertPtrEquals(tc, a, alist->nexttype); CuAssertPtrEquals(tc, 0, a->nexttype); + a_remove(&alist, alist); + CuAssertPtrEquals(tc, a, alist->nexttype); + + CuAssertPtrNotNull(tc, (a = a_add(&alist, a_new(&at_bar)))); + a_remove(&alist, alist->nexttype); + CuAssertPtrEquals(tc, a, alist->nexttype); + a_removeall(&alist, &at_foo); a_removeall(&alist, &at_bar); } diff --git a/src/util/language.c b/src/util/language.c index e0384e9b6..1e8cd1a4b 100644 --- a/src/util/language.c +++ b/src/util/language.c @@ -243,8 +243,32 @@ void *get_translation(const struct locale *lang, const char *str, int index) { return NULL; } -void free_locales(void) +const char *localenames[] = { + "de", "en", + NULL +}; + +extern void init_locale(struct locale *lang); + +static int locale_init = 0; + +void init_locales(void) { + int l; + if (locale_init) return; + for (l = 0; localenames[l]; ++l) { + struct locale *lang = get_or_create_locale(localenames[l]); + init_locale(lang); + } + locale_init = 1; +} + +void reset_locales(void) { + locale_init = 0; +} + +void free_locales(void) { + locale_init = 0; while (locales) { int i; locale * next = locales->next; @@ -261,4 +285,5 @@ void free_locales(void) free(locales); locales = next; } -} \ No newline at end of file + memset(lstrs, 0, sizeof(lstrs)); // TODO: does this data need to be free'd? +} diff --git a/src/util/language.h b/src/util/language.h index 7083dec1f..5dd35c7b2 100644 --- a/src/util/language.h +++ b/src/util/language.h @@ -29,7 +29,9 @@ extern "C" { /** managing multiple locales: **/ extern struct locale *get_locale(const char *name); extern struct locale *get_or_create_locale(const char *key); - extern void free_locales(void); + void init_locales(void); + void free_locales(void); + void reset_locales(void); /** operations on locales: **/ extern void locale_setstring(struct locale *lang, const char *key, diff --git a/src/util/unicode.test.c b/src/util/unicode.test.c new file mode 100644 index 000000000..52392fda4 --- /dev/null +++ b/src/util/unicode.test.c @@ -0,0 +1,23 @@ +#include +#include "unicode.h" +#include +#include +#include + +static void test_unicode_tolower(CuTest * tc) +{ + char buffer[32]; + CuAssertIntEquals(tc, 0, unicode_utf8_tolower(buffer, sizeof(buffer), "HeLlO W0Rld")); + CuAssertStrEquals(tc, "hello w0rld", buffer); + memset(buffer, 0, sizeof(buffer)); + buffer[5]='X'; + CuAssertIntEquals(tc, ENOMEM, unicode_utf8_tolower(buffer, 5, "HeLlO W0Rld")); + CuAssertStrEquals(tc, "helloX", buffer); +} + +CuSuite *get_unicode_suite(void) +{ + CuSuite *suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_unicode_tolower); + return suite; +}