diff --git a/conf/e2/config.json b/conf/e2/config.json
index 1ac8fc195..c8bedf2b3 100644
--- a/conf/e2/config.json
+++ b/conf/e2/config.json
@@ -1,6 +1,7 @@
{
"include": [
- "keywords.json"
+ "keywords.json",
+ "e2/terrains.json"
],
"settings": {
"game.id": 2,
diff --git a/conf/e2/config.xml b/conf/e2/config.xml
index 367f43c29..cea730405 100644
--- a/conf/e2/config.xml
+++ b/conf/e2/config.xml
@@ -20,8 +20,6 @@
-
-
diff --git a/conf/e2/terrains.json b/conf/e2/terrains.json
new file mode 100644
index 000000000..709f1b1a4
--- /dev/null
+++ b/conf/e2/terrains.json
@@ -0,0 +1,296 @@
+{
+ "terrains": {
+ "ocean": {
+ "size": 100,
+ "flags": [ "swim", "sea", "sail", "fly" ]
+ },
+ "plain": {
+ "size": 10000,
+ "herbs": [ "h0", "h1", "h2", "h3", "h4", "h5" ],
+ "seed": 3,
+ "road": 50,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.1,
+ "base": "5d8",
+ "div": "2d20+10",
+ "level": "2d4-1"
+ },
+ "stone": {
+ "chance": 0.15,
+ "base": "5d8",
+ "div": "2d30+20",
+ "level": "1d4"
+ },
+ "laen": {
+ "chance": 0.01,
+ "base": "1d4",
+ "div": "2d20+50",
+ "level": "1d4"
+ }
+ }
+ },
+ "swamp": {
+ "size": 2000,
+ "herbs": [ "h6", "h7", "h8" ],
+ "seed": 2,
+ "road": 75,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.02,
+ "base": "5d8",
+ "div": "2d20+10",
+ "level": "2d4-1"
+ },
+ "stone": {
+ "chance": 0.02,
+ "base": "5d8",
+ "div": "2d30+20",
+ "level": "1d4"
+ },
+ "laen": {
+ "chance": 0.02,
+ "base": "1d4",
+ "div": "2d20+50",
+ "level": "1d4"
+ }
+ }
+ },
+ "desert": {
+ "size": 500,
+ "herbs": [ "h9", "h10", "h11" ],
+ "seed": 2,
+ "road": 100,
+ "flags": [ "land", "walk", "sail", "fly", "cavalry" ],
+ "production": {
+ "iron": {
+ "chance": 0.15,
+ "base": "5d8",
+ "div": "2d20+10",
+ "level": "2d4-1"
+ },
+ "stone": {
+ "chance": 0.25,
+ "base": "5d8",
+ "div": "2d30+20",
+ "level": "1d4"
+ },
+ "laen": {
+ "chance": 0.025,
+ "base": "1d4",
+ "div": "2d20+50",
+ "level": "1d4"
+ }
+ }
+ },
+ "highland": {
+ "size": 4000,
+ "herbs": [ "h12", "h13", "h14" ],
+ "seed": 2,
+ "road": 100,
+ "flags": [ "land", "walk", "sail", "fly", "cavalry" ],
+ "production": {
+ "iron": {
+ "chance": 0.15,
+ "base": "5d8",
+ "div": "2d20+10",
+ "level": "2d4-1"
+ },
+ "stone": {
+ "chance": 0.25,
+ "base": "5d8",
+ "div": "2d30+20",
+ "level": "1d4"
+ },
+ "laen": {
+ "chance": 0.025,
+ "base": "1d4",
+ "div": "2d20+50",
+ "level": "1d4"
+ }
+ }
+ },
+ "mountain": {
+ "size": 1000,
+ "herbs": [ "h15", "h16", "h17" ],
+ "seed": 2,
+ "road": 250,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 1.0,
+ "base": "50",
+ "div": "50",
+ "level": "1"
+ },
+ "stone": {
+ "chance": 1.0,
+ "base": "100",
+ "div": "100",
+ "level": "1"
+ },
+ "laen": {
+ "chance": 0.05,
+ "base": "4",
+ "div": "100",
+ "level": "1"
+ }
+ }
+ },
+ "glacier": {
+ "size": 100,
+ "herbs": [ "h15", "h16", "h17" ],
+ "seed": 2,
+ "road": 250,
+ "flags": [ "arctic", "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 1.0,
+ "base": "3",
+ "div": "50",
+ "level": "1"
+ },
+ "stone": {
+ "chance": 1.0,
+ "base": "2",
+ "div": "100",
+ "level": "1"
+ },
+ "laen": {
+ "chance": 0.05,
+ "base": "4",
+ "div": "100",
+ "level": "1"
+ }
+ }
+ },
+ "iceberg": {
+ "size": 100,
+ "herbs": [ "h18", "h19", "h20" ],
+ "flags": [ "arctic", "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.9,
+ "base": "3",
+ "div": "50",
+ "level": "1"
+ },
+ "stone": {
+ "chance": 0.9,
+ "base": "2",
+ "div": "100",
+ "level": "1"
+ }
+ }
+ },
+ "iceberg_sleep": {
+ "size": 100,
+ "herbs": [ "h18", "h19", "h20" ],
+ "flags": [ "arctic", "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.9,
+ "base": "3",
+ "div": "50",
+ "level": "1"
+ },
+ "stone": {
+ "chance": 0.9,
+ "base": "2",
+ "div": "100",
+ "level": "1"
+ },
+ "laen": {
+ "chance": 0.05,
+ "base": "4",
+ "div": "100",
+ "level": "1"
+ }
+ }
+ },
+ "firewall": {
+ "size": 100,
+ "road": 250,
+ "flags": [ "forbidden" ]
+ },
+ "fog": {
+ "flags": [ "walk", "fly" ]
+ },
+ "thickfog": {
+ "flags": [ "forbidden" ]
+ },
+ "volcano": {
+ "size": 500,
+ "road": 250,
+ "seed": 1,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.5,
+ "level": 1,
+ "base": 50,
+ "div": 50
+ },
+ "stone": {
+ "chance": 0.5,
+ "level": 1,
+ "base": 100,
+ "div": 100
+ },
+ "laen": {
+ "chance": 0.075,
+ "level": 1,
+ "base": 4,
+ "div": 100
+ }
+ }
+ },
+ "activevolcano": {
+ "size": 500,
+ "road": 250,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.5,
+ "level": 1,
+ "base": 50,
+ "div": 50
+ },
+ "stone": {
+ "chance": 0.5,
+ "level": 1,
+ "base": 100,
+ "div": 100
+ },
+ "laen": {
+ "chance": 0.075,
+ "level": 1,
+ "base": 4,
+ "div": 100
+ }
+ }
+ },
+ "hell": {
+ "flags": [ "land", "walk" ]
+ },
+ "hall1": {
+ "flags": [ "land", "walk", "sail" ]
+ },
+ "corridor1": {
+ "flags": [ "land", "walk", "sail" ]
+ },
+ "wall1": {
+ "flags": [ "forbidden" ]
+ },
+ "default": {
+ "size": 0,
+ "herbs": [],
+ "seed": 0,
+ "road": 0,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {}
+ }
+ }
+}
diff --git a/conf/e3/config.json b/conf/e3/config.json
index 33b0aa52d..d28dda80f 100644
--- a/conf/e3/config.json
+++ b/conf/e3/config.json
@@ -1,6 +1,7 @@
{
"include": [
- "keywords.json"
+ "keywords.json",
+ "e3/terrains.json"
],
"settings": {
"game.id": 3,
diff --git a/conf/e3/config.xml b/conf/e3/config.xml
index a1dff207a..f1f403ecd 100644
--- a/conf/e3/config.xml
+++ b/conf/e3/config.xml
@@ -14,7 +14,6 @@
-
diff --git a/conf/e3/terrains.json b/conf/e3/terrains.json
new file mode 100644
index 000000000..2688312ab
--- /dev/null
+++ b/conf/e3/terrains.json
@@ -0,0 +1,235 @@
+{
+ "terrains": {
+ "ocean": {
+ "size": 100,
+ "flags": [ "sea", "swim", "sail", "fly" ]
+ },
+ "plain": {
+ "size": 4000,
+ "herbs": [ "h0", "h4" ],
+ "seed": 3,
+ "road": 50,
+ "flags": [ "forest", "cavalry", "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.1,
+ "level": "2d4-1",
+ "base": "5d8",
+ "div": "2d20+10"
+ },
+ "stone": {
+ "chance": 0.15,
+ "level": "1d4",
+ "base": "5d8",
+ "div": "2d30+20"
+ },
+ "laen": {
+ "chance": 0.01,
+ "level": "1d4",
+ "base": "1d4",
+ "div": "2d20+50"
+ }
+ }
+ },
+ "swamp": {
+ "size": 1200,
+ "herbs": [ "h6", "h8" ],
+ "seed": 2,
+ "road": 75,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.02,
+ "level": "2d4-1",
+ "base": "5d8",
+ "div": "2d20+10"
+ },
+ "stone": {
+ "chance": 0.02,
+ "level": "1d4",
+ "base": "5d8",
+ "div": "2d30+20"
+ },
+ "laen": {
+ "chance": 0.02,
+ "level": "1d4",
+ "base": "1d4",
+ "div": "2d20+50"
+ }
+ }
+ },
+ "desert": {
+ "size": 400,
+ "seed": 2,
+ "road": 75,
+ "flags": [ "cavalry", "land", "walk", "sail", "fly" ],
+ "herbs": [ "h9", "h11" ],
+ "production": {
+ "iron": {
+ "chance": 0.15,
+ "level": "2d4-1",
+ "base": "5d8",
+ "div": "2d20+10"
+ },
+ "stone": {
+ "chance": 0.25,
+ "level": "1d4",
+ "base": "5d8",
+ "div": "2d30+20"
+ },
+ "laen": {
+ "chance": 0.025,
+ "level": "1d4",
+ "base": "1d4",
+ "div": "2d20+50"
+ }
+ }
+ },
+ "highland": {
+ "size": 2300,
+ "seed": 2,
+ "road": 100,
+ "flags": [ "cavalry", "land", "walk", "sail", "fly" ],
+ "herbs": [ "h12", "h14" ],
+ "production": {
+ "iron": {
+ "chance": 0.15,
+ "level": "2d4-1",
+ "base": "5d8",
+ "div": "2d20+10"
+ },
+ "stone": {
+ "chance": 0.25,
+ "level": "1d4",
+ "base": "5d8",
+ "div": "2d30+20"
+ },
+ "laen": {
+ "chance": 0.025,
+ "level": "1d4",
+ "base": "1d4",
+ "div": "2d20+50"
+ }
+ }
+ },
+ "mountain": {
+ "size": 600,
+ "seed": 2,
+ "road": 250,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "herbs": [ "h15", "h17" ],
+ "production": {
+ "iron": {
+ "chance": 1.0,
+ "level": "1",
+ "base": "50",
+ "div": "50"
+ },
+ "stone": {
+ "chance": 1.0,
+ "level": "1",
+ "base": "100",
+ "div": "100"
+ },
+ "laen": {
+ "chance": 0.05,
+ "level": "1",
+ "base": "4",
+ "div": "100"
+ }
+ }
+ },
+ "glacier": {
+ "size": 150,
+ "seed": 2,
+ "road": 250,
+ "flags": [ "arctic", "land", "walk", "sail", "fly" ],
+ "herbs": [ "h18", "h20" ],
+ "production": {
+ "iron": {
+ "chance": 1.0,
+ "level": "1",
+ "base": "3",
+ "div": "50"
+ },
+ "stone": {
+ "chance": 1.0,
+ "level": "1",
+ "base": "2",
+ "div": "100"
+ },
+ "laen": {
+ "chance": 0.05,
+ "level": "1",
+ "base": "4",
+ "div": "100"
+ }
+ }
+ },
+ "packice": {
+ "flags": [ "arctic", "swim", "walk", "sail", "fly" ]
+ },
+ "firewall": {
+ "flags": [ "forbidden" ]
+ },
+ "volcano": {
+ "size": 400,
+ "seed": 1,
+ "road": 250,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.5,
+ "level": "1",
+ "base": "50",
+ "div": "50"
+ },
+ "stone": {
+ "chance": 0.5,
+ "level": "1",
+ "base": "100",
+ "div": "100"
+ },
+ "laen": {
+ "chance": 0.075,
+ "level": "1",
+ "base": "4",
+ "div": "100"
+ }
+ }
+ },
+ "activevolcano": {
+ "size": 400,
+ "road": 250,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {
+ "iron": {
+ "chance": 0.5,
+ "level": "1",
+ "base": "50",
+ "div": "50"
+ },
+ "stone": {
+ "chance": 0.5,
+ "level": "1",
+ "base": "100",
+ "div": "100"
+ },
+ "laen": {
+ "chance": 0.075,
+ "level": "1",
+ "base": "4",
+ "div": "100"
+ }
+ }
+ },
+ "default": {
+ "size": 0,
+ "herbs": [],
+ "seed": 0,
+ "road": 0,
+ "flags": [ "land", "walk", "sail", "fly" ],
+ "production": {}
+ }
+ }
+}
\ No newline at end of file
diff --git a/conf/e4/config.json b/conf/e4/config.json
index 0f31d8362..b6a0e16ab 100644
--- a/conf/e4/config.json
+++ b/conf/e4/config.json
@@ -1,6 +1,7 @@
{
"include": [
- "keywords.json"
+ "keywords.json",
+ "e3/terrains.xml"
],
"settings": {
"game.id": 4,
diff --git a/conf/e4/config.xml b/conf/e4/config.xml
index 8e0fad67c..011f19821 100644
--- a/conf/e4/config.xml
+++ b/conf/e4/config.xml
@@ -14,7 +14,6 @@
-
diff --git a/res/core/messages.xml b/res/core/messages.xml
index 084ffd20a..43939b2b4 100644
--- a/res/core/messages.xml
+++ b/res/core/messages.xml
@@ -6425,7 +6425,7 @@
- "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat soetwas nicht."
+ "$unit($unit) in $region($region): '$order($command)' - Die Einheit hat so etwas nicht."
"$unit($unit) in $region($region): '$order($command)' - The unit does not have this."
diff --git a/res/core/terrains.xml b/res/core/terrains.xml
deleted file mode 100644
index 67238c966..000000000
--- a/res/core/terrains.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/e3a/terrains.xml b/res/e3a/terrains.xml
deleted file mode 100644
index 8d9d6f17a..000000000
--- a/res/e3a/terrains.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/eressea/terrains.xml b/res/eressea/terrains.xml
deleted file mode 100644
index e506c5dd4..000000000
--- a/res/eressea/terrains.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/res/terrains.xml b/res/terrains.xml
deleted file mode 100644
index f5786d42a..000000000
--- a/res/terrains.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/kernel/item.c b/src/kernel/item.c
index f801cf226..4aab13112 100644
--- a/src/kernel/item.c
+++ b/src/kernel/item.c
@@ -54,6 +54,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/* libc includes */
#include
+#include
#include
#include
@@ -179,9 +180,14 @@ static void rt_register(resource_type * rtype)
resource_type *rt_get_or_create(const char *name) {
resource_type *rtype = rt_find(name);
if (!rtype) {
- rtype = (resource_type *)calloc(sizeof(resource_type), 1);
- rtype->_name = _strdup(name);
- rt_register(rtype);
+ rtype = calloc(1, sizeof(resource_type));
+ if (!rtype) {
+ perror("resource_type allocation failed");
+ }
+ else {
+ rtype->_name = _strdup(name);
+ rt_register(rtype);
+ }
}
return rtype;
}
diff --git a/src/kernel/jsonconf.c b/src/kernel/jsonconf.c
index 7b2297146..b9fe278b5 100644
--- a/src/kernel/jsonconf.c
+++ b/src/kernel/jsonconf.c
@@ -185,6 +185,39 @@ static void json_construction(cJSON *json, construction **consp) {
*consp = cons;
}
+static void json_terrain_production(cJSON *json, terrain_production *prod) {
+ assert(json->type == cJSON_Object);
+ cJSON *child;
+ for (child = json->child; child; child = child->next) {
+ switch (child->type) {
+ case cJSON_String:
+ if (strcmp(child->string, "base") == 0) {
+ prod->base = _strdup(child->valuestring);
+ }
+ else if (strcmp(child->string, "level") == 0) {
+ prod->startlevel = _strdup(child->valuestring);
+ }
+ else if (strcmp(child->string, "div") == 0) {
+ prod->divisor = _strdup(child->valuestring);
+ }
+ else {
+ log_error("terrain_production %s contains unknown attribute %s", json->string, child->string);
+ }
+ break;
+ case cJSON_Number:
+ if (strcmp(child->string, "chance") == 0) {
+ prod->chance = (float)child->valuedouble;
+ }
+ else {
+ log_error("terrain_production %s contains unknown attribute %s", json->string, child->string);
+ }
+ break;
+ default:
+ log_error("terrain_production %s contains unknown attribute %s", json->string, child->string);
+ }
+ }
+}
+
static void json_terrain(cJSON *json, terrain_type *ter) {
cJSON *child;
if (json->type != cJSON_Object) {
@@ -193,6 +226,29 @@ static void json_terrain(cJSON *json, terrain_type *ter) {
}
for (child = json->child; child; child = child->next) {
switch (child->type) {
+ case cJSON_Object:
+ if (strcmp(child->string, "production") == 0) {
+ cJSON *entry;
+ int size = cJSON_GetArraySize(child);
+ if (size > 0) {
+ int n;
+ ter->production = (terrain_production *)calloc(size + 1, sizeof(terrain_production));
+ ter->production[size].type = 0;
+ for (n = 0, entry = child->child; entry; entry = entry->next, ++n) {
+ ter->production[n].type = rt_get_or_create(entry->string);
+ if (entry->type != cJSON_Object) {
+ log_error("terrain %s contains invalid production %s", json->string, entry->string);
+ }
+ else {
+ json_terrain_production(entry, ter->production + n);
+ }
+ }
+ }
+ }
+ else {
+ log_error("terrain %s contains unknown attribute %s", json->string, child->string);
+ }
+ break;
case cJSON_Array:
if (strcmp(child->string, "flags") == 0) {
const char * flags[] = {
@@ -200,6 +256,32 @@ static void json_terrain(cJSON *json, terrain_type *ter) {
};
ter->flags = json_flags(child, flags);
}
+ else if (strcmp(child->string, "herbs") == 0) {
+ cJSON *entry;
+ int size = cJSON_GetArraySize(child);
+ if (size > 0) {
+ int n;
+ ter->herbs = malloc(sizeof(const item_type *) * (size + 1));
+ ter->herbs[size] = 0;
+ for (n = 0, entry = child->child; entry; entry = entry->next) {
+ ter->herbs[n++] = it_get_or_create(rt_get_or_create(entry->valuestring));
+ }
+ }
+ }
+ else {
+ log_error("terrain %s contains unknown attribute %s", json->string, child->string);
+ }
+ break;
+ case cJSON_Number:
+ if (strcmp(child->string, "size") == 0) {
+ ter->size = child->valueint;
+ }
+ else if (strcmp(child->string, "road") == 0) {
+ ter->max_road = (short)child->valueint;
+ }
+ else if (strcmp(child->string, "seed") == 0) {
+ ter->distribution = (short)child->valueint;
+ }
else {
log_error("terrain %s contains unknown attribute %s", json->string, child->string);
}
@@ -702,14 +784,20 @@ static void json_include(cJSON *json) {
fclose(F);
config = cJSON_Parse(data);
free(data);
- json_config(config);
- cJSON_Delete(config);
+ if (config) {
+ json_config(config);
+ cJSON_Delete(config);
+ }
+ else {
+ log_error("invalid JSON, could not parse %s", child->valuestring);
+ }
}
}
}
void json_config(cJSON *json) {
cJSON *child;
+ assert(json);
if (json->type != cJSON_Object) {
log_error("config is not a json object: %d", json->type);
return;
@@ -751,6 +839,7 @@ void json_config(cJSON *json) {
}
else if (strcmp(child->string, "terrains") == 0) {
json_terrains(child);
+ init_terrains();
}
else {
log_error("config contains unknown attribute %s", child->string);
diff --git a/src/kernel/jsonconf.test.c b/src/kernel/jsonconf.test.c
index c317fc15a..2fd8e3efe 100644
--- a/src/kernel/jsonconf.test.c
+++ b/src/kernel/jsonconf.test.c
@@ -389,7 +389,13 @@ static void test_configs(CuTest * tc)
static void test_terrains(CuTest * tc)
{
- const char * data = "{\"terrains\": { \"plain\" : { \"flags\" : [ \"land\", \"fly\", \"walk\" ] } }}";
+ const char * data = "{\"terrains\": { \"plain\" : { "
+ "\"herbs\": [ \"h0\", \"h1\" ], "
+ "\"production\": { \"stone\": { \"chance\": 0.1, \"base\": \"1d4\", \"div\": \"1d5\", \"level\": \"1d6\" }, \"iron\": {} }, "
+ "\"size\": 4000, "
+ "\"road\": 50, "
+ "\"seed\": 3, "
+ "\"flags\" : [ \"forbidden\", \"arctic\", \"cavalry\", \"sea\", \"forest\", \"land\", \"sail\", \"fly\", \"swim\", \"walk\" ] } }}";
const terrain_type *ter;
cJSON *json = cJSON_Parse(data);
@@ -401,7 +407,23 @@ static void test_terrains(CuTest * tc)
json_config(json);
ter = get_terrain("plain");
CuAssertPtrNotNull(tc, ter);
- CuAssertIntEquals(tc, ter->flags, LAND_REGION | FLY_INTO | WALK_INTO);
+ CuAssertIntEquals(tc, ARCTIC_REGION | LAND_REGION | SEA_REGION | FOREST_REGION | CAVALRY_REGION | FORBIDDEN_REGION | FLY_INTO | WALK_INTO | SWIM_INTO | SAIL_INTO, ter->flags);
+ CuAssertIntEquals(tc, 4000, ter->size);
+ CuAssertIntEquals(tc, 50, ter->max_road);
+ CuAssertIntEquals(tc, 3, ter->distribution);
+ CuAssertPtrNotNull(tc, ter->herbs);
+ CuAssertPtrEquals(tc, rt_get_or_create("h0"), ter->herbs[0]->rtype);
+ CuAssertPtrEquals(tc, rt_get_or_create("h1"), ter->herbs[1]->rtype);
+ CuAssertPtrEquals(tc, 0, (void *)ter->herbs[2]);
+ CuAssertPtrNotNull(tc, ter->name); // anything named "plain" uses plain_name()
+ CuAssertPtrNotNull(tc, ter->production);
+ CuAssertPtrEquals(tc, rt_get_or_create("stone"), (resource_type *)ter->production[0].type);
+ CuAssertDblEquals(tc, 0.1, ter->production[0].chance, 0.01);
+ CuAssertStrEquals(tc, "1d4", ter->production[0].base);
+ CuAssertStrEquals(tc, "1d5", ter->production[0].divisor);
+ CuAssertStrEquals(tc, "1d6", ter->production[0].startlevel);
+ CuAssertPtrEquals(tc, rt_get_or_create("iron"), (resource_type *)ter->production[1].type);
+ CuAssertPtrEquals(tc, 0, (void *)ter->production[2].type);
test_cleanup();
}
diff --git a/src/kernel/region.c b/src/kernel/region.c
index 8b82edbea..1b4bf838e 100644
--- a/src/kernel/region.c
+++ b/src/kernel/region.c
@@ -1119,14 +1119,19 @@ void terraform_region(region * r, const terrain_type * terrain)
}
if (oldterrain == NULL || terrain->size != oldterrain->size) {
+ int horses = 0, trees = 0;
+ if (terrain->size>0) {
+ horses = rng_int() % (terrain->size / 50);
+ trees = terrain->size * (30 + rng_int() % 40) / 1000;
+ }
if (terrain == newterrain(T_PLAIN)) {
- rsethorses(r, rng_int() % (terrain->size / 50));
- if (rng_int() % 100 < 40) {
- rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000);
+ rsethorses(r, horses);
+ if (chance(0.4)) {
+ rsettrees(r, 2, trees);
}
}
- else if (chance(0.2)) {
- rsettrees(r, 2, terrain->size * (30 + rng_int() % 40) / 1000);
+ else if (trees>0 && chance(0.2)) {
+ rsettrees(r, 2, trees);
}
else {
rsettrees(r, 2, 0);
@@ -1146,7 +1151,7 @@ void terraform_region(region * r, const terrain_type * terrain)
/** ENNO:
* ich denke, das das hier nicht sein sollte.
- * statt dessen sollte ein attribut an der region sein, das das erledigt,
+ * statt dessen sollte ein attribut an der region sein, dass das erledigt,
* egal ob durch den spell oder anderes angelegt.
**/
#include "curse.h"
diff --git a/src/kernel/terrain.c b/src/kernel/terrain.c
index f27fe1bd0..e72e94bfa 100644
--- a/src/kernel/terrain.c
+++ b/src/kernel/terrain.c
@@ -59,10 +59,18 @@ static terrain_type *registered_terrains;
void free_terrains(void)
{
while (registered_terrains) {
+ int n;
terrain_type * t = registered_terrains;
registered_terrains = t->next;
free(t->_name);
- free(t->production);
+ if (t->production) {
+ for (n = 0; t->production[n].type; ++n) {
+ free(t->production[n].base);
+ free(t->production[n].divisor);
+ free(t->production[n].startlevel);
+ }
+ free(t->production);
+ }
free(t);
}
}
diff --git a/src/kernel/terrain.h b/src/kernel/terrain.h
index 64b0aa299..945d07794 100644
--- a/src/kernel/terrain.h
+++ b/src/kernel/terrain.h
@@ -51,9 +51,9 @@ extern "C" {
typedef struct terrain_production {
const struct resource_type *type;
- const char *startlevel;
- const char *base;
- const char *divisor;
+ char *startlevel;
+ char *base;
+ char *divisor;
float chance;
} terrain_production;
diff --git a/src/kernel/xmlreader.c b/src/kernel/xmlreader.c
index 2deb15be7..5d8f081cc 100644
--- a/src/kernel/xmlreader.c
+++ b/src/kernel/xmlreader.c
@@ -1883,131 +1883,6 @@ static int parse_races(xmlDocPtr doc)
return 0;
}
-static int parse_terrains(xmlDocPtr doc)
-{
- xmlXPathContextPtr xpath;
- xmlXPathObjectPtr terrains;
- xmlNodeSetPtr nodes;
- int i;
-
- xpath = xmlXPathNewContext(doc);
-
- /* reading eressea/terrains/terrain */
- terrains =
- xmlXPathEvalExpression(BAD_CAST "/eressea/terrains/terrain", xpath);
- nodes = terrains->nodesetval;
- for (i = 0; i != nodes->nodeNr; ++i) {
- xmlNodePtr node = nodes->nodeTab[i];
- terrain_type *terrain;
- xmlChar *propValue;
- xmlXPathObjectPtr xpathChildren;
- xmlNodeSetPtr children;
-
- propValue = xmlGetProp(node, BAD_CAST "name");
- assert(propValue != NULL);
- terrain = get_or_create_terrain((const char *)propValue);
- xmlFree(propValue);
-
- terrain->max_road = (short)xml_ivalue(node, "road", 0);
- assert(terrain->max_road >= 0);
- terrain->size = xml_ivalue(node, "size", 0);
-
- if (xml_bvalue(node, "forbidden", false))
- terrain->flags |= FORBIDDEN_REGION;
- else {
- if (xml_bvalue(node, "fly", true))
- terrain->flags |= FLY_INTO;
- if (xml_bvalue(node, "sail", true))
- terrain->flags |= SAIL_INTO;
- if (xml_bvalue(node, "walk", true))
- terrain->flags |= WALK_INTO;
- if (xml_bvalue(node, "swim", false))
- terrain->flags |= SWIM_INTO;
- if (xml_bvalue(node, "cavalry", false))
- terrain->flags |= CAVALRY_REGION;
- }
- if (xml_bvalue(node, "sea", false))
- terrain->flags |= SEA_REGION;
- if (xml_bvalue(node, "arctic", false))
- terrain->flags |= ARCTIC_REGION;
- if (xml_bvalue(node, "land", true))
- terrain->flags |= LAND_REGION;
- if (xml_bvalue(node, "forest", false))
- terrain->flags |= FOREST_REGION;
-
- terrain->distribution = (short)xml_ivalue(node, "seed", 0);
-
- xpath->node = node;
- xpathChildren = xmlXPathEvalExpression(BAD_CAST "herb", xpath);
- children = xpathChildren->nodesetval;
- if (children->nodeNr > 0) {
- int k;
-
- terrain->herbs = malloc((children->nodeNr + 1) * sizeof(item_type *));
- terrain->herbs[children->nodeNr] = NULL;
- for (k = 0; k != children->nodeNr; ++k) {
- xmlNodePtr nodeHerb = children->nodeTab[k];
- const struct resource_type *rtype;
-
- propValue = xmlGetProp(nodeHerb, BAD_CAST "name");
- assert(propValue != NULL);
- rtype = rt_find((const char *)propValue);
- assert(rtype != NULL && rtype->itype != NULL
- && fval(rtype->itype, ITF_HERB));
- terrain->herbs[k] = rtype->itype;
- xmlFree(propValue);
- }
- }
- xmlXPathFreeObject(xpathChildren);
-
- xpath->node = node;
- xpathChildren = xmlXPathEvalExpression(BAD_CAST "resource", xpath);
- children = xpathChildren->nodesetval;
- if (children->nodeNr > 0) {
- int k;
-
- terrain->production =
- malloc((children->nodeNr + 1) * sizeof(terrain_production));
- terrain->production[children->nodeNr].type = NULL;
- for (k = 0; k != children->nodeNr; ++k) {
- xmlNodePtr nodeProd = children->nodeTab[k];
-
- propValue = xmlGetProp(nodeProd, BAD_CAST "name");
- assert(propValue != NULL);
- terrain->production[k].type = rt_find((const char *)propValue);
- assert(terrain->production[k].type);
- xmlFree(propValue);
-
- propValue = xmlGetProp(nodeProd, BAD_CAST "level");
- assert(propValue);
- terrain->production[k].startlevel = _strdup((const char *)propValue);
- xmlFree(propValue);
-
- propValue = xmlGetProp(nodeProd, BAD_CAST "base");
- assert(propValue);
- terrain->production[k].base = _strdup((const char *)propValue);
- xmlFree(propValue);
-
- propValue = xmlGetProp(nodeProd, BAD_CAST "div");
- assert(propValue);
- terrain->production[k].divisor = _strdup((const char *)propValue);
- xmlFree(propValue);
-
- terrain->production[k].chance =
- (float)xml_fvalue(nodeProd, "chance", 1.0);
- }
- }
- xmlXPathFreeObject(xpathChildren);
-
- }
- xmlXPathFreeObject(terrains);
-
- xmlXPathFreeContext(xpath);
-
- init_terrains();
- return 0;
-}
-
static int parse_messages(xmlDocPtr doc)
{
xmlXPathContextPtr xpath;
@@ -2287,7 +2162,6 @@ void register_xmlreader(void)
xml_register_callback(parse_resources);
xml_register_callback(parse_rules);
- xml_register_callback(parse_terrains); /* requires resources */
xml_register_callback(parse_buildings); /* requires resources */
xml_register_callback(parse_ships); /* requires terrains */
xml_register_callback(parse_spells); /* requires resources */
diff --git a/src/move.test.c b/src/move.test.c
index 4e2b5f41e..de515be16 100644
--- a/src/move.test.c
+++ b/src/move.test.c
@@ -215,6 +215,31 @@ static void test_walkingcapacity(CuTest *tc) {
test_cleanup();
}
+static void test_is_guarded(CuTest *tc) {
+ unit *u1, *u2;
+ region *r;
+ race *rc;
+
+ test_cleanup();
+ rc = rc_get_or_create("dragon");
+ rc->flags |= RCF_UNARMEDGUARD;
+ r = test_create_region(0, 0, 0);
+ u1 = test_create_unit(test_create_faction(0), r);
+ u2 = test_create_unit(test_create_faction(rc), r);
+ CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TRAVELTHRU));
+ CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_PRODUCE));
+ CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TREES));
+ CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_MINING));
+ guard(u2, GUARD_MINING | GUARD_PRODUCE);
+ CuAssertIntEquals(tc, GUARD_CREWS | GUARD_LANDING | GUARD_TRAVELTHRU | GUARD_TAX | GUARD_PRODUCE | GUARD_RECRUIT, guard_flags(u2));
+ CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TRAVELTHRU));
+ CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_TREES));
+ CuAssertPtrEquals(tc, 0, is_guarded(r, u1, GUARD_MINING));
+ CuAssertPtrEquals(tc, u2, is_guarded(r, u1, GUARD_PRODUCE));
+
+ test_cleanup();
+}
+
CuSuite *get_move_suite(void)
{
CuSuite *suite = CuSuiteNew();
@@ -226,5 +251,6 @@ CuSuite *get_move_suite(void)
SUITE_ADD_TEST(suite, test_ship_has_harbormaster_contact);
SUITE_ADD_TEST(suite, test_ship_has_harbormaster_ally);
SUITE_ADD_TEST(suite, test_ship_has_harbormaster_same_faction);
+ SUITE_ADD_TEST(suite, test_is_guarded);
return suite;
}