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;
+}